第47回 1手読み(ランダム打ち)のリバーシを作成しました
README
[プログラムの説明] リバーシプログラムである。 コンピュータは1手読みでランダムな座標に打ってくる。 [起動方法] $ ruby main_console.rb [ログについて] ログはlogディレクトリの下に作られていく。 ログレベルは、Conf.rbにDEBUGを指定している。 プログラムのなかでもすべてDEBUGレベルによる 出力を行なっているので、気に入らなければレベルを 他のレベルに変えればよい。 [操作方法] BまたはWで黒または白を決定後、 a,5 のようにカンマ区切りで 座標を指定する事で石を置いていく。 [終了方法] 最後(石を置くおところが無くなった状況)までゲーム行なった場合、 自動的に処理は終了するが途中で止めたい場合は、Ctr + c でプログ ラムを止める [ディレクトリ構造] reversi_random トップディレクトリ +-- README リードミー +-- main_console.rb プログラム起動ファイル +-- log | `-- reversi_random.log ログファイル +-- class | |-- Com_console.rb コンピュータを表すクラス | |-- Conf.rb 設定ファイルを表すクラス | |-- Human_console.rb 人を表すクラス | |-- Point.rb 座標を表すクラス | `-- System_console.rb システムを表すクラス `-- module |-- com Com_console.rbにのみ取り込まれるモジュールを入れたディレクトリ | `-- AI_random.rb ランダム打ちに必要な処理を集めたモジュール |-- common 複数のクラスに取り込まれるモジュールを入れたディレクトリ | |-- Check.rb 石が置けるかどうかチェックする関数群を集めたモジュール | `-- Update.rb ボードを更新するための関数を集めたモジュール |-- human Human_console.rbにのみ取り込まれるモジュールを入れたディレクトリ | `-- H_Console.rb Human_consoleクラスの中から、コンソール出力が必要な処理の部分を集めたモジュール `-- system System_console.rbにのみ取り込まれるモジュールを入れたディレクトリ `-- S_Console.rb System_consoleクラスの中から、コンソール出力が必要な処理の部分を集めたモジュール [ソース説明] 人を表すクラスはHuman_consoleクラスであるが、コンソール出力に必要な処理は、 H_Consoleモジュールに抜き出してある。 同様に、システムを表すクラスからもコンソール出力に必要な処理は、S_Console.rb に抜き出されている。 クラスは、多くの機能をモジュールによって追加される方針で作られている。 これは複数のクラスで同じ処理をする関数がたくさん作られるからである。 これら共通の関数群を抜き出してモジュールにしている。 以上は、共通する項目についてモジュールにした例であるが、今回のプログラ ムにのみ起因する部分もモジュールとして抜き出している。 例えば、コンソール出力に必要な関数を抜きだしたモジュールなどがそれである。 将来、ブラウザで遊べるようにしたいとなった場合、このコンソールに必要なモ ジュールをインクールドするのをやめ、新しく作ったモジュールをインクルードし なおすだけで、それを可能にしようという発想からである。 また、コンピュータの思考ルーチンに関する部分もモジュールとして抜き出してある。 これも後から別の思考ルーチンを使いたいとなったばあいに、今使っているモジュール をインクルードするのをやめ、新しいモジュールをインクルードするだけで思考ルーチ ンが変わるようにするためである。 [クラス説明] Com_consoleクラス 1手読み(ランダム打ち)を行なうコンピュータを表すクラス 実際に石が置けるかどうかチェックするのはCheckモジュール 実際にボードの更新を行なうのはUpdateモジュール Human_consoleクラス 人を表すクラス 石を置く場所を入力してもらう処理を行なう 実際には、H_ConsoleモジュールがCheckモジュールのチェックメソッドを使い、 入力される値を求める System_consoleクラス システムを表すクラス ボードの更新 ボードの表示 人の先手、後手を決める ゲームの終了判定 を行なう *以上の大まかなクラスがほとんどの処理を行なう。 *おおざっぱな流れとしては、人の手番では人クラスがが座標を決め、 *その座標をシステムクラスに渡し、システムクラスがボードを裏返 *す(更新する)。 コンピュータの手番ではコンピュータクラスが *座標を決め、その座標をシステムクラスに渡しシステムクラスが *ボードを裏返す(更新する)という手順で行なわれる。 [インクルードしているモジュール] Com_consoleクラス - Checkモジュール - Updateモジュール *今回は深読みしないので実はUpdateモジュールは使われていない - AI_randomモジュール Human_consoleクラス - Checkモジュール - H_Consoleモジュール System_consoleクラス - Checkモジュール - Updateモジュール - S_Consoleモジュール
main_console.rb
require 'class/System_console.rb' require 'class/Human_console.rb' require 'class/Com_console.rb' require 'class/Point.rb' require 'class/Conf.rb' require 'logger' require 'pp' conf = Conf.new logger = Logger.new(conf.log_file, conf.log_rotate) logger.level = conf.log_level logger.progname = __FILE__ logger.debug{ 'main_console start' } first_board = [ ['S','S','S','S','S','S','S','S','S','S'], ['S','E','E','E','E','E','E','E','E','S'], ['S','E','E','E','E','E','E','E','E','S'], ['S','E','E','E','E','E','E','E','E','S'], ['S','E','E','E','W','B','E','E','E','S'], ['S','E','E','E','B','W','E','E','E','S'], ['S','E','E','E','E','E','E','E','E','S'], ['S','E','E','E','E','E','E','E','E','S'], ['S','E','E','E','E','E','E','E','E','S'], ['S','S','S','S','S','S','S','S','S','S'] ] sys = System_console.new(first_board, 'B', 0) #--------------------------------------------------------------------------- # 先手、後手を決める #--------------------------------------------------------------------------- sys.commit_player # ボードを表示 sys.print_board while !sys.is_game_over logger.debug{ '手数: ' + sys.turn.to_s } logger.debug{ 'プレイヤー: ' + "\n" + sys.get_player.pretty_inspect } if !sys.is_pass then logger.debug{ 'パスでない' } #--------------------------------------------------------------------------- # パスでない場合 #--------------------------------------------------------------------------- # 石を打つ座標を取得 point_info = sys.get_player.select_point_info logger.debug{ '置く場所: ' + point_info.pretty_inspect } # 打った座標を登録 sys.point = point_info[:point] # ボードを更新 sys.update(point_info) # 手数を更新 sys.turn = sys.turn + 1 # ボードを表示 sys.print_board else logger.debug{ 'パス' } #--------------------------------------------------------------------------- # パスの場合 #--------------------------------------------------------------------------- # パスであることを表示 sys.print_pass end # 次の手番のプレイヤーに交代 sys.change_player # 次の手番の色に交代 sys.change_color end logger.debug{ 'main_console end' }
Com_console.rb
require 'module/common/Check.rb' require 'module/common/Update.rb' require 'module/com/AI_random' require 'logger' require 'pp' #////////////////////////////////////////////////////////////////////////////////// # Com_consoleクラス # ------------------------ インスタンス変数 ----------------------------------- # @conf 設定ファイル # @logger ロガー # @board ボードの情報(コピーしたものを持つ) # @color コンピュータの色 # @e_color コンピュータの敵の色 # -------------------- インクルードするモジュール ------------------------------- # Checkモジュール 石が置けるかどうかのメソッド群 # Updateモジュール 盤を更新する(石をひっくり返す)メソッド群 # AI_randomモジュール ランダム打ちAIを搭載するためのメソッド群 # ---------------------------- 内容説明 ------------------------------------------ # 1手読み(ランダム打ち)を行なうコンピュータを表すクラス # 実際に石が置けるかどうかチェックするのはCheckモジュール # 実際にボードの更新を行なうのはUpdateモジュール #////////////////////////////////////////////////////////////////////////////////// class Com_console ################################################################################# # 処理内容: # コンストラクタ ################################################################################# def initialize(board, color) @conf = Conf.new @logger = Logger.new(@conf.log_file, @conf.log_rotate) @logger.level = @conf.log_level @logger.progname = __FILE__ @logger.debug{ 'Com_console initialize start' } @board = board.dup @color = color @e_color = @color == 'W' ? 'B' : 'W' @logger.debug{ 'Com_console initialize end' } end ################################################################################# # インクルード ################################################################################# include Check include Update include AI_random end
Conf.rb
require 'logger' #////////////////////////////////////////////////////////////////////////////////// # Confクラス # ------------------------ インスタンス変数 ----------------------------------- # @log_file ログファイルの場所 # @log_rotate ログローテーとの数 # @log_level ログのレベル # ---------------------------- 内容説明 ------------------------------------------ # 設定ファイルの役目をするクラス # インスタンス変数の内容が設定内容である #////////////////////////////////////////////////////////////////////////////////// class Conf def initialize @log_file = 'log/reversi_random.log' @log_rotate = 5 @log_level = Logger::DEBUG end attr_accessor :log_file, :log_rotate, :log_level end
Human_console.rb
require 'module/common/Check.rb' require 'module/human/H_Console.rb' require 'pp' #////////////////////////////////////////////////////////////////////////////////// # Human_consoleクラス # ------------------------ インスタンス変数 ----------------------------------- # @conf 設定ファイル # @logger ロガー # @board ボードの情報(コピーしたものを持つ) # @color 人の色 # @e_color 人の敵の色 # -------------------- インクルードするモジュール ------------------------------- # Checkモジュール 石が置けるかどうかのメソッド群 # H_Consoleモジュール コンソール出力が必要なメソッド群 # ---------------------------- 内容説明 ------------------------------------------ # 人を表すクラス # 石を置く場所を入力してもらう処理を行なう # 実際には、H_ConsoleモジュールがCheckモジュールのチェックメソッドを使い、 # 入力される値を求める #////////////////////////////////////////////////////////////////////////////////// class Human_console ################################################################################# # 処理内容: # コンストラクタ ################################################################################# def initialize(board, color) @conf = Conf.new @logger = Logger.new(@conf.log_file, @conf.log_rotate) @logger.level = @conf.log_level @logger.progname = __FILE__ @logger.debug{ 'Human_console initialize start' } @board = board.dup @color = color @e_color = @color == 'W' ? 'B' : 'W' @logger.debug{ 'Human_console initialize end' } end include Check include H_Console end
Point.rb
#////////////////////////////////////////////////////////////////////////////////// # Pointクラス # ----------------------- インスタンス変数 ----------------------------------- # @y y座標を保持 # @x x座標を保持 # -------------------- インクルードするモジュール ------------------------------- # なし # ---------------------------- 内容説明 ------------------------------------------ # boardの座標を保持するクラス # 石が置ける場所の情報のやりとりに使われる #////////////////////////////////////////////////////////////////////////////////// class Point def initialize(y, x) @y = y @x = x end attr_accessor :y, :x end
System_console.rb
require 'module/common/Check.rb' require 'module/common/Update.rb' require 'module/system/S_Console.rb' require 'class/Human_console.rb' require 'class/Com_console.rb' require 'class/Conf.rb' require 'logger' require 'pp' #////////////////////////////////////////////////////////////////////////////////// # System_consoleクラス # ------------------------ インスタンス変数 ----------------------------------- # @board 思考対象時のボード # @color 思考対象時の色 # @e_color 思考対象時の的の色 # @turn 思考対象時の手数 # @point 今回プレイヤーが打った座標 # @player [ # 思考対象時の手数のときのプレイヤーが0要素目, # 思考対象時の手数のときにプレイヤーでないものが1要素目 # ] # -------------------- インクルードするモジュール ------------------------------- # S_Consoleモジュール コンソール出力が必要なメソッド群 # Checkモジュール 石が置けるかどうかのメソッド群 # Updateモジュール ボードを更新するメソッド群 # ---------------------------- 内容説明 ------------------------------------------ # システムを表すクラス # ボードの更新 # ボードの表示 # 人の先手、後手を決める # ゲームの終了判定 # を行なう #////////////////////////////////////////////////////////////////////////////////// class System_console ################################################################################# # 処理内容: # コンストラクタ # # 引数: # board 思考対象のボード # color 思考対象時の打ち手の色 # turn 思考対象時の手数 ################################################################################# def initialize(board, color, turn) @conf = Conf.new @logger = Logger.new(@conf.log_file, @conf.log_rotate) @logger.level = @conf.log_level @logger.progname = __FILE__ @logger.debug{ 'System_console initialize start' } @board = board @color = color @e_color = @color == 'W' ? 'B' : 'W' @turn = turn @point = Point.new(0,0) @player = [] @logger.debug{ 'System_console initialize end' } end attr_accessor :board, :color, :e_color, :turn, :point include Check include Update include S_Console ################################################################################# # 処理内容: # 今回パスかどうか判断する # 戻り値: # false パスでない場合 # true パスである場合 ################################################################################# def is_pass @logger.debug{ 'is_pass start' } if self.get_mobility_info.length == 0 then @logger.debug{ 'is_pass end : return true' } return true else @logger.debug{ 'is_pass end : return false' } return false end end ################################################################################# # 処理内容: # ゲーム終了判定 # 戻り値: # false 終了でない場合 # true 終了である場合 ################################################################################# def is_game_over @logger.debug{ 'is_game_over start' } #----------------------------------------------------------------------------# # 現在の手で置ける場所があるか調べる #----------------------------------------------------------------------------# if self.is_pass then #----------------------------------------------------------------------------# # 次の手番でも置ける場所があるか調べる #----------------------------------------------------------------------------# # 次の手に色を変える self.change_color if self.is_pass then # 次の手番でも置ける場所がなかったのでゲームオーバー @logger.debug{ 'is_game_over end : return true' } return true end # 元の手に色を戻す self.change_color end @logger.debug{ 'is_game_over end : return false' } return false end ################################################################################# # 処理内容: # 現在手番のプレイヤーを登録 ################################################################################# def commit_player @logger.debug{ 'commit_player start' } if self.select_human_turn == 'B' then @player[0] = Human_console.new(@board, 'B') @player[1] = Com_console.new(@board, 'W') else @player[0] = Com_console.new(@board, 'B') @player[1] = Human_console.new(@board, 'W') end @logger.debug{ 'commit_player end' } end ################################################################################# # 処理内容: # 次の手番用にプレイヤーを交代 ################################################################################# def change_player @logger.debug{ 'change_player start' } @player.reverse! @logger.debug{ 'change_player end' } end ################################################################################# # 処理内容: # 次の手番用に色を交代 ################################################################################# def change_color @logger.debug{ 'change_color start' } @color, @e_color = @e_color, @color @logger.debug{ 'change_color end' } end ################################################################################# # 処理内容: # 現在の手番のプレイヤーを返す ################################################################################# def get_player @player[0] end end
AI_random.rb
#////////////////////////////////////////////////////////////////////////////////// # AI_randomモジュール # --------------------- インクルードされるクラス ----------------------------------- # Com_randomクラス # ---------------------------- 内容説明 ------------------------------------------ # 1手読み(ランダム打ち)に必要な関数を集めたモジュール #////////////////////////////////////////////////////////////////////////////////// module AI_random ################################################################################# # 処理内容: # 石が置ける座標の中からランダムでひとつ返す # 戻り値: # 石が置ける座標の情報 # { point => 石が置ける座標, dir => 石が置ける向き } ################################################################################# def select_point_info @logger.debug{ 'select_point_info start' } mobility_info = self.get_mobility_info r_info = mobility_info[rand(mobility_info.length)] @logger.debug{ 'select_point_info end : return ' + "\n" + r_info.pretty_inspect } return r_info end end
Check.rb
#////////////////////////////////////////////////////////////////////////////////// # Checkモジュール # --------------------- インクルードするクラス ----------------------------------- # Com_*クラス # Human_*クラス # ---------------------------- 内容説明 ------------------------------------------ # 石が置けるかどうかチェックする関数群を集めたモジュールである # 石が置ける座標を列挙する関数も持つ #////////////////////////////////////////////////////////////////////////////////// module Check ################################################################################# # 処理内容: # 座標が'E'でなあるかチェック # (つまりすでに石が置かれていないかチェック) # 戻り値: # true 座標が'E'であるとき # false 座標が'E'でないとき ################################################################################# def is_empty(point) @board[point.y][point.x] == 'E' ? true : false end ################################################################################# # 処理内容: # 上向きにひっくり返せるか探索 # 戻り値: # 'up' 上にひっくり返せるとき # '' 上にひっくり返せないとき ################################################################################# def check_up(point) if @board[point.y-1][point.x] == @e_color then check_y, check_x = point.y-2, point.x while @board[check_y][check_x] == @e_color do check_y = check_y - 1 end return 'up' if @board[check_y][check_x] == @color end return '' end ################################################################################# # 処理内容: # 下向きにひっくり返せるか探索 # 戻り値: # 'down' 下にひっくり返せるとき # '' 下にひっくり返せないとき ################################################################################# def check_down(point) if @board[point.y+1][point.x] == @e_color then check_y, check_x = point.y+2, point.x while @board[check_y][check_x] == @e_color do check_y = check_y + 1 end return 'down' if @board[check_y][check_x] == @color end return '' end ################################################################################# # 処理内容: # 左向きにひっくり返せるか探索 # 戻り値: # 'left' 左にひっくり返せるとき # '' 左にひっくり返せないとき ################################################################################# def check_left(point) if @board[point.y][point.x-1] == @e_color then check_y, check_x = point.y, point.x-2 while @board[check_y][check_x] == @e_color do check_x = check_x - 1 end return 'left' if @board[check_y][check_x] == @color end return '' end ################################################################################# # 処理内容: # 右向きにひっくり返せるか探索 # 戻り値: # 'right' 右にひっくり返せるとき # '' 右にひっくり返せないとき ################################################################################# def check_right(point) if @board[point.y][point.x+1] == @e_color then check_y, check_x = point.y, point.x+2 while @board[check_y][check_x] == @e_color do check_x = check_x + 1 end return 'right' if @board[check_y][check_x] == @color end return '' end ################################################################################# # 処理内容: # 右上向きにひっくり返せるか探索 # 戻り値: # 'right_up' 右上にひっくり返せるとき # '' 右にひっくり返せないとき ################################################################################# def check_right_up(point) if @board[point.y-1][point.x+1] == @e_color then check_y, check_x = point.y-2, point.x+2 while @board[check_y][check_x] == @e_color do check_x = check_x + 1; check_y = check_y - 1; end return 'right_up' if @board[check_y][check_x] == @color end return '' end ################################################################################# # 処理内容: # 左上向きにひっくり返せるか探索 # 戻り値: # 'left_up' 左上にひっくり返せるとき # '' 左上にひっくり返せないとき ################################################################################# def check_left_up(point) if @board[point.y-1][point.x-1] == @e_color then check_y, check_x = point.y-2, point.x-2 while @board[check_y][check_x] == @e_color do check_x = check_x - 1; check_y = check_y - 1; end return 'left_up' if @board[check_y][check_x] == @color end return '' end ################################################################################# # 処理内容: # 左下向きにひっくり返せるか探索 # 戻り値: # 'left_down' 左下にひっくり返せるとき # '' 左上にひっくり返せないとき ################################################################################# def check_left_down(point) if @board[point.y+1][point.x-1] == @e_color then check_y, check_x = point.y+2, point.x-2 while @board[check_y][check_x] == @e_color do check_x = check_x - 1; check_y = check_y + 1; end return 'left_down' if @board[check_y][check_x] == @color end return '' end ################################################################################# # 処理内容: # 右下向きにひっくり返せるか探索 # 戻り値: # 'right_down' 右下にひっくり返せるとき # '' 右上にひっくり返せないとき ################################################################################# def check_right_down(point) if @board[point.y+1][point.x+1] == @e_color then check_y, check_x = point.y+2, point.x+2 while @board[check_y][check_x] == @e_color do check_x = check_x + 1; check_y = check_y + 1; end return 'right_down' if @board[check_y][check_x] == @color end return '' end ################################################################################# # 処理内容: # 石を置ける座標を列挙する # 返り値: # 置ける座標のPointと置ける向きの情報を持った配列 # [ # { :point => Point.new(座標), :dir => [置ける向き1, 置ける向き2, .. ] }, # ... # ] ################################################################################# def get_mobility_info @logger.debug{ 'get_mobility_info start' } mobility_info = [] for check_y in (1..@board.length-2).to_a for check_x in (1..@board.length-2).to_a point = Point.new(check_y, check_x) #=======================================================================# # 'E'である場所を探す #=======================================================================# if self.is_empty(point) then checks = [ self.check_up(point), self.check_down(point), self.check_left(point), self.check_right(point), self.check_right_up(point), self.check_left_up(point), self.check_left_down(point), self.check_right_down(point) ] #=======================================================================# # 全部 '' でないものがあった場合、 その座標を登録 #=======================================================================# if ! checks.all?{|v| v == ''} then mobility_info.push( {:point => point, :dir => checks.select{|v| v != ''}} ) end end end end @logger.debug{ 'get_mobility_info end : return ' + "\n" + mobility_info.pretty_inspect } return mobility_info end end
Update.rb
#////////////////////////////////////////////////////////////////////////////////// # Updateモジュール # --------------------- インクルードされるクラス ----------------------------------- # Com_*クラス # System_*クラス # ---------------------------- 内容説明 ------------------------------------------ # ボードを更新するための関数を集めたモジュール #////////////////////////////////////////////////////////////////////////////////// module Update ################################################################################# # 処理内容: # 受け取ったPointと方向を元に石をひっくり返す ################################################################################# def update(mobility_info) @logger.debug{ 'update start' } @logger.debug{ 'mobility_info : ' + "\n" + mobility_info.pretty_inspect } @board[mobility_info[:point].y][mobility_info[:point].x] = @color mobility_info[:dir].each{|dir| @logger.debug{ 'call : ' + "\n" + dir.pretty_inspect } self.method( 'update_' + dir ).call(mobility_info[:point]) } @logger.debug{ 'update end' } end ################################################################################# # 処理内容: # 上向きにひっくり返す ################################################################################# def update_up(point) update_y, update_x = point.y-1, point.x while @board[update_y][update_x] != @color @board[update_y][update_x] = @color update_y = update_y - 1 end end ################################################################################# # 処理内容: # 下向きにひっくり返す ################################################################################# def update_down(point) update_y, update_x = point.y+1, point.x while @board[update_y][update_x] != @color @board[update_y][update_x] = @color update_y = update_y + 1 end end ################################################################################# # 処理内容: # 左向きにひっくり返す ################################################################################# def update_left(point) update_y, update_x = point.y, point.x-1 while @board[update_y][update_x] != @color @board[update_y][update_x] = @color update_x = update_x - 1 end end ################################################################################# # 処理内容: # 右向きにひっくり返す ################################################################################# def update_right(point) update_y, update_x = point.y, point.x+1 while @board[update_y][update_x] != @color @board[update_y][update_x] = @color update_x = update_x + 1 end end ################################################################################# # 処理内容: # 右上向きにひっくり返す ################################################################################# def update_right_up(point) update_y, update_x = point.y-1, point.x+1 while @board[update_y][update_x] != @color @board[update_y][update_x] = @color update_y = update_y - 1 update_x = update_x + 1 end end ################################################################################# # 処理内容: # 左上向きにひっくり返す ################################################################################# def update_left_up(point) update_y, update_x = point.y-1, point.x-1 while @board[update_y][update_x] != @color @board[update_y][update_x] = @color update_y = update_y - 1 update_x = update_x - 1 end end ################################################################################# # 処理内容: # 左下向きにひっくり返す ################################################################################# def update_left_down(point) update_y, update_x = point.y+1, point.x-1 while @board[update_y][update_x] != @color @board[update_y][update_x] = @color update_y = update_y + 1 update_x = update_x - 1 end end ################################################################################# # 処理内容: # 右下向きにひっくり返す ################################################################################# def update_right_down(point) update_y, update_x = point.y+1, point.x+1 while @board[update_y][update_x] != @color @board[update_y][update_x] = @color update_y = update_y + 1 update_x = update_x + 1 end end end
H_Console.rb
#////////////////////////////////////////////////////////////////////////////////// # H_Consoleモジュール # --------------------- インクルードされるクラス ----------------------------------- # Human_consoleクラス # ---------------------------- 内容説明 ------------------------------------------ # Human_consoleクラスの中から、コンソール出力が必要な処理の部分を集めた関数群 #////////////////////////////////////////////////////////////////////////////////// module H_Console ################################################################################# # 処理内容: # 人がどこの座標に置くか決める # 返り値: # 人が置く座標の情報 # { :point => 置ける座標, :dir => ひっくり返せる向き } ################################################################################# def select_point_info #--------------------------------------------------------------------------------------- # 石が置ける座標を求める #--------------------------------------------------------------------------------------- mobility_info = self.get_mobility_info #--------------------------------------------------------------------------------------- # 入力された値をチェック用に一時保存する変数 #--------------------------------------------------------------------------------------- point = [] #--------------------------------------------------------------------------------------- # 正しい入力があるまで繰り返し #--------------------------------------------------------------------------------------- puts '以下の箇所に置くことができます' mobility_info.each{|v| print 'x軸: ' + ['','a','b','c','d','e','f','g','h'][v[:point].x] + ', ' + 'y軸' + v[:point].y.to_s + "\n" } print ' どこに打ちますか? (x軸,y軸) ==> ' while 1 point = gets.chomp point = point.split(/,/) #--------------------------------------------------------------------------------------- # カンマ区切りで かつ 合計3文字の入力かチェック #--------------------------------------------------------------------------------------- if point.length != 2 then puts '=========================================' puts '入力はカンマ区切りで1文字づつです' puts 'もう一度入力してください。 入力例: a,3' puts '=========================================' print ' どこに打ちますか? (x軸,y軸) ==> ' next end #--------------------------------------------------------------------------------------- # a~hの値が入力されているかチェック #--------------------------------------------------------------------------------------- if !(/[abcdefgh]/ =~ point[0]) then puts '=========================================' puts '1つ目はa~hです' puts 'もう一度入力してください。 入力例: a,3' puts '=========================================' print ' どこに打ちますか? (x軸,y軸) ==> ' next end #--------------------------------------------------------------------------------------- # 1~8の値が入力されているかチェック #--------------------------------------------------------------------------------------- if !(/[12345678]/ =~ point[1]) then puts '=========================================' puts '2つ目は1~8です' puts 'もう一度入力してください。 入力例: a,3' puts '=========================================' print ' どこに打ちますか? (x軸,y軸) ==> ' next end #--------------------------------------------------------------------------------------- # a~hをboardの配列の位置に変換 #--------------------------------------------------------------------------------------- point[0] = {'a'=>1, 'b'=>2, 'c'=>3, 'd'=>4, 'e'=>5, 'f'=>6, 'g'=>7, 'h'=>8}[point[0]] point[1] = point[1].to_i #--------------------------------------------------------------------------------------- # 石が置ける座標かどうか判断 #--------------------------------------------------------------------------------------- if mobility_info.map{|v| v[:point] }.find_all{|po| (po.x == point[0]) && (po.y == point[1]) } == [] then puts '=========================================' puts 'そこには石が置けません ' puts '=========================================' print ' どこに打ちますか? (x軸,y軸) ==> ' next end #--------------------------------------------------------------------------------------- # すべてのチェックをくぐり抜けているとループを抜ける(正しい値を得た) #--------------------------------------------------------------------------------------- break end return mobility_info.map.find{|v| v[:point].x == point[0] && v[:point].y == point[1] } end end
S_Console.rb
#////////////////////////////////////////////////////////////////////////////////// # S_Consoleモジュール # --------------------- インクルードされるクラス ----------------------------------- # System_consoleクラス # ---------------------------- 内容説明 ------------------------------------------ # System_consoleクラスの中から、コンソール出力が必要な処理の部分を集めた関数群 # 人の先手、後手を決める処理 # ボードの表示 #////////////////////////////////////////////////////////////////////////////////// module S_Console ################################################################################# # 処理内容: # 人の先手、後手を決める ################################################################################# def select_human_turn puts '**************************************' puts ' 先手、後手 どちらで開始しますか? ' puts '======================================' puts ' Black ○ 先手: B ' puts ' White ● 後手: W ' puts '======================================' print '==> ' while 1 turn = gets.chomp if (turn == 'B') || (turn == 'W') then break else print 'BかWで入力してください ==> ' end end return turn end ################################################################################# # 処理内容: # パスである旨を表示し、リターンキーで処理を進めさせる ################################################################################# def print_pass puts '==================================================' puts self.get_player.instance_of?(Human_console) ? '人は' : 'コンピュータは' puts ' パスです リターンキーを押して次に進んでください ' puts '==================================================' print '==> ' while 1 message = gets if message == "\n" then break else print 'リターンキーを押してください ==> ' end end end ################################################################################# # 処理内容: # @boardを出力する ################################################################################# def print_board puts '****** ' '現在の手数: ' + self.turn.to_s + ' ******' if @turn != 0 then print '******↓ ' print self.get_player.instance_of?(Human_console) ? '人' : 'コンピュータ' print '(' + ['','a','b','c','d','e','f','g','h'][@point.x] + ', ' + @point.y.to_s + ')' print ' ↓******' + "\n" end puts ' a b c d e f g h ' puts ' ┌─┬─┬─┬─┬─┬─┬─┬─┐' i = 1 p_board = @board[1..8] p_board.each{|x_line| print i.to_s + '|' i = i + 1 x_line.each{|v| print '○' + '|' if v == 'B' print '●' + '|' if v == 'W' print ' ' + '|' if v == 'E' } print "\n" } puts ' └─┴─┴─┴─┴─┴─┴─┴─┘' end end