LoginSignup
2
1

More than 3 years have passed since last update.

Laravelで将棋アプリを作りたい(第四回)

Last updated at Posted at 2021-04-09

第一回:プロジェクト作成 ~ 盤面作成
第二回:駒移動
第三回:DB連携

今回は歩配置と駒を取る挙動の実装

目次

0.前回からの修正
1.歩配置
2.手番を設定
3.駒を取る動作
4.ゲーム終了の設定

0. 前回からの修正

共通部分だった最新手の取得をメソッドにする(getLastRecordという名前でメソッドを作成)。
駒の番号を$pieceIdとして定義する。0→王将または玉将、1~9→歩

ShogiController.php
public function getLastRecord($turn, $pieceId)
{
    // 手番と駒の番号を引数にとり、最新手を返す。
    $lastRecord = GameRecord::where('turn', $turn)->where('piece', $pieceId)->orderBy('id', 'desc')->first();
    $record = (!empty($lastRecord['square'])) ? $lastRecord : config('const.start.' . $turn . '.' . $pieceId);
    return $record;
}

1. 歩配置

歩を配置する。現段階では初期値はconst.phpでfor文を用いて以下のように定義。

const.php
for ($i=1; $i<10; $i++) {
    // 先手の歩
    $start['start'][0][$i] = [
        'turn' => 0,
        'piece' => $i,
        'square' => $i . 7
    ];
    // 後手の歩
    $start['start'][1][$i] = [
        'turn' => 1,
        'piece' => $i,
        'square' => $i . 3
    ];
}

index.phpでは王将と同様にselectメソッドへのリンクのついた「歩」マスを作成する。

スクリーンショット 2021-04-09 17.44.22.png

歩は1マス前方にしか進めないので、移動可能ます取得の処理を王将とは別に記述する。

ShogiController.php
// selectメソッド内で記述
// $select[2]は列番号、$select[3]は行番号
// 例)先手27歩の移動可能マスは26歩なので行番号を-1する。

if ($selectPiece['turn'] == 0) {
    // 先手番の歩の移動可能マス取得
    $ways[] = $select[2] . ((int)$select[3])-1;
} elseif ($selectPiece['turn'] == 1) {
    // 後手番の歩の移動可能マスを取得
    $ways[] = $select[2] . ((int)$select[3])+1;
}

2. 手番を設定

先手後手交互に操作できるように手番を設定する。
コントローラーでDBから取得した手番をビューに渡し、ビューでは手番に一致しないマスはリンクを無効にする。

スクリーンショット 2021-04-09 17.57.17.png

3. 駒を取る動作

移動する時はリクエストにmoveという名前をつけた時と同様に、移動先に相手の駒がある場合はtakeという名前をつけて、コントローラーで処理を分ける。

リクエストでtakeが渡ってきたら、以下の動作で駒を取る動作を実現する。

  1. 移動先のマスから取られる駒を割り出す。

  2. その駒の手番を100(先手の駒になる場合)または101(後手の駒になる場合)としてデータを更新する。通常時の駒の取得には手番は0か1で取得するので、これらは取得されなくなり、盤面から消える。

  3. 駒を移動させる。

4. ゲーム終了の設定

王将または玉将が取られた時、ゲームを終了として、別ページにリダイレクトさせる。

スクリーンショット 2021-04-09 18.08.13.png

修正後のindexメソッド

ShogiController.php
public function index(Request $request)
    {
        if ($request->isMethod('post')) {
            // POSTでのアクセス時の処理
            if (!empty($request->input('move'))) {
                $data = new GameRecord;
                $data->turn = $request->input('turn'); // 手番
                $data->piece = $request->input('piece'); // 駒
                $data->square = $request->input('move'); // 移動先マス
                $data->save();
            } elseif (!empty($request->input('take'))) {
                // 取られた駒の保存処理
                $takenData = new GameRecord;
                $turn = ($request->input('turn') == '0') ? '1' : '0';
                $takenData->turn = 100 + (int)$turn;
                $takenPiece = GameRecord::where('turn', $turn)->where('square', $request->input('take'))->first();
                $takenData->piece = $takenPiece['piece'];
                $takenData->square = $request->input('take');
                $takenData->save();
                // 動く駒の保存処理
                $data = new GameRecord;
                $data->turn = $request->input('turn'); // 手番
                $data->piece = $request->input('piece'); // 駒
                $data->square = $request->input('take'); // 移動先マス
                $data->save();
                // 王(玉)が取られた時はゲーム終了
                if ($takenData['piece'] == 0) {
                    $win = ($turn == '1') ? '先手' : '後手';
                    return view('shogi/result', compact('win'));
                }
            }
        }
        // 先手番の最新手を取得
        $bKing = $this->getLastRecord(0, 0);
        $bPawn = $this->getPawn(0);
        // 後手番の最新手を取得
        $wKing = $this->getLastRecord(1, 0);
        $wPawn = $this->getPawn(1);
        $nextTurn = $this->getNextTurn();
        return view('shogi/index', compact('bKing', 'wKing', 'nextTurn', 'bPawn', 'wPawn'));
    }

今回はここまで。

スクリーンショット 2021-04-09 18.12.39.png

Github

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