CODE VS 2.1 をSQLでやるとどうなる5
前回の続きです。今回は、パックを投下するところまでを作ります。
作るのは http://codevswc.jp/jpn/rule.html これです。データは、与えられるInputのサンプルとします。
是非、ルールをよく読んで、「自分なら SQL でこういう方針で作る」
「Javaなら、.Netなら、Rubyなら…… こういう方針で作る」
と想像しながら読んでください。
プログラムを作るよりも解説の方がはるかに難しい……。だんだん手抜きになってきていますがご容赦。
Turnテーブル(シミュレーション用)から全通りのパックを投下する
前回作ったTurnテーブル(シミュレーション用)から、1つ目のパックが取り得る全通りのパターンで投下します。
まず、現在、盤面に残っているブロック(現状は空)に、新しい SimulationID 次のターンにインサートします。
INSERT INTO Board (GameID, SimulationID, Turn, Row, Col, Num) SELECT t.GameID , t.SimulationID , t.Turn , b.Row , b.Col , b.Num FROM Turn t LEFT JOIN board b ON t.GameID = b.GameID AND 0 = b.SimulationID -- 採用したパターン AND t.Turn = b.Turn -1 WHERE t.GameID = 0 AND t.Turn = 1;
続いて、パックデータを投下します
尚、上のSQLのSELECT部分と、下のSQLのSELECT部分を、UNION ALLで繋いで1回にしても同じです。
INSERT INTO Board (GameID, SimulationID, Turn, Row, Col, Num) SELECT tp.GameID , tp.SimulationID , tp.Turn , ISNULL(b.MaxRow, -1) -- ゼロオリジンなのでブロックがないときは-1 + RANK() OVER(PARTITION BY tp.SimulationID, tp.tCol ORDER BY tp.tRow) , tp.tCol , tp.Num FROM (SELECT t.GameID, t.Turn, t.SimulationID, t.Rot , dbo.ChangeRow(t.Rot, p.Row, p.Col, 4) AS tRow -- 回転後のRow , dbo.ChangeCol(t.Rot, p.Row, p.Col, 4) + t.XPos AS tCol -- 回転後落とす位置のCol , p.Num FROM Turn t INNER JOIN Pack p --参照されるPackテーブル ON t.GameID = p.GameID AND t.Turn = p.Turn + 1 -- Turnテーブルのターンはカウントアップ済み WHERE t.Turn = 1 ) AS tp LEFT JOIN ( SELECT MAX(Row) As MaxRow, Col FROM Board WHERE Turn = 0 -- コピー元を観た方が効率的 GROUP BY Col) As b ON tp.tCol = b.Col ; -- 確認 xx に1〜52までの数字を入れて、パックを回転させて -- 狙った位置に投下できているか確認しましょう。 SELECT * FROM DispBoard10(0, xx, 1, 0) ORDER BY Row DESC;