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)

Structure cell
  isMine.i
  display.c ;character to displays for cell, one of these {'.', '?', ' ', #)
EndStructure
 
Global Dim grid.cell(0,0)
Global mineCount, minesMarked, isGameOver
 
Procedure makeGrid(n, m)
  Protected rm, x, y
  Dim grid.cell(n - 1, m - 1)
  mineCount = n * m * (Random(4) + 2) / 10
  If mineCount < 0: mineCount = 1: EndIf
 
  For x = 0 To n - 1
    For y = 0 To m - 1
      grid(x, y)\display = '.'
    Next
  Next
 
  rm = mineCount
  While rm
    x = Random(n - 1)
    y = Random(m - 1)
    If Not grid(x, y)\isMine
      rm - 1: grid(x, y)\isMine = #True
    EndIf 
  Wend
  minesMarked = 0
  isGameOver = #False
EndProcedure
 
Procedure displayGrid(isEndOfGame = #False)
  #lMargin = 4
  Protected x, y, display.s
  If Not isEndOfGame
    PrintN("Grid has " + Str(mineCount) + " mines, " + Str(minesMarked) + " mines marked.")
  EndIf 
  PrintN(Space(#lMargin + 1) + ReplaceString(Space(ArraySize(grid(), 1) + 1), " ", "-"))
  For y = 0 To ArraySize(grid(), 2)
    Print(RSet(Str(y + 1), #lMargin, " ") + ":")
    For x = 0 To ArraySize(grid(), 1)
      Print(Chr(grid(x,y)\display))
    Next
    PrintN("")
  Next
EndProcedure
 
Procedure endGame(msg.s)
  Protected ans.s
  isGameOver = #True
  PrintN(msg): Print("Another game (y/n)?"): ans = Input()
  If LCase(Left(Trim(ans),1)) = "y"
    makeGrid(6, 4)
  EndIf 
EndProcedure
 
Procedure resign()
  Protected x, y, found
  For y = 0 To ArraySize(grid(), 2)
    For x = 0 To ArraySize(grid(), 1)
      With grid(x,y)
        If \isMine
          If \display = '?'
            \display = 'Y'
            found + 1
          ElseIf \display <> 'x'
            \display = 'N'
          EndIf
        EndIf
      EndWith
    Next
  Next
  displayGrid(#True)
  endGame("You found " + Str(found) + " out of " + Str(mineCount) + " mines.")
EndProcedure
 
Procedure usage()
  PrintN("h or ? - this help,")
  PrintN("c x y  - clear cell (x,y),")
  PrintN("m x y  - marks (toggles) cell (x,y),")
  PrintN("n      - start a new game,")
  PrintN("q      - quit/resign the game,")
  PrintN("where x is the (horizontal) column number and y is the (vertical) row number." + #CRLF$)
EndProcedure
 
Procedure markCell(x, y)
  If grid(x, y)\display = '?'
    minesMarked - 1: grid(x, y)\display = '.'
  ElseIf grid(x, y)\display = '.'
    minesMarked + 1: grid(x, y)\display = '?'
  EndIf 
EndProcedure
 
Procedure countAdjMines(x, y)
  Protected count, i, j
  For j = y - 1 To y + 1
    If j >= 0 And j <= ArraySize(grid(), 2)
      For i = x - 1 To x + 1
        If i >= 0 And i <= ArraySize(grid(), 1)
          If grid(i, j)\isMine
            count + 1
          EndIf 
        EndIf 
      Next
    EndIf 
  Next
 
  ProcedureReturn count 
EndProcedure
 
Procedure clearCell(x, y)
  Protected count
  If x >= 0 And x <= ArraySize(grid(), 1) And y >= 0 And y <= ArraySize(grid(), 2)
    If grid(x, y)\display = '.'
      If Not grid(x,y)\isMine
        count = countAdjMines(x, y)
        If count 
          grid(x, y)\display = Asc(Str(count))
        Else
          grid(x, y)\display = ' '
          clearCell(x + 1, y)
          clearCell(x + 1, y + 1)
          clearCell(x    , y + 1)
          clearCell(x - 1, y + 1)
          clearCell(x - 1, y)
          clearCell(x - 1, y - 1)
          clearCell(x    , y - 1)
          clearCell(x + 1, y - 1)
        EndIf 
      Else
        grid(x, y)\display = 'x'
        PrintN("Kaboom!  You lost!")
        resign()
      EndIf 
    EndIf 
  EndIf
EndProcedure
 
Procedure testforwin()
  Protected x, y, isCleared
  If minesMarked = mineCount
    isCleared = #True
    For x = 0 To ArraySize(grid(), 1)
      For y = 0 To ArraySize(grid(), 2)
        If grid(x, y)\display = '.': isCleared = #False: EndIf 
      Next
    Next
  EndIf
  If isCleared: endGame("You won!"): EndIf
EndProcedure
 
If OpenConsole()
  Define action.s
  usage()
  makeGrid(6, 4): displayGrid()
  Repeat
    PrintN(""): Print(">"):  action = Input()
    Select Asc(LCase(Left(action, 1)))
      Case 'h', '?'
        usage()
      Case 'n'  
        makeGrid(6, 4): displayGrid()
      Case 'c'
        clearCell(Val(StringField(action, 2, " ")) - 1, Val(StringField(action, 3, " ")) - 1)
        If Not isGameOver: displayGrid(): Else: testforwin(): EndIf 
      Case 'm'
        markCell(Val(StringField(action, 2, " ")) - 1, Val(StringField(action, 3, " ")) - 1)
        displayGrid()
        testforwin()
      Case 'q'
        resign()
    EndSelect
  Until isGameOver
 
  Print(#CRLF$ + #CRLF$ + "Press ENTER to exit"): Input()
  CloseConsole()
EndIf