{"id":983,"date":"2010-09-02T00:00:00","date_gmt":"2010-09-02T00:00:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/minesweeper-in-t-sql\/"},"modified":"2021-09-29T16:21:57","modified_gmt":"2021-09-29T16:21:57","slug":"minesweeper-in-t-sql","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/databases\/sql-server\/t-sql-programming-sql-server\/minesweeper-in-t-sql\/","title":{"rendered":"Minesweeper in T-SQL"},"content":{"rendered":"<div id=\"code\">\n<p class=\"editor\">Whatever happened to the idea that programming in TSQL can be fun? A Simple-Talk reader contributes an article to remind us all that there is more to TSQL than wrestling with DMVs and pummelling recalcitrant correlated subqueries.  <\/p>\n<p>\/* As a fun exercise I decided to program Minesweeper in T-SQL. I think it worked out quite nicely, so I&#8217;d like to share it with the world. But first, for anyone who doesn&#8217;t know what minesweeper is, a <a href=\"http:\/\/en.wikipedia.org\/wiki\/Minesweeper_(computer_game)\">description is available here<\/a>. <\/p>\n<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1132-img20.gif\" class=\"float-right\" alt=\"1132-img20.gif\" \/><\/p>\n<p>I&#8217;ve used SQL Server Management Studio 2008 Express, but other versions should work as well (although the layout of the resultgrid might require some work).<\/p>\n<p>I wanted a minefield that was variable in length and width, so I created three tables: *\/<\/p>\n<p>CREATE TABLE Grid  <\/p>\n<p>&#160;&#160;&#160; (<\/p>\n<p>&#160;&#160;&#160;&#160; X INT NOT NULL,&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8212; X coordinate<\/p>\n<p>&#160;&#160;&#160;&#160; Y INT NOT NULL,&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8212; Y coordinate<\/p>\n<p>&#160;&#160;&#160;&#160; S INT NULL,&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8212; Status, see the user defined function udf_S<\/p>\n<p>&#160;&#160;&#160;&#160; CONSTRAINT PK_Grid PRIMARY KEY (X ASC, Y ASC)<\/p>\n<p>&#160;&#160;&#160; )<\/p>\n<\/p>\n<p>CREATE TABLE Mine<\/p>\n<p>&#160;&#160;&#160; (<\/p>\n<p>&#160;&#160;&#160;&#160; X INT NOT NULL,&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8212; X coordinate<\/p>\n<p>&#160;&#160;&#160;&#160; Y INT NOT NULL,&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8212; Y coordinate<\/p>\n<p>&#160;&#160;&#160;&#160; CONSTRAINT PK_Mine PRIMARY KEY (X ASC, Y ASC)<\/p>\n<p>&#160;&#160;&#160; )<\/p>\n<\/p>\n<p>\/* The setting table will only ever hold one record *\/<\/p>\n<p>CREATE TABLE Settings <\/p>\n<p>&#160;&#160;&#160; (<\/p>\n<p>&#160;&#160;&#160;&#160; MaxX INT NOT NULL,&#160;&#160;&#160;&#160;&#160;&#160; &#8212; Number of rows<\/p>\n<p>&#160;&#160;&#160;&#160; MaxY INT NOT NULL,&#160;&#160;&#160;&#160;&#160;&#160; &#8212; Number of columns<\/p>\n<p>&#160;&#160;&#160;&#160; NumberOfMines INT NOT NULL<\/p>\n<p>&#160;&#160;&#160; )<\/p>\n<\/p>\n<p>\/* Inserting some default values *\/<\/p>\n<div>INSERT&#160; INTO Settings <\/div>\n<p>VALUES&#160; (10, 10, 10)<\/p>\n<\/p>\n<p>GO<\/p>\n<\/p>\n<p>CREATE FUNCTION udf_S (@S INT)<\/p>\n<p>RETURNS CHAR(1)<\/p>\n<div>\/* A user defined function for the visual representation of the status *\/AS <\/div>\n<p>&#160;&#160;&#160; BEGIN<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; RETURN (CASE<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHEN @S = -100 THEN &#8216;F&#8217;&#160;&#160;&#160;&#160;&#160;&#160; &#8211;Flagged<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHEN @S = -10 THEN &#8216;S&#8217;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8211;Safe<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHEN @S = -1 THEN &#8216;?&#8217;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8211;Unknown<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHEN @S = 0 THEN &#8221;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8211;No mines in the vicinity<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHEN @S = 9 THEN &#8216;M&#8217;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8211;Exploded mine<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ELSE CONVERT(CHAR(1),@S)&#160;&#160;&#160;&#160;&#160; <\/p>\n<div>&#8211;Number of mines in the vicinity <\/div>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; END<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; )<\/p>\n<p>&#160;&#160;&#160; END<\/p>\n<\/p>\n<p>GO&#160;&#160;&#160; <\/p>\n<\/p>\n<p>CREATE PROCEDURE p_Initialize<\/p>\n<p>&#160;&#160;&#160; (<\/p>\n<p>&#160;&#160;&#160;&#160; @MaxX INT = NULL,<\/p>\n<p>&#160;&#160;&#160;&#160; @MaxY INT = NULL,<\/p>\n<p>&#160;&#160;&#160;&#160; @NumberOfMines INT = NULL,<\/p>\n<p>&#160;&#160;&#160;&#160; @Seed INT = NULL<\/p>\n<p>&#160;&#160;&#160; )<\/p>\n<div>\/* Initializing the game by creating the grid and randomly dropping the mines. I included a @seed parameter to be able to create the same map multiple times. If you call the procedure without any parameters he&#8217;ll use the same as last game, except the seed naturally *\/ <\/div>\n<p>AS  <\/p>\n<p>&#160;&#160;&#160; BEGIN<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; UPDATE&#160; Settings<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; SET&#160;&#160;&#160;&#160; MaxX = ISNULL(@MaxX, MaxX),<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; MaxY = ISNULL(@MaxY, MaxY),<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; NumberOfMines = ISNULL(@NumberOfMines, NumberOfMines)<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; SELECT&#160; @MaxX = MaxX,<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; @MaxY = MaxY,<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; @NumberOfMines = NumberOfMines<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; FROM&#160;&#160;&#160; Settings<\/p>\n<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; TRUNCATE TABLE Mine<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; TRUNCATE TABLE Grid<\/p>\n<p>&#160; <\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; DECLARE @x INT<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; DECLARE @y INT<\/p>\n<div> <\/div>\n<p>\/* Creating records to represent the squares of the grid *\/&#160;&#160;&#160;&#160;&#160;&#160;&#160; <\/p>\n<div>&#160;&#160;&#160;&#160;&#160;&#160;&#160; SET @x = 1 <\/div>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHILE @x &lt;= @MaxX <\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; BEGIN<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; SET @y = 1<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHILE @y &lt;= @MaxY <\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; BEGIN<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; INSERT&#160; INTO grid<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; VALUES&#160; (@x, @y, -1)<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; SET @y = @y + 1<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; END<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; SET @x = @x + 1<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; END<\/p>\n<div>\/* Setting the seed if necessary *\/<br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; IF @seed IS NOT NULL <\/div>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; SET @x = RAND(@seed)<\/p>\n<\/p>\n<p>\/* Dropping mines, but never on the same square *\/<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHILE @NumberOfMines &gt; 0 <\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; BEGIN<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; SET @x = FLOOR(RAND() * @MaxX) + 1<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; SET @y = FLOOR(RAND() * @MaxY) + 1<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; IF (SELECT&#160; COUNT(*)<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; FROM&#160;&#160;&#160; mine<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHERE&#160;&#160; x = @x<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AND y = @y<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ) = 0 <\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; BEGIN<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; INSERT&#160; INTO Mine<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; VALUES&#160; (@x, @y)<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; SET @NumberOfMines = @NumberOfMines &#8211; 1<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; END<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; END&#160;&#160; <\/p>\n<p>&#160;&#160;&#160; END<\/p>\n<p>&#160;&#160;&#160; <\/p>\n<p>&#160;GO<\/p>\n<p>&#160; <\/p>\n<p>CREATE PROCEDURE p_Draw<\/p>\n<div>\/* Using a bit of dynamic SQL to draw the grid *\/ <\/div>\n<p>AS <\/p>\n<p>&#160;&#160;&#160; BEGIN<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; DECLARE @sql VARCHAR(MAX)<\/p>\n<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; SELECT&#160; @sql = ISNULL(@sql + &#8216;, &#8216; + CHAR(13) + CHAR(9), &#8216;SELECT &#8216;)<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; + &#8216;MAX(CASE WHEN Y = &#8216; + CONVERT(VARCHAR(3), y)<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; + &#8216; THEN dbo.udf_S(S) END) as [&#8216; + CONVERT(VARCHAR(3), y)<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; + &#8216;]&#8217;<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; FROM&#160;&#160;&#160; grid<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; GROUP BY y<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; ORDER BY y<\/p>\n<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; SET @sql = @sql + CHAR(13) + &#8216;FROM GRID<\/p>\n<p>&#160;&#160;&#160;&#160;&#160; GROUP BY X<\/p>\n<p>&#160;&#160;&#160;&#160;&#160; ORDER BY X&#8217;<\/p>\n<p>&#160;&#160;&#160;&#160;&#160; <\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8211;PRINT @sql&#160; &#8211;Uncomment this to see the SQL statement generated<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; EXEC (@sql)<\/p>\n<p>&#160;&#160;&#160; END<\/p>\n<p>GO<\/p>\n<\/p>\n<p>CREATE PROCEDURE p_MarkSafeSquares<\/p>\n<div>\/* Mark all unexplored squares next to a square with no mines in the vicinity (a blank square) See procedure p_Explore *\/ <\/div>\n<p>AS <\/p>\n<p>&#160;&#160;&#160; UPDATE&#160; grid<\/p>\n<p>&#160;&#160;&#160; SET&#160;&#160;&#160;&#160; S = -10<\/p>\n<p>&#160;&#160;&#160; FROM&#160;&#160;&#160; (SELECT g2.x,<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; g2.y<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; FROM&#160;&#160; grid g1<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; INNER JOIN grid g2 ON g1.x &#8211; g2.x BETWEEN -1 AND 1<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AND g1.y &#8211; g2.y BETWEEN -1 AND 1<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHERE&#160; g1.S = 0<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AND g2.S = -1<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ) subset<\/p>\n<p>&#160;&#160;&#160; WHERE&#160;&#160; subset.x = grid.X<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AND subset.y = grid.y<\/p>\n<\/p>\n<p>GO<\/p>\n<\/p>\n<p>CREATE PROCEDURE p_ExploreSafeSquares (@count INT OUTPUT)<\/p>\n<div>\/* Explore all squares marked as safe. See procedure p_Explore *\/ <\/div>\n<p>AS &#8211;First update all safe squares with mines in the vicinity<\/p>\n<p>&#160;&#160;&#160; UPDATE&#160; Grid<\/p>\n<p>&#160;&#160;&#160; SET&#160;&#160;&#160;&#160; S = MinesDetected<\/p>\n<p>&#160;&#160;&#160; FROM&#160;&#160;&#160; (SELECT g.x,<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; g.y,<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; COUNT(*) AS MinesDetected<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; FROM&#160;&#160; Grid g<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; INNER JOIN Mine m ON g.x &#8211; m.x BETWEEN -1 AND 1<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AND g.y &#8211; m.y BETWEEN -1 AND 1<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHERE&#160; S = -10<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; GROUP BY g.x,<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; g.y<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ) s1<\/p>\n<p>&#160;&#160;&#160; WHERE&#160;&#160; s1.x = grid.x<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AND s1.y = grid.y<\/p>\n<p>&#160;&#160;&#160;&#160;&#160; <\/p>\n<p>&#160;&#160;&#160;&#160;&#160; &#8211;Determine if the procedure should be run again <\/p>\n<p>&#160;&#160;&#160; SELECT&#160; @count = COUNT(*)<\/p>\n<p>&#160;&#160;&#160; FROM&#160;&#160;&#160; grid<\/p>\n<p>&#160;&#160;&#160; WHERE&#160;&#160; s = -10<\/p>\n<p>&#160;&#160;&#160; <\/p>\n<p>&#160;&#160;&#160;&#160;&#160; &#8211;Second, update all other safe squares to blank squares&#160;&#160;&#160; <\/p>\n<p>&#160;&#160;&#160; UPDATE&#160; Grid<\/p>\n<p>&#160;&#160;&#160; SET&#160;&#160;&#160;&#160; S = 0<\/p>\n<p>&#160;&#160;&#160; WHERE&#160;&#160; S = -10<\/p>\n<p>&#160;&#160;&#160;&#160;&#160; <\/p>\n<p>GO<\/p>\n<\/p>\n<p>CREATE PROCEDURE p_Explore (@x INT, @y INT)<\/p>\n<div>\/* Expore an unknown square *\/ <\/div>\n<p>AS <\/p>\n<p>&#160;&#160;&#160; BEGIN<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; IF (SELECT&#160; COUNT(*)<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; FROM&#160;&#160;&#160; Grid<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHERE&#160;&#160; @x = x<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AND @y = y<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AND S = -100<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ) = 0 &#8211;Check if a square is flagged<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; IF (SELECT&#160; COUNT(*)<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; FROM&#160;&#160;&#160; Mine<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHERE&#160;&#160; @x = x<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AND @y = y<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ) = 0 &#8211;Check if there&#8217;s a mine<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; BEGIN<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; DECLARE @count INT<\/p>\n<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; SET @count = (SELECT&#160;&#160;&#160; COUNT(*)<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; FROM&#160;&#160;&#160;&#160;&#160; (SELECT x,<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; y<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; FROM&#160;&#160; Mine<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHERE&#160; x &#8211; @x BETWEEN -1 AND 1<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AND y &#8211; @y BETWEEN -1 AND 1<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; GROUP BY x,<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; y<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ) subset<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;) <\/p>\n<p>&#8211;Count the number of mines in the vicinity<\/p>\n<\/p>\n<p>&#8211;Update the square to the number of mines in the vicinity<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; UPDATE&#160; Grid<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; SET&#160;&#160;&#160;&#160; S = @count<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHERE&#160;&#160; x = @x<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AND y = @y<\/p>\n<div>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <\/div>\n<p>\/* Here&#8217;s where the fun starts! In another language you would probably use recursion to solve this square by square, but with a single update you can explore multiple squares that you know are safe. It&#8217;s probably possible to do this in a single update instead of the 3 sequential updates, but I&#8217;ll leave that up to someone else. *\/<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; DECLARE @BlankSquares INT<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; IF @count = 0 <\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; SET @BlankSquares = 1<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHILE @BlankSquares &gt; 0 <\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; BEGIN<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; EXEC p_MarkSafeSquares<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; EXEC p_ExploreSafeSquares @BlankSquares OUTPUT<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; END<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; END<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ELSE <\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8211;A mine was hit!<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; UPDATE&#160; Grid<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; SET&#160;&#160;&#160;&#160; S = 9<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHERE&#160;&#160; x = @x<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AND y = @y<\/p>\n<p>&#160;&#160;&#160; END<\/p>\n<\/p>\n<p>GO<\/p>\n<\/p>\n<p>CREATE PROCEDURE p_GameState<\/p>\n<div>\/* Showing the gamestate *\/ <\/div>\n<p>AS <\/p>\n<p>&#160;&#160;&#160; BEGIN<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; DECLARE @NumberOfMines INT<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; DECLARE @MaxX INT<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; DECLARE @MaxY INT<\/p>\n<p>&#160;&#160;&#160;&#160;&#160; <\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; SELECT&#160; @NumberOfMines = NumberOfMines,<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; @MaxX = MaxX,<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; @MaxY = MaxY<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; FROM&#160;&#160;&#160; Settings<\/p>\n<p>&#160;&#160;&#160;&#160;&#160; <\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; DECLARE @SquaresExplored INT,<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; @MinesExploded INT,<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; @SquaresFlagged INT<\/p>\n<p>&#160;&#160;&#160;&#160;&#160; <\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; SELECT&#160; @SquaresExplored = SUM(CASE WHEN S BETWEEN 0 AND 8 THEN 1<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ELSE 0<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; END),<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; @MinesExploded = SUM(CASE WHEN S = 9 THEN 1<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ELSE 0<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; END),<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; @SquaresFlagged = SUM(CASE WHEN S = -100 THEN 1<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ELSE 0<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; END)<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; FROM&#160;&#160;&#160; Grid<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; <\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; SELECT&#160; @SquaresExplored AS SquaresExplored,<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; @MinesExploded AS MinesExploded,<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; @SquaresFlagged AS SquaresFlagged,<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; @NumberOfMines AS NumberOfMines,<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; @MaxX * @MaxY AS TotalSquares,<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; CASE WHEN @MinesExploded &gt; 0 THEN &#8216;You lost!&#8217;<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHEN @SquaresExplored + @NumberOfMines = @MaxX * @MaxY<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; THEN &#8216;You won!&#8217;<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ELSE &#8216;Keep on playing!&#8217;<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; END AS GameState&#160;&#160;&#160;&#160;&#160; <\/p>\n<p>&#160;&#160;&#160; END<\/p>\n<\/p>\n<p>GO<\/p>\n<\/p>\n<p>CREATE PROCEDURE p_flag (@X INT, @Y INT)<\/p>\n<div>\/* A procedure to flag\/unflag an unknown square as suspect *\/ <\/div>\n<p>AS <\/p>\n<p>&#160;&#160;&#160; BEGIN<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; UPDATE&#160; Grid<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; SET&#160;&#160;&#160;&#160; S = CASE WHEN S = -1 THEN -100&#160; &#8211;Flag when unknown<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHEN S = -100 THEN -1&#160; &#8211;Unflag when flagged<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ELSE S&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8211;Otherwise no change<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; END<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHERE&#160;&#160; @x = X<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AND @y = y<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <\/p>\n<p>&#160;&#160;&#160; END<\/p>\n<\/p>\n<p>GO<\/p>\n<\/p>\n<p>CREATE PROCEDURE E (@X INT, @Y INT)<\/p>\n<div>\/* A procedure with a very short name to play the game. E for Explore *\/ <\/div>\n<p>AS <\/p>\n<p>&#160;&#160;&#160; BEGIN<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; EXEC p_Explore @X, @Y<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; EXEC p_Draw<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; EXEC p_GameState<\/p>\n<p>&#160;&#160;&#160; END<\/p>\n<\/p>\n<p>GO<\/p>\n<\/p>\n<p>CREATE PROCEDURE F (@X INT, @Y INT)<\/p>\n<div>\/* A procedure with a very short name to play the game. F for Flag *\/ <\/div>\n<p>AS <\/p>\n<p>&#160;&#160;&#160; BEGIN<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; EXEC p_Flag @X, @Y<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; EXEC p_Draw<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; EXEC p_GameState<\/p>\n<p>&#160;&#160;&#160; END<\/p>\n<\/p>\n<p>GO<\/p>\n<\/p>\n<p>CREATE PROCEDURE p_Solve1<\/p>\n<div>\/* It&#8217;s quite easy to write SQL statements to help clear the minefield. This one flags the only non-explored square next to a 1. *\/ <\/div>\n<p>AS <\/p>\n<p>&#160;&#160;&#160; UPDATE&#160; Grid<\/p>\n<p>&#160;&#160;&#160; SET&#160;&#160;&#160;&#160; S = -100<\/p>\n<p>&#160;&#160;&#160; FROM&#160;&#160;&#160; (SELECT<\/p>\n<p>&#160;&#160;&#160;&#160;&#160; DISTINCT&#160;&#160;&#160;&#160;&#160; x2,<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; y2<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; FROM&#160;&#160; (SELECT x1,<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; y1,<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; MAX(x2) x2,<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; MAX(y2) y2<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; FROM&#160;&#160; (SELECT g1.x AS x1,<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; g1.y AS y1,<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; g2.x AS x2,<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; g2.y AS y2<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; FROM&#160;&#160; grid g1<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; INNER JOIN grid g2 ON g1.x &#8211; g2.X BETWEEN -1 AND 1<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;AND g1.y &#8211; g2.y BETWEEN -1 AND 1<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WHERE&#160; g1.S = 1<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AND g2.S IN (-1, -100)<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ) s1<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; GROUP BY x1,<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; y1<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; HAVING COUNT(*) = 1<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ) s2<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ) s3<\/p>\n<p>&#160;&#160;&#160; WHERE&#160;&#160; grid.x = s3.x2<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AND grid.y = s3.y2<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AND grid.s = -1<\/p>\n<p>GO<\/p>\n<\/p>\n<p>EXEC p_Initialize 10, 10, 10, 10<\/p>\n<p>EXEC e 1, 1<\/p>\n<div><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1132-Minesweeper1.jpg\" width=\"520\" height=\"515\" alt=\"1132-Minesweeper1.jpg\" \/><\/p>\n<p>&#8211;the rest of the solution to &#8216;p_Initialize 10, 10, 10, 10&#8217; <\/p><\/div>\n<div>\/*<br \/>EXEC e 7, 6 <\/div>\n<p>EXEC f 8, 3 <\/p>\n<p>EXEC e 8, 4 <\/p>\n<p>EXEC e 9, 3<\/p>\n<div class=\"float-right\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1132-img1C.gif\" alt=\"1132-img1C.gif\" \/><br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; \/* &#8220;You lost&#8221; *\/<\/div>\n<p>EXEC f 10, 1 <\/p>\n<p>EXEC e 10, 2<\/p>\n<p>EXEC e 10, 3<\/p>\n<p>EXEC f 7, 5<\/p>\n<p>EXEC e 8, 5<\/p>\n<p>EXEC f 9, 5<\/p>\n<p>EXEC e 5, 6<\/p>\n<p>EXEC e 6, 6<\/p>\n<p>EXEC f 4, 6<\/p>\n<p>EXEC e 3, 6<\/p>\n<p>EXEC f 2, 6<\/p>\n<p>EXEC e 1, 6<\/p>\n<p>EXEC e 6, 7<\/p>\n<p>EXEC e 5, 7<\/p>\n<p>EXEC e 4, 7<\/p>\n<p>EXEC e 3, 7<\/p>\n<p>EXEC e 3, 8<\/p>\n<p>EXEC e 4, 8<\/p>\n<p>EXEC f 2, 7<\/p>\n<p>EXEC e 1, 7<\/p>\n<p>EXEC f 10, 8<\/p>\n<p>EXEC e 8, 7<\/p>\n<p>EXEC e 9, 7<\/p>\n<p>EXEC e 10, 7<\/p>\n<p>EXEC f 7, 7<\/p>\n<p>EXEC f 8, 6<\/p>\n<p>EXEC e 10, 5<\/p>\n<p>EXEC e 10, 6<\/p>\n<p>EXEC e 9, 6<\/p>\n<p>*\/<\/p>\n<\/p>\n<p>&#8211;A bigger one<\/p>\n<p>\/*<\/p>\n<p>EXEC p_Initialize 30, 30, 60, 10<\/p>\n<p>exec e 1,1<\/p>\n<p>*\/<\/p>\n<\/p>\n<p>&#8211;A really big one, with only a few mines, to see how long it takes the &#8216;auto explore&#8217; to clear the field. (about 32 sec on my PC)<\/p>\n<p>\/*<\/p>\n<p>EXEC p_Initialize 50, 50, 10, 10<\/p>\n<p>EXEC e 1,1<\/p>\n<p>*\/<\/p>\n<div>\/* Although there are situations where the field can&#8217;t be cleared without guessing a lot can probably solved with procedures like p_Solve1. It might even be possible to have a procedure make an educated guess.<\/p>\n<p><strong>Competition:<\/strong> <\/div>\n<\/p>\n<p>Create a series of procedures that can solve a multitude of grids. Submit them as comments to this article. (forget the pretty formatting, this happens later) &#160;They will be judged on effectiveness, creativity and style!&#160; The winner will get a license for SQL Prompt Pro, or SQL Data Generator, whichever they prefer *\/<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Whatever happened to the idea that programming in TSQL can be fun? A Simple-Talk reader contributes an article to remind us all that there is more to TSQL than wrestling with DMVs and pumelling recalcitrant correlated subqueries.&hellip;<\/p>\n","protected":false},"author":14783,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143531],"tags":[4150,4183,4252,4190],"coauthors":[],"class_list":["post-983","post","type-post","status-publish","format-standard","hentry","category-t-sql-programming-sql-server","tag-sql","tag-t-sql","tag-t-sql-programming","tag-tsql"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/983","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/14783"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=983"}],"version-history":[{"count":5,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/983\/revisions"}],"predecessor-version":[{"id":92546,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/983\/revisions\/92546"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=983"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=983"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=983"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=983"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}