平成19年 春期 基本情報技術者 午後 問12
問12 Java
次の Java プログラムの説明及びプログラムを読んで,設問1,2に答えよ。
〔プログラムの説明〕
三目並べを行うプログラムである。
盤は 3 × 3 の升(ます)目をもち,2人のプレーヤは交互に自分の記号( o 又は x )を書く。
たて,横,斜めでの三つの升の並びを列と呼び,先に,どれかの列で三つの升すべてに,
自分の記号を書いた方を勝ちとする。
また,盤のすべての升に記号が書かれていて,どちらの勝ちでもないときは,引き分けとする。
先手は o ,後手は x を使う。
先手(o)が勝ちの例を図1に示す。
図 1 先手(o)が勝ちの例
列挙型 Mark は記号を表し,先手は Mark.CIRCLE,後手は Mark.CROSS を使うこととする。
また,升に何も書かれていない状態を Mark.BLANKで表す。
クラス TicTacToeBoard は盤を表し,(1) 〜 (4) のメソッドをもつ。
(1) Progress put(int x, int y, Mark mark)
盤の位置 (x, y) に mark で表される記号を書く。
盤の状態を列挙型 Progress で返す。
戻り値と盤の状態の対応は,次のとおりである。
Progress.CIRCLE_WON ― 先手の勝ち
Progress.CROSS_WON ― 後手の勝ち
Progress.DRAWN ― 引き分け
Progress.IN_PROGRESS ― 進行中
指定位置が盤の範囲外のときは ArrayIndexOutOfBoundsException を投げる。
既に勝敗が決まっているとき(引き分けを含む)は IllegalStateException を投げ,
次のいずれかに該当するときは IllegalArgumentException を投げる。
@ 指定位置に既に記号が書かれている。
A 指定された記号が書けるプレーヤの番ではない。
(2) boolean check(int x, int y, int dx, int dy, Mark mark)
盤のある一つの列の三つの升すべてに,指定された記号が書かれているか否かを
検査する。位置 (x, y),(x + dx, y + dy),(x + 2 * dx, y + 2 * dy)
の三つの升に書かれている記号が,mark と等しければ true を返す。
(3) Mark get(int x, int y)
盤の位置(x, y)に書かれている記号を返す。
(4) void undo()
直前に書いた記号を消す。ただし,勝敗が決まった後は消すことができない。
クラス TicTester はテスト用のプログラムである。実行結果の一部を図2に示す。
Turn : CROSS : IN_PROGRESS
o x
x
o x o
Turn : CIRCLE : IN_PROGRESS
o x
x o
o x o
undo
o x
x
o x o
Turn : CIRCLE : CIRCLE_WON
o x
o x
o x o
Game is over.
|
図2 実行結果の一部
〔参考:列挙(enum)について〕
プログラム中の Mark と Progress はそれぞれ列挙型であり,列挙型 Mark は
三つの列挙定数 CIRCLE,CROSS,BLANK を,列挙型 Progress は四つの
列挙定数 CIRCLE_WON,CROSS_WON,DRAWN,IN_PROGRESS をもつ。
列挙型はクラスの。
一種であり,列挙定数は列挙型のインスタンスである。
〔プログラム1〕
public enum Mark {
// 記号の種類を表す列挙。各列挙定数では定数 symbol を定義する。
// 定数 symbol の値は各コンストラクタで与えられた値('o'など)である。
CIRCLE('o'), CROSS('x'), BLANK(' ');
public final char symbol;
Mark(char symbol) {
this.symbol = symbol;
}
}
〔プログラム2〕
public class TicTacToeBoard {
// ゲームの進行状況を表す列挙
public enum Progress {CIRCLE_WON, CROSS_WON, DRAWN, IN_PROGRESS}
private Mark[][] board = new Mark[3][3]; // 盤
private Mark turn = Mark.CIRCLE;
private Progress progress = Progress.IN_PROGRESS;
private int count = 0; // 盤に書かれた記号の個数
private int lastx, lasty; // 最後に記号が書かれた位置を保持する。
public TicTacToeBoard() { // 盤を初期化する。
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
board[i][j] = ;
}
public synchronized Progress put(int x, int y, Mark mark) {
if ( )
throw new IllegalStateException();
if (board[x][y] != Mark.BLANK || mark != turn)
throw new IllegalArgumentException();
board[x][y] = mark;
lastx = x;
lasty = y;
count++;
// 勝ちか否かを検査する。
boolean game =
// たてと横の列を検査する。
check(x, 0, 0, 1, mark) || check(0, y, 1, 0, mark) ||
// 斜めの列を検査する。
check(0, 0, 1, 1, mark) || check(0, 2, , mark);
if (game)
if (turn == Mark.CIRCLE)
progress = Progress.CIRCLE_WON;
else progress = Progress.CROSS_WON;
else if (count == 9) progress = Progress.DRAWN;
// 次に書かれる記号の種類を決定する。
if (turn == Mark.CIRCLE) turn = Mark.CROSS;
else turn = Mark.CIRCLE;
return progress;
}
private boolean check(int x, int y, int dx, int dy, Mark mark) {
return (board[x][y] == mark &&
board[x + dx][y + dy] == mark &&
board[x + 2 * dx][y + 2 * dy] == mark);
}
public Mark get(int x, int y) {
return board[x][y];
}
public synchronized void undo() {
if (progress == Progress.IN_PROGRESS &&
board[lastx][lasty] != Mark.BLANK) {
turn = board[lastx][lasty];
board[lastx][lasty] = Mark.BLANK;
count--;
} else {
throw new IllegalStateException();
}
}
}
〔プログラム3 〕
public class TicTester {
public static void main(String[] args) {
// 記号を書く位置(x, y)を定義した配列。null のときは undo を呼ぶ。
int[][] p = {{0, 0}, {1, 1}, {2, 2}, {2, 0}, {0, 2}, {1, 2},
{2, 1}, null, {0, 1}, {1, 0}};
TicTacToeBoard board = new TicTacToeBoard();
Mark marks[] = {Mark.CIRCLE, Mark.CROSS};
for (int i = 0; i < p.length; i++) {
try {
if (p[i] == null) {
System.out.println("undo");
board.undo();
} else {
Mark turn = marks[ ];
System.out.println("Turn : " + turn + " : " +
board.put(p[i][0], p[i][1], turn));
}
for (int y = 0; y < 3; y++) {
for (int x = 0; x < 3; x++)
System.out.print(board.get(x, y).symbol + " ");
System.out.println();
}
} catch (IllegalStateException ise) {
System.out.println("Game is over.");
}
}
}
}
設問1 プログラム中の に入れる正しい答えを,
解答群の中から選べ。
a に関する解答群
ア Mark.BLANK イ Mark.CIRCLE
ウ Mark.CROSS エ null
b に関する解答群
ア count < 0
イ count >= 9
ウ progress != Progress.IN_PROGRESS
エ progress == Progress.IN_PROGRESS
c に関する解答群
ア -1, -1 イ -1, 1 ウ 1, -1 エ 1, 1
d に関する解答群
ア i イ i % 2 ウ i & 2 エ i / 2
ア
ウ
ウ
イ
基本情報技術者試験
設問2 クラス TicTacToeBoard のメソッド undo に関する記述として正しい答えを,
解答群の中から二つ選べ。
解答群
ア 2手目以降で続けて2回呼ぶと,二つ消せる。
イ 2手目以降で続けて2回呼ぶと,呼ばなかった状態に戻る。
ウ 2手目以降で続けて2回呼んでも,消せるのは一つだけである。
エ ゲーム中で先手後手とも,それぞれ1回しか消せない。
オ 消すことができなければ例外を投げる。
ウ、オ
[←前の問題]
[次の問題→]
[問題一覧表]
[分野別]
[基本情報技術者試験TOP
]
©2004-2024 情報処理試験.jp
|
|
|