LoginSignup
0
1

More than 3 years have passed since last update.

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

Last updated at Posted at 2021-02-28

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

今回はデータベース連携と玉将配置

目次

1.データベース作成
2.駒の移動先をデータベースに保存
3.駒の位置をデータベースから取得
4.先手後手の導入と玉将配置

1. データベース作成

駒の移動履歴を記録するためにデータベースを使用する。
今回は以下のようなgame_recordsテーブルを作成したい。

カラム データ型 説明
id bigIncrement
turn integer 手番(0:先手、1:後手)
piece integer 駒番号(0:王将)
square varchar マス番号

MySQLを起動してログインする。

ターミナル
$ mysql.server start
Starting MySQL
... SUCCESS! 
$ mysql -uroot -p
Enter password:

shogi_appというデータベースを新しく作成する。この中に、game_recordsテーブルが作成されるようにする。

ターミナル
mysql> create database shogi_app;

Laravelの.envファイルに記されているデータベース設定を必要に応じて修正する

.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=shogi_app
DB_USERNAME=root
DB_PASSWORD={ログイン時に使用しているパスワード}

モデルを使ってデータベース操作を行う。
まず、アプリ配下で以下を実行してモデルとマイグレーションファイルを作成する。

ターミナル
$ php artisan make:model GameRecord --migration

作成されたマイグレーションファイルのupメソッドでテーブルを定義する。

databases/migrations/2021_02_xx_xxxx_create_game_records_table.php
public function up()
    {
        Schema::create('game_records', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->integer('turn');
            $table->integer('piece');
            $table->string('square');
            $table->timestamps();
        });
    }

マイグレーションを実行してテーブルを作成!

ターミナル
$ php artisan migrate

2. 駒の移動先をデータベースに保存

indexメソッドにPOST送信されてくる移動先の駒情報をDBに保存する。
まず、コントローラにモデルの使用を宣言する。

app/Http/Controllers/ShogiController.php
use Illuminate\Http\Request;
use App\Models\GameRecord; // 追加

POST送信された時の保存処理は以下のように書ける。
new モデル名でモデルのインスタンスを新規に作成して、操作・保存できる。

$data = new GameRecord;
$data->turn = $request->input('turn'); // 手番
$data->piece = 0; // 王将
$data->square = $request->input('move'); // 移動先マス
$data->save();

3. 駒の位置をデータベースから取得

モデルを使って簡単にデータを取得できる。

例:$bLastとして直近の先手のデータを取得する場合
idの逆順に並べ【orderBy】、turnが0(先手)のデータを検索して【where】、一件だけを取得【first】で実現できる。

$bLast = GameRecord::where('turn', 0)->orderBy('id', 'desc')->first();

これを使ってコントローラーでデータベースから駒の位置を取得して、それをビューに渡すようにする。

ここで、データがない場合のことを考えて、configフォルダに初期値を設定しておく。(配列で定義)

config/const.php
<!-- 新規作成 -->
<?php
return [
    'start' => [
        'bKing' => [ // 先手の初期値
            'turn' => 0,
            'piece' => 0,
            'square' => 59,
        ],
        'wKing' => [ //後手の初期値
            'turn' => 1,
            'piece' => 0,
            'square' => 51,
        ],
    ]
];

config配下に記述した定数は以下のようにコントローラーから呼び出すことができる。

例:先手の初期値を取得
config('const.start.bKing')

以上で
「(最初だけ)初期値をconst.phpから取得」→「移動したらデータベースに保存」→「直近のデータをデータベースから取得」
を繰り返して、駒の移動を実現する。

4. 先手後手の導入と玉将配置

将棋は二人でやるものだと気づいたので、先手・後手の違いをつける。

indexメソッドとselectメソッド共に、先手「王将」と後手「玉将」それぞれのデータを取得し、$bKing$wKingとしてビューに渡す。

selectメソッドでは(初期値またはデータベースから)取得した「選択中の駒」の情報が渡されている。それを参考に先手と後手で処理を分けた際に$turnという変数を手番に合わせて定義して、ビューに渡す。

