【问题标题】:Snake Game going too fast console c++Snake Game 太快了控制台 C++
【发布时间】:2022-01-01 15:27:18
【问题描述】:

我一直在关注一些关于制作有点蛇游戏的教程,但不是一个完整的游戏,一切正常,我认为我几乎做对了,但我有两个问题

#include <bits/stdc++.h>
#include <conio.h>
#include <unistd.h>
using namespace std;

int side,x,y;
int fruitx,fruity,score,flag;
bool isOver;

void randomize();
void frame(int);
void userinp();
void game();

int main(){
    do{
        cout << "Enter the side of your frame!(not less than 20)\n";
        cin >> side;
    }while(side < 20);
    randomize();
    while(!isOver){
        frame(side);
        userinp();
        game();
    }
    return 0;
}

void randomize(){
    x = side/2;
    y = side/2;
    label1: fruitx = rand()%side;
    if (fruitx == 0 || fruitx == side)
        goto label1;
    label2:
    fruity = rand()%side;
    if (fruity == 0 || fruity == side)
        goto label2;

    score = 0;
}
void frame(int s){
    system("cls");
    for(int i=1;i<=s;i++){
        for(int j=1;j<=s;j++){
            if(i == 1 || i == s || j == 1 || j == s)
                cout << "*";
            else{
                if(i == x && j == y){
                    cout << "-";
                }
                else if(i == fruitx && j == fruity){
                    cout << "x";
                }
                else
                    cout << " ";
            }
        }
        cout << "\n";
    }
    cout << "Your score: " << score << endl;
}
void userinp(){
    if(kbhit()){
        switch (getch()){
        case 'a':
            flag = 1;
            break;
        case 's':
            flag = 2;
            break;
        case 'd':
            flag = 3;
            break;
        case 'w':
            flag = 4;
            break;
        default:
            isOver = true;
        }
    }
}
void game(){
    sleep(0.899);
    switch (flag){
    case 1:
        y--;
        break;
    case 2:
        x++;
        break;
    case 3:
        y++;
        break;
    case 4:
        x--;
        break;
    }
     if (x < 0 || x > side || y < 0 || y > side){
        x = side/2;
        y = side/2;
     }
     if (x == fruitx && y == fruity) {
        label3: fruitx = rand()%(side);
        if (fruitx == 0)
            goto label3;

        label4: fruity = rand()%(side);
        if (fruity == 0)
            goto label4;

        score++;
    }
}

第一个问题:

使用 system"(cls") 帮助屏幕多次不下降有点使用sleep()函数,它要么太慢要么太快屏幕,是否有不同的方法来处理整个事情或者函数本身不适合在这里使用?

第二个问题: 每当我用 20 输入边时,我根本找不到水果本身,但是当它超过这个数字时,它确实向我展示了随机水果就好了所以有没有办法解决为什么只是 side = 20 它不会工作吗?

PS:如果除了这两个问题之外还有什么可以改进的,我将不胜感激..提前致谢!

【问题讨论】:

标签: c++ console-application


【解决方案1】:

第一次睡觉有点难熬。在此处查看答案以获得更好的解决方案:Sleep for milliseconds

其次,您不考虑自己的开销。您的程序可能在不同的设置上运行得更快/更慢。对于一般游戏,您希望使用稍微精确但快速的时间函数来了解移动所有东西的量(当然蛇并不真正需要)。有关此主题的更多建议,请参阅此问题:How to Make a Basic FPS Counter?

最后,控制台并不适合这种应用程序。我建议切换到一个简单的 GUI,这样您就不必处理疯狂的控制台。如果您的目标是制作某种演示来学习并继续前进,那可能没问题,并且可以忍受这种奇怪的行为。

关于水果的问题:

  • 永远不要使用 goto。很难推理它以及处理它的标准工具。使用更容易推理的函数/循环。在您的情况下,do{ friutx = ...; } while (friuitx==0) 可以。
  • 您设置水果的两个地方使用不同的代码。很可能即使您修复了一个,另一个可能仍然会损坏。创建一个函数并从两个位置调用它。
  • % 会做一个提醒(0side-1,包括在内)。看起来您的目标是 2 到 1,所以也许可以使用 rand()%(side-1) + 1 或更好,使用 std::uniform_int_distribution
  • 我不清楚为什么它没有被正确看到。在渲染帧时使用调试器检查水果的坐标是什么。它们可能与边缘重叠并被替换为*

【讨论】:

  • 永远不要使用 goto 太强。 goto 有一些有效的用例,例如跳出嵌套循环。
  • 谢谢,是的,我检查了坐标,它被* 覆盖,所以我必须检查它是否不是 0、1 或 side-1。但是我能问一下为什么很多参考/人们总是说我们不应该使用 goto 吗?我认为它与循环相同,那么有什么区别?
  • Edgar Dijkstra:Contra Goto:homepages.cwi.nl/~storm/teaching/reader/Dijkstra68.pdf (1968); Donald E. Knuth:Pro Goto:pic.plover.com/knuth-GOTO.pdf (1974); Peter Naur:Contra Goto:sci-hub.se/https://doi.org/10.1007/BF01939987 (1963)。 Dijkstra 和 Knuth 没有强烈的意见,而是更平衡的观点。
  • @Oliver_Queen 至少对我而言,主要原因是与循环相比,您可能会犯更多错误(比如说有一个拼写错误,说 label1 而不是 label2),而且在更复杂的情况下,它更难阅读和理解代码。只需在循环中添加更多条件,也许是一个等价的中断,很容易错过您正在使用未初始化的变量,或者双重删除某些东西或其他类似的琐碎错误,否则您不会这样做。当我阅读传统循环时,我可以专注于条件和逻辑,而不必担心跳转中有错误。
猜你喜欢
  • 1970-01-01
  • 2012-09-29
  • 1970-01-01
  • 2018-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多