Generating the grid is simple. There are a couple simple algorithms that you need when executing the player's move, to determine which squares to open up and whether they have lost or won.
Generating the grid
The simplest algorithm is to place all of the mines randomly. (Make sure you don't overlap them!)
Problem: The player's first click might be a mine.
Improvement: Delay the generation of the grid until the user clicks on the first square, and don't put any mines in that square.
Problem: The player's first click might reveal a non-zero number, and they will be forced to click randomly until something opens up.
Improvement: Don't generate any mines in the (up to) eight squares around the first click, either.
Problem: The player might be forced to guess at some point, making this a sad excuse for a logic puzzle.
Improvement: Run the solver alongside the generator, making sure that the puzzle has a unique solution. This takes some cleverness, and isn't done in most variants.
Another, less common way to resolve ambiguities is to detect when the player knows they are choosing between equally likely possibilities and "collapse the waveform" into the position they decided on. I have never seen this in action, but it would be kind of fun.
Playing the game
Besides marking flags, the player can make two kinds of moves to attempt to uncover squares:
Single guess: The player clicks on a square with unknown state and no flag. Reveal the square, see if the player died, and put a number in it. If the square contains a 0, repeat this recursively for all the surrounding squares. This should be in a dedicated function, to separate it from the GUI's event handler, to make the recursion easy, and because it's reused in the multiguess.
Multiguess: The player clicks on a square that is uncovered and known to be safe. If the number of flags surrounding equals the number in this square, we open up the unflagged squares using the same procedure as above.
Winning the game
If the number of squares that are covered up is the same as the number of mines, then the player has won, even if they haven't placed a flag on every square.
When the player loses, it is customary to mark any incorrect guesses that they made, the remaining mines, and the mine that they stepped on.
As Henri mentioned, the correct way of solving minesweeper is with mathematics, specifically Linear Algebra Matrix mathematics for the deterministic part. I have a whole post here that:
explains how that method works
has working code that you can compile and run on any platform
contains the code to make the game and a solver too
I would recommend reading through that and then having a good thought about it. The probabilistic part of Minsweeper can be solved using statistics too but I don't have a good plan for that yet. However, other people have looked into it too.
I just want to add the following if you try to write a solver - Minesweeper is NP complete (Archive Link). That means until someone proves P = NP it might be possible that you can do nothing better then performing a brute force search in some situations (but maybe the game it is not NP complete for small fields).
I'm definitely not a minesweeper expert, but here's the algorithm I use when I try to solve it:
Go over all the squares that are the border of the revealed area. For each of these squares, count the number of mines you have revealed next to it. subtract the number that is written in the square (the true number of mines that are around it). That is the number of unrevealed mines left around this square. Divide that by the number of unrevealed squares around the current square. That is the probability of each of the adjacent square containing a mine. If any square has a probability of 1, you mark it as a mine. If any square has a probability of 0 you mark it as safe. Then you update the relevant numbers.
What do you do if no square has probability 0 or 1? An optimal algorithm would take into consideration constraints from multiple squares. But as a I wrote in the begining, I'm not a minesweeper expert, so I choose randomly from the other squares that has probability closest to 0 or to 1.
The comments are that you don't need an algorithm to build the game. I believe you mean an algorithm in the sense of solving and everyone might be understanding it that way as well.
However any solution to a problem can be considered an algorithm.
Like most math problems you can dissect the whole algorithm into smaller less complex algorithms, until you get down to something small enough to solve. This will get you the first correct solution. Later you can optimize the smaller algorithms in the context of the whole algorithm.
The gameboard can be thought of as a 2 dimensional array. You will have an algorithm associated with each operation. The first operation would probably be a randomly generated set of mine locations with x, y coordinates with a parameter of the number of mines and size of board. You would have another algorithm associated with revealing a square, which takes the board and a location and determines how many mines are adjacent to it. The final algorithm would take the board and check if any squares without mines are left to reveal.
Now you can take each of these algorithms and attempt to optimize each of them for better performance and say "what's the best way to count the squares with mines adjacent to a current square, given a 2 dimensional array using x,y coordinates.
Any position on the board, that cant be solved intuitively with the monkey-reasoning is a matrix that could be able to solve some individual(or the whole position) squares which can lead to better solving rates. Simple random guessing didn't produce good results. I implemented this method into my solving algorithm in C++ by adding a linear system of equations-solver. I am researching the difficulcy of Minesweeper by running tens of thousands games through the algorithm and doing statistics.
My algorithm solves upto 85% of (9,9,10) easy level minesweepers. I haven't yet ran complete tests on other difficulcy levels, but smaller tests suggest that medium level (16,16,40) has a solving rate of 55-60 % and Hard level(30,16,99) as low as 5-10%. I am going to add a few new things that would make it most optimal.
发布评论
评论(8)
生成网格很简单。在执行玩家的移动时,您需要一些简单的算法来确定要打开哪些方格以及他们是否输了或赢了。
生成网格
最简单的算法是随机放置所有地雷。 (确保不要重叠它们!)
问题:玩家的第一次点击可能是地雷。
改进:延迟生成网格,直到用户单击第一个方块,并且不要在该方块中放置任何地雷。
问题:玩家的第一次点击可能会显示一个非零数字,他们将被迫随机点击,直到出现一些东西。
改进:也不要在第一次点击周围的(最多)八个方格内生成任何地雷。
问题:玩家可能会被迫在某个时刻进行猜测,这成为逻辑谜题的一个可悲的借口。
改进:与生成器一起运行求解器,使得确保谜题有独特的解决方案。这需要一些技巧,但在大多数变体中都没有做到。
另一种不太常见的解决歧义的方法是检测玩家何时知道他们正在同等可能的可能性之间进行选择,并将波形“折叠”到他们决定的位置。我从来没有见过这个动作,但这会很有趣。
玩游戏
除了标记旗帜之外,玩家还可以采取两种动作来尝试揭开方块:
单次猜测: 玩家单击状态未知且没有旗帜的方块。揭示方块,看看玩家是否死亡,并在其中输入一个数字。如果该方块包含 0,则对所有周围的方块递归地重复此操作。这应该在一个专用函数中,将其与 GUI 的事件处理程序分开,使递归变得容易,并且因为它在多重猜测中重用。
多重猜测:玩家点击一个未被覆盖且已知安全的方块。如果周围的旗帜数量等于该方格中的数量,我们将使用与上述相同的过程打开未标记的方格。
赢得游戏
如果被覆盖的方格数量与地雷数量相同,那么玩家就获胜,即使他们没有在每个方格上放置旗帜。
当玩家输了时,习惯上会标记他们做出的任何错误猜测、剩余的地雷以及他们踩到的地雷。
Generating the grid is simple. There are a couple simple algorithms that you need when executing the player's move, to determine which squares to open up and whether they have lost or won.
Generating the grid
The simplest algorithm is to place all of the mines randomly. (Make sure you don't overlap them!)
Problem: The player's first click might be a mine.
Improvement: Delay the generation of the grid until the user clicks on the first square, and don't put any mines in that square.
Problem: The player's first click might reveal a non-zero number, and they will be forced to click randomly until something opens up.
Improvement: Don't generate any mines in the (up to) eight squares around the first click, either.
Problem: The player might be forced to guess at some point, making this a sad excuse for a logic puzzle.
Improvement: Run the solver alongside the generator, making sure that the puzzle has a unique solution. This takes some cleverness, and isn't done in most variants.
Another, less common way to resolve ambiguities is to detect when the player knows they are choosing between equally likely possibilities and "collapse the waveform" into the position they decided on. I have never seen this in action, but it would be kind of fun.
Playing the game
Besides marking flags, the player can make two kinds of moves to attempt to uncover squares:
Single guess: The player clicks on a square with unknown state and no flag. Reveal the square, see if the player died, and put a number in it. If the square contains a 0, repeat this recursively for all the surrounding squares. This should be in a dedicated function, to separate it from the GUI's event handler, to make the recursion easy, and because it's reused in the multiguess.
Multiguess: The player clicks on a square that is uncovered and known to be safe. If the number of flags surrounding equals the number in this square, we open up the unflagged squares using the same procedure as above.
Winning the game
If the number of squares that are covered up is the same as the number of mines, then the player has won, even if they haven't placed a flag on every square.
When the player loses, it is customary to mark any incorrect guesses that they made, the remaining mines, and the mine that they stepped on.
正如亨利提到的,解决扫雷问题的正确方法是使用数学,特别是确定性部分的线性代数矩阵数学。我在这里有一整篇文章:
您可以在这里看到所有内容:https://massaioli.wordpress.com/2013/01/12/solving-minesweeper-with -matricies/
我建议通读一遍,然后好好思考一下。 Minsweeper 的概率部分也可以使用统计来解决,但我还没有一个好的计划。然而,其他人也对此进行了研究。
As Henri mentioned, the correct way of solving minesweeper is with mathematics, specifically Linear Algebra Matrix mathematics for the deterministic part. I have a whole post here that:
You can see that all here: https://massaioli.wordpress.com/2013/01/12/solving-minesweeper-with-matricies/
I would recommend reading through that and then having a good thought about it. The probabilistic part of Minsweeper can be solved using statistics too but I don't have a good plan for that yet. However, other people have looked into it too.
如果您尝试编写求解器,我只想添加以下内容 - 扫雷是 NP 完整的(存档链接)。这意味着,除非有人证明P = NP,否则您可能无法做任何比执行更好的事情在某些情况下进行强力搜索(但对于小域来说,游戏可能不是 NP 完全的)。
I just want to add the following if you try to write a solver - Minesweeper is NP complete (Archive Link). That means until someone proves P = NP it might be possible that you can do nothing better then performing a brute force search in some situations (but maybe the game it is not NP complete for small fields).
我绝对不是扫雷专家,但这是我在尝试解决该问题时使用的算法:
遍历显示区域边界的所有方块。对于每个方格,计算您在其旁边发现的地雷数量。减去写在方格中的数字(周围地雷的真实数量)。这是这个广场周围剩余的未发现地雷的数量。将其除以当前方块周围未显示的方块数量。这就是每个相邻方格包含地雷的概率。如果任何方格的概率为 1,则将其标记为地雷。如果任何方格的概率为 0,则将其标记为安全。然后更新相关数字。
如果没有方格的概率为 0 或 1,你会怎么做?最佳算法将考虑多个方格的约束。但正如我在开头所写的,我不是扫雷专家,所以我从概率最接近 0 或 1 的其他方格中随机选择。
I'm definitely not a minesweeper expert, but here's the algorithm I use when I try to solve it:
Go over all the squares that are the border of the revealed area. For each of these squares, count the number of mines you have revealed next to it. subtract the number that is written in the square (the true number of mines that are around it). That is the number of unrevealed mines left around this square. Divide that by the number of unrevealed squares around the current square. That is the probability of each of the adjacent square containing a mine. If any square has a probability of 1, you mark it as a mine. If any square has a probability of 0 you mark it as safe. Then you update the relevant numbers.
What do you do if no square has probability 0 or 1? An optimal algorithm would take into consideration constraints from multiple squares. But as a I wrote in the begining, I'm not a minesweeper expert, so I choose randomly from the other squares that has probability closest to 0 or to 1.
这是我的扫雷求解器:
这里是一个实际的实现,注意它使用子集规则,这个规则更难解释
https://github.com/SHiNKiROU /Minesweeper/blob/master/src/org/shinkirou/minesweeper/MinesweeperSolver.java#L27
当然,我的算法有时会失败。我计划实现一个 Prolog 风格的回溯求解器
Here is my minesweeper solver:
Here is an actual implementation, notice it used the subset rule, which is harder to explain
https://github.com/SHiNKiROU/Minesweeper/blob/master/src/org/shinkirou/minesweeper/MinesweeperSolver.java#L27
Of course, my algorithm can fail sometimes. I'm planning to implement a Prolog-style backtracking solver
评论是你不需要算法来构建游戏。我相信你指的是解决问题意义上的算法,每个人也可能都是这样理解的。
然而,任何问题的解决方案都可以被视为一种算法。
像大多数数学问题一样,您可以将整个算法分解为更小的、不太复杂的算法,直到您找到足够小的问题来解决。这将为您提供第一个正确的解决方案。稍后您可以在整个算法的上下文中优化较小的算法。
游戏板可以被认为是一个二维数组。您将拥有与每个操作相关的算法。第一个操作可能是随机生成的一组地雷位置,其中 x、y 坐标以及地雷数量和棋盘尺寸参数。您将有另一种与揭示方块相关的算法,该算法采用棋盘和位置并确定与其相邻的地雷数量。最终的算法将在棋盘上检查是否有任何没有地雷的方块被留下来揭示。
现在,您可以采用这些算法中的每一个,并尝试优化它们以获得更好的性能,并说“给定一个使用 x,y 坐标的二维数组,计算当前方格附近有地雷的方格的最佳方法是什么。
The comments are that you don't need an algorithm to build the game. I believe you mean an algorithm in the sense of solving and everyone might be understanding it that way as well.
However any solution to a problem can be considered an algorithm.
Like most math problems you can dissect the whole algorithm into smaller less complex algorithms, until you get down to something small enough to solve. This will get you the first correct solution. Later you can optimize the smaller algorithms in the context of the whole algorithm.
The gameboard can be thought of as a 2 dimensional array. You will have an algorithm associated with each operation. The first operation would probably be a randomly generated set of mine locations with x, y coordinates with a parameter of the number of mines and size of board. You would have another algorithm associated with revealing a square, which takes the board and a location and determines how many mines are adjacent to it. The final algorithm would take the board and check if any squares without mines are left to reveal.
Now you can take each of these algorithms and attempt to optimize each of them for better performance and say "what's the best way to count the squares with mines adjacent to a current square, given a 2 dimensional array using x,y coordinates.
检查一下:http://quantum-p.livejournal.com/19616.html
任何棋盘上的位置,不能用猴子推理直观地解决,是一个矩阵,可以解决一些单独的(或整个位置)方格,这可以带来更好的解决率。简单的随机猜测并不能产生好的结果。
我通过添加线性方程组求解器将该方法实现到我的 C++ 求解算法中。我正在通过算法运行数万个游戏并进行统计来研究扫雷的难度。
我的算法可以解决高达 85% 的 (9,9,10) 简单级别的扫雷游戏。我还没有对其他难度级别进行完整的测试,但较小的测试表明中等级别(16,16,40)的解决率为 55-60%,困难级别(30,16,99)低至 5 -10%。我将添加一些新内容以使其达到最佳状态。
Check this: http://quantum-p.livejournal.com/19616.html
Any position on the board, that cant be solved intuitively with the monkey-reasoning is a matrix that could be able to solve some individual(or the whole position) squares which can lead to better solving rates. Simple random guessing didn't produce good results.
I implemented this method into my solving algorithm in C++ by adding a linear system of equations-solver. I am researching the difficulcy of Minesweeper by running tens of thousands games through the algorithm and doing statistics.
My algorithm solves upto 85% of (9,9,10) easy level minesweepers. I haven't yet ran complete tests on other difficulcy levels, but smaller tests suggest that medium level (16,16,40) has a solving rate of 55-60 % and Hard level(30,16,99) as low as 5-10%. I am going to add a few new things that would make it most optimal.
您看过这个游戏的 C# 实现吗?源代码可下载,并解释了对象模型。
Have you seen this C# implementation of the game? The source code is downloadable, and the object model is explained.