読者です 読者をやめる 読者になる 読者になる

Unityで騎士巡回問題

C# Unity プログラミング

騎士サーの姫【無料お試し版】
 といってもC#のアレを移植しただけですが。pongeponge.hatenablog.jp
pongeponge.hatenablog.jp



 赤い点がナイトが移動した点。
全部赤になったら終了。


Mainクラス

using UnityEngine;
using System.Collections;

public class Main : MonoBehaviour {

    public GameObject go;

    GameObject[,] board;

    knightloot kl;

    int width;
    int height;

    Color black = new Color(0, 0, 0);
    Color red = new Color(1, 0, 0);
    Color green = new Color(0, 1, 0);


    // Use this for initialization
    void Start()
    {
        this.width = 7;
        this.height = 7;

        kl = GetComponent<knightloot>();

        this.board = new GameObject[this.width, this.height];
        for (int x = 0; x < this.width; x++)
        {
            for (int y = 0; y < this.height; y++)
            {
                this.board[x, y] = Instantiate(go);
                this.board[x, y].transform.position = new Vector3(x + 0.1f*x, 0, y+0.1f*y);
                this.board[x, y].GetComponent<Renderer>().material.color = this.black;
            }
        }

        kl.start(this.width, this.height, 2, 2);

        if (kl.find) StartCoroutine(replay());
    }
	
	// Update is called once per frame
	void Update () {
	
	}

    public IEnumerator replay()
    {
        int count = this.width*this.height;

        for (int step = 1; step <= count; step++)
        {
            bool find = false;
            for (int x = 0; x < this.width; x++)
            {
                for (int y = 0; y < this.height; y++)
                {
                    if (this.kl.result[x, y] == step)
                    {
                        find = true;
                        this.board[x, y].GetComponent<Renderer>().material.color = this.red;
                        break;
                    }
                }
                if (find) break;
            }
            yield return new WaitForSeconds(1.0f);
        }

        yield return 0;
    }
    
}


knightlootクラス

using UnityEngine;
using System.Collections;

public class knightloot : MonoBehaviour {

/*	// Use this for initialization
	void Start () {
        
	}
	
	// Update is called once per frame
	void Update () {
	
	}*/

    public int[,] result;
    public bool find;

    private chessboard board;

    //移動8方向
    private point[] move = { new point(-2, -1), new point(-2, 1), new point(-1, -2), new point(-1, 2),
                       new point(1, -2), new point(1, 2), new point(2, -1), new point(2, 1)};

    /// <summary>
    /// 開始
    /// </summary>
    /// <param name="xs">盤面の横サイズ</param>
    /// <param name="ys">盤面の縦サイズ</param>
    /// <param name="px">スタートx座標</param>
    /// <param name="py">スタートy座標</param>
    public void start(int xs, int ys, int px, int py)
    {
        this.board = new chessboard(xs, ys);

        result = new int[xs, ys];
        this.find = false;

        loot(1, new point(px, py));
    }


    public void loot(int step, point now)
    {
        if (this.find) return;

        //現在位置に番号が既にあれば戻る
        if (this.board.board[now.x, now.y] != 0) return;

        //現在位置にステップ数を記録
        this.board.WriteNumber(now, step);

        //全て踏んだ場合
        if (step == this.board.sumCells)
        {
            Debug.Log("Cong! ");
            this.board.copy(this.result);
            this.find = true;
            return;
        }

        //確認用
        //this.board.Draw();

        foreach (point p in move)
        {
            //次の位置
            point next = now + p;

            //盤面からはみ出ない&ステップ未記入の場合
            if ((next.x < this.board.width && next.x >= 0) && (next.y < this.board.height && next.y >= 0))
            {
                //ステップを1増やして次へ
                loot(step + 1, next);
                if (this.find) return;
            }
        }

        //どこにも行けない場合
        this.board.WriteNumber(now, 0);
        return;
    }

    //inner class
    public class point
    {
        public int x;
        public int y;

        public point(int X, int Y)
        {
            this.x = X;
            this.y = Y;
        }

        public static point operator +(point a, point b)
        {
            return new point(a.x + b.x, a.y + b.y);
        }
    }

    public class chessboard
    {
        public int[,] board;   //盤面
        public int width;      //幅
        public int height;     //高さ
        public int sumCells;   //目の総数

        public bool isInit = false; //初期化フラグ

        //初期化
        public chessboard(int w, int h)
        {
            this.board = new int[w, h];
            this.width = w;
            this.height = h;
            this.sumCells = w * h;
            this.isInit = true;
        }

        //盤面に数字を打つ
        public void WriteNumber(point p, int n)
        {
            if (this.isInit == false) return;

            this.board[p.x, p.y] = n;
        }

        //描画
        public void copy(int[,] r)
        {
            for (int y = 0; y < this.height; y++)
            {
                for (int x = 0; x < this.width; x++)
                {
                    r[x,y] = this.board[x, y];
                }
            }

        }

    }
}