五目並べ問題をrubyで解いてみる
最近PAIZAの勉強をしており、その練習問題に出てきた問題。
正直解答を見てもよくわからなかったので、一行ずつ読み解いてみます。
自分用のメモなので、他の方にはわかりにくいかもしれません。
問題はこちら
問題文
5行5列の五目並べの盤面が与えられます。
盤面の各マスには、"O"か"X"か"."が書かれています。
"O"と"X"は、それぞれプレイヤーの記号を表します。
同じ記号が縦か横か斜めに連続で5つ並んでいれば、その記号のプレイヤーが勝者となります。
勝者の記号を1行で表示してください。
勝者がいない場合は、引き分けとして、"D"を表示してください。
それではいきます〜〜
# `$'で始まる変数はグローバル変数で、プログラムのどこからでも参照できます
$board = []
# 盤面の初期化
# 5回入力する(二次元配列を作る)
(1..5).each { $board.push(gets.chomp.split('')) }
この段階で、例えば入力値を
CVGFH
GBHHN
DFVHN
EFRTY
ZXCVB
と入力後、
puts $board[0][1]をすると、0回目に入力された行(CVGFH)の中から1番目の文字が出力されるので、Vが出力されます。
対象の文字列が5つ並んでいた時のそれぞれの定義をしていきます
# 5つ並んでいるかどうか
def aligned?(o, x)
if o == 5
'O' #oが5つ並んでいたらOを出力する
elsif x == 5
'X' #xがXつ並んでいたらOを出力する
else
'D' # それ以外はD
end
end
まずは横に5回連続して並ぶことで勝つパターンの定義をします。
# 横並びを定義
def row_aligned?
result = ''
#入力値を行に分解する
$board.each do |row|
#o,xの初期値を定義
o = 0 #oが横に0回並んでいる
x = 0 #xが横に0回並んでいる
#行に書かれている値にさらに分解していく
#(0..4)になっているのは5文字ずつ入力されているから0番目〜4番目を展開していくということになるということ
(0..4).each do |i|
# 展開した行のi番目がOであればoに1足していく
if row[i] == 'O'
o = o + 1
# 展開した行のi番目がXであればxに1足していく
elsif row[i] == 'X'
x = x + 1
else
break
end
end
#先ほど定義したaligned?(o, x)をresultに代入する
result = aligned?(o, x)
break if result != 'D'
end
result
end
続いて縦に5回連続して並ぶことで勝つパターンの定義をします。
# 縦並びを定義
def collum_aligned?
result = ''
(0..4).each do |i|
o = 0 #oが縦に0回並んでいる
x = 0 #xが縦に0回並んでいる
#入力値を列ごとに分解
$board.each do |row|
#展開した列のi番目がOであればoに1足していく
if row[i] == 'O'
o = o + 1
#展開した列のi番目がXであればxに1足していく
elsif row[i] == 'X'
x = x + 1
end
end
result = aligned?(o, x)
break if result != 'D'
end
result
end
最後に斜めに5回連続して並ぶことで勝つパターンの定義をする。
斜めで記号が揃うパターンは、0 から 4 までの i に対して board[i][i] が同じ記号か、board[i][4 - i] が同じ記号の 2 パターン。
board[i][i] が同じ記号なのは左上から右下まで一直線に揃うパターン、board[i][4 - i] が同じ記号なのは右上から左下まで一直線に揃うパターンです。
# 斜めを定義
def oblique_aligned?
result = ''
#0はboard[i][i] が同じ記号であるパターン
#1はboard[i][4 - i] が同じ記号であるパターン
(0..1).each do |time|
#i,j,o,xそれぞれの初期値を定義していく。
i = 0
#if time == 0と意味は同じらしい
if time.zero?
j = 0
else
j = 4
end
o = 0
x = 0
(1..5).each do
#i列目のj番目がOの時oに1足していく
if $board[i][j] == 'O'
o = o + 1
#i列目のj番目がXの時xに1足していく
elsif $board[i][j] == 'X'
x = x + 1
end
#iとjをそれぞれ更新していく
i = i + 1
if time.zero?
j = j + 1
else
j = j - 1
end
end
result = aligned?(o, x)
break if result != 'D'
end
result
end
疲れてきた、、
最後の最後に、
横列 or 縦列 or 斜めにOが並んだ場合はOを出力、
横列 or 縦列 or 斜めにXが並んだ場合はXを出力、
それ以外はDを出力するif文を書く!
if row_aligned? == 'O' || collum_aligned? == 'O' || oblique_aligned? == 'O'
puts 'O'
elsif row_aligned? == 'X' || collum_aligned? == 'X' || oblique_aligned? == 'X'
puts 'X'
else
puts 'D'
end
以上でした
メモとして書いているのでわかりづらかったらすみません。