Game Development Reference
In-Depth Information
There is a design decision in the code that the comments point out. We take the
first helper who can help and go with it. It is possible that a different helper could
come up with more moves for the original square. Rather than evaluate them all,
we go with the first one that qualifies. The match portion of a rule needs to be
computationally efficient because the framework will run it often.
That completes the rule. The rule will never run if we fail to put it into the
framework. Find the PlayingField Load event handler and add the following line
after the first one:
Run the code. After you get a game started, you can chase the perimeter by madly
right-clicking revealed squares. Slow down and watch carefully, and you will see
the two-square rule fire and leave a single-square move that another right-click
will pick up. If the game ever steps on a mine, you have a bug or the player has
manually flagged a safe square. Look at the thoughts output to make sure that the
first rule with the most squares is the one that executes. That way, we know that
the framework is working properly.
Play a number of games using the AI as much as possible. How much fun is
Minesweeper now? Is the AI too smart or not smart enough?
The AI can still use more help. If you think about it, you may realize that the
helper square does not have to come from the directly adjacent squares (usually
eight of them). The helper could be from one of the squares surrounding the
directly adjacent squares. There are usually 16 such surrounding squares. The
original square and the helper will have common squares directly between them.
If one or more of these are blank, and the original square has other private blanks,
the same method works from farther away.
All we need is access to the next outer ring of neighbors. Switch to the Code view
of PlayingField.vb and find the NearNeighbors code. We need a different set of
offsets for the new neighbors. Add the following to the class file:
Private FarNeighborOffsets() As Point = { _
New Point(-2, -2), New Point(-2, -1), New Point(-2, 0), _
New Point(-2, 1), New Point(-2, 2), _
New Point(-1, -2), New Point(-1, 2), _
New Point(0, -2), New Point(0, 2), _