Menu
CoddyTech

No en la serpiente

Lección 9 de 14 del curso Juego de Unity: Serpiente 3D de Coddy.

MoveFood() elige cualquier celda, incluidas las celdas que ocupa la serpiente. La comida debajo de la serpiente no se puede comer hasta que la serpiente se aparte de ella, y cuanto más larga sea la serpiente, más a menudo ocurre.

Una solución es volver a elegir hasta que la celda esté libre. Funciona en un tablero vacío, pero hacen falta cada vez más intentos a medida que se llena el tablero y, cuando ya no quedan celdas libres, nunca termina. La solución estable primero crea una lista de las celdas libres y elige una: todas las celdas libres tienen la misma probabilidad de ser elegidas y siempre basta con una elección. En un cine se asigna un asiento a un invitado que llega tarde de la misma manera:

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) devuelve un índice de 0 al último, ya que el valor máximo queda excluido. Para crear la lista, el tablero le pregunta a la serpiente si ocupa una celda: un método de Snake que comprueba la cabeza y cada segmento.

challenge icon

Desafío

Intermedio

La comida nunca aparece sobre la serpiente.

  1. En Snake, escribe public bool Occupies(Vector3 cell): true para la celda de la cabeza o la de cualquier segmento de la cola.
  2. En GameManager, dentro de MoveFood(), recorre x y z desde -snake.edge hasta snake.edge, añade cada celda donde se cumpla !snake.Occupies(cell) a una List<Vector3> free y coloca la comida en free[Random.Range(0, free.Count)].

Pulsa «Jugar» y haz crecer la serpiente: la comida siempre aparece en una celda vacía. Después, pulsa «Comprobar».

Pruébalo tú mismo

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 iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Juego de Unity: Serpiente 3D

Practica por tu cuenta: Playground de Unity