How to resolve the algorithm Minesweeper game step by step in the Ruby programming language
How to resolve the algorithm Minesweeper game step by step in the Ruby programming language
Table of Contents
Problem Statement
There is an n by m grid that has a random number (between 10% to 20% of the total number of tiles, though older implementations may use 20%..60% instead) of randomly placed mines that need to be found. Positions in the grid are modified by entering their coordinates where the first coordinate is horizontal in the grid and the second vertical. The top left of the grid is position 1,1; the bottom right is at n,m. The Task is to create a program that allows you to play minesweeper on a 6 by 4 grid, and that assumes all user input is formatted correctly and so checking inputs for correct form may be omitted. You may also omit all GUI parts of the task and work using text input and output. Note: Changes may be made to the method of clearing mines to more closely follow a particular implementation of the game so long as such differences and the implementation that they more accurately follow are described. C.F: wp:Minesweeper (computer game)
Let's start with the solution:
Step by Step solution about How to resolve the algorithm Minesweeper game step by step in the Ruby programming language
The provided Ruby code is a text-based implementation of the classic Minesweeper game. Here's a detailed explanation of the code:
-
Game Introduction:
- The program starts by displaying the rules of Minesweeper:
- A grid is randomly populated with mines, and the player's goal is to uncover all non-mine cells.
- The player can mark suspected mine positions or clear non-mine cells.
- Clearing a non-mine cell may recursively uncover adjacent non-mine cells.
- The program starts by displaying the rules of Minesweeper:
-
Game Constants:
- The game is played on a fixed-size grid:
WIDTH = 6
(horizontal cells) andHEIGHT = 4
(vertical cells). - The percentage of cells that are mines is defined by
PCT = 0.15
, resulting inNUM_MINES = 3
mines in this grid size.
- The game is played on a fixed-size grid:
-
Grid Representation:
- Two data structures represent the game state:
$mines
: A 2D array that stores the true positions of mines on the grid. Initially, it's set tonil
until the player starts uncovering cells.$screen
: A 2D array that represents the player's view of the grid. Initially, all cells are obscured with a single dot (.
).
- Two data structures represent the game state:
-
Game Initialization:
- The game starts with a welcome message and an empty grid (
show_grid
).
- The game starts with a welcome message and an empty grid (
-
Input Handling:
- The game loop continuously prompts the player for input.
- The player can enter one of the following commands:
m <x> <y>
: Toggle a mine mark at position<x>, <y>
c <x> <y>
: Clear the cell at position<x>, <y>
p
: Print the current state of the gridquit
,exit
,x
,q
: Quit the game
-
Mine Placement:
- When the player starts uncovering cells, the
create_mines
method is called to randomly place theNUM_MINES
mines on the grid, avoiding the initial position entered by the player.
- When the player starts uncovering cells, the
-
Marking Cells:
- The
m <x> <y>
command toggles the mark status of the cell at position<x>, <y>
between a dot (.
- unmarked) and a question mark (?
- marked).
- The
-
Clearing Cells:
- The
c <x> <y>
command triggers the following actions:- It checks if the cell at position
<x>, <y>
is a mine. If it is, the player loses, and the mines are revealed. - If the cell is not a mine, the
clear_space
method is called to recursively uncover adjacent non-mine cells. - The
clear_space
method counts the number of surrounding mines and updates the cell with the count or a space (
- It checks if the cell at position
- The
-
Victory Check:
- The
victory?
method checks if the player has correctly identified all mines. If all mines are marked and no clear cells remain unmarked, the player wins.
- The
-
Quitting the Game:
- The player can quit the game by entering any of the following commands:
quit
,exit
,x
, orq
.
- Main Game Loop:
- The game loop continues until the player quits or wins.
- Each iteration of the loop prompts the player for input, validates it, and performs the corresponding action.
Source code in the ruby programming language
puts <<EOS
Minesweeper game.
There is an n by m grid that has a random number of between 20% to 60%
of randomly hidden mines that need to be found.
Positions in the grid are modified by entering their coordinates
where the first coordinate is horizontal in the grid and the second
vertical. The top left of the grid is position 1,1; the bottom right is
at n,m.
* The total number of mines to be found is shown at the beginning of the
game.
* Each mine occupies a single grid point, and its position is initially
unknown to the player
* The grid is shown as a rectangle of characters between moves.
* You are initially shown all grids as obscured, by a single dot '.'
* You may mark what you think is the position of a mine which will show
as a '?'
* You can mark what you think is free space by entering its coordinates.
:* If the point is free space then it is cleared, as are any adjacent
points that are also free space- this is repeated recursively for
subsequent adjacent free points unless that point is marked as a mine
or is a mine.
::* Points marked as a mine show as a '?'.
::* Other free points show as an integer count of the number of adjacent
true mines in its immediate neighbourhood, or as a single space ' ' if the
free point is not adjacent to any true mines.
* Of course you loose if you try to clear space that starts on a mine.
* You win when you have correctly identified all mines.
When prompted you may:
Toggle where you think a mine is at position x, y:
m <x> <y>
Clear the grid starting at position x, y (and print the result):
c <x> <y>
Print the grid so far:
p
Quit
q
Resigning will first show the grid with an 'N' for unfound true mines, a
'Y' for found true mines and a '?' for where you marked clear space as a
mine
EOS
WIDTH, HEIGHT = 6, 4
PCT = 0.15
NUM_MINES = (WIDTH * HEIGHT * PCT).round
def create_mines sx, sy
arr = Array.new(WIDTH) { Array.new(HEIGHT, false) }
NUM_MINES.times do
x, y = rand(WIDTH), rand(HEIGHT)
# place it if it isn't at (sx, sy) and we haven't already placed a mine
redo if arr[x][y] or (x == sx and y == sy)
arr[x][y] = true
end
arr
end
def num_marks
$screen.inject(0) { |sum, row| sum + row.count("?") }
end
def show_grid revealed = false
if revealed
puts $mines.transpose.map { |row| row.map { |cell| cell ? "*" : " " }.join(" ") }
else
puts "Grid has #{NUM_MINES} mines, #{num_marks} marked."
puts $screen.transpose.map{ |row| row.join(" ") }
end
end
SURROUND = [-1,0,1].product([-1,0,1]) - [[0,0]] # surround 8
def surrounding x, y
# apply the passed block to each spot around (x, y)
SURROUND.each do |dx, dy|
# don't check if we're out of bounds, or at (0,0)
yield(x+dx, y+dy) if (0...WIDTH).cover?(x+dx) and (0...HEIGHT).cover?(y+dy)
end
end
def clear_space x, y
return unless $screen[x][y] == "."
# check nearby spaces
count = 0
surrounding(x, y) { |px, py| count += 1 if $mines[px][py] }
if count == 0
$screen[x][y] = " "
surrounding(x, y) { |px, py| clear_space px, py }
else
$screen[x][y] = count.to_s
end
end
def victory?
return false if $mines.nil? # first one, don't need to check
return false if num_marks != NUM_MINES
mines_left = NUM_MINES
WIDTH.times do |x|
HEIGHT.times do |y|
mines_left -= 1 if $mines[x][y] and $screen[x][y] == "?"
end
end
mines_left == 0
end
def check_input x, y
x, y = x.to_i - 1, y.to_i - 1
[x, y] if (0...WIDTH).cover?(x) and (0...HEIGHT).cover?(y)
end
$mines = nil
$screen = Array.new(WIDTH) { Array.new(HEIGHT, ".") }
puts "Welcome to Minesweeper!"
show_grid
loop do
print "> "
action = gets.chomp.downcase
case action
when "quit", "exit", "x", "q"
puts "Bye!"
break
when /^m (\d+) (\d+)$/
# mark this cell
x, y = check_input $1, $2
next unless x
if $screen[x][y] == "."
# mark it
$screen[x][y] = "?"
if victory?
show_grid
puts "You win!"
break
end
elsif $screen[x][y] == "?"
# unmark it
$screen[x][y] = "."
end
show_grid
when /^c (\d+) (\d+)$/
x, y = check_input $1, $2
next unless x
$mines ||= create_mines(x, y)
if $mines[x][y]
puts "You hit a mine!"
show_grid true
break
else
clear_space x, y
show_grid
if victory?
puts "You win!"
break
end
end
when "p"
show_grid
end
end
You may also check:How to resolve the algorithm Repeat step by step in the Fe programming language
You may also check:How to resolve the algorithm Deceptive numbers step by step in the Python programming language
You may also check:How to resolve the algorithm Variable size/Get step by step in the ooRexx programming language
You may also check:How to resolve the algorithm Determine if a string is numeric step by step in the Batch File programming language
You may also check:How to resolve the algorithm Averages/Arithmetic mean step by step in the Maxima programming language