Created
October 12, 2008 13:56
-
-
Save hakobe/16396 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
class Stone | |
@@STONE_COLORS = [:white, :black] | |
def initialize(heads_color) | |
raise "Invalid type" unless @@STONE_COLORS.include?(heads_color) | |
@heads = heads_color | |
end | |
attr_reader :heads # 表の色 | |
def tails # 裏の色 | |
@heads == :white ? :black : :white | |
end | |
def flip | |
@heads = self.tails | |
end | |
end | |
class Board | |
@@DEFAULT_BOARD_SIZE = 8 | |
def initialize(board_size = @@DEFAULT_BOARD_SIZE) | |
@BOARD_SIZE = board_size | |
@box = Array.new(@BOARD_SIZE) { Array.new(@BOARD_SIZE, nil) } | |
end | |
def set(point, stone) | |
raise "Out of board" unless self.in_board?(point) | |
raise "Invalid stone" unless Stone === stone | |
raise "Already set" if self.get(point) | |
row, column = *point | |
@box[row][column]= stone | |
end | |
def get(point) | |
raise "Out of board" unless self.in_board?(point) | |
row, column = *point | |
@box[row][column] | |
end | |
alias_method :[], :get | |
alias_method :[]=, :set | |
def to_s | |
out = [] | |
rule = { :white => 'w', :black => 'b' } | |
header = " " + (0...@BOARD_SIZE).to_a.join(' ') | |
out.push(header) | |
@box.each_with_index do |row, i| | |
line = i.to_s + "|" | |
row.each do |cell| | |
line += cell ? rule[cell.heads] : ' ' | |
line += "|" | |
end | |
out.push(line) | |
end | |
return out.join("\n") | |
end | |
def in_board?(point) | |
point.all? { |n| (0...@BOARD_SIZE).include?(n) } | |
end | |
end | |
class Game | |
@@DEFAULT_BOARD_SIZE = 8 | |
def initialize(board_size = @@DEFAULT_BOARD_SIZE) | |
@BOARD_SIZE = board_size | |
@board = Board.new(@BOARD_SIZE) | |
c = @BOARD_SIZE / 2 # center | |
@board[[c-1,c-1]] = Stone.new(:black) | |
@board[[c, c ]] = Stone.new(:black) | |
@board[[c-1,c ]] = Stone.new(:white) | |
@board[[c, c-1]] = Stone.new(:white) | |
@current_turn = :black | |
end | |
attr_reader :current_turn | |
def put(point) | |
raise "Invalid point" if point.any? {|e| !(Integer === e)} || point.size != 2 | |
self.flip(point) | |
@board[point] = Stone.new(@current_turn) | |
self.change | |
end | |
def change | |
@current_turn = @current_turn == :white ? :black : :white | |
end | |
def flip_with_dir_from(point, row_dir, colmn_dir) | |
# flip可能か調べる | |
found = nil | |
row, column = *point | |
loop do | |
row += row_dir | |
column += colmn_dir | |
break unless @board.in_board?([row, column]) # ボード外 | |
break unless @board[[row, column]] # 石が連続していない | |
next if @board[[row, column]].heads != @current_turn # まだ続く | |
found = [row, column]; break | |
end | |
return nil if !found || | |
((point[0] - found[0]).abs == 1 || (point[1] - point[1]).abs == 1) | |
# flipする | |
row, column = *point | |
found_row, found_column = *found | |
loop do | |
row += row_dir | |
column += colmn_dir | |
break if row == found_row && column == found_column | |
@board[[row,column]].flip | |
end | |
return found | |
end | |
def flip(point) | |
# 8方向のflipを行う | |
results = [ | |
[ 0,+1], # 右 | |
[ 0,-1], # 左 | |
[+1, 0], # 下 | |
[-1, 0], # 上 | |
[+1,+1], # 右下 | |
[-1,+1], # 右上 | |
[+1,-1], # 左下 | |
[-1,-1], # 左上 | |
].map { |dir| self.flip_with_dir_from(point, *dir) } | |
raise "Invalid flip" if results.all? {|r| r.nil?} | |
end | |
def to_s | |
@board.to_s | |
end | |
end | |
# main | |
game = Game.new | |
error = nil | |
loop do | |
begin | |
puts game | |
puts game.current_turn.to_s + "'s turn" | |
if error | |
puts "!!! " + error + " !!!" | |
error = nil | |
end | |
print '> ' | |
point = gets.chomp.split.map {|e| e.to_i} rescue raise("Invalid input") | |
game.put(point) | |
rescue => e | |
error = e | |
end | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment