今回はデータベース連携と玉将配置
#目次
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ファイルに記されているデータベース設定を必要に応じて修正する
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メソッドでテーブルを定義する。
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に保存する。
まず、コントローラにモデルの使用を宣言する。
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
フォルダに初期値を設定しておく。(配列で定義)
<!-- 新規作成 -->
<?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ビューの修正箇所
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ビューの修正箇所
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
.turnw {
transform:rotate(180deg);
}
手番別の記述を追加したindexメソッド
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'));
}
以上でデータベース連携 & 玉将配置までできた。今回はここまで。