我正在尝试在控制台中编程蛇。蛇随机走了几步之后,便产生了一个新的GameObject(例如,使蛇长大的苹果或使蛇更快的蘑菇)。
我创建了一个随机的gameObject(在随机(左,上)坐标上,然后我需要检查该gameObject是在snakeBodyPart顶部还是在另一个gameObject顶部生成。如果是这种情况,我创建了一个新的gameObject然后再次尝试相同的操作。只有当它不与另一个gameObject或Snake碰撞时,它才会生成。
snakeElemnts =一个列表,其中包含所有蛇体部分; gameObjects =包含所有现有gameObjects的列表;
如果noCollisionAmount == snakeElements和GameObjects的数量,则应该没有碰撞,并且应该生成新的GameObject。
不幸的是,在某一点(早期),蛇只是停止移动而没有任何反应(没有异常或任何事情)。
我无法调试,因为我正在运行KeyboardWatcher,它检查是否按下了某个键。因此,当我按下break键时,我只能检查键盘观察器。
设置断点没有用,因为出现问题时我永远不会中断。
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);
}
答案 0 :(得分:1)
基于您的评论,删除此代码块会导致问题停止,我认为稍微整理一下代码并使用continue语句删除潜在的无限循环可能会很好。利用一些LINQ Enumerable.Any和一个do-while循环,我们可以简化上述代码的逻辑。实际上,无需计算冲突,因为代码的目的是创建一个新对象 iff ,以检测到冲突。这意味着,如果我们检测到与蛇的碰撞,那么我们想生成一个新的对象,或者如果我们检测到与另一个现有物体的碰撞,那么我们想要生成一个新的对象。因此,我们使用Any
语句来检查与蛇或现有对象是否存在任何碰撞,而不是进行计数。如果存在,则生成一个新对象。如果不是,则使用该对象并继续。注意:为了使用Enumerable.Any
,您将需要为命名空间using
添加System.Linq
语句。
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);
}
答案 1 :(得分:0)
我认为您可能不了解“继续”的工作原理。
if (noCollision > snakeElements.Count + gameObjects.Count)
{
continue;
}
在while循环开始时就已经有了。如果找到的话,您将陷入无限循环。
其次,那里有一个While(true),它将永远不会保存有效的结果,因为它在循环之外。您应将do替换为do while并在其末尾检查有效结果,然后循环进行碰撞(如果有冲突)。