【问题标题】:Snake game -- tail movement蛇游戏——尾巴运动
【发布时间】:2020-05-13 18:23:05
【问题描述】:

我正在做一个蛇游戏,但尾巴运动有问题。我理解这部分的逻辑,即尾部的每一段都跟随上一段,从尾部的末端开始。我在看别人的代码,看起来是这样的


 #include <iostream>
#include <conio.h>
#include <windows.h>
using namespace std;
bool gameOver;
const int width = 20;
const int height = 20;
int x, y, fruitX, fruitY, score;
int tailx[100], taily[100];
int nTail;
enum eDirecton { Stop, Left, Right, Up, Down } dir;

void Setup()
{
 gameOver = false;
 dir = Stop;
 x = width / 2;
 y = height / 2;
 fruitX = rand() % width;
 fruitY = rand() % height;
 score = 0;
}
void Draw()
{
 system("cls"); 
 for (int i = 0; i < width + 2; i++)
     cout << "#";
 cout << endl;

 for (int i = 0; i < height; i++)
 {
     for (int j = 0; j < width; j++)
     {
         if (j == 0)
             cout << "#";
         if (i == y && j == x)
             cout << "O";
         else if (i == fruitY && j == fruitX)
             cout << "F";
         else
         {
             bool print = false;
             for (int k = 0; k < nTail; k++)
             {
                 if (tailx[k] == j && taily[k] == i)
                 {
                     cout << "o";
                     print = true;
                 }
             }
             if (!print)
                 cout << " ";
         }


         if (j == width - 1)
             cout << "#";
     }
     cout << endl;
 }

 for (int i = 0; i < width + 2; i++)
     cout << "#";
 cout << endl;
 cout << "Score:" << score << endl;
}
void Input()
{
 if (_kbhit())
 {
     switch (_getch())
     {
     case 'a':
         dir = Left;
         break;
     case 'd':
         dir = Right;
         break;
     case 'w':
         dir = Up;
         break;
     case 's':
         dir = Down;
         break;
     case 'x':
         gameOver = true;
         break;
     }
 }
}
void Logic()
{
 for (int i = nTail - 1; i > 0; i--)
 {
     tailx[i] = tailx[i - 1];
     taily[i] = taily[i - 1];
 }
 tailx[0] = x;
 taily[0] = y;

 switch (dir)
 {
 case Left:
     x--;
     break;
 case Right:
     x++;
     break;
 case Up:
     y--;
     break;
 case Down:
     y++;
     break;
 default:
     break;
 }

 if (x >= width) x = 0; else if (x < 0) x = width - 1;
 if (y >= height) y = 0; else if (y < 0) y = height - 1;

 for (int i = 0; i < nTail; i++)
     if (tailx[i] == x && taily[i] == y)
         gameOver = true;

 if (x == fruitX && y == fruitY)
 {
     score += 10;
     fruitX = rand() % width;
     fruitY = rand() % height;
     nTail++;
 }
}
int main()
{
 Setup();
 while (!gameOver)
 {
     Draw();
     Input();
     Logic();
     Sleep(50); 
 }
 return 0;
}

我理解其中的逻辑,但我不明白它为什么会起作用。当我们创建一个数组时,每个元素的值只是一个垃圾值,没有初始化每个元素。所以在上面的代码中,当做

tailx[i] = tailx[i-1];
taily[i] = taily[i-1];

为每个元素分配什么值? 显示蛇时,它有一个 for 循环遍历屏幕的每个坐标,并且在它内部还有另一个 for 循环将 tailx[i] 和 taily[i] 与每个坐标进行比较,以找出打印每个段的正确位置尾巴。由于 tailx 和 tialy 不存储尾部段的坐标,所以这段代码是怎么工作的?

非常感谢!!

【问题讨论】:

  • 你有多确定它有效?
  • 大概是在绘制蛇时,使用了nTail 的当前值,并且该值在代码的其他地方被初始化或更新(当蛇得到食物时)。
  • 您粘贴的 sn-p 声明了三个变量,没有初始化它们,并立即使用所有三个变量。您确定 sn-p 中没有缺少代码吗?
  • 我很抱歉造成混乱!我已经更新了帖子并添加了整个程序。

