Created
July 30, 2015 10:01
-
-
Save JaciBrunning/fecbe9205627676bea5d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'io/console' | |
require 'optparse' | |
# Field Constants | |
@field_size = 10 | |
@bomb_count = 10 | |
OptionParser.new do |o| | |
o.on("-f SIZE", "--field", "Set the field size (square)") { |f| @field_size = f.to_i } | |
o.on("-b COUNT", "--bomb", "Set the bomb count") { |b| @bomb_count = b.to_i } | |
end.parse! | |
# Colors | |
RED = [31, 0] | |
GREEN = [32, 0] | |
BROWN = [33, 0] | |
WHITE = [0, 0] | |
GRAY = [37, 0] | |
BLACK = [30, 0] | |
WHITE_BG = [47, 0] | |
# The currently selected cell | |
SELECTED = [0, 0] | |
# Read character from input -- Parses arrows and other codes | |
def readchar | |
input = STDIN.getch | |
if input == "\e" | |
input << STDIN.read_nonblock(3) rescue nil | |
input << STDIN.read_nonblock(2) rescue nil | |
end | |
input | |
end | |
# Colorize a String | |
def col color, s | |
"\033[#{color[0]}m#{s}\033[#{color[1]}m" | |
end | |
# Symbol Constants | |
NONE = "-" | |
FLAG = col BROWN, "*" | |
BOMB = col RED, "x" | |
# Generate Bombs | |
@field = Array.new(@field_size).fill { Array.new(@field_size).fill { {:bomb => false, :revealed => false, :flagged => false, :adj => 0} } } | |
@bomb_count.times do |x| | |
sample = @field.sample.sample | |
while (sample[:bomb]) | |
sample = @field.sample.sample | |
end | |
@field.sample.sample[:bomb] = true | |
end | |
# Get all adjacent cells | |
def get_adj cell | |
cells = [] | |
3.times do |dx| | |
3.times do |dy| | |
nx = cell[0] + 1 - dx | |
ny = cell[1] + 1 - dy | |
if (nx != -1 && nx < @field_size && ny != -1 && ny < @field_size) | |
cells << [nx, ny] | |
end | |
end | |
end | |
cells | |
end | |
# Generate adjacents | |
@field.each_with_index do |row, x| | |
row.each_with_index do |cell, y| | |
unless cell[:bomb] | |
count = 0 | |
cells = get_adj [x, y] | |
cells.each {|x| count += 1 if @field[x[0]][x[1]][:bomb] } | |
cell[:adj] = count | |
end | |
end | |
end | |
def sel | |
@field[SELECTED[0]][SELECTED[1]] | |
end | |
# Draw the board | |
def draw | |
@field.each_with_index do |row, rind| | |
print " " | |
row.each_with_index do |cell, cind| | |
s = [rind, cind] == SELECTED | |
txt = cell[:adj] | |
txt = NONE unless cell[:revealed] | |
txt = FLAG if cell[:flagged] | |
txt = BOMB if (cell[:revealed] && cell[:bomb]) | |
if s | |
print col(WHITE_BG, col(BLACK, txt)) | |
else | |
print txt | |
end | |
print " " | |
end | |
puts | |
end | |
end | |
# Delete the board | |
def del | |
@field_size.times do | |
print "\r\e[A\e[K" | |
end | |
end | |
draw | |
@do = true | |
# Lose game | |
def lose | |
@do = false | |
@field.each do |row| | |
row.each do |cell| | |
cell[:revealed] = true | |
cell[:flagged] = false | |
end | |
end | |
draw | |
puts col RED, "You Lose!" | |
readchar | |
end | |
# Win game | |
def win | |
@do = false | |
@field.each do |row| | |
row.each do |cell| | |
cell[:revealed] = true | |
end | |
end | |
draw | |
puts col GREEN, "You Win!" | |
readchar | |
exit | |
end | |
# Check for a win | |
def check_win | |
@rev = true | |
@flag = true | |
@field.each do |row| | |
row.each do |cell| | |
if cell[:flagged] && !cell[:bomb] | |
@rev = false | |
elsif !cell[:revealed] && !cell[:bomb] | |
@rev = false | |
end | |
if !cell[:flagged] && cell[:bomb] | |
@flag = false | |
end | |
end | |
end | |
win if (@flag || @rev) | |
end | |
# Reveal a cell, and adjacents if '0' | |
def reveal cell | |
c = @field[cell[0]][cell[1]] | |
unless c[:revealed] | |
c[:revealed] = true | |
if c[:adj] == 0 | |
cells = get_adj cell | |
cells.map { |x| @field[x[0]][x[1]][:bomb] ? nil : x }.compact.each do |x| | |
reveal x | |
end | |
end | |
end | |
end | |
# Read keys | |
while @do | |
char = readchar | |
@do = false if char == "\u0003" | |
match = char.match /\e\[(\w)/ | |
del | |
if match != nil | |
c = match[1] | |
if c == "A" | |
SELECTED[0] -= 1 | |
SELECTED[0] = @field_size - 1 if SELECTED[0] == -1 | |
elsif c == "B" | |
SELECTED[0] += 1 | |
SELECTED[0] = 0 if SELECTED[0] == @field_size | |
elsif c == "C" | |
SELECTED[1] += 1 | |
SELECTED[1] = 0 if SELECTED[1] == @field_size | |
elsif c == "D" | |
SELECTED[1] -= 1 | |
SELECTED[1] = @field_size - 1 if SELECTED[1] == -1 | |
end | |
elsif char == "f" | |
sel[:flagged] = !sel[:flagged] | |
elsif char == "\r" | |
unless (sel[:flagged] || sel[:revealed]) | |
reveal(SELECTED) | |
if sel[:bomb] | |
lose | |
exit | |
end | |
end | |
end | |
check_win | |
draw | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment