There is an n by m grid that has a random number (between 10% to 20% of the total number of tiles, though older implementations may use 20%..60% instead) of randomly placed mines that need to be found.

Positions in the grid are modified by entering their coordinates where the first coordinate is horizontal in the grid and the second vertical. The top left of the grid is position 1,1; the bottom right is at n,m.

 The total number of mines to be found is shown at the beginning of the game.
 Each mine occupies a single grid point, and its position is initially unknown to the player
 The grid is shown as a rectangle of characters between moves.
 You are initially shown all grids as obscured, by a single dot '.'
 You may mark what you think is the position of a mine which will show as a '?'
 You can mark what you think is free space by entering its coordinates.
 If the point is free space then it is cleared, as are any adjacent points that are also free space- this is repeated recursively for subsequent adjacent free points unless that point is marked as a mine or is a mine.
 Points marked as a mine show as a '?'.
 Other free points show as an integer count of the number of adjacent true mines in its immediate neighborhood, or as a single space ' ' if the free point is not adjacent to any true mines.
 Of course you lose if you try to clear space that has a hidden mine.
 You win when you have correctly identified all mines.
The Task is to create a program that allows you to play minesweeper on a 6 by 4 grid, and that assumes all user input is formatted correctly and so checking inputs for correct form may be omitted.
You may also omit all GUI parts of the task and work using text input and output.

Note: Changes may be made to the method of clearing mines to more closely follow a particular implementation of the game so long as such differences and the implementation that they more accurately follow are described.


C.F: wp:Minesweeper (computer game)

constant help = """ 
 
Minesweeper
===========
 
Enter eg A1 to open a cell, FA1 to flag a cell, Q to quit.
 
The board is initially displayed with 10-20% of cells mined, as follows:
 
. - an unknown cell (unopened and not flagged)
_ - an empty cell, with no surrounding mines
1..8 - an empty cell, with some nearby mines
? - a cell you have flagged as a mine
    (a flag can only be cleared by opening)
 
On completion:
X - the mine you detonated (if any)
* - a mine which was not flagged
+ - a mine which was correctly flagged
"""
 
string board = """ 
 
 123456
A......
B......
C......
D......
"""
 
sequence data = repeat(repeat(0,6),4)
-- 0: empty, no nearby mines
-- 1-8: empty, with surrounding mines
-- 9: a mine
 
-- data[row][col] maps to board[row*8+4+col], lets quickly verify that:
if find('.',board)!=13 then ?9/0 end if
if rfind('.',board)!=42 then ?9/0 end if
-- (above may trigger if copy/paste/dowload etc messed up whitespace)
 
constant prompt = "\nEnter eg A1 to open a cell, FA1 to flag a cell, Q to quit, or ? for help:"
 
integer mines = round((6*4)*0.10+rand(6*4)*0.10),  -- 10-20%
        cleared = 0,
        flagged = 0,
        flag = false,
        row = 0,
        col
 
procedure plant_mines()
    for i=1 to mines do
        while 1 do
            row = rand(4)
            col = rand(6)
            if data[row][col]!=9 then
                data[row][col] = 9
                for rx=row-1 to row+1 do
                    if rx>=1 and rx<=4 then
                        for cx=col-1 to col+1 do
                            if cx>=1 and cx<=6 then
                                if data[rx][cx]!=9 then
                                    data[rx][cx] += 1
                                end if
                            end if
                        end for
                    end if
                end for
                exit
            end if
        end while
    end for
    printf(1,"%d mines planted\n",mines)
    row = 0
end procedure
 
procedure clear_cell(integer row, col, drc)
    board[row*8+4+col] = iff(drc?drc+'0':' ')
    cleared += 1
    if drc=0 then
        for rx=row-1 to row+1 do
            if rx>=1 and rx<=4 then
                for cx=col-1 to col+1 do
                    if cx>=1 and cx<=6 then
                        drc = data[rx][cx]
                        if drc!=9
                        and board[rx*8+4+cx]='.' then
                            clear_cell(rx,cx,drc)
                        end if
                    end if
                end for
            end if
        end for
    end if
end procedure
 
function make_move()
    integer brc = row*8+4+col
    if flag then
        if board[brc]='.' then
            board[brc] = '?'
            flagged += 1
        end if
    else
        integer drc = data[row][col]
        if drc=9 then
            board[brc] = 'X'
            puts(1,"\n\n***BOOM!***")
            return true
        end if
        if find(board[brc],".?") then
            clear_cell(row,col,drc)
        end if
    end if
    row = 0
    flag = false
    -- nb: flagged and cleared may be wrong following incorrect input.
    if flagged=mines
    or cleared=6*4-mines then
        puts(1,"\n\n***You Win!***")
        return true
    end if
    return false    -- no "BOOM" yet!
end function
 
procedure disclose()
    for row=1 to 4 do
        for col=1 to 6 do
            if data[row][col]=9 then
                integer bdx = row*8+4+col,
                        bch = board[bdx]
                if bch='.' then
                    bch = '*'
                elsif bch='?' then
                    bch = '+'
                elsif bch!='X' then
                    ?9/0
                end if
                board[bdx] = bch
            end if
        end for
    end for
end procedure
 
plant_mines()
while 1 do
    if not flag and row=0 then
        puts(1,board)
        puts(1,prompt)
    end if
    integer ch = upper(getc(0))
    puts(1,ch)
    if ch='Q' then exit end if
    if ch='?' then
        puts(1,help)
    elsif ch='F' then
        flag = true
    elsif ch>='A'
      and ch<='D' then
        row = ch-'@'
    elsif ch>='1'
      and ch<='6' then
        col = ch-'0'
        if make_move() then exit end if
    else
        printf(1,"\n\nunrecognised:%c\n\n",ch)
        flag = false
        row = 0
    end if
end while
disclose()
puts(1,board&"game over\n\n")
{} = wait_key()