bate's blog

調べたこと実装したことなどを取りとめもなく書きます。

ライフゲーム

https://dl.dropbox.com/u/67579260/Unity/Test01/WebPlayer/WebPlayer.html

ライフゲームを作った。
ランダムで配置して[NEXT]ボタンを押すと次の世代に進む。
コードはもっと工夫できそう。

using UnityEngine;
using System.Collections;

public class cLifeGame : MonoBehaviour {
	
	enum eState{ ALIVE, DEAD };
	
	[SerializeField]
	int m_gridNum = 30;
	public int GridNum {
		get { return m_gridNum; }
		set { m_gridNum = value; }
	}
	
	eState [,] m_currentGridLogical;
	eState [,] m_nextGridLogical;
	GameObject [,] m_grid;
	GameObject m_quadPrefab;
	Vector3 m_gridBasePoint;
	
	void Awake() {
		m_gridBasePoint = new Vector3(m_gridNum/2, m_gridNum/2, 0);
		m_quadPrefab = Resources.Load("Test01/Cell") as GameObject;
		Debug.Log(m_quadPrefab);
		m_grid = new GameObject[m_gridNum, m_gridNum];
		m_currentGridLogical = new eState[m_gridNum, m_gridNum];
		m_nextGridLogical = new eState[m_gridNum, m_gridNum];
		for(int y = 0; y < m_gridNum; ++y) {
			for(int x = 0; x < m_gridNum; ++x) {
				m_currentGridLogical[x, y] = eState.DEAD;
				m_nextGridLogical[x, y] = eState.DEAD;
				
				m_grid[x, y] = Instantiate(m_quadPrefab, new Vector3((x-m_gridBasePoint.x)*2.0f, (y-m_gridBasePoint.y)*2.0f, 0), Quaternion.identity) as GameObject;
				m_grid[x, y].transform.localScale = new Vector3(2, 2, 2);
				m_grid[x, y].transform.parent = this.transform;
				var boxCollider = m_grid[x, y].AddComponent<BoxCollider>();
				boxCollider.center = Vector3.zero;
			}
		}
	}

	// Use this for initialization
	void Start () {
		for(int y = 0; y < m_gridNum; ++y) {
			for(int x = 0; x < m_gridNum; ++x) {
				int rnd = Random.Range(0, 9876397);
				if(rnd % 2 == 0) {
					m_currentGridLogical[x, y] = eState.ALIVE;
					m_grid[x, y].renderer.material.color = Color.red;
				}
			}
		}
	}
	
	// Update is called once per frame
	void Update () {
		if(Input.anyKeyDown) {
			//Select();
		}
	}
	
	void Select() {
		Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
		RaycastHit hit;
		if(Physics.Raycast(ray, out hit)) {
			GameObject obj = hit.collider.gameObject;
			if(obj) {
				obj.renderer.material.color = Color.red;
			}
		}
	}
	
	void OnGUI() {
		if(GUILayout.Button("Titleに移動")) {
			Application.LoadLevel("Title");
		}
		if(GUILayout.Button("Next")) {
			Step();
		}
	}
	
	void Step() {
		CalculateNext();
		SwapGridLogical();
	}
	
	void SwapGridLogical() {
		for(int y = 0; y < m_gridNum; ++y) {
			for(int x = 0; x < m_gridNum; ++x) {
				m_currentGridLogical[x, y] = m_nextGridLogical[x, y];
				m_nextGridLogical[x, y] = eState.DEAD;
				if(eState.DEAD == m_currentGridLogical[x, y]) {
					m_grid[x, y].renderer.material.color = Color.white;
				} else {
					m_grid[x, y].renderer.material.color = Color.red;
				}
			}
		}
	}
	
	void CalculateNext() {
		for(int y = 0; y < m_gridNum; ++y) {
			for(int x = 0; x < m_gridNum; ++x) {
				DecideCellState(x, y);
			}
		}
	}
	
	void DecideCellState(int x, int y) {
		int aliveNum = GetAliveNum(x, y);
		eState nextState = eState.DEAD;
		eState prevState = m_currentGridLogical[x, y];
		if(eState.DEAD == prevState) {
			if(aliveNum == 3) {
				nextState = eState.ALIVE;
			}
		}
		else {
			if(aliveNum == 2 || aliveNum == 3) {
				nextState = eState.ALIVE;
			}
		}
		m_nextGridLogical[x, y] = nextState;
	}
	
	int GetAliveNum(int x, int y) {
		int aliveNum = 0;
		for(int cy = 0; cy < 3; ++cy) {
			for(int cx = 0; cx < 3; ++cx) {
				int gx = GetIndex(x+cx-1);
				int gy = GetIndex(y+cy-1);
				if(!(x == gx && y == gy)) {
					if(eState.ALIVE == m_currentGridLogical[gx, gy]) {
						++aliveNum;
					}
				}
			}
		}
		return aliveNum;
	}
	
	int GetIndex(int index) {
		int ret = index;
		if(index < 0) {
			ret = m_gridNum-1;
		}
		else if(index > m_gridNum-1) {
			ret = 0;
		}
		return ret;
	}
}