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

## 近況報告
　dockerのNginx環境の構築沼にハマり何も勉強が進まなかったので，今回気分転換にオセロを作ってみました。基本的にチュートリアルの範囲からは逸脱しないので文法の復習にはうってつけだと思いました。本項の構成としては最初に●×ゲームを紹介した後にオセロのコーディングを紹介します。

#本日のお題
　オセロを作成する
　　・盤面の作成
　　・石の配置
　　・石を裏返す
　　・反復
 ⬆️の四項目さえできればうまくいくと思う

## 環境
　ruby: 2.5.3

### ●×ゲーム
縦に長いので一部変えています。

```
line1 = "123"　　line2 = "456"　　line3 = "789"　n = 1

puts line1　　
puts line2　⇨３＊３のマスができる　以後この部分は（＊）と省略
puts line3
puts "#{n}ターン目　プレイヤー１のターンです"
input = gets.to_i

unless input > 10　⇨ここの分岐で１〜９以外を弾く
  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　　　☆この段階で０から９９まで入った
  row = []　　　　　配列が出来上がる。ただし，まだ
  m_col.times do　 この段階では８＊８の盤ができて
    row << blank　 いないので，その処理を行う。
  end
  field << row　
end

#壁作成
0.upto(m_col - 1) do |i|　☆０列目と９列目に壁を作る
  field[0][i] = wall     field[m_row - 1 ][i] = wall
end

0.upto(m_row - 1 ) do |i|　☆０行目と９行目に壁を作る
  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|　　　　　　　　　☆隣接している石を時計回りで１つずつ判断していく
    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 "黒の番です 入力例：２(タテ)，３(ヨコ)　"
  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 "白の番です  入力例：２(タテ)，３(ヨコ)　"
  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