balabala丶 2022-03-16 00:17 采纳率: 66.7%
浏览 44
已结题

俄罗斯方块,掉到底后就只剩下一个方块

问题遇到的现象和发生背景
问题相关代码,请勿粘贴截图
using namespace sf;  //声明 命名空间 
//行列数
const int ROW_COUNT = 20;
const int COL_COUNT = 10;

struct Point {
    int x;
    int y;
} curBlock[4], bakBlock[4];


//游戏区的表示
//table[i][j] == 0 表示 第i行第j列 是空白的,否则表示 有方块
//table[i][j] == 1 表示有方块,而且是第一仲方块(使用第一种颜色)
int table[ROW_COUNT][COL_COUNT] = { 0 };

//当前方块的种类
int blockIndex;

//检查方块位置合法性
bool check() {
    for (int i = 0; i < 4; i++) {
        if (curBlock[i].x<0 
            || curBlock[i].x>=COL_COUNT
            || curBlock[i].y >= ROW_COUNT
            || table[curBlock[i].y][curBlock[i].x]) { //已经有方块了
            return false;

        }
        return true;
    }
}



//开发步骤:
//1.搭建SFML环境
//2.处理按键
//3生成方块

//3.1俄罗斯方块的表示
int blocks[7][4] = {
{1,3,5,7},  // 1字型
{2,4,5,7},  // Z 1 型
{3,5,4,6},  //Z 2型
{3,5,4,7},  // T
{2,3,5,7},    //L
{3,5,7,6},    //J
{2,3,4,5},   //田
};






//游戏方块表示


const float  SPEED_NORMAL=0.5;
const float SPEED_QUICK = 0.05;

//表示下降速度
float delay =SPEED_NORMAL;

Sound sou;

//键盘移动的偏移处理
void moveLeftRight(int dx) {
    for (int i = 0; i < 4; i++) {
        bakBlock[i] = curBlock[i];
        curBlock[i].x += dx;

     }
    if (!check()) {
        for (int i = 0; i < 4; i++) {
            curBlock[i] = bakBlock[i];
        }
    }
}

//旋转处理
void doRotate() {
    if (blockIndex == 7) {
        return;
    }
    //先备份
    for (int i = 0; i < 4; i++) {
        bakBlock[i] = curBlock[i];
    }
    //旋转中心
    Point p = curBlock[1];
    // x坐标计算: p.x -a[i].y +p.x
    // y坐标计算:
    for (int i = 0; i < 4; i++) {
        Point tmp = curBlock[i];
        curBlock[i].x = p.x - tmp.y + p.y;
        curBlock[i].y = tmp.x - p.x + p.y;
    }

    //检查合法性
    if (!check()) {
        for (int i = 0; i < 4; i++) {
            curBlock[i] = bakBlock[i];
        }
    }
}

//处理按键
void keyEven(RenderWindow *window){
    bool rotate = false; //表示是否旋转
    Event e; //事件变量
    int dx = 0; //偏移量
    //pollEvent 从事件队列中取出一个事件
    //如果没有事件了,就返回false
    while (window->pollEvent(e)){
        if (e.type == Event::Closed) {
            window->close();
        }
        if (e.type == Event::KeyPressed) {
            switch (e.key.code) {
            case Keyboard::Up:
                rotate = true;
                break;
            case Keyboard::Left:
                dx= - 1;
                break;
            case Keyboard::Right:
                dx = 1;
                break;
            default:
                break;
            }
        }
        //处理下降
        if (Keyboard::isKeyPressed(Keyboard::Down)) {
            delay = SPEED_QUICK;
        }
        if (dx != 0) {
            moveLeftRight(dx);
        }
        if (rotate) {
            doRotate();
        }
    }

}



//生成方块
void newBlock(){
    // 获取一个随机值 (1...7)
    blockIndex = (rand()%7)+1;
    int n = blockIndex - 1;

    // 序号【0-7】 %2  就是 x 坐标  【0-1// 序号/20-7】   就是 y坐标 【0-3for (int i = 0; i < 4; i++) {
        curBlock[i].x = blocks[n][i] % 2;
        curBlock[i].y = blocks[n][i] / 2;
    }


}

void drawBlock(Sprite *spriteBlock, RenderWindow* window) {
    //1.已经降落到底部的俄罗斯方块
    for (int i = 0; i < ROW_COUNT; i++) {
        for (int j = 0; j < COL_COUNT; j++) {
            if (table[i][j] != 0) {
                //画小方块
                //需要先用Sprite 表示完整的方块图片
                spriteBlock->setTextureRect(IntRect(table[i][j] * 18, 0, 18, 18));  //table[i][j] --》表格中的第 几个 方块
                spriteBlock->setPosition(j * 18, i * 18);

                //设置偏移量
                spriteBlock->move(28, 31);
                //绘制
                window->draw(*spriteBlock);
            }
        }
    }


    //2.正在降落过程中的方块(当前方块)
    for (int i = 0; i < 4; i++) {
        spriteBlock->setTextureRect(IntRect(blockIndex * 18, 0, 18, 18));  //blockIndex --》当前第 几个方块
        spriteBlock->setPosition(curBlock[i].x * 18, curBlock[i].y * 18);

        //设置偏移量
        spriteBlock->move(28, 31);
        //绘制
        window->draw(*spriteBlock);

    }


}