selectページでは受け取った$turnも以下のような隠しフォームでindexページにPOST送信するようにする。

echo '<input type="hidden" value="' . $turn . '" name="turn"></input>';

ビューで後手の「玉将」を表示させる。

indexビューの修正箇所

resources/views/shogi/index.blade.php
if ($square == $bKing['square']) {
    // 王将
    echo '<p class="piece row turnb square' . $square . '" id="square' . $square . '"><a style="text-decoration:none" href="' . action('App\Http\Controllers\ShogiController@select', $bKing['turn'] .  ':' . $bKing['piece'] . ':' . $r . ':' . $c) . '">王</a></p>';
} elseif ($square == $wKing['square']) {
    // 玉将
    echo '<p class="piece row turnw square' . $square . '" id="square' . $square . '"><a style="text-decoration:none" href="' . action('App\Http\Controllers\ShogiController@select', $wKing['turn'] .  ':' . $wKing['piece'] . ':' . $r . ':' . $c) . '">玉</a></p>';
}

selectビューの修正箇所

resources/views/shogi/select.blade.php
if ($square == $bKing['square']) {
    // 駒マス「王将」
    echo '<p class="piece row turnb square' . $square . ' selected" id="square' . $square . '">王</p>';
} elseif ($square == $wKing['square']) {
    // 駒マス「玉将」
    echo '<p class="piece turnw row square' . $square . ' selected" id="square' . $square . '">玉</p>';
}

玉将の文字を反転するために追加したCSS

public/css/style.css
.turnw {
    transform:rotate(180deg);
}

手番別の記述を追加したindexメソッド

app/Http/Controllers/ShogiController.php
    public function index(Request $request)
    {
        if ($request->isMethod('post')) {
            // POST時の処理
            $data = new GameRecord;
            $data->turn = $request->input('turn'); // 手番
            $data->piece = 0; // 王将
            $data->square = $request->input('move'); // 移動先マス
            $data->save();
        }
        // 先手番の最新手を取得
        $bLast = GameRecord::where('turn', 0)->orderBy('id', 'desc')->first();
        $bKing = (!empty($bLast['square'])) ? $bLast : config('const.start.bKing');
        // 後手番の最新手を取得
        $wLast = GameRecord::where('turn', 1)->orderBy('id', 'desc')->first();
        $wKing = (!empty($wLast['square'])) ? $wLast : config('const.start.wKing');
        return view('shogi/index', compact('bKing', 'wKing'));
    }

手番別の記述を追加したselectメソッド

    public function select($piece)
    {
        // $pieceには 0:0:5:9 のように手番、駒番、列、行が「:」でくっついた形が入る。
        $king = array();
        $select = explode(":", $piece);
        $king = array(
            'turn' => $select[0],
            'piece' => $select[1],
            'square' => $select[2] . $select[3],
        );
        // 移動可能マス配列としてselectページに渡す
        $ways = array();
        // 王将の移動可能マスを割り出して、$waysに追加する。
        for ($c = $select[3]-1; $c < $select[3]+2 ; $c++) {
            for ($r = $select[2]-1; $r < $select[2]+2 ; $r++) {
                $ways[] = $r . $c;
            }
        }
        $way = array_unique($ways);
        if ($select[0] == 0) {
            // 先手番の処理
            $bKing = $king;
            $wLast = GameRecord::where('turn', 1)->orderBy('id', 'desc')->first();
            $wKing = (!empty($wLast['square'])) ? $wLast : config('const.start.wKing');
            $turn = 0;
        } elseif ($select[0] == 1) {
            // 後手番の処理
            $wKing = $king;
            $bLast = GameRecord::where('turn', 0)->orderBy('id', 'desc')->first();
            $bKing = (!empty($bLast['square'])) ? $bLast : config('const.start.bKing');
            $turn= 1;
        }
        return view('shogi/select', compact('bKing', 'wKing', 'way', 'turn'));
    }

以上でデータベース連携 & 玉将配置までできた。今回はここまで。

スクリーンショット 2021-02-28 17.56.01.png

Github

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