标签: c++


【解决方案1】:

大概,您在结尾处遗漏了一行,如下所示:

if(nTail < 100) { nTail++; }

假设是这样,nTail 被初始化为 0,并且这一切都在一个循环中,代码可能看起来像这样(我使用 5 而不是 100 的大小来使可视化更容易)

int tailx[5];
int taily[5];
int nTail = 0; //length

while(true) {
    for(int i = nTail -1; i > 0; i--)
    {
         tailx[i] = tailx[i-1];
         taily[i] = taily[i-1];
    }

    // Let's assume there's some logic here the fetches a new
    //   x and y. For the sake of debugging, let's assume the
    //   values will be {(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)}

    tailx[0] = x; // x is the x-coordinate of the head
    taily[0] = y; //y is the y-coordinate of the head
    if(nTail < 5) { nTail++; }
}

让我们一步一步来!

在我们进入循环之前,您的尾部数组将如下所示:(我在这里使用NA 表示“垃圾”)

nTail = 0

+-------------------------+
|Name | 0 | 1 | 2 | 3 | 4 |
|-------------------------|
|  X  | NA| NA| NA| NA| NA|
+-------------------------+
|  Y  | NA| NA| NA| NA| NA|
+-------------------------+

我们进入循环,将i初始化为nTail - 1,即-1。这没有通过i &gt; 0的检查,所以我们甚至没有进入循环。

我们现在将获取新的xy val 并将它们分配到尾部,同时递增nTail。所以进入下一个循环,我们的变量将如下所示:

nTail = 1

+-------------------------+
|Name | 0 | 1 | 2 | 3 | 4 |
|-------------------------|
|  X  | 1 | NA| NA| NA| NA|
+-------------------------+
|  Y  | 1 | NA| NA| NA| NA|
+-------------------------+

我们将继续,将i 初始化为nTail - 1 =&gt; 0。这没有通过i &gt; 0 的检查,所以我们再次没有进入循环(这对我来说听起来不对......也许你正在将nTail 初始化为 1 而不是 0?)。

我们继续前进,获取新的 x/y 值并增加 nTail 并重新启动循环:

nTail = 2

+-------------------------+
|Name | 0 | 1 | 2 | 3 | 4 |
|-------------------------|
|  X  | 2 | NA| NA| NA| NA|
+-------------------------+
|  Y  | 2 | NA| NA| NA| NA|
+-------------------------+

i初始化为nTail - 1 =&gt; 1意味着因为i &gt; 0我们最终会进入内部循环。

使用i = 1,我们更新了尾数组:

tailx[1] = tailx[0];
taily[1] = taily[0];

然后低头,获取新值并增加nTail。我们的变量现在看起来像:

nTail = 3

+-------------------------+
|Name | 0 | 1 | 2 | 3 | 4 |
|-------------------------|
|  X  | 3 | 2 | NA| NA| NA|
+-------------------------+
|  Y  | 3 | 2 | NA| NA| NA|
+-------------------------+

在下一个循环之后,情况将如下所示:

nTail = 4

+-------------------------+
|Name | 0 | 1 | 2 | 3 | 4 |
|-------------------------|
|  X  | 4 | 3 | 2 | NA| NA|
+-------------------------+
|  Y  | 4 | 3 | 2 | NA| NA|
+-------------------------+

如果您愿意,我会留给您继续追踪。

【讨论】:

  • 非常感谢您的帮助!
【解决方案2】:

你是对的;此代码无法运行,并且具有未定义的行为。

nTail 甚至没有初始化为任何东西。

你确定它是一个完整的程序,而不是把 sn-ps 粘在一起吗?还是一种“伪代码”来显示逻辑而不是实际有效的 C++?您需要 nTail 和所有数组元素的值。

【讨论】:

  • 我建议与您获取代码的人交谈。
  • 代码只是为了展示逻辑。在原始程序中,它确实初始化了 nTail,并且每次蛇的长度增加时都会更新 nTail。
  • 请不要问我们关于代码的问题,然后向我们展示一些完全不同的代码。这浪费了我们所有的时间。
猜你喜欢
  • 1970-01-01
  • 2019-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-05
相关资源
最近更新 更多