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.
Desafío
IntermedioLa comida nunca aparece sobre la serpiente.
- En
Snake, escribepublic bool Occupies(Vector3 cell): true para la celda de la cabeza o la de cualquier segmento de la cola. - En
GameManager, dentro deMoveFood(), recorre x y z desde-snake.edgehastasnake.edge, añade cada celda donde se cumpla!snake.Occupies(cell)a unaList<Vector3> freey coloca la comida enfree[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);
}
}
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