Menu
CoddyTech

不在蛇身上

Coddy Unity 3D 贪吃蛇游戏 课程的第 9 课,共 14 课。

MoveFood() 会随机选择任意一个格子,包括被蛇占据的格子。蛇身下的食物要等蛇移开后才能吃到,蛇越长,这种情况发生得越频繁。

一种解决方法是不断重新选择,直到选到空格。这在空棋盘上可行,但棋盘越满,需要尝试的次数就越多;如果没有空格了,就会一直尝试。更可靠的解决方法是先列出所有空格,再从中选一个:每个空格被选中的概率相同,而且只需选一次就够了。电影院也会用同样的方式为迟到的客人安排座位:

List<int> free = new List<int>();
for (int seat = 1; seat <= 40; seat++)
{
    if (!taken.Contains(seat)) free.Add(seat);
}
int pick = free[Random.Range(0, free.Count)];

Random.Range(0, free.Count) 会返回从 0 到最后一个索引之间的索引,因为最大值不包含在内。为了生成列表,棋盘会询问蛇是否占据某个格子:这是 Snake 中的一个方法,用来检查蛇头和每一节蛇身。

challenge icon

挑战

中等

食物不会落在蛇身上。

  1. 在 Snake 中,编写 public bool Occupies(Vector3 cell):如果该位置是蛇头所在的格子或任意一节蛇尾所在的格子,就返回 true。
  2. 在 GameManager 的 MoveFood() 中,让 x 和 z 从 -snake.edge 循环到 snake.edge,把每个满足 !snake.Occupies(cell) 的格子添加到 List<Vector3> free,然后将食物放在 free[Random.Range(0, free.Count)] 上。

按下 Play 并让蛇变长:食物总会落在空格子上。然后点击 Check。

亲手试试

using UnityEngine;

public class GameManager : MonoBehaviour
{
    public static GameManager Instance;

    public Snake snake;
    public GameObject foodPrefab;
    private Transform food;
    private int score;

    void Awake()
    {
        Instance = this;
    }

    void Start()
    {
        food = Instantiate(foodPrefab).transform;
        MoveFood();
    }

    public bool IsFood(Vector3 cell)
    {
        return cell == food.position;
    }

    public void Eat()
    {
        score++;
        MoveFood();
    }

    void MoveFood()
    {
        int x = Random.Range(-snake.edge, snake.edge + 1);
        int z = Random.Range(-snake.edge, snake.edge + 1);
        food.position = new Vector3(x, 0f, z);
    }
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

Unity 3D 贪吃蛇游戏中的所有课

自己练习: Unity 在线编辑器