(defn take-random [n coll]
  (->> (repeatedly #(rand-nth coll))
       distinct
       (take n ,)))

(defn postwalk-fs
  "Depth first post-order traversal of form, apply successive fs at each level.
  (f1 (map f2 [..]))"
  [[f & fs] form]
  (f
   (if (and (seq fs) (coll? form))
     (into (empty form) (map (partial postwalk-fs fs) form))
     form)))

(defn neighbors [x y n m pred]
  (for [dx (range (Math/max 0 (dec x)) (Math/min n (+ 2 x)))
	dy (range (Math/max 0 (dec y)) (Math/min m (+ 2 y)))
	:when (pred dx dy)]
    [dx dy]))

(defn new-game [n m density]
  (let [mines (set (take-random (Math/floor (* n m density)) (range (* n m))))]
    (->> (for [y (range m)
	       x (range n)
	       :let [neighbor-mines (count (neighbors x y n m #(mines (+ %1 (* %2 n)))))]]
	   (#(if (mines (+ (* y n) x)) (assoc % :mine true) %) {:value neighbor-mines}))
	 (partition n ,)
	 (postwalk-fs [vec vec] ,))))

(defn display [board]
  (postwalk-fs [identity println #(condp % nil
				    :marked \?
				    :opened (:value %)
				    \.)] board))

(defn boom [{board :board}]
  (postwalk-fs [identity println #(if (:mine %) \* (:value %))] board)
  true)

(defn open* [board [[x y] & rest]]
  (if-let [value (get-in board [y x :value])] ; if nil? value -> nil? x -> nil? queue
    (recur
     (assoc-in board [y x :opened] true)
     (if (pos? value)
       rest
       (concat rest
	       (neighbors x y (count (first board)) (count board)
			  #(not (get-in board [%2 %1 :opened]))))))
    board))

(defn open [board x y]
  (let [x (dec x), y (dec y)]
    (condp (get-in board [y x]) nil
      :mine {:boom true :board board}
      :opened board
      (open* board [[x y]]))))

(defn mark [board x y]
  (let [x (dec x), y (dec y)]
    (assoc-in board [y x :marked] (not (get-in board [y x :marked])))))

(defn done? [board]
  (if (:boom board)
    (boom board)
    (do (display board)
	(->> (flatten board)
	     (remove :mine ,)
	     (every? :opened ,)))))

(defn play [n m density]
  (let [board (new-game n m density)]
    (println [:mines (count (filter :mine (flatten board)))])
    (loop [board board]
      (when-not (done? board)
	(print ">")
	(let [[cmd & xy] (.split #" " (read-line))
	      [x y] (map #(Integer. %) xy)]
	  (recur ((if (= cmd "mark") mark open) board x y)))))))


(defclass minefield ()
  ((mines :initform (make-hash-table :test #'equal))
   (width :initarg :width)
   (height :initarg :height)
   (grid :initarg :grid)))

(defun make-minefield (width height num-mines)
  (let ((minefield (make-instance 'minefield
                                  :width width
                                  :height height
                                  :grid (make-array
                                          (list width height)
                                          :initial-element #\.)))
        (mine-count 0))
    (with-slots (grid mines) minefield
      (loop while (< mine-count num-mines)
            do (let ((coords (list (random width) (random height))))
                 (unless (gethash coords mines)
                   (setf (gethash coords mines) T)
                   (incf mine-count))))
      minefield)))

(defun print-field (minefield)
  (with-slots (width height grid) minefield
    (dotimes (y height)
      (dotimes (x width)
        (princ (aref grid x y)))
      (format t "~%"))))

(defun mine-list (minefield)
  (loop for key being the hash-keys of (slot-value minefield 'mines) collect key))

(defun count-nearby-mines (minefield coords)
  (length (remove-if-not
            (lambda (mine-coord)
              (and
                (> 2 (abs (- (car coords) (car mine-coord))))
                (> 2 (abs (- (cadr coords) (cadr mine-coord))))))
            (mine-list minefield))))

(defun clear (minefield coords)
  (with-slots (mines grid) minefield
    (if (gethash coords mines)
      (progn
        (format t "MINE! You lose.~%")
        (dolist (mine-coords (mine-list minefield))
          (setf (aref grid (car mine-coords) (cadr mine-coords)) #\x))
        (setf (aref grid (car coords) (cadr coords)) #\X)
        nil)
      (setf (aref grid (car coords) (cadr coords))
            (elt " 123456789"(count-nearby-mines minefield coords))))))

(defun mark (minefield coords)
  (with-slots (mines grid) minefield
    (setf (aref grid (car coords) (cadr coords)) #\?)))

(defun win-p (minefield)
  (with-slots (width height grid mines) minefield
    (let ((num-uncleared 0))
      (dotimes (y height)
        (dotimes (x width)
          (let ((square (aref grid x y)))
            (when (member square '(#\. #\?) :test #'char=)
              (incf num-uncleared)))))
      (= num-uncleared (hash-table-count mines)))))

(defun play-game ()
  (let ((minefield (make-minefield 6 4 5)))
    (format t "Greetings player, there are ~a mines.~%"
            (hash-table-count (slot-value minefield 'mines)))
    (loop
      (print-field minefield)
      (format t "Enter your command, examples: \"clear 0 1\" \"mark 1 2\" \"quit\".~%")
      (princ "> ")
      (let ((user-command (read-from-string (format nil "(~a)" (read-line)))))
        (format t "Your command: ~a~%" user-command)
        (case (car user-command)
          (quit (return-from play-game nil))
          (clear (unless (clear minefield (cdr user-command))
                   (print-field minefield)
                   (return-from play-game nil)))
          (mark (mark minefield (cdr user-command))))
        (when (win-p minefield)
          (format t "Congratulations, you've won!")
          (return-from play-game T))))))

(play-game)


len cell[] 56
len cnt[] 56
len flag[] 56
#
subr initvars
  state = 0
  ticks = 0
  indx = -1
  no_time = 0
.
func getind r c . ind .
  ind = -1
  if r >= 0 and r <= 6 and c >= 0 and c <= 7
    ind = r * 8 + c
  .
.
func draw_cell ind h . .
  r = ind div 8
  c = ind mod 8
  x = c * 12 + 2.5
  y = r * 12 + 14.5
  move x y
  rect 11 11
  if h > 0
    # count
    move x + 3 y + 2
    color 000
    text h
  elif h = -3
    # flag
    x += 4
    color 000
    linewidth 0.8
    move x y + 3
    line x y + 8
    color 600
    linewidth 2
    move x + 0.5 y + 4
    line x + 2 y + 4
  elif h <> 0
    # mine
    color 333
    if h = -2
      color 800
    .
    move x + 5 y + 6
    circle 3
    line x + 8 y + 2
  .
.
func open ind . .
  if ind <> -1 and cell[ind] = 0
    cell[ind] = 2
    flag[ind] = 0
    color 686
    call draw_cell ind cnt[ind]
    if cnt[ind] = 0
      r0 = ind div 8
      c0 = ind mod 8
      for r = r0 - 1 to r0 + 1
        for c = c0 - 1 to c0 + 1
          if r <> r0 or c <> c0
            call getind r c ind
            call open ind
          .
        .
      .
    .
  .
.
func show_mines m . .
  for ind range 56
    if cell[ind] = 1
      color 686
      if m = -1
        color 353
      .
      call draw_cell ind m
    .
  .
.
func outp col s$ . .
  move 2.5 2
  color col
  rect 59 11
  color 000
  move 5 4.5
  text s$
.
func upd_info . .
  nm = 0
  nc = 0
  for i range 56
    nm += flag[i]
    if cell[i] < 2
      nc += 1
    .
  .
  if nc = 8
    call outp 484 "Well done"
    call show_mines -1
    state = 1
  else
    call outp 464 8 - nm & " mines left"
  .
.
func test ind . .
  if cell[ind] < 2 and flag[ind] = 0
    if cell[ind] = 1
      call show_mines -1
      color 686
      call draw_cell ind -2
      call outp 844 "B O O M !"
      state = 1
    else
      call open ind
      call upd_info
    .
  .
.
background 676
func start . .
  clear
  color 353
  for ind range 56
    cnt[ind] = 0
    cell[ind] = 0
    flag[ind] = 0
    call draw_cell ind 0
  .
  n = 8
  while n > 0
    c = random 8
    r = random 7
    ind = r * 8 + c
    if cell[ind] = 0
      n -= 1
      cell[ind] = 1
      for rx = r - 1 to r + 1
        for cx = c - 1 to c + 1
          call getind rx cx ind
          if ind > -1
            cnt[ind] += 1
          .
        .
      .
    .
  .
  call initvars
  call outp 464 ""
  textsize 4
  move 5 3
  text "Minesweeper - 8 mines"
  move 5 7.8
  text "Long-press for flagging"
  textsize 6
  timer 0
.
on mouse_down
  if state = 0
    if mouse_y < 14 and mouse_x > 60
      no_time = 1
      move 64.5 2
      color 464
      rect 33 11
    .
    call getind (mouse_y - 14) div 12 (mouse_x - 2) div 12 indx
    ticks0 = ticks
  elif state = 3
    call start
  .
.
on mouse_up
  if state = 0 and indx <> -1
    call test indx
  .
  indx = -1
.
on timer
  if state = 1
    state = 2
    timer 1
  elif state = 2
    state = 3
  elif no_time = 0 and ticks > 3000
    call outp 844 "B O O M !"
    call show_mines -2
    state = 2
    timer 1
  else
    if indx > -1 and ticks = ticks0 + 2
      if cell[indx] < 2
        color 353
        flag[indx] = 1 - flag[indx]
        opt = 0
        if flag[indx] = 1
          opt = -3
        .
        call draw_cell indx opt
        call upd_info
      .
      indx = -1
    .
    if no_time = 0 and ticks mod 10 = 0
      move 64.5 2
      color 464
      if ticks >= 2500
        color 844
      .
      rect 33 11
      color 000
      move 66 4.5
      text "Time:" & 300 - ticks / 10
    .
    ticks += 1
    timer 0.1
  .
.
call start


'--- Declaration of global variables ---
Type mina
    Dim   mina As Byte
    Dim   flag As Byte
    Dim   ok As Byte
    Dim   numero As Byte
End Type

Dim Shared As Integer size = 16, NX = 20, NY = 20
Dim Shared As Double mina = 0.10

Dim Shared tablero(NX+1,NY+1) As mina
Dim Shared As Integer GameOver, ddx, ddy, kolor, nbDESCANSO
Dim Shared As Double temps
Dim As String tecla

'--- SUBroutines and FUNCtions ---
Sub VerTodo
    Dim As Integer x, y
    For x = 1 To NX
        For y = 1 To NY
            With tablero(x,y)
                If .mina = 1 Or .flag > 0 Then .ok = 1
            End With
        Next y
    Next x
End Sub

Sub ShowGrid
    Dim As Integer x, y
    Line(ddx-1,ddy-1)-(1+ddx+size*NX,1+ddy+size*NY),&hFF0000,B
    For x = 1 To NX
        For y = 1 To NY
            With tablero(x,y)
                'Si la casilla no se hace click
                If .ok = 0 Then
                    Line(ddx+x*size,ddy+y*size)-(ddx+(x-1)*size,ddy+(y-1)*size),&h888888,BF
                    Line(ddx+x*size,ddy+y*size)-(ddx+(x-1)*size,ddy+(y-1)*size),&h444444,B
                    'bandera verde
                    If .flag = 1 Then
                        Circle (ddx+x*size-size/2,ddy+y*size-size/2),size/4,&h00FF00,,,,F
                        Circle (ddx+x*size-size/2,ddy+y*size-size/2),size/4,&h0
                    End If
                    'bandera azul
                    If .flag = 2 Then
                        Circle (ddx+x*size-size/2,ddy+y*size-size/2),size/4,&h0000FF,,,,F
                        Circle (ddx+x*size-size/2,ddy+y*size-size/2),size/4,&h0
                    End If
                    'Si se hace clic
                Else
                    If .mina = 0 Then
                        If .numero > 0 Then
                            Select Case .numero
                            Case 1: kolor = &h3333FF
                            Case 2: kolor = &h33FF33
                            Case 3: kolor = &hFF3333
                            Case 4: kolor = &hFFFF33
                            Case 5: kolor = &h33FFFF
                            Case 6: kolor = &hFF33FF
                            Case 7: kolor = &h999999
                            Case 8: kolor = &hFFFFFF
                            End Select
                            Draw String(ddx+x*size-size/1.5,ddy+y*size-size/1.5),Str(.numero),kolor
                        End If
                        If GameOver = 1 Then
                            'Si no hay Mina y una bandera verde >> rojo completo
                            If .flag = 1 Then
                                Circle (ddx+x*size-size/2,ddy+y*size-size/2),size/4,&h330000,,,,F
                                Circle (ddx+x*size-size/2,ddy+y*size-size/2),size/4,&h555555
                            End If
                            'Si no hay Mina y una bandera azul >> azul oscuro
                            If .flag = 2 Then
                                Circle (ddx+x*size-size/2,ddy+y*size-size/2),size/4,&h000033,,,,F
                                Circle (ddx+x*size-size/2,ddy+y*size-size/2),size/4,&h555555
                            End If
                        End If
                    Else
                        'Si hay una Mina sin bandera >> rojo
                        If .flag = 0 Then
                            Circle (ddx+x*size-size/2,ddy+y*size-size/2),size/4,&hFF0000,,,,F
                            Circle (ddx+x*size-size/2,ddy+y*size-size/2),size/4,&hFFFF00
                        Else
                            'Si hay una Mina con bandera verde >>> verde
                            If .flag = 1 Then
                                Circle (ddx+x*size-size/2,ddy+y*size-size/2),size/4,&h00FF00,,,,F
                                Circle (ddx+x*size-size/2,ddy+y*size-size/2),size/4,&hFFFF00
                            End If
                            If .flag = 2 Then
                                'Si hay una Mina con bandera azul >>>> verde oscuro
                                Circle (ddx+x*size-size/2,ddy+y*size-size/2),size/4,&h003300,,,,F
                                Circle (ddx+x*size-size/2,ddy+y*size-size/2),size/4,&hFFFF00
                            End If
                        End If
                    End If
                End If
            End With
        Next y
    Next x
End Sub

Sub Calcul
    Dim As Integer x, y
    For x = 1 To NX
        For y = 1 To NY
            tablero(x,y).numero = _
            Iif(tablero(x+1,y).mina=1,1,0) + Iif(tablero(x-1,y).mina=1,1,0) + _
            Iif(tablero(x,y+1).mina=1,1,0) + Iif(tablero(x,y-1).mina=1,1,0) + _
            Iif(tablero(x+1,y-1).mina=1,1,0) + Iif(tablero(x+1,y+1).mina=1,1,0) + _
            Iif(tablero(x-1,y-1).mina=1,1,0) + Iif(tablero(x-1,y+1).mina=1,1,0)
        Next y
    Next x
End Sub

Sub Inicio
    size = 20
    If NX > 720/size Then size = 720/NX
    If NY > 520/size Then size = 520/NY

    Redim tablero(NX+1,NY+1) As mina
    Dim As Integer x, y
    For x = 1 To NX
        For y = 1 To NY
            With tablero(x,y)
                .mina = Iif(Rnd > (1-mina), 1, 0)
                .ok = 0
                .flag = 0
                .numero = 0
            End With
        Next y
    Next x
    ddx = (((800/size)-NX)/2)*size
    ddy = (((600/size)-NY)/2)*size
    Calcul
End Sub

Function isGameOver As Integer
    Dim As Integer x, y, nbMINA, nbOK, nbAZUL, nbVERT
    For x = 1 To NX
        For y = 1 To NY
            If tablero(x,y).ok = 1 And tablero(X,y).mina = 1 Then
                Return -1
            End If
            If tablero(x,y).ok = 0 And tablero(x,y).flag = 1 And tablero(X,y).mina = 1 Then
                nbOK += 1
            End If
            If  tablero(X,y).mina = 1 Then
                nbMINA + =1
            End If
            If  tablero(X,y).flag = 2 Then
                nbAZUL += 1
                'End If
            Elseif  tablero(X,y).flag = 1 Then
                nbVERT += 1
            End If
        Next y
    Next x

    If nbMINA = nbOK And nbAZUL = 0 Then Return 1
    nbDESCANSO = nbMINA - nbVERT
End Function

Sub ClicRecursivo(ZX As Integer, ZY As Integer)
    If tablero(ZX,ZY).ok = 1 Then Exit Sub
    If tablero(ZX,ZY).flag > 0 Then Exit Sub
    'CLICK
    tablero(ZX,ZY).ok = 1

    If tablero(ZX,ZY).mina = 1 Then Exit Sub
    If tablero(ZX,ZY).numero > 0 Then Exit Sub

    If ZX > 0 And ZX <= NX And ZY > 0 And ZY <= NY Then
        ClicRecursivo(ZX+1,ZY)
        ClicRecursivo(ZX-1,ZY)
        ClicRecursivo(ZX,ZY+1)
        ClicRecursivo(ZX,ZY-1)
        ClicRecursivo(ZX+1,ZY+1)
        ClicRecursivo(ZX+1,ZY-1)
        ClicRecursivo(ZX-1,ZY+1)
        ClicRecursivo(ZX-1,ZY-1)
    End If
End Sub

'--- Main Program ---
Screenres 800,600,24',,1
Windowtitle"Minesweeper game"
Randomize Timer
Cls
Dim As Integer mx, my, mb, fmb, ZX, ZY, r, tt
Dim As Double t
Inicio
GameOver = 1
Do
    tecla = Inkey
    If GameOver = 1 Then
        Select Case Ucase(tecla)
        Case Chr(Asc("X"))
            NX += 5
            If NX > 80 Then NX = 10
            Inicio
        Case Chr(Asc("Y"))
            NY += 5
            If NY > 60 Then NY = 10
            Inicio
        Case Chr(Asc("M"))
            mina += 0.01
            If mina > 0.26 Then mina = 0.05
            Inicio
        Case Chr(Asc("S"))
            Inicio
            GameOver = 0
            temps = Timer
        End Select
    End If

    Getmouse mx,my,,mb
    mx -= ddx-size
    my -= ddy-size
    ZX = (MX-size/2)/size
    ZY = (MY-size/2)/size

    If GameOver = 0 And zx > 0 And zx <= nx And zy > 0 And zy <= ny Then
        If MB=1 And fmb=0 Then ClicRecursivo(ZX,ZY)
        If MB=2 And fmb=0 Then
            tablero(ZX,ZY).flag += 1
            If tablero(ZX,ZY).flag > 2 Then tablero(ZX,ZY).flag = 0
        End If
        fmb = mb
    End If

    r = isGameOver
    If r = -1 And GameOver = 0 Then
        VerTodo
        GameOver = 1
    End If
    If r = 1 And GameOver = 0 Then GameOver = 1
    If GameOver = 0 Then tt = Timer-temps

    Screenlock
    Cls
    ShowGrid
    If GameOver = 0 Then
        Draw String (210,4), "X:" & NX & " Y:" & NY & " MINA:" & Int(mina*100) & "%   TIMER : " & Int(TT) & " S   REMAINING:" & nbDESCANSO,&hFFFF00
    Else
        Draw String (260,4), "PRESS: 'S' TO START     X,Y,M TO SIZE"   ,&hFFFF00
        Draw String (330,17), "X:" & NX & " Y:" & NY & " MINA:" & Int(mina*100) & "%"   ,&hFFFF00
        If r = 1 Then
            t += 0.01
            If t > 1000 Then t = 0
            Draw String (320,280+Cos(t)*100),"!! CONGRATULATION !!",&hFFFF00
        End If
    End If
    Screenunlock
Loop Until tecla = Chr(27)
Bsave "Minesweeper.bmp",0
End


package main

import (
    "bufio"
    "fmt"
    "math"
    "math/rand"
    "os"
    "strconv"
    "strings"
    "time"
)

type cell struct {
    isMine  bool
    display byte // display character for cell
}

const lMargin = 4

var (
    grid        [][]cell
    mineCount   int
    minesMarked int
    isGameOver  bool
)

var scanner = bufio.NewScanner(os.Stdin)

func makeGrid(n, m int) {
    if n <= 0 || m <= 0 {
        panic("Grid dimensions must be positive.")
    }
    grid = make([][]cell, n)
    for i := 0; i < n; i++ {
        grid[i] = make([]cell, m)
        for j := 0; j < m; j++ {
            grid[i][j].display = '.'
        }
    }
    min := int(math.Round(float64(n*m) * 0.1)) // 10% of tiles
    max := int(math.Round(float64(n*m) * 0.2)) // 20% of tiles
    mineCount = min + rand.Intn(max-min+1)
    rm := mineCount
    for rm > 0 {
        x, y := rand.Intn(n), rand.Intn(m)
        if !grid[x][y].isMine {
            rm--
            grid[x][y].isMine = true
        }
    }
    minesMarked = 0
    isGameOver = false
}

func displayGrid(isEndOfGame bool) {
    if !isEndOfGame {
        fmt.Println("Grid has", mineCount, "mine(s),", minesMarked, "mine(s) marked.")
    }
    margin := strings.Repeat(" ", lMargin)
    fmt.Print(margin, " ")
    for i := 1; i <= len(grid); i++ {
        fmt.Print(i)
    }
    fmt.Println()
    fmt.Println(margin, strings.Repeat("-", len(grid)))
    for y := 0; y < len(grid[0]); y++ {
        fmt.Printf("%*d:", lMargin, y+1)
        for x := 0; x < len(grid); x++ {
            fmt.Printf("%c", grid[x][y].display)
        }
        fmt.Println()
    }
}

func endGame(msg string) {
    isGameOver = true
    fmt.Println(msg)
    ans := ""
    for ans != "y" && ans != "n" {
        fmt.Print("Another game (y/n)? : ")
        scanner.Scan()
        ans = strings.ToLower(scanner.Text())
    }
    if scanner.Err() != nil || ans == "n" {
        return
    }
    makeGrid(6, 4)
    displayGrid(false)
}

func resign() {
    found := 0
    for y := 0; y < len(grid[0]); y++ {
        for x := 0; x < len(grid); x++ {
            if grid[x][y].isMine {
                if grid[x][y].display == '?' {
                    grid[x][y].display = 'Y'
                    found++
                } else if grid[x][y].display != 'x' {
                    grid[x][y].display = 'N'
                }
            }
        }
    }
    displayGrid(true)
    msg := fmt.Sprint("You found ", found, " out of ", mineCount, " mine(s).")
    endGame(msg)
}

func usage() {
    fmt.Println("h or ? - this help,")
    fmt.Println("c x y  - clear cell (x,y),")
    fmt.Println("m x y  - marks (toggles) cell (x,y),")
    fmt.Println("n      - start a new game,")
    fmt.Println("q      - quit/resign the game,")
    fmt.Println("where x is the (horizontal) column number and y is the (vertical) row number.\n")
}

func markCell(x, y int) {
    if grid[x][y].display == '?' {
        minesMarked--
        grid[x][y].display = '.'
    } else if grid[x][y].display == '.' {
        minesMarked++
        grid[x][y].display = '?'
    }
}

func countAdjMines(x, y int) int {
    count := 0
    for j := y - 1; j <= y+1; j++ {
        if j >= 0 && j < len(grid[0]) {
            for i := x - 1; i <= x+1; i++ {
                if i >= 0 && i < len(grid) {
                    if grid[i][j].isMine {
                        count++
                    }
                }
            }
        }
    }
    return count
}

func clearCell(x, y int) bool {
    if x >= 0 && x < len(grid) && y >= 0 && y < len(grid[0]) {
        if grid[x][y].display == '.' {
            if !grid[x][y].isMine {
                count := countAdjMines(x, y)
                if count > 0 {
                    grid[x][y].display = string(48 + count)[0]
                } 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)
                }
            } else {
                grid[x][y].display = 'x'
                fmt.Println("Kaboom! You lost!")
                return false
            }
        }
    }
    return true
}

func testForWin() bool {
    isCleared := false
    if minesMarked == mineCount {
        isCleared = true
        for x := 0; x < len(grid); x++ {
            for y := 0; y < len(grid[0]); y++ {
                if grid[x][y].display == '.' {
                    isCleared = false
                }
            }
        }
    }
    if isCleared {
        fmt.Println("You won!")
    }
    return isCleared
}

func splitAction(action string) (int, int, bool) {
    fields := strings.Fields(action)
    if len(fields) != 3 {
        return 0, 0, false
    }
    x, err := strconv.Atoi(fields[1])
    if err != nil || x < 1 || x > len(grid) {
        return 0, 0, false
    }
    y, err := strconv.Atoi(fields[2])
    if err != nil || y < 1 || y > len(grid[0]) {
        return 0, 0, false
    }
    return x, y, true
}

func main() {
    rand.Seed(time.Now().UnixNano())
    usage()
    makeGrid(6, 4)
    displayGrid(false)
    for !isGameOver {
        fmt.Print("\n>")
        scanner.Scan()
        action := strings.ToLower(scanner.Text())
        if scanner.Err() != nil || len(action) == 0 {
            continue
        }
        switch action[0] {
        case 'h', '?':
            usage()
        case 'n':
            makeGrid(6, 4)
            displayGrid(false)
        case 'c':
            x, y, ok := splitAction(action)
            if !ok {
                continue
            }
            if clearCell(x-1, y-1) {
                displayGrid(false)
                if testForWin() {
                    resign()
                }
            } else {
                resign()
            }
        case 'm':
            x, y, ok := splitAction(action)
            if !ok {
                continue
            }
            markCell(x-1, y-1)
            displayGrid(false)
            if testForWin() {
                resign()
            }
        case 'q':
            resign()
        }
    }
}


global DEFARGS,MF

record minefield(mask,grid,rows,cols,mines,density,marked)

$define _DEFAULTS  [6,  4, .2, .6]  # task defaults
#$define _DEFAULTS  [6, 7, .05, .1]   # defaults for debugging
$define _INDENT    6
$define _MINE      "Y"
$define _TRUEMINE  "Y"
$define _FALSEMINE "N"
$define _MASK      "."
$define _MARK      "?"
$define _TOGGLE1   ".?"
$define _TOGGLE2   "?."

procedure main(arglist)                           #: play the game
static trace
initial trace := -1

DEFARGS := _DEFAULTS
if *arglist = 0 then arglist := DEFARGS

newgame!arglist
while c := trim(read()) do {
   c ? {  tab(many(' '))
          case move(1) of {
                                                 # required commands
            "c": clear() & showgrid()            #   c  clear 1 sq and show
            "m": mark()                          #   m flag/unflag a mine
            "p": showgrid()                      #   p show the mine field
            "r": endgame("Resigning.")           #   r resign this game
                                                 # optional commands
            "n": newgame!arglist                 #   n new game grid
            "k": clearunmarked() & showgrid()    #   k clears adjecent unmarked cells if #flags = count
            "x": clearallunmarked()              #   x clears every unflagged cell at once win/loose fast
            "q": stop("Quitting")                #   q quit
            "t": &trace :=: trace                #   t toggle tracing for debugging
            default: usage()
            }}
   testforwin(g)
   }
end

procedure newgame(r,c,l,h)                       #: start a new game
local i,j,t

MF := minefield()

MF.rows := 0 < integer(\r) | DEFARGS[1]
MF.cols := 0 < integer(\c) | DEFARGS[2]

every !(MF.mask := list(MF.rows)) := list(MF.cols,_MASK)  # set mask
every !(MF.grid := list(MF.rows)) := list(MF.cols,0)      # default count

l := 1 > (0 < real(\l))  | DEFARGS[3]
h := 1 > (0 < real(\h))  | DEFARGS[4]
if l > h then l :=: h

until MF.density := l <= ( h >= ?0 )                      # random density between l:h
MF.mines := integer(MF.rows * MF.cols * MF.density)       # mines needed
MF.marked := 0

write("Creating ",r,"x",c," mine field with ",MF.mines," (",MF.density * 100,"%).")
every 1 to MF.mines do until \MF.grid[r := ?MF.rows, c := ?MF.cols] := &null                # set mines
every \MF.grid[i := 1 to MF.rows,j:= 1 to MF.cols] +:= (/MF.grid[i-1 to i+1,j-1 to j+1], 1) # set counts

showgrid()
return
end

procedure usage()                                         #: show usage
return write(
"h or ? - this help\n",
"n      - start a new game\n",
"c i j  - clears x,y and displays the grid\n",
"m i j  - marks (toggles) x,y\n",
"p      - displays the grid\n",
"k i j  - clears adjecent unmarked cells if #marks = count\n",
"x      - clears ALL unmarked flags at once\n",
"r      - resign the game\n",
"q      - quit the game\n",
"where i is the (vertical) row number and j is the (horizontal) column number." )
end

procedure getn(n)                                         #: command parsing
  tab(many(' '))
  if n := n >= ( 0 < integer(tab(many(&digits)))) then return n
  else write("Invalid or out of bounds grid square.")
end

procedure showgrid()                                      #: show grid
local r,c,x

   write(right("",_INDENT),"   ",repl("----+----|",MF.cols / 10 + 1)[1+:MF.cols])
   every r := 1 to *MF.mask do {
      writes(right(r,_INDENT)," : ")
      every c := 1 to *MF.mask[r] do
         writes( \MF.mask[r,c] | map(\MF.grid[r,c],"0"," ") | _MINE)
      write()
      }
   write(MF.marked," marked mines and ",MF.mines - MF.marked," mines left to be marked.")
end

procedure mark()                                          #: mark/toggle squares
local i,j

   if \MF.mask[i := getn(MF.rows), j :=getn(MF.cols)] := map(MF.mask[i,j],_TOGGLE1,_TOGGLE2) then {
      case MF.mask[i,j] of {
         _MASK : MF.marked -:= 1
         _MARK : MF.marked +:= 1
         }
      }
end

procedure clear()                                         #: clear a square
local i,j

   if ( i := getn(MF.rows) ) & ( j :=getn(MF.cols) ) then
      if /MF.mask[i,j] then
         write(i," ",j," was already clear")
      else if /MF.grid[i,j] then endgame("KABOOM! You lost.")
         else return revealclearing(i,j)
end

procedure revealclearing(i,j)                             #: reaveal any clearing

   if \MF.mask[i,j] := &null then {
      if MF.grid[i,j] = 0 then
         every revealclearing(i-1 to i+1,j-1 to j+1)
      return
      }
end

procedure clearunmarked()                                 #: clears adjecent unmarked cells if #flags = count
local i,j,k,m,n

   if ( i := getn(MF.rows) ) & ( j :=getn(MF.cols) ) then
      if /MF.mask[i,j] & ( k := 0 < MF.grid[i,j] ) then {
         every (\MF.mask[i-1 to i+1,j-1 to j+1] == _MARK) & ( k -:= 1)
         if k = 0 then {
            every (m := i-1 to i+1) & ( n := j-1 to j+1) do
               if \MF.mask[m,n] == _MASK then MF.mask[m,n] := &null
            revealclearing(i,j)
            return
            }
         else
            write("Marked squares must match adjacent mine count.")
            }
      else write("Must be adjecent to one or more marks to clear surrounding squares.")
end

procedure clearallunmarked()                             #: fast win or loose
local i,j,k

   every (i := 1 to MF.rows) & (j := 1 to MF.cols) do {
      if \MF.mask[i,j] == _MASK then {
         MF.mask[i,j] := &null
         if /MF.grid[i,j] then k := 1
         }
      }
   if \k then endgame("Kaboom - you loose.")
end

procedure testforwin()                                  #: win when rows*cols-#_MARK-#_MASK are clear and no Kaboom
local t,x

   t :=  MF.rows * MF.cols - MF.mines
   every x := !!MF.mask do if /x then t -:= 1
   if t = 0 then endgame("You won!")
end

procedure endgame(tag)                                  #: end the game
local i,j,m

   every !(m := list(MF.rows)) := list(MF.cols)         # new mask
   every (i := 1 to MF.rows) & (j := 1 to MF.cols) do
      if \MF.mask[i,j] == _MARK then
         m[i,j] := if /MF.grid[i,j] then _TRUEMINE else _FALSEMINE
   MF.mask := m
   write(tag) & showgrid()
end


{-# LANGUAGE TemplateHaskell #-}

module MineSweeper
  ( Board
  , Cell(..)
  , CellState(..)
  , Pos
    -- lenses / prisms
  , pos
  , coveredLens
  , coveredFlaggedLens
  , coveredMinedLens
  , xCoordLens
  , yCoordLens
    -- Functions
  , emptyBoard
  , groupedByRows
  , displayCell
  , isLoss
  , isWin
  , exposeMines
  , openCell
  , flagCell
  , mineBoard
  , totalRows
  , totalCols )
where

import Control.Lens  ((%~), (&), (.~), (^.), (^?), Lens', Traversal', _1, _2,
                      anyOf, filtered, folded, lengthOf, makeLenses, makePrisms,
                      preview, to, view)
import Data.List     (find, groupBy, nub, delete, sortBy)
import Data.Maybe    (isJust)
import System.Random (getStdGen, getStdRandom, randomR, randomRs)

type Pos = (Int, Int)
type Board = [Cell]

data CellState = Covered   { _mined :: Bool, _flagged :: Bool }
               | UnCovered { _mined :: Bool }
               deriving (Show, Eq)

data Cell = Cell
          { _pos :: Pos
          , _state :: CellState
          , _cellId :: Int
          , _adjacentMines :: Int }
          deriving (Show, Eq)

makePrisms ''CellState
makeLenses ''CellState
makeLenses ''Cell

-- Re-useable lens.
coveredLens :: Traversal' Cell (Bool, Bool) --'
coveredLens = state . _Covered

coveredMinedLens, coveredFlaggedLens, unCoveredLens :: Traversal' Cell Bool --'
coveredMinedLens = coveredLens . _1
coveredFlaggedLens = coveredLens . _2
unCoveredLens = state . _UnCovered

xCoordLens, yCoordLens :: Lens' Cell Int --'
xCoordLens = pos . _1
yCoordLens = pos . _2

-- Adjust row and column size to your preference.
totalRows, totalCols :: Int
totalRows = 4
totalCols = 6

emptyBoard :: Board
emptyBoard = (\(n, p) -> Cell { _pos = p
                              , _state = Covered False False
                              , _adjacentMines = 0
                              , _cellId = n }) <$> zip [1..] positions
  where
    positions = (,) <$> [1..totalCols] <*> [1..totalRows]

updateCell :: Cell -> Board -> Board
updateCell cell = fmap (\c -> if cell ^. cellId == c ^. cellId then cell else c)

updateBoard :: Board -> [Cell] -> Board
updateBoard = foldr updateCell

okToOpen :: [Cell] -> [Cell]
okToOpen = filter (\c -> c ^? coveredLens == Just (False, False))

openUnMined :: Cell -> Cell
openUnMined = state .~ UnCovered False

openCell :: Pos -> Board -> Board
openCell p b = f $ find (\c -> c ^. pos == p) b
 where
  f (Just c)
    | c ^? coveredFlaggedLens == Just True = b
    | c ^? coveredMinedLens == Just True = updateCell
      (c & state .~ UnCovered True)
      b
    | isCovered c = if c ^. adjacentMines == 0 && not (isFirstMove b)
      then updateCell (openUnMined c) $ expandEmptyCells b c
      else updateCell (openUnMined c) b
    | otherwise = b
  f Nothing = b
  isCovered = isJust . preview coveredLens

expandEmptyCells :: Board -> Cell -> Board
expandEmptyCells board cell
  | null openedCells = board
  | otherwise = foldr (flip expandEmptyCells) updatedBoard (zeroAdjacent openedCells)
 where
  findMore _ [] = []
  findMore exclude (c : xs)
    | c `elem` exclude        = findMore exclude xs
    | c ^. adjacentMines == 0 = c : adjacent c <>
      findMore (c : exclude <> adjacent c) xs
    | otherwise               = c : findMore (c : exclude) xs
  adjacent     = okToOpen . flip adjacentCells board
  openedCells  = openUnMined <$> nub (findMore [cell] (adjacent cell))
  zeroAdjacent = filter (view (adjacentMines . to (== 0)))
  updatedBoard = updateBoard board openedCells

flagCell :: Pos -> Board -> Board
flagCell p board = case find ((== p) . view pos) board of
  Just c  -> updateCell (c & state . flagged %~ not) board
  Nothing -> board

adjacentCells :: Cell -> Board -> [Cell]
adjacentCells Cell {_pos = c@(x1, y1)} = filter (\c -> c ^. pos `elem` positions)
  where
    f n = [pred n, n, succ n]
    positions = delete c $ [(x, y) | x <- f x1, x > 0, y <- f y1, y > 0]

isLoss, isWin, allUnMinedOpen, allMinesFlagged, isFirstMove :: Board -> Bool
isLoss = anyOf (traverse . unCoveredLens) (== True)
isWin b = allUnMinedOpen b || allMinesFlagged b

allUnMinedOpen = (== 0) . lengthOf (traverse . coveredMinedLens . filtered (== False))
allMinesFlagged b = minedCount b == flaggedMineCount b
 where
  minedCount = lengthOf (traverse . coveredMinedLens . filtered (== True))
  flaggedMineCount = lengthOf (traverse . coveredLens . filtered (== (True, True)))

isFirstMove = (== totalCols * totalRows) . lengthOf (folded . coveredFlaggedLens . filtered (== False))

groupedByRows :: Board -> [Board]
groupedByRows = groupBy (\c1 c2 -> yAxis c1 == yAxis c2)
              . sortBy (\c1 c2 -> yAxis c1 `compare` yAxis c2)
  where
    yAxis = view yCoordLens

displayCell :: Cell -> String
displayCell c
  | c ^? unCoveredLens            == Just True = "X"
  | c ^? coveredFlaggedLens       == Just True = "?"
  | c ^? (unCoveredLens . to not) == Just True =
    if c ^. adjacentMines > 0 then show $ c ^. adjacentMines else "▢"
  | otherwise = "."

exposeMines :: Board -> Board
exposeMines = fmap (\c -> c & state . filtered (\s -> s ^? _Covered . _1 == Just True) .~ UnCovered True)

updateMineCount :: Board -> Board
updateMineCount b = go b
 where
  go []       = []
  go (x : xs) = (x & adjacentMines .~ totalAdjacentMines b) : go xs
   where
    totalAdjacentMines =
      foldr (\c acc -> if c ^. (state . mined) then succ acc else acc) 0 . adjacentCells x

-- IO
mineBoard :: Pos -> Board -> IO Board
mineBoard p board = do
  totalMines <- randomMinedCount
  minedBoard totalMines >>= \mb -> pure $ updateMineCount mb
 where
  mines n = take n <$> randomCellIds
  minedBoard n = (\m ->
    fmap (\c -> if c ^. cellId `elem` m then c & state . mined .~ True else c)
        board) . filter (\c -> openedCell ^. cellId /= c)
      <$> mines n
  openedCell = head $ filter (\c -> c ^. pos == p) board

randomCellIds :: IO [Int]
randomCellIds = randomRs (1, totalCols * totalRows) <$> getStdGen

randomMinedCount :: IO Int
randomMinedCount = getStdRandom $ randomR (minMinedCells, maxMinedCells)
 where
  maxMinedCells = floor $ realToFrac (totalCols * totalRows) * 0.2
  minMinedCells = floor $ realToFrac (totalCols * totalRows) * 0.1


NB. minefield.ijs script
NB. =========================================================
NB. Game engine

NB.require 'guid'
NB.([ 9!:1) _2 (3!:4) , guids 1            NB. randomly set initial random seed

coclass 'mineswpeng'

newMinefield=: 3 : 0
  if. 0=#y do. y=. 9 9 end.
  Marked=: Cleared=: y$0
  NMines=: <. */(0.01*10+?20),y            NB. 10..20% of tiles are mines
  mines=. (i. e. NMines ? */) y            NB. place mines
  Map=: (9*mines) >. y{. (1,:3 3) +/@,;.3 (-1+y){.mines
)

markTiles=: 3 : 0
  Marked=: (<"1 <:y) ([email protected]{)`[`]} Marked    NB. toggle marked state of cell(s)
)

clearTiles=: [email protected]:<:                 NB. decrement coords - J arrays are 0-based

clearcell=: verb define
  if. #y do.
    free=. (#~ (Cleared < 0 = Map) {~ <"1) y
    Cleared=: 1 (<"1 y)} Cleared           NB. set cell(s) as cleared
    if. #free do.
      clearcell (#~ Cleared [email protected]{~ <"1) ~. (<:$Map) (<."1) 0 >. getNbrs free
    end.
  end.
)

getNbrs=: [: ,/^:(3=#@$) +"1/&(<: 3 3#: i.9)

eval=: verb define
  if. 9 e. Cleared #&, Map do.            NB. cleared mine(s)?
    1; 'KABOOM!!'
  elseif. *./ 9 = (-.Cleared) #&, Map do. NB. all cleared except mines?
    1; 'Minefield cleared.'
  elseif. do.                             NB. else...
    0; (": +/, Marked>Cleared),' of ',(":NMines),' mines marked.'
  end.                                    NB. result: isEnd; message
)

showField=: 4 : 0
  idx=. y{ (2 <. Marked + +:Cleared) ,: 2
  |: idx} (11&{ , 12&{ ,: Map&{) x  NB. transpose result - J arrays are row,column
)

NB. =========================================================
NB. User interface

Minesweeper_z_=: conew&'mineswp'

coclass 'mineswp'
coinsert 'mineswpeng'        NB. insert game engine locale in copath

Tiles=: ' 12345678**.?'

create=: verb define
  smoutput Instructions
  startgame y
)
destroy=: codestroy
quit=: destroy

startgame=: [email protected]
clear=: [email protected]
mark=: [email protected]

update=: 3 : 0
  'isend msg'=. eval ''
  smoutput msg
  smoutput < Tiles showField isend
  if. isend do.
    msg=. ('K'={.msg) {:: 'won';'lost'
    smoutput 'You ',msg,'! Try again?'
    destroy ''
  end.
  empty''
)

Instructions=: 0 : 0
=== MineSweeper ===
Object:
   Uncover (clear) all the tiles that are not mines.

How to play:
 - the left, top tile is: 1 1
 - clear an uncleared tile (.) using the command:
      clear__fld <column index> <row index>
 - mark and uncleared tile (?) as a suspected mine using the command:
      mark__fld <column index> <row index>
 - if you uncover a number, that is the number of mines adjacent
   to the tile
 - if you uncover a mine (*) the game ends (you lose)
 - if you uncover all tiles that are not mines the game ends (you win).
 - quit a game before winning or losing using the command:
      quit__fld ''
 - start a new game using the command:
      fld=: MineSweeper <num columns> <num rows>
)


--------------------------------- START of Main.java ---------------------------------
//By xykmz. Enjoy!

import java.util.Scanner;

public class Main {

    static int intErrorTrap (int x, int y){

        int max, min;

        if (x < y) {
            min = x;
            max = y;
        } else {
            min = y;
            max = x;
        }

        int input;
        boolean loopEnd;

        do {

            System.out.println("Please enter an integer between " + min + " to " + max + ".");
            Scanner userInput = new Scanner(System.in); //Player inputs a guess

            try
            {
                input = userInput.nextInt();

                if(input > max) //Input is too high
                {
                    loopEnd = false;
                    System.out.println("Input is invalid.");
                    return -1;
                }

                else if(input < min) //Input is too low
                {
                    loopEnd = false;
                    System.out.println("Input is invalid.");
                    return -1;
                }

                else //Input is within acceptable range
                {
                    loopEnd = true;
                    System.out.println(input + " is a valid input.");
                    return input;

                }
            }

            catch (Exception e)
            {
                loopEnd = false;
                userInput.next();
                System.out.println("Input is invalid.");
                return 0;
            }

        } while (loopEnd == false);
    }

    public static void main(String[] args) {

    	System.out.println ("Enter width.");
    	int x = intErrorTrap (0,60);

    	System.out.println ("Enter height.");
    	int y = intErrorTrap (0,30);

    	System.out.println ("Enter difficulty.");
    	int d = intErrorTrap (0,100);

        new Minesweeper(x, y, d); //Suggested: (60, 30, 15)
    }

}

//--------------------------------- END of Main.java ---------------------------------

//--------------------------------- START of Cell.java ---------------------------------

public class Cell{ //This entire class is quite self-explanatory. All we're really doing is setting booleans.

    private boolean isMine, isFlagged, isCovered;
    private int number;

    public Cell(){
        isMine = false;
        isFlagged = false;
        isCovered = true;
        number = 0;
    }

    public void flag(){
        isFlagged = true;
    }

    public void unflag(){
        isFlagged = false;
    }

    public void setMine(){
        isMine = true;
    }

    public boolean isMine(){
        return isMine;
    }

    public void reveal(){
        isCovered = false;
    }

    public void setNumber(int i){ //Set the number of the cell
        number = i;
    }

    public int getNumber(){ //Request the program for the number of the cell
        return number;
    }

    public boolean isFlagged(){
        return isFlagged;
    }

    public boolean isCovered(){
        return isCovered;
    }

}

//--------------------------------- END of Cell.java ---------------------------------

//--------------------------------- START of Board.java ---------------------------------

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JPanel;

public class Board extends JPanel{

    private static final long serialVersionUID = 1L; //Guarantees consistent serialVersionUID value across different java compiler implementations,
    												 //Auto-generated value might screw things up

    private Minesweeper mine;
    private Cell[][] cells;

    public void paintComponent(Graphics g){

        cells = mine.getCells();

        for (int i = 0; i < mine.getx(); i++){

            for (int j = 0; j < mine.gety(); j++){

                Cell current = cells[i][j];

                //Flagged cells
                if (current.isFlagged()){

                    if (current.isMine() && mine.isFinished()){

                        g.setColor(Color.ORANGE); //Let's the player know which mines they got right when the game is finished.
                        g.fillRect(i * 20, j * 20, i * 20 + 20, j * 20 + 20);
                        g.setColor(Color.BLACK);

                        g.drawLine(i * 20, j * 20, i * 20 + 20, j * 20 + 20);
                        g.drawLine(i * 20, j * 20 + 20, i * 20 + 20, j * 20);
                    }
                    else if (mine.isFinished()){ //Shows cells that the player incorrectly identified as mines.
                        g.setColor(Color.YELLOW);
                        g.fillRect(i * 20, j * 20, i * 20 + 20, j * 20 + 20);
                        g.setColor(Color.BLACK);
                    }
                    else{
                        g.setColor(Color.GREEN); //Flagging a mine.
                        g.fillRect(i * 20, j * 20, i * 20 + 20, j * 20 + 20);
                        g.setColor(Color.BLACK);
                    }
                }

                //Unflagged cells
                else if (current.isCovered()){ //Covered cells
                    g.setColor(Color.DARK_GRAY);
                    g.fillRect(i * 20, j * 20, i * 20 + 20, j * 20 + 20);
                    g.setColor(Color.BLACK);
                }
                else if (current.isMine()){ //Incorrect cells are shown when the game is over.=
                    g.setColor(Color.RED);
                    g.fillRect(i * 20, j * 20, i * 20 + 20, j * 20 + 20);
                    g.setColor(Color.BLACK);
                    g.drawLine(i * 20, j * 20, i * 20 + 20, j * 20 + 20);
                    g.drawLine(i * 20, j * 20 + 20, i * 20 + 20, j * 20);
                }
                else{ //Empty cells or numbered cells
                    g.setColor(Color.LIGHT_GRAY);
                    g.fillRect(i * 20, j * 20, i * 20 + 20, j * 20 + 20);
                    g.setColor(Color.BLACK);
                }

                //The following part is very self explanatory - drawing the numbers.
                //Not very interesting work.
                //Not a fun time.
                //Rating: 0/10. Would not recommend.

                if (!current.isCovered()){
                    if (current.getNumber() == 1){
                        g.drawLine(i * 20 + 13, j * 20 + 5, i * 20 + 13, j * 20 + 9);    //3
                        g.drawLine(i * 20 + 13, j * 20 + 11, i * 20 + 13, j * 20 + 15);    //6
                    }
                    else if (current.getNumber() == 2){
                        g.drawLine(i * 20 + 8, j * 20 + 4, i * 20 + 12, j * 20 + 4);    //2
                        g.drawLine(i * 20 + 13, j * 20 + 5, i * 20 + 13, j * 20 + 9);    //3
                        g.drawLine(i * 20 + 8, j * 20 + 10, i * 20 + 12, j * 20 + 10);    //4
                        g.drawLine(i * 20 + 7, j * 20 + 11, i * 20 + 7, j * 20 + 15);    //5
                        g.drawLine(i * 20 + 8, j * 20 + 16, i * 20 + 12, j * 20 + 16);    //7
                    }
                    else if (current.getNumber() == 3){
                        g.drawLine(i * 20 + 8, j * 20 + 4, i * 20 + 12, j * 20 + 4);    //2
                        g.drawLine(i * 20 + 13, j * 20 + 5, i * 20 + 13, j * 20 + 9);    //3
                        g.drawLine(i * 20 + 8, j * 20 + 10, i * 20 + 12, j * 20 + 10);    //4
                        g.drawLine(i * 20 + 13, j * 20 + 11, i * 20 + 13, j * 20 + 15);    //6
                        g.drawLine(i * 20 + 8, j * 20 + 16, i * 20 + 12, j * 20 + 16);    //7
                    }
                    else if (current.getNumber() == 4){
                        g.drawLine(i * 20 + 7, j * 20 + 5, i * 20 + 7, j * 20 + 9);        //1
                        g.drawLine(i * 20 + 13, j * 20 + 5, i * 20 + 13, j * 20 + 9);    //3
                        g.drawLine(i * 20 + 8, j * 20 + 10, i * 20 + 12, j * 20 + 10);    //4
                        g.drawLine(i * 20 + 13, j * 20 + 11, i * 20 + 13, j * 20 + 15);    //6
                    }
                    else if (current.getNumber() == 5){
                        g.drawLine(i * 20 + 7, j * 20 + 5, i * 20 + 7, j * 20 + 9);        //1
                        g.drawLine(i * 20 + 8, j * 20 + 4, i * 20 + 12, j * 20 + 4);    //2
                        g.drawLine(i * 20 + 8, j * 20 + 10, i * 20 + 12, j * 20 + 10);    //4
                        g.drawLine(i * 20 + 13, j * 20 + 11, i * 20 + 13, j * 20 + 15);    //6
                        g.drawLine(i * 20 + 8, j * 20 + 16, i * 20 + 12, j * 20 + 16);    //7
                    }
                    else if (current.getNumber() == 6){
                        g.drawLine(i * 20 + 7, j * 20 + 5, i * 20 + 7, j * 20 + 9);        //1
                        g.drawLine(i * 20 + 8, j * 20 + 4, i * 20 + 12, j * 20 + 4);    //2
                        g.drawLine(i * 20 + 8, j * 20 + 10, i * 20 + 12, j * 20 + 10);    //4
                        g.drawLine(i * 20 + 7, j * 20 + 11, i * 20 + 7, j * 20 + 15);    //5
                        g.drawLine(i * 20 + 13, j * 20 + 11, i * 20 + 13, j * 20 + 15);    //6
                        g.drawLine(i * 20 + 8, j * 20 + 16, i * 20 + 12, j * 20 + 16);    //7
                    }
                    else if (current.getNumber() == 7){
                        g.drawLine(i * 20 + 8, j * 20 + 4, i * 20 + 12, j * 20 + 4);    //2
                        g.drawLine(i * 20 + 13, j * 20 + 5, i * 20 + 13, j * 20 + 9);    //3
                        g.drawLine(i * 20 + 13, j * 20 + 11, i * 20 + 13, j * 20 + 15);    //6
                    }
                    else if (current.getNumber() == 8){
                        g.drawLine(i * 20 + 7, j * 20 + 5, i * 20 + 7, j * 20 + 9);        //1
                        g.drawLine(i * 20 + 8, j * 20 + 4, i * 20 + 12, j * 20 + 4);    //2
                        g.drawLine(i * 20 + 13, j * 20 + 5, i * 20 + 13, j * 20 + 9);    //3
                        g.drawLine(i * 20 + 8, j * 20 + 10, i * 20 + 12, j * 20 + 10);    //4
                        g.drawLine(i * 20 + 7, j * 20 + 11, i * 20 + 7, j * 20 + 15);    //5
                        g.drawLine(i * 20 + 13, j * 20 + 11, i * 20 + 13, j * 20 + 15);    //6
                        g.drawLine(i * 20 + 8, j * 20 + 16, i * 20 + 12, j * 20 + 16);    //7
                    }
                }
                g.setColor(Color.BLACK);
                g.drawRect(i * 20, j * 20, i * 20 + 20, j * 20 + 20);
            }
        }
    }

    public Board(Minesweeper m){ //Creating a new game so we can draw a board for it
        mine = m;
        cells = mine.getCells();

        addMouseListener(new Actions(mine));

        setPreferredSize(new Dimension(mine.getx() * 20, mine.gety() * 20));
    }

}

//--------------------------------- END of Board.java ---------------------------------

//--------------------------------- START of Actions.java ---------------------------------

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

public class Actions implements ActionListener, MouseListener{

    private Minesweeper mine;

    //These following four are not important. We simply tell the machine to pay no mind when mouse is pressed, released, etc.
    //If these weren't here the computer would freak out and panic over what to do because no instructions were given.

    public void mouseEntered(MouseEvent e){

    }

    public void mouseExited(MouseEvent e){

    }

    public void mousePressed(MouseEvent e){

    }

    public void mouseReleased(MouseEvent e){

    }

    //Where the fun begins

    public Actions(Minesweeper m){

        mine = m;
    }

    //Any time an action is performed, redraw the board and keep it up to date.
    public void actionPerformed(ActionEvent e){

        mine.reset();

        mine.refresh();
    }

    //Mouse clicky clicky
    public void mouseClicked(MouseEvent e){

    	//Left click - opens mine
        if (e.getButton() == 1)
        {
            int x = e.getX() / 20;
            int y = e.getY() / 20;

            mine.select(x, y);
        }

        //Right click - marks mine
        if (e.getButton() == 3)
        {
            int x = e.getX() / 20;
            int y = e.getY() / 20;

            mine.mark(x, y);
        }

        mine.refresh(); //Gotta keep it fresh
    }

}

//--------------------------------- END of Actions.java ---------------------------------

//--------------------------------- START of Minesweeper.java ---------------------------------

import java.awt.BorderLayout;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

public class Minesweeper extends JFrame
{
    private static final long serialVersionUID = 1L;
    private int width, height;
    private int difficulty;
    private Cell[][] cells;
    private Board board;
    private JButton reset;
    private boolean finished;

    public void select(int x, int y){ //Select a mine on the board

        if (cells[x][y].isFlagged()) //Is the mine flagged?
        	return;

        cells[x][y].reveal(); //Reveal the cell
        resetMarks(); //Reset marks and redraw board
        refresh();

        if (cells[x][y].isMine()) //If a mine is revealed, you lose.
        {
            lose();
        }
        else if (won()) //If the game has been won, you win. Hahahahahaha.
        {
            win();
        }
    }

    private void setNumbers(){ //For each cell, count the amount of mines in surrounding squares.
    	                       //Because the board is modeled as a 2D array, this is relatively easy - simply check the surrounding addresses for mines.
    						   //If there's a mine, add to the count.

        for (int i = 0; i < width; i++){

            for (int j = 0; j < height; j++){

                int count = 0;

                if (i > 0 &&  j > 0 && cells[i - 1][j - 1].isMine())
                	count++;

                if (j > 0 && cells[i][j - 1].isMine())
                	count++;

                if (i < width - 1 && j > 0 && cells[i + 1][j - 1].isMine())
                	count++;

                if (i > 0 && cells[i - 1][j].isMine())
                	count++;

                if (i < width - 1 && cells[i + 1][j].isMine())
                	count++;

                if (i > 0 && j < height - 1 && cells[i - 1][j + 1].isMine())
                	count++;

                if (j < height - 1 && cells[i] [j + 1].isMine())
                	count++;

                if (i < width - 1 && j < height - 1 && cells[i + 1][j + 1].isMine())
                	count++;

                cells[i][j].setNumber(count);

                if (cells[i][j].isMine())
                    cells[i][j].setNumber(-1);

                if (cells[i][j].getNumber() == 0)
                    cells[i][j].reveal();

            }
        }

        for (int i = 0; i < width; i++){ //This is for the beginning of the game.
        	                             //If the 8 cells around certain cell have no mines beside them (hence getNumber() = 0) beside them, this cell is empty.

            for (int j = 0; j < height; j++){

                if (i > 0 && j > 0 && cells[i - 1][j - 1].getNumber() == 0)
                	cells[i][j].reveal();

                if (j > 0 && cells[i][j - 1].getNumber() == 0)
                	cells[i][j].reveal();

                if (i < width - 1 && j > 0 && cells[i + 1][j - 1].getNumber() == 0)
                	cells[i][j].reveal();

                if (i > 0 && cells[i - 1][j].getNumber() == 0)
                	cells[i][j].reveal();

                if (i < width - 1 && cells[i + 1][j].getNumber() == 0)
                	cells[i][j].reveal();

                if (i > 0 && j < height - 1 && cells[i - 1][j + 1].getNumber() == 0)
                	cells[i][j].reveal();

                if (j < height - 1 && cells[i][j + 1].getNumber() == 0)
                	cells[i][j].reveal();

                if (i < width - 1 && j < height - 1 && cells[i + 1][j + 1].getNumber() == 0)
                	cells[i][j].reveal();
            }
        }
    }

    public void mark(int x, int y){ //When a player wants to flag/unflag a cell

        if (cells[x][y].isFlagged()) //If the cell is already flagged, unflag it.
        	cells[x][y].unflag();

        else if (cells[x][y].isCovered()) //If the cell has nothing on it and is covered, flag it.
        	cells[x][y].flag();

        resetMarks();
    }

    private void resetMarks(){ //If a cell is not covered, then it cannot be flagged.
    	                       //Every time a player does something, this should be called to redraw the board.

        for (int i = 0; i < width; i++){
            for (int j = 0; j < height; j++){

                if (!cells[i][j].isCovered())
                	cells[i][j].unflag();

            }
        }
    }

    public void reset(){ //Reset the positions of the mines on the board
    	                 //If randomly generated number from 0 to 100 is less than the chosen difficulty, a mine is placed down.
    	                 //This will somewhat accurately reflect the mine percentage that the user requested - the more cells, the more accurate.

        Random random = new Random();
        finished = false;

        for (int i = 0; i < width; i++)  {
            for (int j = 0; j < height; j++)   {

                Cell c = new Cell();
                cells[i][j] = c;
                int r = random.nextInt(100);

                if (r < difficulty)
                {
                    cells[i][j].setMine(); //Put down a mine.
                }

            }
        }
        setNumbers(); //Set the numbers after mines have been put down.
    }

    public int getx() {
        return width;
    }

    public int gety() {
        return height;
    }

    public Cell[][] getCells() {
        return cells;
    }

    public void refresh(){ //Refresh the drawing of the board
        board.repaint();
    }

    private void win(){ //Winning a game
        finished = true;
        for (int i = 0; i < width; i++)
        {
            for (int j = 0; j < height; j++)
            {
                cells[i][j].reveal();//Reveal all cells

                if (!cells[i][j].isMine())
                	cells[i][j].unflag();
            }
        }

        refresh();
        JOptionPane.showMessageDialog(null, "Congratulations! You won!"); //Tell the user they won. They probably deserve to know.
        reset();
    }

    private void lose(){ //Losing a game...basically the same as above.
        finished = true;
        for (int i = 0; i < width; i++)
        {
            for (int j = 0; j < height; j++)
            {
                if (!cells[i][j].isCovered())
                	cells[i][j].unflag();

                cells[i][j].reveal();
            }
        }
        refresh();
        JOptionPane.showMessageDialog(null, "GAME OVER."); //Dialogue window letting the user know that they lost.
        reset();
    }

    private boolean won(){ //Check if the game has been won
        for (int i = 0; i < width; i++){
            for (int j = 0; j < height; j++){

                if (cells[i][j].isCovered() && !cells[i][j].isMine())
                {
                    return false;
                }
            }
        }

        return true;
    }

    public boolean isFinished(){ //Extremely self-explanatory.
        return finished;
    }

    public Minesweeper(int x, int y, int d){

        width = x; //Width of the board
        height = y; //Height of the board
        difficulty = d; //Percentage of mines in the board
        cells = new Cell[width][height];

        reset(); //Set mines on the board

        board = new Board(this); //Create new board
        reset = new JButton("Reset"); //Reset button

        add(board, BorderLayout.CENTER); //Put board in the center
        add(reset, BorderLayout.SOUTH); //IT'S A BUTTON! AND IT WORKS! VERY COOL

        reset.addActionListener(new Actions(this)); //ActionListener to watch for mouse actions

        //GUI window settings
        setTitle("Minesweeper");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(false);
        pack();
        setVisible(true);
    }

}

//--------------------------------- END of Minesweeper.java ---------------------------------


# Minesweeper:

mutable struct Field
    size::Tuple{Int, Int}
    numbers::Array{Int, 2}
    possible_mines::Array{Bool, 2}
    actual_mines::Array{Bool, 2}
    visible::Array{Bool, 2}
end

function Field(x, y)
    size = (x, y)
    actual_mines = convert(Array{Bool, 2}, rand(x, y) .< 0.15)
    possible_mines = zeros(Bool, x, y)
    numbers = zeros(Int, x, y)
    visible = zeros(Bool, x, y)
    for i = 1:x
        for j = 1:y
            n = 0
            for di = -1:1
                for dj = -1:1
                    n += (0 < di+i <= x && 0 < dj+j <= y) ?
                         (actual_mines[di+i, dj+j] ? 1 : 0) : 0
                end
            end
            numbers[i, j] = n
        end
    end
    return Field(size, numbers, possible_mines, actual_mines, visible)
end

function printfield(f::Field; showall = false)
    spaces = Int(floor(log(10, f.size[2])))

    str = " "^(4+spaces)
    for i in 1:f.size[1]
        str *= string(" ", i, " ")
    end
    str *= "\n" * " "^(4+spaces) * "___"^f.size[1] * "\n"
    for j = 1:f.size[2]
        str *= " " * string(j) * " "^(floor(log(10, j)) > 0 ? 1 : spaces+1) * "|"
        for i = 1:f.size[1]
            if showall
                str *= f.actual_mines[i, j] ? " * " : "   "
            else
                if f.visible[i, j]
                    str *= " " * string(f.numbers[i, j] > 0 ? f.numbers[i, j] : " ") * " "
                elseif f.possible_mines[i, j]
                    str *= " ? "
                else
                    str *= " . "
                end
            end
        end
        str *= "\r\n"
    end
    println("Found " * string(length(f.possible_mines[f.possible_mines.==true])) *
            " of " * string(length(f.actual_mines[f.actual_mines.==true])) * " mines.\n")
    print(str)
end

function parse_input(str::String)
    input = split(chomp(str), " ")
    mode = input[1]
    println(str)
    coords =  length(input) > 1 ? (parse(Int,input[2]), parse(Int,input[3])) : (0, 0)
    return mode, coords
end

function eval_input(f::Field, str::String)
    mode, coords = parse_input(str)
    (coords[1] > f.size[1] || coords[2] > f.size[2]) && return true
    if mode == "o"
        reveal(f, coords...) || return false
    elseif mode == "m" && f.visible[coords...] == false
        f.possible_mines[coords...] = !f.possible_mines[coords...]
    elseif mode == "close"
        error("You closed the game.")
    end
    return true
end

function reveal(f::Field, x::Int, y::Int)
    (x > f.size[1] || y > f.size[2]) && return true # check for index out of bounds
    f.actual_mines[x, y] && return false # check for mines
    f.visible[x, y] = true
    if f.numbers[x, y] == 0
        for di = -1:1
            for dj = -1:1
                if (0 < di+x <= f.size[1] && 0 < dj+y <= f.size[2]) &&
                        f.actual_mines[x+di, y+dj] == false &&
                        f.visible[x+di, y+dj] == false
                    reveal(f, x+di, y+dj)
                end
            end
        end
    end
    return true
end

function play()
    print("\nWelcome to Minesweeper\n\nEnter the gridsize x  y:\n")
    s = split(readline(), " ")
    f = Field(parse.(Int,s)...)
    won = false
    while true
        printfield(f)
        print("\nWhat do you do? (\"o x y\" to reveal a field; \"m x y\" to toggle a mine; close)\n")
        eval_input(f, readline()) || break
        print("_"^80 * "\n")
        (f.actual_mines == f.possible_mines ||
              f.visible == .!f.actual_mines) && (won = true; break)
    end
    println(won ? "You won the game!" : "You lost the game:\n")
    printfield(f, showall = true)
end

play()


10 mode 1:randomize time
20 defint a-z
30 boardx=6:boardy=4
40 dim a(boardx,boardy)
50 dim c(boardx+2,boardy+2)
60 dim c2(boardx+2,boardy+2)
70 nmines=int((rnd/3+.1)*boardx*boardy)
80 for i=1 to nmines
90 ' place random mines
100 xp=int(rnd*(boardx-1)+1)
110 yp=int(rnd*(boardy-1)+1)
120 if a(xp,yp) then 100
130 a(xp,yp)=64
140 for xx=xp to xp+2
150 for yy=yp to yp+2
160 c(xx,yy)=c(xx,yy)+1
170 next yy
180 next xx
190 next i
200 gosub 350
210 x=1:y=1
220 gosub 600
230 ' wait for key press
240 k$=lower$(inkey$)
250 if k$="" then 240
260 if k$="q" and y>1 then gosub 660:y=y-1:gosub 600
270 if k$="a" and y<boardy then gosub 660:y=y+1:gosub 600
280 if k$="o" and x>1 then gosub 660:x=x-1:gosub 600
290 if k$="p" and x<boardx then gosub 660:x=x+1:gosub 600
300 if k$="m" then a(x,y)=a(x,y) xor 128:gosub 600:gosub 1070
310 if k$=" " then a(x,y)=a(x,y) or 512:gosub 700:sx=x:sy=y:gosub 450:x=sx:y=sy:gosub 600
320 goto 240
330 end
340 ' print board
350 mode 1
360 gosub 450
370 locate 1,12
380 print "Move on the board with the Q,A,O,P keys"
390 print "Press Space to clear"
400 print "Press M to mark as a potential mine"
410 print
420 print "There are"nmines"mines."
430 return
440 ' update board
450 for y=1 to boardy
460 for x=1 to boardx
470 locate 2*x,y
480 gosub 530
490 next
500 next
510 return
520 ' print tile
530 if a(x,y) and 128 then print "?":return
540 if c(x+1,y+1)=0 then d$=" " else d$=chr$(c(x+1,y+1)+48)
550 if a(x,y) and 256 then print d$:return
560 'if a(x,y) and 64 then print "M":return
570 print "."
580 return
590 ' turn on tile
600 locate 2*x,y
610 pen 0:paper 1
620 gosub 530
630 pen 1:paper 0
640 return
650 ' turn off tile
660 locate 2*x,y
670 gosub 530
680 return
690 ' clear tile
700 if a(x,y) and 64 then locate 15,20:print "*** BOOM! ***":end
710 locate 1,25:print "-WAIT-";
720 for x2=1 to boardx
730 for y2=1 to boardy
740 c2(x2+1,y2+1)=a(x2,y2)
750 next
760 next
770 ' iterate clearing
780 cl=0
790 for x2=1 to boardx
800 for y2=1 to boardy
810 if c2(x2+1,y2+1) and 512 then gosub 940:cl=cl+1
820 next y2
830 next x2
840 if cl then 780
850 for x2=1 to boardx
860 for y2=1 to boardy
870 vv=c2(x2+1,y2+1)
880 if vv>1000 then a(x2,y2)=vv xor 1024
890 next y2
900 next x2
910 locate 1,25:print "      ";
920 return
930 ' find neighbors
940 c2(x2+1,y2+1)=(c2(x2+1,y2+1) xor 512) or 256 or 1024
950 for ii=0 to 2
960 for jj=0 to 2
970 if ii=0 and jj=0 then 1030
980 if c2(x2+ii,y2+jj) and 64 then 1030
990 if c2(x2+ii,y2+jj) and 128 then 1030
1000 if c2(x2+ii,y2+jj) and 1024 then 1030
1010 c2(x2+ii,y2+jj)=c2(x2+ii,y2+jj) or 512
1020 ' next tile
1030 next jj
1040 next ii
1050 return
1060 ' update discovered mine count
1070 mm=0
1080 for x2=1 to boardx
1090 for y2=1 to boardy
1100 if (a(x2,y2) and 128)>0 and (a(x2,y2) and 64)>0 then mm=mm+1
1110 next
1120 next
1130 if mm=nmines then locate 5,22:print "Congratulations, you've won!":end
1140 return


Module Minesweeper {
      Font "Arial Black"
      Bold 0
      Form 60,40
      Refresh 1000
      Def com$, com_label$
      Def x, b_row, b_col, where, top_where
      Def rows=4, columns=6, swap_first%
      Def boolean skiptest, end_game, cheat
      Dim Board$(0 to rows+1, 0 to columns+1)="? "
      Def mines%, i%, j%, used%, acc%, n%, m%
      mines%=max.data(random(int(columns*rows*.1),int(columns*rows*.2)-1), 1)
      For i%=1 to rows:For j%=1 to columns
            Board$(i%,j%)=". "
      Next j%:Next i%
      used%=mines%
      While used%
            used%--
            Do
                  i%=random(1,rows)
                  j%=random(1, columns)
            Until right$(Board$(i%,j%),1)=" "
            Board$(i%,j%)=".*"
      End While
      used%=rows*columns-mines%
      \\ remove rem so to never loose from first open
      Rem :
      swap_first%=used%
      \\ when mines%=0 or used%=0 then player win
      Report {Minesweeper - rosettacode task
            Commands:
            -  ? 1 2  flag/unflag 1 2
            -  1 2   open 1 2
            -  q  to quit
            You can pass multiple commands in a line, but q erase all before execute
      }
      top_where=Row
      While not End_Game {GameLoop()}
      End
      Sub PrintBoard()
      Cls, top_where
      Print
      Print "   X  ";
      For j%=1 to columns {
            Print format$("{0::-3}  ", j%);
      }
      Print
      For i%=1 to rows {
            Print format$(" {0::-3}  ", i%);
            For j%=1 to columns {
                  Print "  ";Left$(Board$(i%,j%),1);"  ";
                  \\ rem above and unrem follow line to display mines
                  Rem: Print "  ";Board$(i%,j%)+" ";
            }
            Print
      }
      End Sub
      Sub PrintMines()
      Cls, top_where
      Print
      Print "   X  ";
      For j%=1 to columns {
            Print format$("{0::-3}  ", j%);
      }
      Print
      For i%=1 to rows {
            Print format$(" {0::-3}  ", i%);
            For j%=1 to columns {
                  Print "  ";Right$(Board$(i%,j%),1);"  ";
            }
            Print
      }
      End Sub
      Sub GameLoop()
            Local com$, loopagain as boolean
            PrintBoard()
            InputCommand()
            do
                  loopagain=true
                  while not empty
                              \\ process game command
                        Read com$
                        if com$="q " Then
                              Print "Quit" : end_game=True : exit
                        Else.if com$="o " Then
                              OpenCell()
                        Else.if com$="n " Then
                              OpenCell2()
                        Else.if com$="? " Then
                              SwapCell()
                        Else.if com$="c " Then
                              Exit Sub
                        End if
                  End While
                  If mines%=0 or used%=0 then
                        PrintBoard(): Print "Player Win": end_game=True: Exit Sub
                  End if
                  If mines%=-1 then
                        if swap_first%=used% then
                              mines%=rows*columns-used%
                              Local n%, m%
                              While mines%
                                    Let n%=random(1,rows), m%=random(1, columns)
                                    If Board$(n%, m%)=". " then  Board$(n%, m%)=".*" : mines%=0
                              End While
                              Board$(i%, j%)=". "
                              mines%=rows*columns-used%
                              swap_first%=-100
                              Push i%, j%, "o "
                              loopagain=false
                        else
                              PrintMines(): Print "Player Loose": end_game=True : Exit Sub
                        end if
                  End If
            Until loopagain
            Flush
            Refresh if(End_Game->10,1000)
      End Sub
      Sub InputCommand()
            where=row
            While com$=""
                  cls, where
                  Print "x x | ? x x | q >";
                  Refresh 10
                  Try {
                        Input "", com$
                  }
            End While
            x=1
            Flush
            While com$<>""
                  com_label$=""
                  ParseCommand()
                  if len(com_label$)<>2 then
                        com$="" : Print com_label$ : Flush
                        Refresh 10
                        push key$ : drop
                  else
                        Data com_label$, b_col, b_row
                  End if
            End While
            Refresh 1000
      End Sub
      Sub ParseCommand()
            com_label$="o "
            skiptest=true
            ReadColumn()
            if len(com_label$)<>2 then
                  com$=""
            Else.if x=-1 then
                  com_label$=lcase$(Left$(com$,1))+" "
                  com$=mid$(com$, 2)
                  x=1
                  if len(com_label$)<>2 then
                        com_label$="no command found"
                  else.if com_label$="? " then
                        ReadColumn()
                        if x>-1 then ReadRow()
                  else.if com_label$="c " then
                        cheat=true
                  else.if com_label$="q " then
                        flush
                        com$=""
                  else
                        com_label$="Use q or ? for commands"
                        com$=""
                  End if
            else
                  ReadRow()
                  if x>-1 then com_label$="o "
            End if
      End Sub
      Sub ReadRow()
            com$=mid$(com$,x)
            b_row=val(com$, "??", x)
            if x=-1 then
                  com_label$="Need a row"
            else.if b_row<1 or b_row>rows then
                  com_label$="Need a row from 1 to "+str$(rows)
                  x=-1
            else
                  com$=mid$(com$,x+1)
                  x=1
            End if
      End Sub
      Sub ReadColumn()
            com$=mid$(com$,x)
            b_col=val(com$, "??", x)
            if x=-1 then
                  if not skiptest then com_label$="Need a column"
            else.if b_col<1 or b_col>columns then
                  com_label$="Need a column from 1 to"+str$(columns)
            else
                  com$=mid$(com$,x+1)
                  x=1
            End if
            skiptest=false
      End Sub
      Sub SwapCell()
            Read j%, i%
            If left$(Board$(i%,j%),1)="?" then
                  Board$(i%,j%) ="."+Right$(Board$(i%,j%),1)
                  If cheat Then if Right$(Board$(i%,j%),1)="*" then mines%++
            Else.If left$(Board$(i%,j%),1)="." then
                  Board$(i%,j%) ="?"+Right$(Board$(i%,j%),1)
                  If cheat Then if Right$(Board$(i%,j%),1)="*" then mines%--
            End if
      End Sub
      Sub OpenCell()
            Read j%, i%
            If left$(Board$(i%,j%),1)="." then {
                  if Right$(Board$(i%,j%),1)="*" then mines%=-1 : flush : exit
                  acc%=0
                  used%--
                  Local n%, m%
                  For n%=i%-1 to i%+1 {
                        For m%=j%-1 to j%+1 {
                                If Right$(Board$(n%,m%),1)="*" then acc%++
                        }
                  }
                  For n%=i%-1 to i%+1 {
                        For m%=j%-1 to j%+1 {
                             if not (n%=i% and m%=j%) then
                                   if not Right$(Board$(n%,m%),1)="*" then
                                         If left$(Board$(n%,m%),1)="." then
                                              Push n%, m%, "n "  ' reverse to stack
                                              Rem : Print stack.size : Refresh
                                         End If
                                   End If
                             End If
                        }
                  }
                  Board$(i%,j%)=if$(acc%=0->"  ",str$(acc%, "# "))
            }
      End Sub
      Sub OpenCell2()
            Read J%, i%
            If left$(Board$(i%,j%),1)="." then {
                  if Right$(Board$(i%,j%),1)="*" then exit
                  acc%=0
                  used%--
                  For n%=i%-1 to i%+1 {
                        For m%=j%-1 to j%+1 {
                                If Right$(Board$(n%,m%),1)="*" then acc%++
                        }
                  }
                  \\ if cell has no mines around then we check all
                  if acc%=0 then
                        Local n%, m%
                        For n%=i%-1 to i%+1
                              For m%=j%-1 to j%+1
                                   if not (n%=i% and m%=j%) then
                                         if not Right$(Board$(n%,m%),1)="*" then
                                               If left$(Board$(n%,m%),1)="." then
                                                    Push n%, m%, "o "  ' reverse to stack
                                                    Rem : Print stack.size : Refresh
                                               End If
                                         End If
                                   End If
                              Next m%
                        Next n%
                  End If
                  Board$(i%,j%)=if$(acc%=0->"  ",str$(acc%, "# "))
            }
      End Sub
}
Minesweeper


DynamicModule[{m = 6, n = 4, minecount, grid, win, reset, clear,
  checkwin},
 reset[] :=
  Module[{minesdata, adjacentmines},
   minecount = RandomInteger[Round[{.1, .2} m*n]];
   minesdata =
    [email protected][# -> 1 & /@
       RandomSample[Tuples[Range /@ {m, n}], minecount], {m, n}];
   adjacentmines =
    ArrayPad[
     Total[RotateLeft[
         ArrayPad[minesdata,
          1], #] & /@ {{-1, -1}, {0, -1}, {1, -1}, {-1, 0}, {1,
         0}, {-1, 1}, {0, 1}, {1, 1}}], -1];
   grid = Array[{If[minesdata[[#1, #2]] == 1, "*",
        adjacentmines[[#1, #2]]], ".", 1} &, {m, n}]; win = ""];
 clear[i_, j_] :=
  If[grid[[i, j, 1]] == "*", win = "You lost.";
    grid = grid /. {{n_Integer, "?", _} :> {n, "x", 0}, {"*",
         ".", _} :> {"*", "*", 0}},
    grid[[i, j]] = {grid[[i, j, 1]], grid[[i, j, 1]], 0};
    If[grid[[i, j, 2]] == 0, grid[[i, j, 2]] = "";
     clear[i + #[[1]],
        j + #[[2]]] & /@ {{-1, -1}, {0, -1}, {1, -1}, {-1, 0}, {1,
        0}, {-1, 1}, {0, 1}, {1, 1}}]] /;
   1 <= i <= m && 1 <= j <= n && grid[[i, j, 2]] == ".";
 checkwin[] :=
  If[FreeQ[grid, {_Integer, "?", _} | {_, "*", _} | {_Integer,
      ".", _}], win = "You win.";
   grid = grid /. {{"*", ".", _} :> {"*", "?", 1}}];
 reset[];
 [email protected]@{[email protected]{[email protected], "\t",
      Button["Reset", reset[]]},
    Grid[Table[
      With[{i = i, j = j},
       EventHandler[
        Button[Dynamic[grid[[i, j, 2]]], Null, ImageSize -> {17, 17},
         Appearance ->
          Dynamic[If[grid[[i, j, 3]] == 0, "Pressed",
            "DialogBox"]]], {{"MouseClicked", 1} :>
          If[win == "", clear[i, j]; checkwin[]], {"MouseClicked",
           2} :> If[win == "",
           Switch[grid[[i, j, 2]], ".", grid[[i, j, 2]] = "?";
            minecount--, "?", grid[[i, j, 2]] = "."; minecount++];
           checkwin[]]}]], {i, 1, m}, {j, 1, n}], Spacings -> {0, 0}],
     Dynamic[win]}]


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


exception Lost
exception Won

let put_mines g m n mines_number =
  let rec aux i =
    if i < mines_number then
    begin
      let x = Random.int n
      and y = Random.int m in
      if g.(y).(x)
      then aux i
      else begin
        g.(y).(x) <- true;
        aux (succ i)
      end
    end
  in
  aux 0

let print_abscissas n =
  print_string "\n      "; for x = 1 to n do print_int (x mod 10) done;
  print_string "\n      "; for x = 1 to n do print_char '|' done;
  print_newline()

let print_display d n =
  print_abscissas n;
  Array.iteri (fun y line ->
    Printf.printf " %2d - " (y+1);  (* print ordinates *)
    Array.iter print_char line;
    print_newline()
  ) d;
  print_newline()

let reveal d g n =
  print_abscissas n;
  Array.iteri (fun y line ->
    Printf.printf " %2d - " (y+1);  (* print ordinates *)
    Array.iteri (fun x c ->
      print_char (
        match c, g.(y).(x) with
        | '0'..'9', _ -> c
        | '.', true -> 'x'
        | '?', true -> 'X'
        | '?', false -> 'N'
        | '.', false -> '.'
        | _ -> c)
    ) line;
    print_newline()
  ) d;
  print_newline()

let toggle_mark d x y =
  match d.(y).(x) with
  | '.' -> d.(y).(x) <- '?'
  | '?' -> d.(y).(x) <- '.'
  | _ -> ()

let rec feedback g d x y =
  if d.(y).(x) = '.' then
  begin
    let n = ref 0 in  (* the number of mines around *)
    for i = (pred y) to (succ y) do
      for j = (pred x) to (succ x) do
        try if g.(i).(j) then incr n
        with _ -> ()
      done;
    done;
    match !n with
    | 0 ->
        (* recursive feedback when no mines are around *)
        d.(y).(x) <- ' ';
        for j = (pred y) to (succ y) do
          for i = (pred x) to (succ x) do
            try feedback g d i j
            with _ -> ()
          done
        done
    | _ ->
        d.(y).(x) <- (string_of_int !n).[0]
  end

let clear_cell g d x y =
  if g.(y).(x)
  then (d.(y).(x) <- '!'; raise Lost)
  else feedback g d x y

let rec user_input g d =
  try
    let s = read_line() in
    match Scanf.sscanf s "%c %d %d" (fun c x y -> c,x,y) with
    | 'm', x, y -> toggle_mark d (x-1) (y-1)
    | 'c', x, y -> clear_cell g d (x-1) (y-1)
    | _ -> raise Exit
  with Exit | Scanf.Scan_failure _
  | Invalid_argument "index out of bounds" ->
      print_string "# wrong input, try again\n> ";
      user_input g d

let check_won g d =
  let won = ref true in
  Array.iteri (fun y line ->
    Array.iteri (fun x c ->
      match c, g.(y).(x) with
      | '.', _ -> won := false
      | '?', false -> won := false
      | _ -> ()
    ) line
  ) d;
  if !won then raise Won

let minesweeper n m percent =
  let round x = int_of_float (floor (x +. 0.5)) in
  let mines_number = round ((float (n * m)) *. percent) in
  (* the ground containing the mines *)
  let g = Array.make_matrix m n false in
  put_mines g m n mines_number;
  Printf.printf "# You have to find %d mines\n" mines_number;
  (* what's displayed to the user *)
  let d = Array.make_matrix m n '.' in
  try
    while true do
      print_display d n;
      print_string "> ";
      user_input g d;
      check_won g d;
    done
  with
  | Lost ->
      print_endline "# You lost!";
      reveal d g n
  | Won ->
      print_endline "# You won!";
      reveal d g n

let () =
  Random.self_init();
  let ios, fos = int_of_string, float_of_string in
  let n, m, percent =
    try ios Sys.argv.(1), ios Sys.argv.(2), fos Sys.argv.(3)
    with _ ->
      try ios Sys.argv.(1), ios Sys.argv.(2), 0.2
      with _ -> (6, 4, 0.2)
  in
  minesweeper n m percent;
;;


#!/usr/bin/perl
use warnings;
use strict;

{   package Local::Field;

    use constant {
        REAL  => 0,
        SHOW  => 1,
        COUNT => 2,
    };

    sub new {
        my ($class, $width, $height, $percent) = @_;
        my $field;
        for my $x (1 .. $width) {
            for my $y (1 .. $height) {
                $field->[$x - 1][$y - 1][REAL] = ' ';
                $field->[$x - 1][$y - 1][SHOW] = '.';
            }
        }
        for (1 .. $percent / 100 * $width * $height) {
            my ($x, $y) = map int rand $_, $width, $height;
            redo if 'm' eq $field->[$x][$y][REAL];
            $field->[$x][$y][REAL] = 'm';
            for my $i ($x - 1 .. $x + 1) {
                for my $j ($y - 1 .. $y + 1) {
                    $field->[$i][$j][COUNT]++
                        if $i >= 0 and $j >= 0
                        and $i <= $#$field and $j <= $#{ $field->[0] };
                }
            }
        }
        bless $field, $class;
    }

    sub show {
        my ($self) = @_;
        print "\n  ";
        printf '%2d ', $_ + 1 for 0 .. $#$self;
        print "\n";

        for my $row (0 .. $#{ $self->[0] }) {
            printf '%2d ', 1 + $row;
            for my $column (0 .. $#$self) {
                print $self->[$column][$row][SHOW], '  ';
            }
            print "\n";
        }
    }

    sub mark {
        my ($self, $x, $y) = @_;
        $_-- for $x, $y;

        if ('.' eq $self->[$x][$y][SHOW]) {
            $self->[$x][$y][SHOW] = '?';

        } elsif ('?' eq $self->[$x][$y][SHOW]) {
            $self->[$x][$y][SHOW] = '.';
        }
    }

    sub end {
        my $self = shift;
        for my $y (0 .. $#{ $self->[0] }) {
            for my $x (0 .. $#$self) {
                $self->[$x][$y][SHOW] = '!' if '.' eq $self->[$x][$y][SHOW]
                    and 'm' eq $self->[$x][$y][REAL];
                $self->[$x][$y][SHOW] = 'x' if '?' eq $self->[$x][$y][SHOW]
                    and 'm' ne $self->[$x][$y][REAL];
            }
        }
        $self->show;
        exit;
    }

    sub _declassify {
        my ($self, $x, $y) = @_;
        return if '.' ne $self->[$x][$y][SHOW];
        if (' ' eq $self->[$x][$y][REAL] and '.' eq $self->[$x][$y][SHOW]) {
            $self->[$x][$y][SHOW] = $self->[$x][$y][COUNT] || ' ';
        }
        return if ' ' ne $self->[$x][$y][SHOW];

        for my $i ($x - 1 .. $x + 1) {
            next if $i < 0 or $i > $#$self;
            for my $j ($y - 1 .. $y + 1) {
                next if $j < 0 or $j > $#{ $self->[0] };
                no warnings 'recursion';
                $self->_declassify($i, $j);
            }
        }
    }

    sub clear {
        my ($self, $x, $y) = @_;
        $_-- for $x, $y;
        return unless '.' eq $self->[$x][$y][SHOW];

        print "You lost.\n" and $self->end if 'm' eq $self->[$x][$y][REAL];

        $self->_declassify($x, $y);
    }

    sub remain {
        my $self = shift;
        my $unclear = 0;
        for my $column (@$self) {
            for my $cell (@$column) {
                $unclear++ if '.' eq $cell->[SHOW];
            }
        }
        return $unclear;
    }

}

sub help {
    print << '__HELP__';
Commands:
h     ... help
q     ... quit
m X Y ... mark/unmark X Y
c X Y ... clear X Y
__HELP__
}

my ($width, $height, $percent) = @ARGV;
$width   ||= 6;
$height  ||= 4;
$percent ||= 15;

my $field = 'Local::Field'->new($width, $height, $percent);

my $help = 1;
while (1) {
    $field->show;
    help() if $help;
    $help = 0;
    my $remain = $field->remain;
    last if 0 == $remain;
    print "Cells remaining: $remain.\n";
    my $command = <STDIN>;
    exit if $command =~ /^q/i;

    if ($command =~ /^m.*?([0-9]+).*?([0-9]+)/i) {
        $field->mark($1, $2);

    } elsif ($command =~ /^c.*?([0-9]+).*?([0-9]+)/i) {
        $field->clear($1, $2);

    } elsif ($command =~ /^h/i) {
        $help = 1;

    } else {
        print "Huh?\n";
    }
}
print "You won!\n";


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()