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)

import random, sequtils, strformat, strscans, strutils
 
const LMargin = 4
 
type
 
  Cell = object
    isMine: bool
    display: char
 
  Grid = seq[seq[Cell]]
 
  Game = object
    grid: Grid
    mineCount: Natural
    minesMarked: Natural
    isOver: bool
 
 
proc initGame(m, n: Positive): Game =
  result.grid = newSeqWith(m, repeat(Cell(isMine: false, display: '.'), n))
  let min = (float(m * n) * 0.1).toInt
  let max = (float(m * n) * 0.2).toInt
  result.mineCount = min + rand(max - min)
  var rm = result.mineCount
  while rm > 0:
    let x = rand(m - 1)
    let y = rand(n - 1)
    if not result.grid[x][y].isMine:
      dec rm
      result.grid[x][y].isMine = true
  result.minesMarked = 0
 
 
template `[]`(grid: Grid; x, y: int): Cell = grid[x][y]
 
 
iterator cells(grid: var Grid): var Cell =
  for y in 0..grid[0].high:
    for x in 0..grid.high:
      yield grid[x, y]
 
 
proc display(game: Game; endOfGame: bool) =
  if not endOfGame:
    echo &"Grid has {game.mineCount} mine(s), {game.minesMarked} mine(s) marked."
  let margin = repeat(' ', LMargin)
  echo margin, toSeq(1..game.grid.len).join()
  echo margin, repeat('-', game.grid.len)
  for y in 0..game.grid[0].high:
    stdout.write align($(y + 1), LMargin)
    for x in 0..game.grid.high:
      stdout.write game.grid[x][y].display
    stdout.write '\n'
 
 
proc terminate(game: var Game; msg: string) =
  game.isOver = true
  echo msg
  var answer = ""
  while answer notin ["y", "n"]:
    stdout.write "Another game (y/n)? "
    answer = try: stdin.readLine().toLowerAscii
             except EOFError: "n"
    if answer == "y":
      game = initGame(6, 4)
      game.display(false)
 
 
proc resign(game: var Game) =
  var found = 0
  for cell in game.grid.cells:
    if cell.isMine:
      if cell.display == '?':
        cell.display = 'Y'
        inc found
      elif cell.display == 'x':
        cell.display = 'N'
  game.display(true)
  let msg = &"You found {found} out of {game.mineCount} mine(s)."
  game.terminate(msg)
 
 
proc markCell(game: var Game; x, y: int) =
  if game.grid[x, y].display == '?':
    dec game.minesMarked
    game.grid[x, y].display = '.'
  elif game.grid[x, y].display == '.':
    inc game.minesMarked
    game.grid[x, y].display = '?'
 
 
proc countAdjMines(game: Game; x, y: Natural): int =
  for j in (y - 1)..(y + 1):
    if j in 0..game.grid[0].high:
      for i in (x - 1)..(x + 1):
        if i in 0..game.grid.high:
          if game.grid[i, j].isMine:
            inc result
 
 
proc clearCell(game: var Game; x, y: int): bool =
 
  if x in 0..game.grid.high and y in 0..game.grid[0].high:
    if game.grid[x, y].display == '.':
 
      if game.grid[x, y].isMine:
        game.grid[x][y].display = 'x'
        echo "Kaboom! You lost!"
        return false
 
      let count = game.countAdjMines(x, y)
      if count > 0:
        game.grid[x][y].display = chr(ord('0') + count)
      else:
        game.grid[x][y].display = ' '
        for dx in -1..1:
          for dy in -1..1:
            if dx != 0 or dy != 0:
              discard game.clearCell(x + dx, y + dy)
 
  result = true
 
 
proc testForWin(game: var Game): bool =
  if game.minesMarked != game.mineCount: return false
  for cell in game.grid.cells:
    if cell.display == '.': return false
  result = true
  echo "You won!"
 
 
proc splitAction(game: Game; action: string): tuple[x, y: int; ok: bool] =
  var command: string
  if not action.scanf("$w $s$i $s$i$s$.", command, result.x, result.y): return
  if command.len != 1: return
  if result.x notin 1..game.grid.len or result.y notin 1..game.grid.len: return
  result.ok = true
 
 
proc printUsage() =
  echo "h or ? - this help,"
  echo "c x y  - clear cell (x,y),"
  echo "m x y  - marks (toggles) cell (x,y),"
  echo "n      - start a new game,"
  echo "q      - quit/resign the game,"
  echo "where 'x' is the (horizontal) column number and 'y' is the (vertical) row number.\n"
 
 
randomize()
printUsage()
var game = initGame(6, 4)
game.display(false)
 
while not game.isOver:
  stdout.write "\n>"
  let action = try: stdin.readLine().toLowerAscii
               except EOFError: "q"
  case action[0]
 
  of 'h', '?':
    printUsage()
 
  of 'n':
    game = initGame(6, 4)
    game.display(false)
 
  of 'c':
    let (x, y, ok) = game.splitAction(action)
    if not ok: continue
    if game.clearCell(x - 1, y - 1):
      game.display(false)
      if game.testForwin(): game.resign()
    else:
      game.resign()
 
  of 'm':
    let (x, y, ok) = game.splitAction(action)
    if not ok: continue
    game.markCell(x - 1, y - 1)
    game.display(false)
    if game.testForWin(): game.resign()
 
  of 'q':
    game.resign()
 
  else:
    continue