95 lines
2.7 KiB
Ruby
95 lines
2.7 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require_relative './position'
|
|
|
|
module ReversiMethods
|
|
WHITE_STONE = 'W'
|
|
BLACK_STONE = 'B'
|
|
BLANK_CELL = '-'
|
|
|
|
def build_initial_board
|
|
# boardは盤面を示す二次元配列
|
|
board = Array.new(8) { Array.new(8, BLANK_CELL) }
|
|
board[3][3] = WHITE_STONE # d4
|
|
board[4][4] = WHITE_STONE # e5
|
|
board[3][4] = BLACK_STONE # d5
|
|
board[4][3] = BLACK_STONE # e4
|
|
board
|
|
end
|
|
|
|
def output(board)
|
|
puts " #{Position::COL.join(' ')}"
|
|
board.each_with_index do |row, i|
|
|
print Position::ROW[i]
|
|
row.each do |cell|
|
|
case cell
|
|
when WHITE_STONE then print ' ○'
|
|
when BLACK_STONE then print ' ●'
|
|
else print ' -'
|
|
end
|
|
end
|
|
print "\n"
|
|
end
|
|
end
|
|
|
|
def copy_board(to_board, from_board)
|
|
from_board.each_with_index do |cols, row|
|
|
cols.each_with_index do |cell, col|
|
|
to_board[row][col] = cell
|
|
end
|
|
end
|
|
end
|
|
|
|
def put_stone(board, cell_ref, stone_color, dry_run: false)
|
|
pos = Position.new(cell_ref)
|
|
raise '無効なポジションです' if pos.invalid?
|
|
raise 'すでに石が置かれています' unless pos.stone_color(board) == BLANK_CELL
|
|
|
|
# コピーした盤面にて石の配置を試みて、成功すれば反映する
|
|
copied_board = Marshal.load(Marshal.dump(board))
|
|
copied_board[pos.row][pos.col] = stone_color
|
|
|
|
turn_succeed = false
|
|
Position::DIRECTIONS.each do |direction|
|
|
next_pos = pos.next_position(direction)
|
|
turn_succeed = true if turn(copied_board, next_pos, stone_color, direction)
|
|
end
|
|
|
|
copy_board(board, copied_board) if !dry_run && turn_succeed
|
|
|
|
turn_succeed
|
|
end
|
|
|
|
def turn(board, target_pos, attack_stone_color, direction)
|
|
return false if target_pos.out_of_board?
|
|
return false if target_pos.stone_color(board) == attack_stone_color
|
|
return false if target_pos.stone_color(board) == BLANK_CELL
|
|
|
|
next_pos = target_pos.next_position(direction)
|
|
if (next_pos.stone_color(board) == attack_stone_color) || turn(board, next_pos, attack_stone_color, direction)
|
|
board[target_pos.row][target_pos.col] = attack_stone_color
|
|
true
|
|
else
|
|
false
|
|
end
|
|
end
|
|
|
|
def finished?(board)
|
|
!placeable?(board, WHITE_STONE) && !placeable?(board, BLACK_STONE)
|
|
end
|
|
|
|
def placeable?(board, attack_stone_color)
|
|
board.each_with_index do |cols, row|
|
|
cols.each_with_index do |cell, col|
|
|
next unless cell == BLANK_CELL
|
|
position = Position.new(row, col)
|
|
return true if put_stone(board, position.to_cell_ref, attack_stone_color, dry_run: true)
|
|
end
|
|
end
|
|
false
|
|
end
|
|
|
|
def count_stone(board, stone_color)
|
|
board.flatten.count { |cell| cell == stone_color }
|
|
end
|
|
end
|