
-----------------------------------
cavetroll
Wed Jul 25, 2007 11:26 pm

Minesweeper help
-----------------------------------
I have a working minesweeper game except for the one feature that is in the windows version. You know when you click a place that has empty spaces all around it shows all the empty places around it. How do I do that, I have researched pathfinding algorithms and have been thinking about ways to modify them. Any source is greatly appreciated.

-----------------------------------
Saad
Thu Jul 26, 2007 2:53 am

RE:Minesweeper help
-----------------------------------
It isnt pathfinding. The algorithm is that for the current cell, if the number of mines around it is not 0 then halt and show the current block, If the value of the current block is > 0 then show the current cell, and for every cell around it call the same algorithm.

-----------------------------------
McKenzie
Thu Jul 26, 2007 7:16 am

Re: Minesweeper help
-----------------------------------
Try looking at the "flood-fill" algorithm, it is a very similar problem.

-----------------------------------
cavetroll
Thu Jul 26, 2007 11:38 am

Re: Minesweeper help
-----------------------------------
Thanks for the quick responses, and yes you were right I wasn't looking for pathfinding but I didn't know the proper term for what I was looking for. I looked up flood-fill algorithms and found how to do it. Again thanks for the response.

-----------------------------------
cavetroll
Thu Jul 26, 2007 12:17 pm

Re: Minesweeper help
-----------------------------------
Sorry I thought I had it but now I can't get the code to work, I am not sure why I tried to do it using recursion(proc floodfill (nodex : int, nodey : int)
    if squares (nodex, nodey, typ) not= 2 then
        return
    else
        squares (nodex, nodey, state) := 2
        for decreasing i : 1 .. -1
            for ii : -1 .. 1
                if nodex - i > 0 and nodex - i < 19 and nodey - ii > 0 and nodey - ii < 19 then
                    if i not= 0 and ii not= 0 then
                        floodfill (nodex - i, nodey - ii)
                    end if
                end if
            end for
        end for
        return
    end if
end floodfillbut it isn't working. Any Ideas?

-----------------------------------
Aziz
Thu Jul 26, 2007 12:23 pm

RE:Minesweeper help
-----------------------------------
There's a recursive and iterative method. I can post  more help later on, when I'm not so swamped at work.

-----------------------------------
Saad
Thu Jul 26, 2007 5:21 pm

RE:Minesweeper help
-----------------------------------
Cant diagnose based on the code you have, What error are you getting?

-----------------------------------
cavetroll
Thu Jul 26, 2007 7:08 pm

Re: Minesweeper help
-----------------------------------
No error messages the code just doesn't do what it is intended to do. Have you read the earlier posts? They explain what the code is supposed to do but it doesn't work. I am just trying to figure out where it went wrong.

-----------------------------------
CodeMonkey2000
Thu Jul 26, 2007 8:35 pm

RE:Minesweeper help
-----------------------------------
How have you implemented your minesweeper game?

-----------------------------------
cavetroll
Fri Jul 27, 2007 12:34 am

Re: Minesweeper help
-----------------------------------
I can post the code if you want but it is very messy right now so I'd rather not, but basically I have an array(squares(1..18,1..18,1..3)) which stores the data(count, type, state) for every square. When the square is click the state value is changed to 2 if it is left-clicked and 3 if it is right-clicked. Then I draw accordingly. The code given is what I want to run if the square clicked has a count of 0. Post if this doesn't help.

-----------------------------------
Saad
Fri Jul 27, 2007 4:05 am

RE:Minesweeper help
-----------------------------------
That alogorithm seems right, only problem I can see is that every square will have set to 2. Since it only checks if that square is 2 because of this all squares will end up as 2. 
You want to check the amount of mines around the current cell aswell. If its not= 0 then return

-----------------------------------
Aziz
Fri Jul 27, 2007 7:50 am

RE:Minesweeper help
-----------------------------------
I can see a major problem in your logic.

Why does your array have three dimensions? Array indices should represent position, not value. Then value is store in a position of an array. So it does not make sense to have a 3D array for Minesweeper. If a user clicks a square, it changes the state, which changes the position, not the value.

What you should do is have a 2D array to store the state. I'm assume the array values already hold whether the square holds a mine or not? So squares(x,y,s) is 0 for mine, 1 for clear?

There's to approaches you could make. Both involved store both the state and the mine/not-mine data in the array (actually, you COULD have parallel arrays, but I'm not even going to bring it up to do horribleness)

1:

The value store at a position (x,y) in the array would be an integer. 1,2,3 would be the state. a negative would represent a mine

