#はじめに
Swiftでパズルゲーを作ろうと持っていたが
思いのほか手こずってしまい気分転換にRubyでリバーシを作ってみた
・環境
OSX10.9.5
ruby 2.0.0p481
terminalで起動
・参考
【プログラミング】オセロを1時間で作ってみた【実況解説】
#ソース
https://github.com/konpeto000/ruby-othelo
#解説
initialize
color_choice
showBoard
player_put
については割愛させていただきます
around_check(nx,ny)
x_root = Array.new
y_root = Array.new
@dx_root = Array.new
@dy_root = Array.new
max_count = 0
for j in 0..2
for i in 0..2
if @field[nx+i-1][ny+j-1] == -1 * $player_color
x_root << i-1
y_root << j-1
end
end
end
if x_root.length <= 0
return false
end
for count in 0..x_root.length - 1
empty_flag = 0
x = x_root[count]
y = y_root[count]
dx = nx
dy = ny
while 1
dx += x
dy += y
if dx > 8 || dy > 8 || dx < 1 || dy < 1
empty_flag = 1
break
end
if @field[dx][dy] == 0
empty_flag = 1
break
end
if @field[dx][dy] == $player_color
break
end
end
if empty_flag == 0
max_count += 1
@dx_root << x_root[count]
@dy_root << y_root[count]
end
end
if @dx_root.length > 0
$max_put << max_count
return true
else
return false
end
石を置きたい場所の周りに自分の色とは違う色が存在するなら
その位置をx_root
とy_root
に保存する、存在しなければ置けないとしfalse
を返す
x_root
とy_root
から要素を取り出し各方向にひっくり返せる石が存在するかどうかを調べる
探索範囲がボード外、途中に空白が存在する場合その方向は無効とし保存せず
終端に自分の色が存在する場合のみその方向の位置を保存する
CPUに関する条件
max_count
はその位置に置いたときどれだけ石をひっくり返せるか数える変数
またその値をmax_put
の配列に入れる
stone_put(nx,ny)
@field[nx][ny] = $player_color
for count in 0..@dx_root.length - 1
x = @dx_root[count]
y = @dy_root[count]
dx = nx
dy = ny
while 1
dx += x
dy += y
if @field[dx][dy] == $player_color
break
end
@field[dx][dy] = -1 * @field[dx][dy]
end
end
自分が置く場所に自分の色の石をおく
around_check
で保存した変数を使いひっくり返せる方向をすべてを自分の色にする
pass_check
for j in 1..SQUARES
for i in 1..SQUARES
if @field[i][j] != 0
next
end
if around_check(i,j)
return false
end
end
end
$pass_count += 1
return true
around_check
関数をつかい自分が置ける石があるばあい置けるとしfalse
を返す
そうでない場合pass_count
を1増やしtrue
を返す
pass_count
が2以上の場合それは白、黒お互い置けないを意味する
gameset
w_count = 0
b_count = 0
for j in 1..SQUARES
for i in 1..SQUARES
case @field[i][j]
when 1
w_count += 1
when -1
b_count += 1
end
end
end
if w_count == b_count
print "W:#{w_count} B:#{b_count} Draw!\n"
return true
end
if w_count > b_count
print "W:#{w_count} B:#{b_count} White win!\n"
else
print "W:#{w_count} B:#{b_count} Black win!\n"
end
pass_count
が2以上の場合呼ばれる
フィールド上の白、黒石の個数を数え石の多い方が勝ちと表示する
また引き分けも存在するのでその場合も追加しておく
cpu
$max_put = Array.new
max_x = Array.new
max_y = Array.new
random = rand(100)
if $pass_count >= 2
return true
end
if $player_color == 1
if pass_check
p "White PASS!"
return false
end
else
if pass_check
p "Black PASS!"
return false
end
end
$pass_count = 0
for j in 1..SQUARES
for i in 1..SQUARES
if @field[i][j] != 0
next
end
if around_check(i,j)
max_x << i
max_y << j
end
end
end
$max_put.shift
if random > 10
n = $max_put.index($max_put.max)
else
n = 0
end
if around_check(max_x[n],max_y[n])
stone_put(max_x[n],max_y[n])
end
p "CPU put (#{max_x[n]},#{max_y[n]})"
return false
end
プレイヤーと同じ処理をただ自動でやってもらうだけなのだが
石を置く選択だけちょっと考えてもらうことにした
まず、置ける場所をmax_x
とmax_y
に保存しそれを使い一番ひっくり返せる場所をaround_check
のmax_count
で保存したmax_put
を使い選択する
また10%の確率で置ける場所の一番左上を選択する
#まとめ
前もそうだったが作っている最中はただ動けばいいと考え書いているのだが
もう一度見直すとすごくわかりにくく汚いなぁと感じる
相手に読んでもらえるように綺麗に書くことを心がけたい