void cleanLine() {
    //从最下面一行开始遍历
    int k = ROW_COUNT - 1;   

     //遍历每一行
    for (int i = ROW_COUNT - 1; i > 0; i--) {
        //该行 已被占的 格子数
        int count = 0;      
        //遍历每个格子
        for (int j = 0; j < COL_COUNT; j++) {
            //已经有方块  数量++
            if (table[i][j]) { 
                count++;
            }
            // 与上一行的遍历相关,
            //若上一行满了,则 用来 覆盖上一行的格子
            //若上一行未满, 则 只是 一个没用的临时变量
            table[k][j] = table[i][j];
        }
        if (count < COL_COUNT) {
            k--;
        }
    
        else {
            //音效
            sou.play();
        }
    }
}

void drop() {
    for (int i = 0; i < 4; i++) {
        bakBlock[i] = curBlock[i];
        curBlock[i].y += 1;
    }
    if (check() == false) {
        //固化处理
        for (int i = 0; i < 4; i++) {
            table[bakBlock[i].y][bakBlock[i].x] = blockIndex;
        }

        //产生一个新方块
        newBlock();
    }
}

int main(void) {
    //生成一个随机种子
    srand(time(0)); 

    ////背景运营月
    //Music music;
    //if (!music.openFromFile("bg2.mp3")) {
    //    return -1;
    //}
    //music.setLoop(true);
    //music.play();

    //SoundBuffer xiaochu;
    //if (xiaochu.loadFromFile("xiaochu.mp3")) {
    //    return -1;
    //}
    //sou.setBuffer(xiaochu);


    //游戏界面
    //1.创建游戏窗口
    //1.1准备窗口的背景图片
    RenderWindow window(
        VideoMode(320,416),  //窗口模式、大小
        "俄罗斯方块");        //窗口标题
    
         //2添加游戏背景

    //把图片文件加载到内存
    Texture t1;       
    t1.loadFromFile("image/bg.jpg");  //背景
    Sprite spriteBg(t1); //根据图片来创建精灵

    Texture t2;
    t2.loadFromFile("image/tiles.png");  //方块素材
    Sprite spriteBlock(t2);



    ////渲染这个精灵
    //window.draw(spriteBg);    
    ////显示(刷新)窗口
    //window.display();

    //生成第一个方块
    newBlock();

    //计时器Clock
    Clock clock;

    float timer = 0;

    //进入游戏循环
    while(window.isOpen()){    //当窗口没被关闭
        //获取从clock被启动/重启后,到现在的时间
       float time =    clock.getElapsedTime().asSeconds();
       clock.restart();
       timer += time;

    //等待用户按下按键,并处理
       keyEven(&window);

        if (timer > delay) {
            //降落
            drop(); //下降一位位置
            timer = 0;
        }

        //消除一行
        cleanLine();

        delay = SPEED_NORMAL;
        //绘制游戏
        window.draw(spriteBg);
        

        //绘制方块
        drawBlock(&spriteBlock,&window);

        window.display();  //刷新并显示窗口
    }
    system("pause");
    
    
    return 0;
    
      
}
运行结果及报错内容

img

img

我的解答思路和尝试过的方法
我想要达到的结果

怎么才能改BUG

  • 写回答

1条回答 默认 最新

  • 赵4老师 2022-03-16 10:40
    关注

    代码功能归根结底不是别人帮自己看或讲解或注释出来的;而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。
    提醒:再牛×的老师也无法代替学生自己领悟和上厕所!
    单步调试和设断点调试(VS IDE中编译连接通过以后,按F10或F11键单步执行,按Shift+F11退出当前函数;在某行按F9设断点后按F5执行停在该断点处。)是程序员必须掌握的技能之一。

    java也一样可以在IDE中调试或写日志文件调试。

    评论 编辑记录

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 7月6日
  • 创建了问题 3月16日

悬赏问题

  • ¥15 x264库中预测模式字IPM、运动向量差MVD、量化后的DCT系数的位置
  • ¥15 curl 命令调用正常,程序调用报 java.net.ConnectException: connection refused
  • ¥20 关于web前端如何播放二次加密m3u8视频的问题
  • ¥15 使用百度地图api 位置函数报错?
  • ¥15 metamask如何添加TRON自定义网络
  • ¥66 关于川崎机器人调速问题
  • ¥15 winFrom界面无法打开
  • ¥30 crossover21 ARM64版本安装软件问题
  • ¥15 mymetaobjecthandler没有进入
  • ¥15 mmo能不能做客户端怪物