近況報告
dockerのNginx環境の構築沼にハマり何も勉強が進まなかったので,今回気分転換にオセロを作ってみました。基本的にチュートリアルの範囲からは逸脱しないので文法の復習にはうってつけだと思いました。本項の構成としては最初に●×ゲームを紹介した後にオセロのコーディングを紹介します。
本日のお題
オセロを作成する
・盤面の作成
・石の配置
・石を裏返す
・反復
⬆️の四項目さえできればうまくいくと思う
環境
ruby: 2.5.3
●×ゲーム
縦に長いので一部変えています。
line1 = "123" line2 = "456" line3 = "789" n = 1
puts line1
puts line2 ⇨3*3のマスができる 以後この部分は(*)と省略
puts line3
puts "#{n}ターン目 プレイヤー1のターンです"
input = gets.to_i
unless input > 10 ⇨ここの分岐で1〜9以外を弾く
if 1 <= input && input <= 3
line1.gsub!("#{input}", "×") ⇨文字の入れ替えメソッドgsub
elsif 4 <= input && input <= 6
line2.gsub!("#{input}", "×")
else
line3.gsub!("#{input}", "×")
end
else
puts "不正な値です。ペナルティ:スキップ"
end
(*) n+= 1
while n < 10 ⇨偶数回の反復しかできないため,最初の一回はwhileから外した
puts "#{n}ターン目 プレイヤー2のターンです"
input = gets.to_i
unless input > 10
if 1 <= input && input <= 3
line1.gsub!("#{input}", "●")
elsif 4 <= input && input <= 6
line2.gsub!("#{input}", "●")
else
line3.gsub!("#{input}", "●")
end
else puts "不正な値です。ペナルティ:スキップ"
end
(*) n += 1
puts "#{n}ターン目 プレイヤー1のターンです"
input = gets.to_i
unless input > 10
if 1 <= input && input <= 3
line1.gsub!("#{input}", "×")
elsif 4 <= input && input <= 6
line2.gsub!("#{input}", "×")
else
line3.gsub!("#{input}", "×")
end
else puts "不正な値です。ペナルティ:スキップ"
end
(*) n += 1
end
こんな感じ。直感的にわかる文で構成されています。しかし,オセロでこれをやると冗長な文が出来上がるので配列を用いて,イメージは数学の行列,二次関数のように作成していきます.
オセロ
BL = "●" WH = "○" wall = "+" blank = "*" field = []
m_row = 10 m_col = 10
# 初期化
m_row.times do ☆この段階で0から99まで入った
row = [] 配列が出来上がる。ただし,まだ
m_col.times do この段階では8*8の盤ができて
row << blank いないので,その処理を行う。
end
field << row
end
# 壁作成
0.upto(m_col - 1) do |i| ☆0列目と9列目に壁を作る
field[0][i] = wall field[m_row - 1 ][i] = wall
end
0.upto(m_row - 1 ) do |i| ☆0行目と9行目に壁を作る
field[i][0] = wall field[i][m_col - 1] = wall
end
# 初期位置 ⇨左上を原点にして
field[4][4] = WH field[5][5] = WH
field[4][5] = BL field[5][4] = BL
def print_field(field, m_row) ⇨盤面に整えるメソッド
print " 123456789\n" ⇨ここに\nいれないとずれる
for i in 0..m_row - 1 ⇨反復メソッド
print i.to_s ☆このとき,\nがないと
row = field[i] +++++++++++********++********...
row.each do |stone| みたいな感じで表示される
print stone
end
print "\n"
end
end
# 裏返しメソッド(黒⇨白)
def reverse_black(bl_row, bl_col, field)
direcrions = [[-1,0], [-1,1], [0,1], [1,1], [1,0], [0,-1], [-1,-1]]
direcrions.each do |direction| ☆隣接している石を時計回りで1つずつ判断していく
reverse_pos = [] ⇨敵の石を見つけたら格納する
reverse_row = bl_row + direction[0].to_i ⇨絶対的な位置の確認
reverse_col = bl_col + direction[1].to_i
if field[reverse_row][reverse_col] != "●" ⇨味方の石でないならそのまま処理を進めていくよ
next
end
reverse_flag = false ⇨敵かどうかの判別
reverse_pos << [reverse_row, reverse_col] ⇨敵の配置を格納
while true ☆そこから伸びていく石の先に
reverse_row += direction[0] 味方の石があれば,そこまで格納
reverse_col += direction[1]
if field[reverse_row][reverse_col] == "●"
reverse_pos << [reverse_row, reverse_col]
elsif field[reverse_row][reverse_col] == "○"
reverse_flag = true
break
else
break
end
end
if reverse_flag 格納した石を味方の石に変化させる
reverse_pos.each do |pos|
field[pos[0]][pos[1]] = "○"
end end end end
# 裏返しメソッド(白⇨黒)
def reverse_white(wh_row, wh_col, field)
direcrions = [[-1,0], [-1,1], [0,1], [1,1], [1,0], [0,-1], [-1,-1]]
direcrions.each do |direction|
reverse_pos = []
reverse_row = wh_row + direction[0].to_i
reverse_col = wh_col + direction[1].to_i
if field[reverse_row][reverse_col] != "○"
next
end
reverse_flag = false
reverse_pos << [reverse_row, reverse_col]
while true
reverse_row += direction[0]
reverse_col += direction[1]
if field[reverse_row][reverse_col] == "○"
reverse_pos << [reverse_row, reverse_col]
elsif field[reverse_row][reverse_col] == "●"
reverse_flag = true
break
else
break
end
end
if reverse_flag
reverse_pos.each do |pos|
field[pos[0]][pos[1]] = "●"
end end end end
# 初期位置完成
print_field(field, m_row)
while true do
# 石を置く
puts "黒の番です 入力例:2(タテ),3(ヨコ) "
puts "タテとヨコは,(カンマ)で区切る パスの場合はpと入力"
bl_side = gets
unless bl_side == "p"
bl_side = bl_side.split(",") ⇨string型なのでinteger
bl_row = bl_side[0].to_i にしっかり変更
bl_col = bl_side[1].to_i
field[bl_row][bl_col] = BL ⇨原点からの絶対的な位置に石を置く
reverse_white( bl_row, bl_col, field)
print_field(field, m_row)
end
puts "白の番です 入力例:2(タテ),3(ヨコ) "
puts = "タテとヨコは,(カンマ)で区切る パスの場合はpと入力"
wh_side = gets
unless wh_side == "p"
wh_side = wh_side.split(",")
wh_row = wh_side[0].to_i
wh_col = wh_side[1].to_i
field[wh_row][wh_col] = WH
reverse_black( wh_row, wh_col, field)
print_field(field, m_row)
end
end
適宜編集してご利用ください。
おわりに
オセロで実装できなかったこと
・まった機能
・元に戻す機能
・置けない場所はリダイレクトする機能
ここら辺ができればかなり完成度が高いのかな。これチェスもできそう。
。。。将棋は今の実力じゃ無理www