1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

rubyで●×ゲームとオセロ(基礎復習)

Posted at

近況報告

 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

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?