蛇形游戏无法生成蛇尾:队列存储相同位置问题排查
蛇形游戏蛇尾生成故障排查与修复
我开发的蛇形游戏无法生成蛇尾,队列中存储的所有元素x、y坐标完全一致。明明设置了removeTail参数为false,本该让蛇身变长,但实际所有位置都相同。相关代码如下:
public void GameTick(Object source, ElapsedEventArgs e) { if (!isGameOver) { //Clear the board of snake and apple board.ClearSnake(snake); board.ClearApple(apple); snake.Move(direction, false); //Draw the snake and the apple again board.DrawApple(apple); board.DrawSnake(snake); } }
public void Move(Direction dir, bool removeTail) { Position pos = Utils.MovePos(positions.Last(), dir); positions.Enqueue(pos); if(removeTail) { positions.Dequeue(); } }
public static Position MovePos(Position pos, Direction direction) { switch (direction) { case Direction.Left: pos.x -= 1; break; case Direction.Right: pos.x += 1; break; case Direction.Up: pos.y -= 1; break; case Direction.Down: pos.y += 1; break; } return pos; }
问题根源
核心问题是Position类型的性质:如果它是引用类型(class),MovePos方法会直接修改传入的pos对象本身,再返回同一个实例。队列positions里存储的都是这个对象的引用,所以每次调用Move时,你只是把同一个Position实例反复加入队列,所有元素自然指向同一个坐标值。
修复方案
有两种简单的解决方式:
方案1:将Position改为值类型(struct)
值类型在传递时会自动创建副本,这样每次MovePos操作的都是新的副本,队列里的每个元素都是独立的坐标对象:
public struct Position { public int x; public int y; }
方案2:在MovePos中创建新的Position实例
不修改传入的原对象,而是创建新实例并返回,确保每次移动都生成独立的坐标对象:
public static Position MovePos(Position pos, Direction direction) { Position newPos = new Position { x = pos.x, y = pos.y }; switch (direction) { case Direction.Left: newPos.x -= 1; break; case Direction.Right: newPos.x += 1; break; case Direction.Up: newPos.y -= 1; break; case Direction.Down: newPos.y += 1; break; } return newPos; }
内容的提问来源于stack exchange,提问作者Theis Jensen
相关产品推荐
相关产品推荐

