棋譜の読み込みまで
棋譜については作るひつようもあまりないかなとは思ったのだけれども打てる場所がなくなって終わる試合などの棋譜を残せば後で変更を加えたときのデバッグが楽になるだろうと思って作ることにした
1. 棋譜の形式を考える
例えば エラー - OWiki のページの棋譜は
e6f4c3c4d3d6e3c2b3d2 f3c5b4f7b6c6b5f2e7f5e2f6c7e8d1a4a5a6d7a3g3h3b2a1g6c8d8f8g4f1e1b1g1h4g5h5h6h7g7c1g2h8g8h1h2a7b7a2a8b8 e6f4c3c4d3d6e3c2b3d2f3b4f5e2e1f1g1f2g3e7 b1a3c5b5a6g4f6h3f7c6c7g6g5d7h6b6e8c8h5h4h2g8f8d8a5d1c1a4a2h7h8g7b8b7a7a8g2h1a1b2
のように一行にまとめられていて複数記載されていたりするが人間が読むこともあるかもしれないので
c4 c3 f5 b4 b3 ...
のような形にする
2. 棋譜を保存する
1. 配列に指し手を保存する
- 棋譜を保存する配列の作成
put_stone
メソッドに引数moveを追加human
,com
それぞれからput_stone
を呼び出すときに指す座標を引数として与える
... def start_game ... @record = [] #棋譜を保存する配列 ... end def put_stone(cell, move) #引数にmoveを追加 ... @record.push(move) ... end
2. ゲーム終了時にタイムスタンプを取得しその名前で棋譜を保存する
#ゲームの進行 require "date" require "fileutils" ... def start_game ... save_record end #棋譜の保存 def save_record print("棋譜を保存しますか?(y/n)\n") ans = gets.chomp! if ans =~ /(y|n)/ if ans == "y" #recordディレクトリがない場合作成する FileUtils.mkdir_p("record") unless FileTest.exist?("record") #現在時刻の取得 time = DateTime.now.strftime('%Y%m%d%H%M') File.open("record/#{time}.record", "w") do |f| @record.each do |rec| f.puts(rec) end end print("#{time}.record で保存しました\n\n") end else print("yかnを入力してください\n") save_record end end
3. 棋譜の読み込み
1. 読み込みモードの作成
... RECORD = 4 ... def menu while true ... if mode =~ /[1-4]/ @mode = mode.to_i case @mode when COM ... when RECORD dir = Dir.glob("record/*.record") #棋譜の一覧の取得 if dir.size == 0 print("棋譜が存在しません\n\n") menu else print("棋譜一覧\n") dir.sort! dir.each_with_index do |name, i| print("#{i+1}: #{name}\n") end print("棋譜ファイル番号を入力してください:") num = gets.chomp!.to_i - 1 file = dir[num] @read_record = [] #読み込んだ棋譜を保存する配列 File.open(file) do |f| f.each_line do |line| @read_record.push(line) end end end end start_game else ... end end end
2. 棋譜の再生
手の表現のされ方は
- 人の指し手 = rowcol(a1~h8)
- comの指し手 = colrow(11~88)
- 棋譜 = rowcol(a1~h8)
put_stoneメソッドが受けつける表現は
`cell = [col, row]
1と3が同じ変換なのでメソッドに分割する
#ゲームの進行 def start_game ... if @mode != RECORD save_record end end def phase ... if turnable_cells.size == 0 ... else ... case @mode when COM #COM戦の場合 ... when HUMAN #対人戦の場合 ... when WATCH #観戦の場合 ... when RECORD #棋譜再生の場合 read_record(@read_record[@turn]) end end end def human(turnable_cells) #人が石を置く操作 ... if move =~ /[a-h][1-8]/ cell = cordinate_transformation(move) #座標の変換 ... else ... end end def read_record(move) #棋譜の場合 print(move) cell = cordinate_transformation(move) put_stone(cell, move) end #座標の変換 def cordinate_transformation(move) cell = move.split("") col = COL_NUM[cell[1]] row = ROW_NUM[cell[0]] cell = [col, row] return cell end