BioinformaticsCS109 Programming ProjectsA sliding puzzleMinesweeper

Minesweeper

In this project we will implement the Minesweeper game.

Minesweeper is played on a rectangle grid. We will use "ASCII art" to represent this grid, as follows (for a 4x4 grid):

  1 2 3 4 
A   1 . 1 
B 1 2 # 1 
C . . 1 1 
D . 2     

When the game starts, a number of bombs are hidden on random positions on the field. In every round, the player "touches" a cell of the field. If the cell contains a bomb, it explodes, the game ends, and the player loses. Otherwise, the cell is uncovered to show the number of bombs in the vicinity, that is, the number of neighboring cells that contain bombs. (Each cell has eight neighbors, including the diagonal neighbors. If the number is zero, the cell is displayed as a blank.)

When the user believes she knows the position of a bomb, she can flag that cell with a marker. It is allowed to change one's mind later and uncover a flagged cell.

If all cells are either uncovered or flagged, and the number of flags is equal to the number of bombs, then the game ends and the player wins.

Here is a run on a small field, ending in a defeat:

 
$ kts minesweeper.kts 4 4 5
                    
  1 2 3 4 
A . . . . 
B . . . . 
C . . . . 
D . . . . 

What cell do you want to check? r3
I don't understand.
What cell do you want to check? a1
                    
  1 2 3 4 
A 1 . . . 
B . . . . 
C . . . . 
D . . . . 

What cell do you want to check? a3
                    
  1 2 3 4 
A 1 . 2 . 
B . . . . 
C . . . . 
D . . . . 

What cell do you want to check? b1
                    
  1 2 3 4 
A 1 . 2 . 
B 3 . . . 
C . . . . 
D . . . . 

What cell do you want to check? d1

BOOM BOOM BOOM BOOM BOOM
                    
  1 2 3 4 
A 1 . 2 . 
B 3 * . * 
C * * . . 
D * . . . 
And a more positive run:
$ kts minesweeper.kts 4 4 5
                    
  1 2 3 4 
A . . . . 
B . . . . 
C . . . . 
D . . . . 

What cell do you want to check? a1
                    
  1 2 3 4 
A 2 . . . 
B . . . . 
C . . . . 
D . . . . 

What cell do you want to check? c1
                    
  1 2 3 4 
A 2 . . . 
B . . . . 
C 2 . . . 
D . . . . 

What cell do you want to check? a3
                    
  1 2 3 4 
A 2 . 4 . 
B . . . . 
C 2 . . . 
D . . . . 

What cell do you want to check? c3
                    
  1 2 3 4 
A 2 . 4 . 
B . . . . 
C 2 . 3 . 
D . . . . 

What cell do you want to check? d4
                    
  1 2 3 4 
A 2 . 4 . 
B . . . . 
C 2 . 3 . 
D . . .   

What cell do you want to check? a1
This cell is already uncovered.
                    
  1 2 3 4 
A 2 . 4 . 
B . . . . 
C 2 . 3 . 
D . . .   

What cell do you want to check? d3
                    
  1 2 3 4 
A 2 . 4 . 
B . . . . 
C 2 . 3 . 
D . . 1   

What cell do you want to check? c4
                    
  1 2 3 4 
A 2 . 4 . 
B . . . . 
C 2 . 3 1 
D . . 1   

What cell do you want to check? #b2
                    
  1 2 3 4 
A 2 . 4 . 
B . # . . 
C 2 . 3 1 
D . . 1   

What cell do you want to check? d1
                    
  1 2 3 4 
A 2 . 4 . 
B . # . . 
C 2 . 3 1 
D 1 . 1   

What cell do you want to check? c1
This cell is already uncovered.
                    
  1 2 3 4 
A 2 . 4 . 
B . # . . 
C 2 . 3 1 
D 1 . 1   

What cell do you want to check? b1
                    
  1 2 3 4 
A 2 . 4 . 
B 2 # . . 
C 2 . 3 1 
D 1 . 1   

What cell do you want to check? #a2
                    
  1 2 3 4 
A 2 # 4 . 
B 2 # . . 
C 2 . 3 1 
D 1 . 1   

What cell do you want to check? #a4
                    
  1 2 3 4 
A 2 # 4 # 
B 2 # . . 
C 2 . 3 1 
D 1 . 1   

What cell do you want to check? b4
                    
  1 2 3 4 
A 2 # 4 # 
B 2 # . 2 
C 2 . 3 1 
D 1 . 1   

What cell do you want to check? #b3
                    
  1 2 3 4 
A 2 # 4 # 
B 2 # # 2 
C 2 . 3 1 
D 1 . 1   

What cell do you want to check? c2
                    
  1 2 3 4 
A 2 # 4 # 
B 2 # # 2 
C 2 3 3 1 
D 1 . 1   

What cell do you want to check? #d2
                    
  1 2 3 4 
A 2 # 4 # 
B 2 # # 2 
C 2 3 3 1 
D 1 # 1   

YOU WIN!

Task

Write a script minesweeper.kts to implement this game. If there are exactly three command line arguments, they are the number of rows, number of columns, and number of bombs. Otherwise, use 8 rows, 8 columns, and 6 bombs.

The field display should look as follows:

$ kts minesweeper.kts 12 36 50
                    1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 
  1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 
A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
B . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
E . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
F . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
G . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
H . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
I . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
J . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
K . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
L . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
You can assume that the number of rows is at most 26 (so the letters A...Z will suffice), and the number of columns is at most 99.

The user enters a cell as g13, that is a letter (uppercase or lowercase is fine) followed by a number.

The user can also flag a cell by entering #g13.

If the cell is already uncovered, an error message is printed. (But it is okay to uncover a cell that was flagged before.)

When a bomb explodes, the whole field is displayed again, this time with the bombs.

Implementation

Since we want to practice data classes and sets, start your script like this:

 
var rows = 8
var cols = 8

data class Pos(val row: Int, val col: Int)
val bombs = mutableSetOf<Pos>() 
val field = Array<Array<Char>>(rows) { Array<Char>(cols) { '.' } }

These are global variables storing the number of rows, number of columns, the positions of the bombs, and the current state of the field. When the game starts, all cells of field are set to '.'. We update them as cells are uncovered or flagged.

Note that field is a two-dimensional array, or, more precisely, an array of arrays. Create it using the syntax shown above. Once this is done, you can use field as a two-dimensional grid. The cell at position row, col can be accessed as field[row][col].

BioinformaticsCS109 Programming ProjectsA sliding puzzleMinesweeper