Created
September 30, 2015 00:14
-
-
Save ryandgoldenberg1/d8da85762ff5637a3c7d to your computer and use it in GitHub Desktop.
Terminal Sudoku in Ruby
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 '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