書いてみた　マインスイーパーをターミナルで遊ぶ (php)

#書いてみた　マインスイーパーをターミナルで遊ぶ (php)

http://qiita.com/konpeto000/items/409c3b1ab7cecbdfc160
を見て、自分も作ってみようと思い作成した。

https://github.com/MasatoYoshioka/MineSweeper

##構成

```zsh
|--MineSweeper.php                 //メイン
|--README.md
|--lib
|  |--Board.php                    //ボード関連
|  |--Config.php                   //設定関連
|  |--CongratulationsException.php //おめでとうException
|  |--Define.php                   //定義
|  |--GameOverException.php　      //ゲームオーバーエクセプション
|  |--Input.php                    //入力関連
|  |--InputException.php           //入力エラー
|  |--Message.php                  //メッセージ関連
|  |--Mine.php                     //爆弾
|  |--User.php                     //ユーザー関連
|  |--Validate.php                 //入力エラー
```

##解説(抜粋)
大変だった箇所を抜粋

###MineSweeper.php

```php
<?php

    public function __construct()
    {
       $this->config  = new Config;
       $this->user    = new User();
        //爆弾を作成
       $this->mine = new Mine( 
            $this->config->side[ $this->user->get( 'level') ][ 'x' ],
            $this->config->side[ $this->user->get( 'level') ][ 'y' ],
            $this->config->mine[ $this->user->get( 'level') ]
        );
        //ゲーム板を作成
        $this->board = new Board(
            $this->config->side[ $this->user->get( 'level') ][ 'x' ],
            $this->config->side[ $this->user->get( 'level') ][ 'y' ],
            $this->mine
        );
    }
```

constractで、必要なオブジェクトを生成

```php
    public function start()
    {
        try{
            $this->board->show();
            $this->next();
        }catch( CongratulationsException $e ){
            echo "Finish a Game";
            echo $e->getMessage();
        }catch( GameOverException $e ){
            $this->board->show();
            echo "GAME OVER" . PHP_EOL;
            echo $e->getMessage() . PHP_EOL;
        }catch( InputException $e ){
            echo $e->getMessage() . PHP_EOL;
            //戻る
            $this->start();
        }catch( Exception $e ){
            echo "予想外のエラーがありました。";
        }
    }
```

Exceptionのキャッチは一箇所で

```php
    public function next()
    {
        $in = $this->user->choose();
        if( $this->mine->is( $in[0], $in[1] )) throw new GameOverException( '爆弾です' );
        $this->board->open( $in[0], $in[1] );
        $this->board->show();
        if( $this->board->getNoOpen() === count( $this->mine->mine )) throw new CongratulationsException( "おめでとうございます" );
        echo "非表示個数:" . $this->board->getNoOpen() . PHP_EOL;
        echo "爆弾個数  :" . count($this->mine->mine)  . PHP_EOL;
        $this->next();
    }
}

$minesweeper = new MineSweeper;
$minesweeper->start();
```

nextを再帰処理

##Board.php

```php

    public function open( $x, $y )
    {
        //範囲外は終了
        if( 1 > $x || $this->x < $x || 1 > $y || $this->y < $y ) return;
        //すでに開いているなら終了
        if($this->box[$x][$y] >= OPEN ) return;
        //爆弾だったら終了
        if( $this->mine->is( $x, $y)) return;
        //そのマスの周りの爆弾を調べる
        $this->box[$x][$y] = $this->around( $x, $y );
        //現在のboxが0だったら探索する
        if( $this->box[$x][$y] === OPEN ) $this->search( $x, $y);
    }
    //今のマスの周りの爆弾を調べる
    public function around( $x, $y )
    {
        $mine = OPEN;
        //上
        if( $this->mine->is( $x    , $y - 1 )) $mine++;
        //右上
        if( $this->mine->is( $x + 1, $y - 1 )) $mine++;
        //右
        if( $this->mine->is( $x + 1, $y     )) $mine++;
        //右下
        if( $this->mine->is( $x + 1, $y + 1 )) $mine++;
        //下
        if( $this->mine->is( $x    , $y + 1 )) $mine++;
        //左下
        if( $this->mine->is( $x - 1, $y + 1 )) $mine++;
        //左
        if( $this->mine->is( $x - 1, $y     )) $mine++;
        //左上
        if( $this->mine->is( $x - 1, $y - 1 )) $mine++;
        return $mine;
    }
    //探索 上,右,下,左
    public function search( $x, $y)
    {
        $this->up(    $x, $y );
        $this->right( $x, $y );
        $this->down(  $x, $y );
        $this->left(  $x, $y );
    }
    public function up( $x, $y )
    {
        return $this->open( $x , $y - 1  );
    }
    public function right($x, $y )
    {
        return $this->open( $x + 1 , $y );
    }
    public function down( $x, $y )
    {
        return $this->open( $x , $y + 1 );
    }
    public function left( $x, $y )
    {
        return $this->open( $x - 1 , $y );
    }
}
```

Board->open()で、指定した座標のマスについて検証を行った後、上下左右に移動して同じ検証を再起してる。

##作ってみた感想
・思ったよりも時間がかかった。(２日程度)
・namespaceを使いたかったがまだちゃんと理解できていなくて、
　使えなかった。(理解していないことがわかってよかった。)
・ターミナルでの入力が面倒くさい(x座標とy座標をそれぞれ入力しないといけないので)
・フラグを立てるを機能は入力をどうするか決められずいれてない。

もしもっとこうしたほうがいいよってあったら、
教えてもらえると幸いです。