ヘビの上ではない
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のメソッドを使います。
チャレンジ
中級Snakeでpublic bool Occupies(Vector3 cell)を記述します。cellが頭のマス、またはしっぽのセグメントのマスであれば true を返します。GameManagerにusing System.Collections.Generic;を追加し、MoveFood()を書き換えます。x と z を盤面のすべてのマスにわたってループし、ヘビが占有していない各マスをList<Vector3> freeに追加して、そのリストからランダムに選んだマスに食べ物を置きます。
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);
}
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。