Skip to content

Instantly share code, notes, and snippets.

@ryandgoldenberg1
Created September 30, 2015 00:14
Show Gist options
  • Save ryandgoldenberg1/d8da85762ff5637a3c7d to your computer and use it in GitHub Desktop.
Save ryandgoldenberg1/d8da85762ff5637a3c7d to your computer and use it in GitHub Desktop.
Terminal Sudoku in Ruby
require 'colorize'
class Tile
attr_reader :value, :given
def initialize(value = 0)
@value = value
@given = value != 0
end
def value=(num)
@value = num unless given
end
def to_s
value.to_s.colorize(color)
end
def color
if given
:green
elsif value == 0
:red
else
:yellow
end
end
end
class Board
attr_reader :grid
def self.from_file(filename)
tiles = File.read(filename).gsub(/\W/, '').split('').map do |num|
Tile.new(num.to_i)
end
Board.new(tiles)
end
def initialize(grid)
@grid = grid
end
def given?(pos)
grid[pos].given
end
def render
grid.each_slice(9) { |row| print_row(row) }
end
def print_row(row)
row.each { |tile| print tile.to_s }
print "\n"
end
def get_row(pos)
(0...9).map { |i| pos / 9 * 9 + i }.map { |i| grid[i].value }
end
def get_col(pos)
(0...9).map { |i| pos % 9 + i * 9 }.map { |i| grid[i].value }
end
def group_solved?(arr)
((1..9).to_a - arr).empty?
end
def get_box(pos)
row_start = (pos / 9) / 3 * 3
col_start = (pos % 9) / 3 * 3
(0...3).map do |i|
(0...3).map do |j|
(row_start + i) * 9 + (col_start + j)
end
end.flatten.map { |i| grid[i].value }
end
def solved?
(0...81).all? do |pos|
group_solved?( get_row(pos) ) &&
group_solved?( get_col(pos) ) &&
group_solved?( get_box(pos) )
end
end
def make_move(choice)
pos = choice[0]
val = choice[1]
@grid[pos].value = val
end
end
class Game
attr_reader :board
def initialize(filename)
@board = Board.from_file(filename)
end
def play
while !solved?
board.render
choice = get_input
make_move(choice)
end
board.render
game_over_message
end
def solved?
board.solved?
end
def get_input
pos = get_pos
val = get_val
[pos, val]
end
def valid_pos?(pos_str)
pos = pos_str.to_i
pos_str =~ /^\d+$/ && pos >= 0 && pos < 81 && !board.given?(pos.to_i)
end
def valid_val?(val_str)
val_str =~ /^[1-9]$/
end
def get_pos
loop do
print "Enter position: "
pos_str = gets.chomp
return pos_str.to_i if valid_pos?(pos_str)
end
end
def get_val
loop do
print "Enter value: "
val_str = gets.chomp
return val_str.to_i if valid_val?(val_str)
end
end
def make_move(choice)
board.make_move(choice)
end
def game_over_message
puts "You win!!"
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment