SQLer 生島勘富 のブログ

RDB・SQLの話題を中心に情報発信をしています。

CODE VS 2.1 をSQLでやるとどうなる2

 作るのは http://codevswc.jp/jpn/rule.html これです
 所謂、「落ちゲー」をSQLで作るにはどうしたらよいか?ということになります。

 かなり複雑でルールを良く読み込まないの理解できないでしょう。
 是非、よく読んで、「自分なら SQL でこういう方針で作る」
 「Javaなら、.Netなら、Rubyなら…… こういう方針で作る」

 と想像しながら読んでください。

悩んでいます(苦笑)

 Javaでやったとき、パックや盤の左上を原点(0, 0)として、それぞれRow, Col(行, 列)としてコーディングしたのですが、一番底の位置がゼロでないのが、どうもしっくりこなかった。

 で、SQLでするのに左下を原点(0, 0)としようと思ったのですが、左下だとこれまたRow, Col(行, 列)と呼んではしっくりこない。

 左下を原点とすると(X, Y)としないとしっくりこないが、そうすると元のRow, Col(行, 列)で言うとCol, Row(列, 行)と逆になることになって、これまたしっくりこない。

 どうするのが一般的なのでしょうか?
 私はゲームをほとんど作ったことがないのでよく分かりませんので、おかしいと思った人はコメントや、Twitterで絡んでください。

 とりあえず、左下を原点、Row, Col(行, 列)としますので、しっくりこない人は適当に読み替えてください。

テーブル

 欲張って、SimulationID というのを付けています。実際に問題を解くにはSimulationIDだけでは足りないと思うけれど……。

 データは 0 以外の数字をPackテーブルに突っ込みます(ここのコードは単純なINSERTなので解説しません)。
 それを、1ターン毎にBoardテーブルに追加していくことでゲームを再現します。

CREATE TABLE Pack
(
    GameID                       int DEFAULT 0 NOT NULL,
    Turn                         int DEFAULT 0 NOT NULL,
    Row                          int DEFAULT 0 NOT NULL,
    Col                          int DEFAULT 0 NOT NULL,
    Num                          int DEFAULT 0 NOT NULL
, PRIMARY KEY (GameID, Turn, Row, Col)
);

CREATE TABLE Board  -- Chain単位で保存する
(
    GameID            int DEFAULT 0 NOT NULL,
    SimulationID      money DEFAULT 0 NOT NULL,
    Turn              int DEFAULT 0 NOT NULL,
    Chain             int DEFAULT 0 NOT NULL,
    Row               int DEFAULT 0 NOT NULL,
    Col               int DEFAULT 0 NOT NULL,
    Num               int DEFAULT 0 NOT NULL
, PRIMARY KEY (GameID, SimulationID, Turn, Chain, Row, Col)
);

CREATE TABLE Deleted  -- なくても良い。ステップで考えるときに必要
(
    GameID            int NOT NULL,
    SimulationID      money NOT NULL,
    Turn              int NOT NULL,
    Chains            int NOT NULL,
    Row               int NOT NULL,
    Col               int NOT NULL
, PRIMARY KEY (GameID, SimulationID, Turn, Chains, Row, Col)
);

CREATE TABLE Turn  -- 記録する
(
    GameID            int DEFAULT 0 NOT NULL,
    SimulationID      money DEFAULT 0 NOT NULL,
    Turn              int DEFAULT 0 NOT NULL,
    XPos              int DEFAULT 0 NOT NULL,
    Rot               int DEFAULT 0 NOT NULL,
    Ereases           int DEFAULT 0 NULL,
    Chains            int DEFAULT 0 NULL,
    FireCounts        int DEFAULT 1 NULL,
    CurScore          money DEFAULT 0 NULL,
    TotalScore        money DEFAULT 0 NULL
, PRIMARY KEY (GameID, SimulationID, Turn)
);

CREATE TABLE Game -- パラメータで渡しても良い気もする
(
    GameID            int DEFAULT 0 NOT NULL,
    Width             int NULL,
    Height            int NULL,
    MaxTurn           int NULL,
    PackSize          int NULL,
    Sums              int NULL,
    P_Point           int NULL,
    A_Point           int NULL,
    B_obs             int NULL,
    Th                int NULL,
    Memo              text NULL
, PRIMARY KEY (GameID)
);

そのほかに必要なテーブル。

CREATE TABLE Direction4  -- 4方向にチェックするときように4レコード保存
(
    Angle                        int NOT NULL,
    RowOffset                    int NULL,
    ColOffset                    int NULL,
    Memo                         nvarchar(8) NULL
, PRIMARY KEY (Angle)
);

CREATE TABLE Direction8  -- 8方向にチェックするときように8レコード保存
(
    Angle                        int NOT NULL,
    RowOffset                    int NULL,
    ColOffset                    int NULL,
    Memo                         nvarchar(8) NULL
, PRIMARY KEY (Angle)
);

Direction4 には、上、右上、右、右下、つまり、RowOffset, ColOffset をそれぞれ、(1, 0)(1, 1)(0, 1)(-1, 1) を登録する。
Direction8 には、上、右上、右、右下、下、左下、左、左上、つまり、RowOffset, ColOffset をそれぞれ、(1, 0)(1, 1)(0, 1)(-1, 1)(-1, 0)(-1, -1)(0, -1)(1, -1) を登録する。

(つづく)