fjord/reversi_methods.rb

96 lines
2.7 KiB
Ruby
Raw Normal View History

2024-04-16 20:15:18 +09:00
# 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