On Tuesday 27 February 2001 16:50, you wrote:
> your "ballremoving" routine was very nice, but actually I only want the
> balls to be removed, if there are 3 or more balls
> connected to eachother horizontally, vertically or diagonally.. (and if
> some of these balls have neighbours with the same
> color, they have to be removed too)
OK, it can be fixed.
The first step, calculating representants using union-find, is unmodified.
After this step you know all the groups. The group size is no longer
relevant, so the old second step is scrapped, as well as the old third step.
The new second step is to search for lines of 3 balls on a row, you can do
this easily by doing a linear search for every ball in 4 directions:
right-up, right, right-down, down (or 4 other directions, as long as they
represent the entire 8-direction star). You can do the search using a single
routine, with delta-x and delta-y as parameters.
Example: ("o" is the ball in question, "x" are balls searched, "-" are balls
not seached)
- - - - x
- - - x -
- - o x x
- - x x -
- - x - x
You don't have to search every direction because they are searched from the
ball on the other end of the line. (A line walked in the opposite direction
is still the same line, no need to check it twice.)
A simple trick is to use sentinels: mark the edge of the playing field with
balls of a color that doesn't occur in the game. Now you no longer have to
check for the coordinates being outside the playing field, instead you can
rely on the fact that no line will ever extend beyond the border of sentinel
balls.
Example: (this is the bottom part of a playing field)
9 1 2 2 3 4 9
9 2 1 2 4 3 9
9 2 2 1 4 1 9
9 9 9 9 9 9 9
Here the balls of color 9 are the sentinels. They also help in other places.
For example, gravity doesn't cause balls to fall out of the playing field,
because the lower line of sentinels will stop them (no coordinate checking
necessary). Also, the side walls form barriers when calculating whether a
sideways move (by the player) is possible.
If balls diagonally connected to a line of balls are neighbours, you only
have to search for lines of length 3. If balls are only considered neighbours
if they are horizontally or vertically next to a line, you should search for
the longest possible line.
All balls on the line are marked for removal, as well as all balls in the
same groups as these balls. An easy way to implement this is as follows:
Step 3a: for every ball on the line, mark its representant for removal.
Step 3b: for every ball, check if the representant is marked for removal, if
it is, mark the ball itself for removal as well.
There is a very useful optimization you can use: once you have all the
datastructures for the current game field, re-use them when the next balls
are dropped. You don't have to recalculate everything, you can apply the
group calculation and the line searching only for each of the new balls. Note
that in this case you do have to search lines in 8 directions, searching half
of them is no longer sufficient because there is no search initiated from the
balls on the other end of the line.
Whenever you remove balls, you will have to recalculate everything. However,
a game typically displays an animation when this happens, so you'll have some
spare CPU time to do the calculation.
Bye,
Maarten
--
For info, see http://www.stack.nl/~wynke/MSX/listinfo.html