No en la serpiente
Lección 9 de 14 del curso Juego de Unity: Snake 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
Intermedio- En
Snake, escribepublic bool Occupies(Vector3 cell): verdadero cuandocelles la celda de la cabeza o la de un segmento de la cola. - En
GameManager, añadeusing System.Collections.Generic;y reescribeMoveFood(): recorre x y z por cada celda del tablero, añade cada celda que la serpiente no ocupe a unaList<Vector3> freey coloca la comida en una celda aleatoria de esa lista.
Pulsa Play y después pulsa Check. Las comprobaciones llenan la mayor parte del tablero con la serpiente y se aseguran de que la comida siga encontrando las celdas libres.
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.