Created
February 9, 2017 08:12
-
-
Save umaz/d4736c2ee98942dc3f59611c1caf1cac to your computer and use it in GitHub Desktop.
com対戦できるオセロ
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
# -*- coding: utf-8 -*- | |
#定数の定義 | |
MAX_TURN = 60 #最大ターン数 | |
BOARD_SIZE = 8 #盤のサイズ(8*8) | |
EMPTY = 0 #空きマス | |
BLACK = 1 #黒石のマス | |
WHITE = -1 #白石のマス | |
WALL = 2 #番兵(ひっくり返すときに使う) | |
ROW_NUM = {"a" => 1, "b" => 2, "c" => 3, "d" => 4, "e" => 5, "f" => 6, "g" => 7, "h" => 8} #列番号 | |
COL_NUM = {"1" => 1, "2" => 2, "3" => 3, "4" => 4, "5" => 5, "6" => 6, "7" => 7, "8" => 8} #行番号 | |
COLOR = {BLACK => "黒", WHITE => "白"} #色 | |
#ひっくり返せる方向 | |
UPPER_LEFT = 1 | |
UPPER = 2 | |
UPPER_RIGHT = 3 | |
RIGHT = 4 | |
LOWER_RIGHT = 5 | |
LOWER = 6 | |
LOWER_LEFT = 7 | |
LEFT = 8 | |
#モード番号 | |
COM = 1 | |
HUMAN = 2 | |
WATCH = 3 | |
#新しい盤の作成 | |
def new_board | |
#盤面を表す二重配列の作成 | |
@board = Array.new(BOARD_SIZE+2){Array.new(BOARD_SIZE+2,EMPTY)} | |
#壁の配置 | |
@board[0].fill(WALL) | |
@board[9].fill(WALL) | |
@board.each do |col| | |
col[0] = WALL | |
col[9] = WALL | |
end | |
#石の初期配置 | |
@board[4][4] = WHITE | |
@board[5][5] = WHITE | |
@board[5][4] = BLACK | |
@board[4][5] = BLACK | |
end | |
#現在の盤の状態を表示 | |
def show_board | |
print("\n\n #{ROW_NUM.keys.join(" ")}\n") #列番号の表示 | |
@board.slice(1...-1).each_with_index do |col, i| | |
print(COL_NUM[(i+1).to_s]) #行番号の表示 | |
col.each do |row| #マスの表示 | |
case row | |
when EMPTY | |
print "\e[32m" | |
print(" □") | |
print "\e[0m" | |
when BLACK | |
print(" ○") | |
when WHITE | |
print(" ●") | |
end | |
end | |
print("\n") | |
end | |
print("\n") | |
end | |
#ゲームの進行 | |
def start_game | |
new_board | |
show_board | |
@turn = 0 | |
@pass_count = 0 | |
@stone_color = BLACK #黒石からスタート | |
while true | |
print("#{COLOR[@stone_color]}の手番です\n") | |
phase | |
show_board | |
stone_count = count | |
print("\n 黒:#{count[0]}, 白:#{count[1]}\n\n") | |
#ゲームの終了 | |
if @turn == MAX_TURN | |
break | |
end | |
if @pass_count == 2 | |
break | |
end | |
end | |
judge | |
end | |
def turnable_direction(col, row) #返せるかどうかの判定とその方向 | |
direction = [] | |
#左上 | |
if @board[col-1][row-1] == -@stone_color #相手の色がある場合 | |
i = 2 | |
while @board[col-i][row-i] == -@stone_color #相手の色が続くまで | |
i += 1 | |
end | |
if @board[col-i][row-i] == @stone_color #相手の色に続くのが自分の色の場合 | |
direction.push(UPPER_LEFT) | |
end | |
end | |
if @board[col-1][row] == -@stone_color #上 | |
i = 2 | |
while @board[col-i][row] == -@stone_color | |
i += 1 | |
end | |
if @board[col-i][row] == @stone_color | |
direction.push(UPPER) | |
end | |
end | |
if @board[col-1][row+1] == -@stone_color #右上 | |
i = 2 | |
while @board[col-i][row+i] == -@stone_color | |
i += 1 | |
end | |
if @board[col-i][row+i] == @stone_color | |
direction.push(UPPER_RIGHT) | |
end | |
end | |
if @board[col][row+1] == -@stone_color #右 | |
i = 2 | |
while @board[col][row+i] == -@stone_color | |
i += 1 | |
end | |
if @board[col][row+i] == @stone_color | |
direction.push(RIGHT) | |
end | |
end | |
if @board[col+1][row+1] == -@stone_color #右下 | |
i = 2 | |
while @board[col+i][row+i] == -@stone_color | |
i += 1 | |
end | |
if @board[col+i][row+i] == @stone_color | |
direction.push(LOWER_RIGHT) | |
end | |
end | |
if @board[col+1][row] == -@stone_color #下 | |
i = 2 | |
while @board[col+i][row] == -@stone_color | |
i += 1 | |
end | |
if @board[col+i][row] == @stone_color | |
direction.push(LOWER) | |
end | |
end | |
if @board[col+1][row-1] == -@stone_color #左下 | |
i = 2 | |
while @board[col+i][row-i] == -@stone_color | |
i += 1 | |
end | |
if @board[col+i][row-i] == @stone_color | |
direction.push(LOWER_LEFT) | |
end | |
end | |
if @board[col][row-1] == -@stone_color #左 | |
i = 2 | |
while @board[col][row-i] == -@stone_color | |
i += 1 | |
end | |
if @board[col][row-i] == @stone_color | |
direction.push(LEFT) | |
end | |
end | |
return direction | |
end | |
#石を置くことができるマスの取得 | |
def get_turnable_cells | |
turnable_cells = [] | |
@board.each_with_index do |col, i| | |
col.each_with_index do |row, j| | |
if row == EMPTY #空きマス | |
turnable_direction = turnable_direction(i,j) #返せる方向の取得 | |
if turnable_direction.size != 0 #ひっくり返せる方向が存在する=石を置けるマス | |
turnable_cells.push([i,j]) #座標を格納 | |
end | |
end | |
end | |
end | |
return turnable_cells | |
end | |
#手番の流れ | |
def phase | |
turnable_cells = get_turnable_cells #石を置くことができるマスの一覧の取得 | |
if turnable_cells.size == 0 | |
print("パスしました\n") | |
@pass_count += 1 | |
@stone_color = -@stone_color | |
else | |
print("#{@turn+1}手目: ") | |
case @mode | |
when COM #COM戦の場合 | |
if @stone_color == @player_color | |
human(turnable_cells) | |
else | |
com(turnable_cells) | |
end | |
when HUMAN #対人戦の場合 | |
human(turnable_cells) | |
when WATCH #観戦の場合 | |
com(turnable_cells) | |
end | |
end | |
end | |
def human(turnable_cells) #人が石を置く操作 | |
cell_list = "" | |
turnable_cells.each do |val| | |
cell_list += "(" + ROW_NUM.key(val[1]) + COL_NUM.key(val[0]) + ")" | |
end | |
move = gets.chomp! | |
if move =~ /[a-h][1-8]/ | |
cell = move.split("") | |
col = COL_NUM[cell[1]] | |
row = ROW_NUM[cell[0]] | |
cell = [col, row] | |
if turnable_cells.include?(cell) #指定されたマスが置くことができるマスの時 | |
put_stone(cell) | |
else | |
print("そのマスには打つことはできません\n") | |
print("打てるマスは#{cell_list}です\n") | |
phase | |
end | |
else | |
print("正しいマスを指定してください\n") | |
phase | |
end | |
end | |
def com(turnable_cells) #COMの場合 | |
cell = turnable_cells.sample | |
col = COL_NUM.key(cell[0]) | |
row = ROW_NUM.key(cell[1]) | |
print(row + col) | |
put_stone(cell) | |
end | |
#石を置く | |
def put_stone(cell) | |
col = cell[0] | |
row = cell[1] | |
@board[col][row] = @stone_color | |
reverse_stone(col, row) | |
@stone_color = -@stone_color #処理が終わったら色を変える | |
@turn += 1 | |
@pass_count = 0 | |
end | |
#石をひっくり返す | |
def reverse_stone(col, row) #石をおいた位置 | |
turn_direction = turnable_direction(col, row) #方向と数を取得 | |
turn_direction.each do |direction| | |
case direction | |
when UPPER_LEFT | |
i = 1 | |
while @board[col-i][row-i] == -@stone_color #相手の色が続くまで | |
@board[col-i][row-i] = @stone_color | |
i += 1 | |
end | |
when UPPER | |
i = 1 | |
while @board[col-i][row] == -@stone_color | |
@board[col-i][row] = @stone_color | |
i += 1 | |
end | |
when UPPER_RIGHT | |
i = 1 | |
while @board[col-i][row+i] == -@stone_color | |
@board[col-i][row+i] = @stone_color | |
i += 1 | |
end | |
when RIGHT | |
i = 1 | |
while @board[col][row+i] == -@stone_color | |
@board[col][row+i] = @stone_color | |
i += 1 | |
end | |
when LOWER_RIGHT | |
i = 1 | |
while @board[col+i][row+i] == -@stone_color | |
@board[col+i][row+i] = @stone_color | |
i += 1 | |
end | |
when LOWER | |
i = 1 | |
while @board[col+i][row] == -@stone_color | |
@board[col+i][row] = @stone_color | |
i += 1 | |
end | |
when LOWER_LEFT | |
i = 1 | |
while @board[col+i][row-i] == -@stone_color | |
@board[col+i][row-i] = @stone_color | |
i += 1 | |
end | |
when LEFT | |
i = 1 | |
while @board[col][row-i] == -@stone_color | |
@board[col][row-i] = @stone_color | |
i += 1 | |
end | |
end | |
end | |
end | |
#石の色を数える | |
def count | |
black = 0 | |
white = 0 | |
@board.each do |col| | |
col.each do |row| | |
case row | |
when BLACK | |
black += 1 | |
when WHITE | |
white += 1 | |
end | |
end | |
end | |
count = [black, white] | |
return count | |
end | |
#勝敗の判定 | |
def judge | |
stone_count = count | |
black = count[0] | |
white = count[1] | |
if black > white | |
print("\n黒:#{black} 対 白:#{white} で黒の勝ち\n\n") | |
elsif white > black | |
print("\n黒:#{black} 対 白:#{white} で白の勝ち\n\n") | |
else | |
print("\n黒:#{black} 対 白:#{white} で引き分け\n\n") | |
end | |
end | |
#メインメニュー | |
def menu | |
while true | |
print("COMと対戦: 1\n") | |
print("二人で対戦: 2\n") | |
print("観戦: 3\n") | |
print("終了: 4\n\n") | |
mode = gets.chomp! | |
if mode.to_i == 4 | |
break | |
end | |
if mode =~ /[1-3]/ | |
@mode = mode.to_i | |
case @mode | |
when COM | |
print("手番を選択してください\n") | |
print("1: 先手(黒), 2: 後手(白)") | |
player = gets.chomp!.to_i | |
case player | |
when 1 | |
print("あなたの先手で始めます\n") | |
@player_color = BLACK | |
when 2 | |
print("comの先手で始めます\n") | |
@player_color = WHITE | |
end | |
end | |
start_game | |
else | |
print("1~4で選択してください\n\n") | |
menu | |
end | |
end | |
end | |
menu |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment