問題
http://nabetani.sakura.ne.jp/hena/1/
三目並べ( tick-tack-toe )の手を入力とし、勝敗を出力する。
- 先攻がo、後攻がx
- すでに打ってある場所に打った場合、反則負け。 x が反則をした場合、「Foul : o won.」と出力
- 縦横斜めのいずれかで一列揃ったら、揃えた方の勝ち。 x が揃えた場合、「x won.」と出力
- 9マス埋まっても揃わなかったら引き分け。 「Draw game.」と出力
- 勝敗が決した後の手は無視する
- 入力文字列は、先攻から順に打った位置を示す。盤上の位置と数の対応は下表を参照。
- 入力文字列が「91593」の場合、「oが9の位置、xが1の位置、oが5の位置、xが9の位置→xの反則負け(最後の3は無視)」となる。
- 以下の様なケースは考慮しなくてよい。 入力が 1〜9 以外の文字を含んでいる。 入力が不足していて、ゲームの勝敗が決まらない。
1 | 2 | 3 |
---|---|---|
4 | 5 | 6 |
7 | 8 | 9 |
コード
Ruby
class TickTackToe
WinPattern = %W(123 456 789 147 258 369 159 357)
def initialize(input)
@input = input.chars.map(&:to_i)
@field = Array.new(10)
@turn = 0 #o
@ptns = WinPattern.map {|pt| pt.chars.map(&:to_i)}
end
def solve
@input.each do |i|
if @field[i]
return "Foul : #{output_turn(false)} won."
else
@field[i] = @turn
if settle?
return "#{output_turn} won."
elsif @field[1..9].all?
return "Draw game."
else
@turn = 1 - @turn
end
end
end
end
def settle?
@ptns.any? do |pt|
a = pt.map {|i| @field[i]}.join
a == "000" || a == "111"
end
end
def output_turn(t = true)
%W(o x)[t ? @turn : 1 - @turn]
end
def self.solve(input)
new(input).solve
end
end
if $0 == __FILE__
data = [79538246, 35497162193, 61978543, 254961323121, 6134278187, 4319581,
9625663381, 7975662, 2368799597, 18652368566, 965715, 38745796, 371929,
758698769, 42683953, 618843927, 36535224, 882973, 653675681, 9729934662,
972651483927, 5439126787, 142583697, 42198637563, 657391482]
data.each do |d|
puts TickTackToe.solve(d.to_s)
end
end