0

我对 Bejewelled 游戏带来的编程挑战很感兴趣。它看起来像一个简单的游戏,但在编程上它看起来更复杂。

在寻找有关如何评估董事会的提示时,我遇到了 Simple-Talk 的好人提出的这个测验。他们已经发布了获胜的答案,但是如果我真的能理解解决方案的工作原理,我会感到很震惊。我可以看到它与矩阵有关,并将单元格值与其行和列分组在一起,但这是我到目前为止所获得的。任何人都可以为我进一步分解它吗?

发布的解决方案(测验的详细信息在上面的链接中):

--====== Table matches needs to be loaded only once
CREATE TABLE matches(offsetRow1 INT, offsetCol1 INT, offsetRow2 INT, ofsetCol2 INT, directions VARCHAR(20))
-- for horizontal 
INSERT INTO matches VALUES(-1, -1, -1, -2, 'up')
INSERT INTO matches VALUES(-1, -1, -1, 1, 'up')
INSERT INTO matches VALUES(-1, 1, -1, 2, 'up')        
INSERT INTO matches VALUES( 1, -1, 1, -2, 'down')           
INSERT INTO matches VALUES( 1, -1, 1, 1, 'down')
INSERT INTO matches VALUES( 1, 1, 1, 2, 'down')       
INSERT INTO matches VALUES( 0, -2, 0, -3, 'left')     
INSERT INTO matches VALUES( 0, 2, 0, 3, 'right')            
-- for verical
INSERT INTO matches VALUES(-2, -1, -1, -1, 'left')
INSERT INTO matches VALUES(-1, -1, 1, -1, 'left')
INSERT INTO matches VALUES( 1, -1, 2, -1, 'left')
INSERT INTO matches VALUES(-2, 1, -1, 1, 'right')
INSERT INTO matches VALUES(-1, 1, 1, 1, 'right')
INSERT INTO matches VALUES( 1, 1, 2, 1, 'right')
INSERT INTO matches VALUES(-2, 0, -3, 0, 'up')
INSERT INTO matches VALUES( 2, 0, 3, 0, 'down')

--==================================================
;WITH CTE
      AS
  (
  SELECT
        [Row] = CAST( [#] AS INT ),
        [Col] = CAST( [Col] AS INT ),
        [Value]
    FROM bejeweled
        UNPIVOT ([Value] FOR [Col] IN ([1],[2],[3],[4],[5],[6],[7],[8],[9])) unpvt
  )
SELECT DISTINCT T.Row, T.Col, T.Value, directions
  FROM CTE T
      JOIN CTE T1
      ON T.Value = T1.Value
      JOIN CTE T2
      ON T.Value = T2.Value
      JOIN matches
      ON (T1.Row - T.Row) = offsetRow1
    AND (T1.Col - T.Col) = offsetCol1
    AND (T2.Row - T.Row) = offsetRow2
    AND (T2.Col - T.Col) = ofsetCol2
  ORDER BY T.Row, T.Col
4

1 回答 1

3

unpivot 函数将原始数据转换为线性列表而不是矩阵。例如,由于原始列中 1,1 的值为 8,因此新表的第一行是 1,1,8 。同样,由于原始表的第一行的第二列是 5,所以我们的新表的第二行是 1,2,5 。

“With CTE”有效地创建了一个名为 CTE 的内存表,因此这个新的 3 列 81 行表称为 CTE。

逻辑发生在内部连接:CTE 中的每个单元格都连接到 CTE 中值匹配的每个单元格,并再次连接到值匹配的自身。这意味着原始表中的每个单元格都知道所有其他可能的三项匹配。也就是说,返回包含值“1”(例如)的 3 个单元格列表的每个排列。

让我们看看值 2。在 (6,2) 处有一个,在 (5,3) 处有另一个,在 (7,3) 处有另一个,因此内部连接的可能值之一是 T.Row 为 6 ,T.Col 为 2,T1.Row 为 5,T1.Col 为 3,T2.Row 为 7,T2.Col 为 3。我们通过查看它知道将 (6,2) 与 (6,3) 交换) 将三个连续。但是 JOIN 语句是怎么知道的呢?

好吧,有效的举动是将 T 置于 T1 和 T2 之间。确定我们的 3 组合是否满足的最简单方法是检查偏移量并将其与有效的相对位置列表进行比较。T1 在 T (-1,1) 的上方和右侧,T2 在 T (1,1) 的下方和右侧。我们检查 (-1,1,1,1) 是否是有效匹配。是的,因此它通过了 JOIN 标准并作为结果保留。

于 2008-12-17T17:30:04.887 回答