エンジニアのひよこ_level10

毎日更新してた人。たまに記事書きます。

PHPでハノイの塔のプログラム!【108日目】

苦節3日、無事に出来上がりました。

むしろ3日かかったのかお前っていう。

寝て起きてシャワーを浴びてを2回繰り返したらプログラム出来ました。

注意。

いないと思いますが、このプログラム出来が良くないので、これをコピーしてプログラミング課題の提出に使うのは、
やめておいた方がいいですよ\(^o^)/

まあ、学生感あふれるコードですが・・・w

コード

<?php
    if (count($argv) > 1 && $argv[1] > 0) {
        $max_tower_number = $argv[1];
    } else {
        $max_tower_number = 3;
    }
    $hanoi = new Hanoi($max_tower_number);
    $hanoi->showTower();
    //スタート位置を0、ゴールの位置を2とする
    $hanoi->solveHanoi($max_tower_number, 0, 2, 1);

    class Hanoi
    {
        //塔を格納する変数
        private $tower = [[], [], []];

        //塔を設定する
        public function __construct($max_tower_number = null)
        {
            if ($max_tower_number == null) {
                $this->tower = [[1,2,3], [], []];
            } else {
                for ($i = 1; $i <= $max_tower_number; $i++) {
                    array_push($this->tower[0], $i);
                }
            }
        }

        //ハノイの塔を解く
        public function solveHanoi($tower_height, $start, $goal, $temp)
        {
            if ($tower_height > 1) {
                //ベースの上の塔を、目的の場所から別な場所に避難させる
                $this->solveHanoi($tower_height - 1, $start, $temp, $goal);
            }
            //N+1のベースをゴールに移動する
            $this->move($start, $goal);
            if ($tower_height > 1) {
                //別な場所に避難した塔をゴールに戻す
                $this->solveHanoi($tower_height - 1, $temp, $goal, $start);
            }
        }

        //ブロックの移動
        public function move($start, $goal)
        {
            try {
                //入力値のチェック
                if ($start >= count($this->tower)) {
                    throw new Exception("移動元が不正な値です");
                }
                if ($goal >= count($this->tower)) {
                    throw new Exception("移動先が不正な値です");
                }

                //ブロックを取り出す
                if (count($this->tower[$start]) === 0) {
                    throw new Exception("移動元が空なので移動できません");
                }
                $item = array_shift($this->tower[$start]);

                //ブロックの移動(ルールを確認する)
                if (count($this->tower[$goal]) > 0) {
                    if ($this->tower[$goal][0] < $item) {
                        array_unshift($this->tower[$start], $item);
                        throw new Exception("移動先が" . $this->tower[$goal][0] . "なので" . $item . "は移動できません");
                    }
                }
                array_unshift($this->tower[$goal], $item);

                //動かしたブロックと、移動元移動先を表示
                //合わせて塔も表示
                print("number:" . $item .  " move:" . $start . "->" . $goal . PHP_EOL);
                $this->showTower();

            } catch (Exception $e) {
                print("例外キャッチ:" . $e->getMessage() . PHP_EOL);
                exit(1);
            }
        }

        //塔の表示
        public function showTower()
        {
            print('-----------------------' . PHP_EOL);
            foreach ($this->tower as $items) {
                foreach ($items as $item) {
                    print("[" . $item . "]");
                }
                print(PHP_EOL);
            }
            print('-----------------------' . PHP_EOL);
        }
    }

実行結果

f:id:willow710kut:20180129204957g:plain

補足

インスタンス化する時に数値を渡せば、コンストラクタで値に応じた塔を作ってくれます。

また、move()showTower()はpublicにしてあるので、エラーとか試したい方は、 テキトーにコードをいじっていただければ!

日記

めっちゃ時間かかりましたが、無事に作成完了!

久々に頭回しまくって楽しかったです!

ただ、シャワー浴びた瞬間にひらめく辺り、
私の頭には『キャッシュ』がたまって、パフォーマンスが落ちるという性質がある可能性が・・・w

この課題、明日〆切だったから、それまでに作成出来てよかった・・・!満足!

さあまた明日の課題頑張るぞー!