13
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Posted at

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

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

##構成

|--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

    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で、必要なオブジェクトを生成

    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のキャッチは一箇所で

    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


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

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

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

13
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?