三目並べ(oxゲーム)を管理・運営するプログラムを作成しよう.

問題

以下の処理を行うプログラムを実装せよ.

  1. 盤面を表示する.
  2. プロンプトを表示する.
  3. 標準入力から「o」(英小文字の「オー」)もしくは「x」(英小文字の「エックス」)を置く場所(を表す数字)を読み込む.
  4. 勝利および引き分け判定を行い,勝負が決着もしくは引き分けた盤面を表示し,その旨を表示してプログラムを終了する.
  5. 1に戻る.

盤面の初期状態は次の通りに表示する.

7|8|9
-+-+-
4|5|6
-+-+-
1|2|3

盤上に「o」もしくは「x」を置くと,その場所が数字ではなくoもしくはxに置き換わる.例えば,5番(中央)に「o」,1番(左下)に「x」を置いた時の盤面は次のように表示する.

7|8|9
-+-+-
4|o|6
-+-+-
x|2|3

先手は「o」,後手は「x」とする.プロンプトは,先手番ならo>,後手番ならx>を表示したのち,1文字の空白を表示する(このタイミングでは改行しないことに注意せよ). プレイヤーは,「o」もしくは「x」を置く場所を盤面の数字(1から9まで)で入力する. この時,以下の仕様を満たすようにせよ.

7|8|9
-+-+-
4|5|6
-+-+-
1|2|3
o> 10

ERROR
o> 5

7|8|9
-+-+-
4|o|6
-+-+-
1|2|3
x> 5

ERROR
x> 9

7|8|x
-+-+-
4|o|6
-+-+-
1|2|3
o>

勝負が決した場合,もしくは引き分けになった場合は,その盤面を表示する. 続けて,先手が勝利した場合はo win!,後手が勝利した場合はx win!,引き分けの場合はeven.と表示する.

実行例

キーボードから入力した場合

7|8|9
-+-+-
4|5|6
-+-+-
1|2|3
o> 7

o|8|9
-+-+-
4|5|6
-+-+-
1|2|3
x> 3

o|8|9
-+-+-
4|5|6
-+-+-
1|2|x
o> 8

o|o|9
-+-+-
4|5|6
-+-+-
1|2|x
x> 2

o|o|9
-+-+-
4|5|6
-+-+-
1|x|x
o> 9

o|o|o
-+-+-
4|5|6
-+-+-
1|x|x
o win!

ファイルから入力をリダイレクトした場合(詳しくは「ヒント」を参照せよ)

#は標準入力,>は標準出力を表す.

# 7
# 3
# 8
# 2
# 9

> 7|8|9
> -+-+-
> 4|5|6
> -+-+-
> 1|2|3
> o>
> o|8|9
> -+-+-
> 4|5|6
> -+-+-
> 1|2|3
> x>
> o|8|9
> -+-+-
> 4|5|6
> -+-+-
> 1|2|x
> o>
> o|o|9
> -+-+-
> 4|5|6
> -+-+-
> 1|2|x
> x>
> o|o|9
> -+-+-
> 4|5|6
> -+-+-
> 1|x|x
> o>
> o|o|o
> -+-+-
> 4|5|6
> -+-+-
> 1|x|x
> o win!

ヒント

(より深く知りたい人へ)ストリーム

標準入力をリダイレクトして外部ファイルから入力系列を読み取りたい場合は,例えば以下のようにファイルを作成すれば良い.

$ echo "7 3 8 2 9" > test.txt
$ ./a.out < test.txt

これで,以下のようにひとつずつ数字を入力(+enter)していく場合と同じ結果が得られる.

$ ./a.out
> 7
> 3
...

あるいは,次のように「ヒア・ストリング」という書き方をしても良い.

$ ./a.out <<< "7 3 8 2 9"`

上のように複数の入力を「まとめ」られるのは,C言語の「ストリーム」の概念とscanfの仕様による. ストリーム(たとえば標準入力)はストリームの現在位置(どこまで読み込んだか)の情報を保持している. scanfが必要な分の入力(たとえば7)を読み込んで空白類文字にぶつかると,ストリームの現在位置が移動し,次にscanfが呼び出されるタイミングで次の文字列の読み込みをはじめる.

ここでの「空白類文字」は,半角スペースのほか,タブ,改行などを含む.したがって,7,3,8を順次改行を挟みながら入力することと,7 3 8という文字列を入力することは,プログラムにとって等価である.