どう書く?org「麻雀ゲーム1」をSQLで考えるメモ
ゲームとしてのアルゴリズムはよくわかりませんが、データ構造はいろいろ考えられそうです。
とりあえず、SQLの勉強として、SQLでモデル化した場合について途中まで考えたメモを残してみます。文法はとりあえずどのRDBMSともつかないものです。勉強中なので、おかしな箇所あったらご指摘ください。なお、この場合、SQLでモデル化することに実用的な意味はないと思います。
データの表現
全体を牌のテーブルとして考えてみます。
CREATE TABLE pais (
id INTEGER NOT NULL,
paitype_id INTEGER NOT NULL, -- → paitypes
paitype_num INTEGER,
location_id INTEGER NOT NULL, -- → locations
location_num INTEGER
);
paitypesはこんな感じで。
CREATE TABLE paitypes (
id INTEGER NOT NULL,
name VARCHAR(5)
);
-- 萬子、索子、筒子
INSERT INTO paitypes (id, name) VALUES (0, 'MAN');
INSERT INTO paitypes (id, name) VALUES (1, 'SOU');
INSERT INTO paitypes (id, name) VALUES (2, 'PIN');
-- 風牌
INSERT INTO paitypes (id, name) VALUES (3, 'TON');
INSERT INTO paitypes (id, name) VALUES (4, 'NAN');
INSERT INTO paitypes (id, name) VALUES (5, 'SHA');
INSERT INTO paitypes (id, name) VALUES (6, 'PEI');
-- 三元牌
INSERT INTO paitypes (id, name) VALUES (7, 'HAKU');
INSERT INTO paitypes (id, name) VALUES (8, 'HATSU');
INSERT INTO paitypes (id, name) VALUES (9, 'CHUN');
locationsはこんな感じで。
CREATE TABLE locations (
id INTEGER NOT NULL,
name VARCHAR(7)
);
-- 山
INSERT INTO locations (id, name) VALUES (0, 'YAMA');
-- 手牌
INSERT INTO locations (id, name) VALUES (1, 'TON');
INSERT INTO locations (id, name) VALUES (2, 'NAN');
INSERT INTO locations (id, name) VALUES (3, 'SHA');
INSERT INTO locations (id, name) VALUES (4, 'PEI');
-- 河
INSERT INTO locations (id, name) VALUES (5, 'TON_HOU');
INSERT INTO locations (id, name) VALUES (6, 'NAN_HOU');
INSERT INTO locations (id, name) VALUES (7, 'SHA_HOU');
INSERT INTO locations (id, name) VALUES (8, 'PEI_HOU');
あとは136牌をINSERT。
なお、リーチもドラも鳴きも、問題文にないので対応していません。
洗牌、山積
2. 牌をかき混ぜてから山を作成する機能.
開門とかは問題文にないので、単なる連番を振ります。
これはpaisからORDER BY rand()とかのランダム順でSELECTした結果に対し、location_idを0にして、location_numに連番を振ることで実現できます。連番を振るのが面倒なRDBMSの場合には、location_numを設定せず、以降の配牌や自摸のときにORDER BY rand()とかのランダム順を使うことになるでしょう。
配牌
これは、paisとlocationsをjoinして、location_idが'YAMA'なものをORDER BY location_numのLIMIT 13(親は14)を取り出し、UPDATEでlocation_idとlocation_numを手牌のものに変えてやれば実現できます。
3. 手牌を理牌する機能
この要件は、location_numで表現できています。手牌を表示する場合は、paisにpaitypesとlocationsをjoinしてWHEREでプレイヤーの手配に絞ってSELECTするだけで実現できます。
自摸、打牌
4. 山から牌を取る操作.
5. 手配を切る操作 (ツモ切りで構いません).
6. 河を保存する機能.
配牌と同じ方法で山から1つを取り出します。ツモ切りということなので、そのままlocation_idをプレイヤーの河に書き変えます。location_numで順番を付けておくとよいでしょう。河の表示は、paisにpaitypesとlocationsをjoinしてWHEREでプレイヤーの河に絞ってSELECTするだけで実現できます。
まとめ
- 136牌のテーブルとして表現する
- 牌ごとに場所の情報を持つ
- 牌の移動はUPDATEで実現する
…書いてみると、なんかすごいあたりまえですね。
コメント
コメントの投稿
トラックバック
http://emasaka.blog65.fc2.com/tb.php/527-38aff978
