Snake 程序无一例外地停止 运行

Snake Program stops running without exception

我正在尝试在控制台中对 snake 进行编程。在蛇采取随机步数后,会生成一个新的游戏对象(例如,使蛇生长的苹果或使蛇更快的蘑菇)。

我创建了一个随机游戏对象(在随机(左、上)坐标上,然后我需要检查该游戏对象是在 snakeBodyPart 顶部还是在另一个游戏对象顶部生成。如果是这样,我创建一个新的游戏对象,然后再试一次。只有当它不与另一个游戏对象或蛇发生碰撞时,它才会生成。

snakeElemnts = 一个列表,里面有所有的蛇- body-parts; gameObjects = 包含所有现有游戏对象的列表;

如果 noCollisionAmount == snakeElements 和 GameObjects 的数量,则应该没有碰撞并且应该产生新的 GameObject。

不幸的是,在某一时刻(早期),蛇只是停止移动,什么也没有发生(没有例外或任何事情)。

我无法调试,因为我有一个 KeyboardWatcher 运行,它会检查是否按下了某个键。因此,当我按下 break 时,我只能检查 keyboardwatcher。

设置断点没有什么用,因为我遇到问题从来不断

if (this.randomStepNumber == 0)                
{
    int noCollision = 0; // this variable counts the amount of times there was no collision

    GameObject validGameObject;

          while (true)
          {
             validGameObject = this.snakeGameObjectFactory.Generate();

             foreach (SnakeElements element in snakeElements)
             {
                   if (validGameObject.XPosition != element.XPosition || validGameObject.YPosition != element.YPosition)
                    {
                      noCollision++;
                    }
                    else
                    {
                       break;
                    }
               }

              foreach (GameObject gameObject in gameObjects)
              {
                  if (noCollision == snakeElements.Count) // if there was no collision of the new gameobject with an element of the snake, the gameobjects will get checked
                  {
                       if (validGameObject.XPosition != gameObject.XPosition || validGameObject.YPosition != gameObject.YPosition)
                       {
                           noCollision++;
                       }
                       else
                       {
                           break;
                        }
                  }
                  else
                  {
                      break;
                   }
               }

               if (noCollision == snakeElements.Count + gameObjects.Count) // if there was no collision at all, the check is ended
               {
                   break;
               }
               else
               {
                  noCollision = 0;
               }
           }

       this.gameObjects.Add(validGameObject);

       this.randomStepNumber = this.random.Next(10, 30);
}

我想你可能不明白"continue"是如何工作的。

  if (noCollision > snakeElements.Count + gameObjects.Count)
            {
                continue;
            }

你在 while 循环的开头有它。如果它被发现是真的,你将陷入无限循环。

其次,你有一个 While(true) 在那里永远不会让你保存有效的结果,因为它在循环之外。您应该将 while 替换为 do while 并在其末尾检查有效结果,然后在发生冲突时循环。

根据您关于删除此代码块导致问题停止的评论,我认为稍微清理一下代码并使用 continue 语句删除潜在的无限循环可能会很好。利用一点 LINQ Enumerable.Any 和一个 do-while 循环,我们可以简化上面代码的逻辑。确实不需要计算碰撞,因为代码的目的是创建一个新对象 iff​​ 检测到碰撞。这意味着如果我们检测到与蛇的碰撞,那么我们想要生成一个新对象,或者如果我们检测到与另一个现有对象的碰撞,那么我们想要生成一个新对象。因此,我们不计算,而是使用 Any 语句来检查是否与蛇或现有对象发生任何碰撞。如果有,则生成一个新对象。如果不是,则使用该对象并继续。注意:为了使用 Enumerable.Any,您需要为命名空间 System.Linq.

添加 using 语句
if (randomStepNumber == 0)                
{    
    GameObject validGameObject;
    do
    {
        validGameObject = snakeGameObjectFactory.Generate();
    }
    while(snakeElements.Any(s => validGameObject.XPosition == s.XPosition && validGameObject.YPosition == s.YPosition) ||
         gameObjects.Any(o => validGameObject.XPosition == o.XPosition && validGameObject.YPosition == o.YPosition));

    gameObjects.Add(validGameObject);
    randomStepNumber = random.Next(10, 30);
}

作为旁注。我删除了 this 关键字,因为看起来您并没有在代码中的所有情况下都使用它,如果您不必使用它,它会使代码更具可读性,因为它不那么冗长。如果由于变量冲突需要将其添加回去,那么我建议将变量重命名为具有相同名称的成员变量和局部变量,这在尝试调试某些内容时也会造成混淆。

补充说明 - 这是不使用 LINQ 的代码版本,以防您的家庭作业不允许这样做。

if (randomStepNumber == 0)                
{    
    GameObject validGameObject = null;
    while(validGameObject == null)
    {
        validGameObject = snakeGameObjectFactory.Generate();
        foreach(var snake in snakeElements)
        {
            if (validGameObject.XPosition == snake.XPosition &&
                validGameObject.YPosition == snake.YPosition)
            {
                validGameObject = null;
                break;
            }
        }

        if (validGameObject != null)
        {
            foreach(var gameObject in gameObjects)
            {
                if (validGameObject.XPosition == gameObject.XPosition &&
                    validGameObject.YPosition == gameObject.YPosition)
                {
                    validGameObject = null;
                    break;
                }
            }
        }
    }

    gameObjects.Add(validGameObject);
    randomStepNumber = random.Next(10, 30);
}