SQLer 生島勘富 のブログ

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

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

 前回の続きです。

 作るのは http://codevswc.jp/jpn/rule.html これです。所謂、「落ちゲー」もある程度、SQLで作れます。

 是非、ルールをよく読んで、「自分なら SQL でこういう方針で作る」

 「Javaなら、.Netなら、Rubyなら…… こういう方針で作る」

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

パックを登録

 前回説明したとおり、左下を(0, 0) として、(行, 列)の組合せで登録してきます。

 例えば、Sampleにあるように、Javaでは以下の様に登録することが多いと思います。

	int[][][] pack = new int[step][size][size];
	String endstr = null;

	for(int i=0;i<step;i++){
		for(int j=0;j<size;j++){
			for(int k=0;k<size;k++){
				pack[i][j][k] = scan.nextInt();  -- 0以外の数字のとき、INSERTする。
			}
		}
		endstr = scan.next();
	}

 この pack[i][j][k] = scan.nextInt(); の j が Row にあたるのですが、左下を(0, 0)としているため、Row = size - j - 1 となります。好みで変えてください。

 0は不要ですので、0のときは INSERT しません。

連番テーブルファンクションを作る

 よく使うので、共通関数としてDBに一つ作っておいても良いかも知れません。

CREATE FUNCTION tf_SequentialNums
(@From int, @To int)
RETURNS TABLE
AS
	RETURN
	(
		WITH SequentialNums (Seq) 
			AS (
			SELECT @From AS Seq
			UNION ALL
			SELECT Seq + 1 FROM SequentialNums
			WHERE Seq + 1 <= @To
			)
		SELECT Seq FROM SequentialNums
	);

 使い方

SELECT * FROM tf_SequentialNums(-3, 10); 

 とすれば、-3から10までの連番を作ることができます。

盤面を確認する

 盤面(Boardテーブル)にパック(Packテーブル)の内容を落としていくゲームですが、Boardテーブルも数値の羅列で何のことか分かりません。しかし、以下のSQLで確認することが可能です。

 残念なことに、SQLでは列を動的に指定することはできません。そのため、盤面の種類毎(今回の大会では、盤の幅が10、15、20)に作るか、一番大きな盤面で代替するかになります。

 よく使うことになるので、これもテーブルファンクションにしておくと良いでしょう。
 個人的に PIVOT は嫌いで、CASEで書くことが多いのですが、今回はPIVOTにしておきました。
 DispBoard15、DispBoard20 は列数が多いだけなので、ご自身で作ってください。

CREATE FUNCTION DispBoard10
(@GameID int, @SimulationID money, @Turn int, @Chain int)
RETURNS TABLE
AS
	RETURN
	(
		SELECT 
			pvt.Seq AS Row
			, [00], [01], [02], [03], [04], [05], [06], [07], [08], [09]
		FROM tf_SequentialNums(0, 19) AS l -- 盤の高さ+Packサイズで良いと思う
			LEFT JOIN Board AS b
				ON l.Seq = b.Row
				AND @GameID = b.GameID -- WHERE句ではなくFROM句に書くのがミソ
				AND @SimulationID = b.SimulationID -- WHERE句ではなくFROM句に書くのがミソ
				AND @Turn = b.Turn -- WHERE句ではなくFROM句に書くのがミソ
				AND @Chain = b.Chain -- WHERE句ではなくFROM句に書くのがミソ
				PIVOT (
					MAX(b.Num) FOR b.Col 
					IN([00], [01], [02], [03], [04], [05], [06], [07], [08], [09])
					) AS pvt
	)
go

 使い方

SELECT * FROM DispBoard10(0, 1, 1, 0)
ORDER BY Row DESC


 現状は空なので、NULLが並んだ盤面が再現されるはずです。


 与えられるInputのサンプル
 Packテーブルにデータを入れるInsert文のサンプル
 (SQLServer2005向けで、2008なら列リストは要らないのですが……)


 (つづく)