SQLer 生島勘富 のブログ

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

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

 前回の続きです。今回はパックを回転するするところまでを作ります。

 作るのは http://codevswc.jp/jpn/rule.html これです。データは、与えられるInputのサンプルとします。

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

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

パックを回転します

 回転するには図の様に、Row、Colを変更する必要があります。これは他の言語でもほぼ同じでしょう。もちろん、左上を (0, 0) としたときは変更の必要があるので、お気を付けください。

 具体的には図の通りになります。

 これは他の言語でもされるように関数にしましょう。
 ……ですが、SQLでは一つずつ作ることになります。

CREATE FUNCTION ChangeRow
(@Rot int, @Row int, @Col int, @Size int)
RETURNS int
BEGIN
	DECLARE @Ret int;
	
	SET @Ret = 
		CASE @Rot 
			WHEN 1 THEN (@Size - 1) - @Col 
			WHEN 2 THEN (@Size - 1) - @Row 
			WHEN 3 THEN @Col
			ELSE @Row 
		END;
	
	RETURN @Ret;
END;

CREATE FUNCTION ChangeCol
(@Rot int, @Row int, @Col int, @Size int)
RETURNS int
BEGIN
	DECLARE @Ret int;
	
	SET @Ret = 
		CASE @Rot 
			WHEN 1 THEN @Row
			WHEN 2 THEN (@Size - 1) - @Col
			WHEN 3 THEN (@Size - 1) - @Row
			WHEN @Col
		END;
	
	RETURN @Ret;
END;

パックを投下するリストを作る

 ルールhttp://codevswc.jp/jpn/rule.html を読むと、パックは横方向(X軸)はマイナスの位置にも落とせます。

 ゼロオリジンになっていますので、取り得るパックを落とす位置の一番右端は、
    0 - パックのサイズ - 1
 となります。

 左端は、
    盤の幅 - 1
 となります。

 パックは90°ずつ回した4パターンがあります。

 今回のゲーム
    パックのサイズ = 4
    盤の幅 = 10
 ですから、パックを投下するパターンは、

    -3 〜 9 = 13通り × 4つの角度 = 52通り
 になります。

SELECT 
	xp.Seq AS XPos 
	, rt.Seq AS Rot
FROM tf_SequentialNums(-3, 10) AS xp
	CROSS JOIN tf_SequentialNums(0, 3) AS rt
	

 1つめのパックを落とせる全てのパターンを作ることができます。
 SimulationID は 1から採番して 0を実際に採用したアウトプットとします。
 投下した時点でTurnはカウントアップされます。

INSERT INTO Turn
	(GameID, SimulationID, Turn, XPos, Rot)
SELECT 
	0, Rank() OVER(ORDER BY xp.Seq, rt.Seq)
	, 0 + 1, xp.Seq, rt.Seq 
FROM tf_SequentialNums(-3, 9) AS xp
	CROSS JOIN tf_SequentialNums(0, 3) AS rt;
	

回転したリスト

 作成したTurn(シミュレーション用)のデータとパックを結合して、回転後のRow、Colの一覧を見る。

SELECT 
	t.SimulationID, t.Rot
	, p.Row, p.Col, p.Num
	, dbo.ChangeRow(t.Rot, p.Row, p.Col, 4) AS tRow -- 回転後のRow
	, dbo.ChangeCol(t.Rot, p.Row, p.Col, 4) AS tCol -- 回転後のCol  
FROM 
	Turn t
	INNER JOIN Pack p --参照されるPackテーブル
		ON t.GameID = p.GameID -- TurnテーブルのキーのSimulationIDと結合して
		AND t.Turn = p.Turn    -- ないのでSimulationIDの種類数倍になる。

つづく