So  a state of 1 would be (I'm assuming) a non-clicked square the is empty. A square with state of -1 would be a non-clicked square that contains a mine.

2: Better, IMO

Declare a type like so:

type block
   record of
      state : int
      mine : boolean
   end record(at least i think thats the right syntax)

and have an array to store the blocks:

var squares : array 1 .. 10, 1 .. 10 of block

for x : 1 .. 10
   for y : 1 .. 10
      squares(x,y).state = 1
      squares(x,y).mine = false
   end for
end for

-----------------------------------
cavetroll
Fri Jul 27, 2007 1:54 pm

Re: Minesweeper help
-----------------------------------
I think you misinterpreted what I said, if not I misinterpreted your message. I have 3 dimensions because the first 2 hold the x and y position on the grid. the second one stores state(whether it has been left or right clicked), count(how many mines are around this square), and type(whether it is a mine(1) or non-mine square(2)). These are accessed using the constants state, count, and typ. All squares start with the state value of 1(2 is left clicked, 3 is right clicked). the count value is different for each square.

-----------------------------------
Aziz
Fri Jul 27, 2007 2:01 pm

RE:Minesweeper help
-----------------------------------
Could you post your source code?

An array's indices should only represent position.

Having an array with indices (x, y, state) represents squares in terms of x,y and state positions

each state (1,2,3) is a different value. The line squares (nodex, nodey, state) := 2 is "set the square at x position nodex, y position nodey, and state position state to 2. It does not mean set the state of square x,y to 2.

Its a bit confounding, so please post your source code and I can better understand it.

-----------------------------------
cavetroll
Fri Jul 27, 2007 2:46 pm

Re: Minesweeper help
-----------------------------------
K here's the code, 

buttonchoose ("multibutton")
setscreen ("graphics:max,max")
const typ : int := 1
const count : int := 2
const state : int := 3
var xback, xfor, yback, yfor : int := 0
var font : int := Font.New ("Arial:20")
var mines : int := 0
var squares : array 1 .. 18, 1 .. 18, 1 .. 3 of int
var x, y, bud, btn : int
proc floodfill (nodex : int, nodey : int) 
    if squares (nodex, nodey, typ) not= 2 then 
        return 
    else 
        squares (nodex, nodey, state) := 2 
        for decreasing i : 1 .. -1 
            for ii : -1 .. 1 
                if nodex - i > 0 and nodex - i < 19 and nodey - ii > 0 and nodey - ii < 19 then 
                    if i not= 0 and ii not= 0 then 
                        floodfill (nodex - i, nodey - ii) 
                    end if 
                end if 
            end for 
        end for 
        return 
    end if 
end floodfill
      
loop
    mines := 0
    for i : 1 .. 18
        for ii : 1 .. 18
            squares (i, ii, count) := 0
            if mines = 75 then
                squares (i, ii, typ) := 2
            else
                squares (i, ii, typ) := Rand.Int (1, 6)
                if squares (i, ii, typ) > 1 then
                    squares (i, ii, typ) := 2
                end if
            end if
            if squares (i, ii, typ) = 1 then
                mines += 1
            end if
            squares (i, ii, state) := 1
        end for
    end for
    exit when mines = 75
end loop
for i : 1 .. 18
    for ii : 1 .. 18
        if squares (i, ii, typ) = 2 then
            for t : -1 .. 1
                for tt : -1 .. 1
                    if i + t > 0 and i + t < 19 and ii + tt > 0 and ii + tt < 19 then
                        if squares (i + t, ii + tt, typ) = 1 then
                            squares (i, ii, count) += 1
                        end if
                        if squares (i, ii, count) = 0 then
                            squares (i, ii, state) := 1
                        else
                            squares (i, ii, state) := 1
                        end if
                    end if
                end for
            end for
        end if
    end for
end for
loop
    for i : 1 .. 18
        for ii : 1 .. 18
            drawfillbox (i * 25, ii * 25, i * 25 + 25, ii * 25 + 25, 29)
            drawbox (i * 25, ii * 25, i * 25 + 25, ii * 25 + 25, 7)
            if squares (i, ii, state) = 2 then
                if squares (i, ii, typ) = 2 then
                    Font.Draw (intstr (squares (i, ii, count)), i * 25 + 5, ii * 25 + 2, font, 12)
                else
                    drawfill (i * 25 + 5, ii * 25 + 5, 42, 7)
                end if
            end if
            if squares (i, ii, state) = 3 then
                drawfillbox (i * 25 + 5, ii * 25 + 5, i * 25 + 20, ii * 25 + 20, 42)
            end if
        end for
    end for
    buttonwait ("down", x, y, btn, bud)
    if x >= 25 and x = 25 and y = 25 and x = 25 and y  0) then
                    Font.Draw (intstr (squares (i, j).value), i * 20 + x + 5, j * 20 + y + 5, font, red)
                end if
            else
                drawfillbox (x + i * 20, y + j * 20, x + i * 20 + 20, y + j * 20 + 20, grey)
                drawbox (x + i * 20, y + j * 20, x + i * 20 + 20, y + j * 20 + 20, black)
            end if
        end for
    end for
end drawboard


% Create Mines
createMine (3, 3)
createMine (3, 4)
createMine (2, 3)
createMine (7,8)
createMine(7,7)
createMine(6,9)
createMine(5,8)
createMine(8,9)

% Equivalent to Click on square at (x,y) => (5,5)
showSquare (5, 5)

% Draw Board After Clicked
drawboard (50, 50)


-----------------------------------
cavetroll
Mon Jul 30, 2007 7:35 pm

Re: Minesweeper help
-----------------------------------
Thanks for all your help, I got it working. Here is the finished procedure. 

proc floodfill (nodex : int, nodey : int)
    if squares (nodex, nodey, state) = 1 then
        if squares (nodex, nodey, typ) not= 2 then
            return
        elsif squares (nodex, nodey, count) > 0 then
            squares (nodex, nodey, state) := 2
            return
        else
            squares (nodex, nodey, state) := 2
            for decreasing i : 1 .. -1
                for ii : -1 .. 1
                    if nodex - i > 0 and nodex - i < sizex + 1 and nodey - ii > 0 and nodey - ii < sizey + 1 then
                        if i = 0 and ii = 0 then
                        else
                            floodfill (nodex - i, nodey - ii)
                        end if
                    end if
                end for
            end for
        end if
    end if
end floodfill
