#書いてみた マインスイーパーをターミナルで遊ぶ (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座標をそれぞれ入力しないといけないので)
・フラグを立てるを機能は入力をどうするか決められずいれてない。
もしもっとこうしたほうがいいよってあったら、
教えてもらえると幸いです。