数据库宝石迷阵 - 该解决方案如何工作?

发布于 2024-07-11 05:55:07 字数 2042 浏览 7 评论 0原文

我对《宝石迷阵》游戏提出的编程挑战很感兴趣。 这看起来是一个简单的游戏,但从编程角度来说,它比看起来更复杂。

在寻找有关如何评估董事会的提示时,我遇到了这个由 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

I'm interested in the programming challenge presented by the game Bejewelled. It seems like a simple game but programmatically it's more complex that it looks.

In my search for hints on how the board is evaluated, I came across this QUIZ put on by the good folks at Simple-Talk. They have posted the winning answer, but I'm tarred and feathered if I can really grok how the solution works. I can see that it has something to do with matrices and grouping the cell values together with their rows and columns, but that's as far as I have gotten so far. Can anyone break it down a little further for me?

POSTED SOLUTION (the details of the quiz are at the link above):

--====== 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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

清醇 2024-07-18 05:55:07

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 标准并作为结果保留。

The unpivot function turns the original data into a linear list rather than a matrix. For example, since the value at 1,1 in the original column was 8, the first row of the new table is 1,1,8 . Likewise, since the second column of the first row of the original table was a 5, the second row of our new table is 1,2,5 .

The 'With CTE' effectively creates an in-memory table named CTE, so this new 3-column, 81-row table is called CTE.

The logic happens with the inner join: every cell in CTE gets joined to every cell in CTE where the values match, and again with itself where the values match. This means that every cell in the original table knows of every other possible three-item match. That is, every single permutation of a list of 3 cells containing value '1' (for example) are returned.

Let's look at the value 2. There is one at (6,2), another at (5,3) and another at (7,3) , so one of the possible values of the inner join would have T.Row be 6, T.Col be 2, T1.Row be 5, T1.Col be 3, T2.Row be 7, and T2.Col be 3. We know by looking at it that swapping (6,2) with (6,3) would put the three in a row. But how does the JOIN statement know?

Well, a valid move is one that puts T in between T1 and T2. The easiest way to determine if our combination of 3 meets that is by checking the offsets and comparing that to a list of relative positions that work. T1 is above and to the right of T (-1,1), and T2 is below and to the right of T (1,1). We check and see if (-1,1,1,1) is a valid match. It is, so it passes the JOIN criteria and is kept as a result.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文