戦国IT - 情報処理技術者試験の過去問対策サイト
ブログお知らせお問い合わせ料金プラン

基本情報技術者 2019年 春期 午後 問11


次のJavaプログラムの説明及びプログラムを読んで、設問1,2に答えよ。

〔プログラムの説明〕  升目を用いて表現された迷路と、迷路上に置かれて外部から操作される駒を表すプログラムである。  迷路は、駒が通れる升(以下、通路という)と通れない升(以下、壁という)から成る。迷路の外周は壁である。通路のうちの一つが開始地点であり、開始地点でない通路のうちの一つがゴール地点である。本問で扱う迷路を、図1に示す。
基本情報技術者試験(令和元年 午後 問11 図1)
 迷路上の升の位置は、2次元の座標(x, y)で表す。xとyはともに非負整数である。ある位置を基準として、xの値が大きくなる方角を東、小さくなる方角を西、yの値が大きくなる方角を南、小さくなる方角を北とする。  駒は、東西南北のいずれかを向いており、向いている方角を基準として、次の三つの操作を外部から受け付ける。  ① 左の方向に向きを変える。  ② 右の方向に向きを変える。  ③ 隣接する前方の升が通路なら、1升前進する。   (1) クラスMazeは迷路を表す。コンストラクタの引数には、文字列で表現した迷路と、迷路の西端から東端までの升の個数を指定する。迷路を表現する文字列は、1升を表す文字を西から東に向かって順に並べた1行分の文字列を、北から南に向かって順に連結したものである。升の種類は、char型の値で表す。“*”は壁を、それ以外の値は通路を表し、“S”は開始地点を、“G”はゴール地点を表す。引数に誤りはないものとする。  メソッドgetStartLocationは開始地点の座標を返す。メソッドisGoalは指定された座標の升がゴール地点であればtrueを、それ以外はfalseを返す。メソッドisBlankは指定された座標の升が通路ならばtrueを、壁ならばfalseを返す。 (2) クラスPieceは、迷路上に置かれる駒を表す。コンストラクタの引数で迷路を指定する。インスタンスは、最初は、開始地点に位置し、北を向いている。  メソッドturnLeftは左の方向に、turnRightは右の方向に向きを変える。  メソッドtryStepForwardは、隣接する前方の升が通路なら1升前進し、前進した方角を履歴リストに追加してからtrueを返す。通路でなければ、前進せずにfalseを返す。  メソッドisAtGoalは、ゴール地点にいればtrueを、それ以外はfalseを返す。  メソッドgetHistoryは、履歴リストを返す。 (3) 列挙Directionは、方角を表す。  メソッドleftは列挙定数が表す方角に向かって左の方角を、rightは右の方角を返す。 (4) クラスLocationは、迷路上の升の位置を示す座標を表す。 (5) クラスPlayMazeは、図1に示す開始地点からゴール地点に至るまで駒を操作し、その後、履歴リストを表示する。
基本情報技術者試験(令和元年 午後 問11 プログラム1)
基本情報技術者試験(令和元年 午後 問11 プログラム2)
基本情報技術者試験(令和元年 午後 問11 プログラム3)
基本情報技術者試験(令和元年 午後 問11 プログラム4)
基本情報技術者試験(令和元年 午後 問11 プログラム5)

設問1:

問題文を見る
 プログラム中のに入れる正しい答えを、解答群の中から選べ。   a, bに関する解答群  ア:%  イ:&  ウ:*  エ:+  オ:-  カ:/  キ:^  ク:|   cに関する解答群  ア:direction  イ:direction.dx, direction.dy  ウ:location + direction  エ:location.x + direction.dx, location.y + direction.dy   dに関する解答群  ア:(ordinal() + 3) % 4  イ:(ordinal() + 3) / 4  ウ:(ordinal() - 1) % 4  エ:(ordinal() - 1) / 4

模範解答

a:ウ、b:ア、c:エ、d:ア

解説

解答の導き方

この問題では、迷路の文字列の中から座標を計算する方法、駒の次の座標を求める方法、方角を左に変える方法を考えます。
まず、迷路の升は、北の行から南の行へ、各行の中では西から東へ並んで文字列に格納されています。したがって、座標 の升が文字列の何文字目にあるかは、上から 行分の文字数に、行内での位置 を加えて求められます。1行の幅がwidthなので、位置は です。
このため、プログラム1のisGoalとisBlankで、yにwidthを掛けてxを足す演算を選びます。つまり、aには乗算を表す「」が入ります。計算した位置の文字を取り出し、「G」ならゴール、「」以外なら通路と判定しています。
次に、locationOfでは、文字列の中で見つけた位置indexから、座標を逆算します。1行の幅で割った余りが、行の中での位置、つまりx座標です。よって、bには剰余を求める「%」が入ります。一方、indexをwidthで割った整数の商が、上から何行目かを示すy座標です。
例えば、幅が7で、開始地点の座標が なら、文字列中の位置は です。15を7で割ると、商は2、余りは1です。これにより、y座標が2、x座標が1と分かります。
プログラム2のtryStepForwardでは、現在位置に、向いている方角の移動量を加えて次の座標を作ります。例えば、北を向いているときの移動量は なので、x座標はそのまま、y座標だけが1小さくなります。Locationのコンストラクタはx座標とy座標の二つを受け取るため、cには「location.x + direction.dx, location.y + direction.dy」が入ります。
次の升が通路ならlocationを更新し、進んだ方角を履歴に加えます。壁なら位置を変えず、履歴にも加えません。つまり、履歴に残るのは、向きを変えた記録ではなく、実際に前進した方角です。
最後に、プログラム3の方角の並びを確認します。列挙定数はNORTH、EAST、SOUTH、WESTの順です。これは、右に向きを変えるたびに次の定数へ進む並びです。したがって、左に向きを変えるには、定義順を一つ戻ります。
ただし、NORTHの位置は0です。そこから単純に1を引くと負の値になり、配列の位置として使えません。そこで3を足して4で割った余りを使えば、NORTHから左に向いたときは位置3、つまりWESTになります。よって、dには「(ordinal() + 3) % 4」が入ります。

誤りやすいポイント

  • 文字列の位置を求める式で、x座標とy座標を逆にしないようにします。行が変わるごとにwidth文字進むため、式は です。
  • 座標を文字列の位置に直す計算と、文字列の位置から座標に戻す計算を混同しないようにします。位置からx座標を求めるのは余り、y座標を求めるのは整数の商です。
  • cでは移動量を現在位置に加えます。direction.dxとdirection.dyだけでは移動量しかなく、Locationを作るための新しいx座標とy座標になりません。
  • 左右の向きは、列挙定数の並びだけで判断せず、各方角の並びと照らし合わせます。この問題では、定義順が右回りなので、左回りは一つ前の位置です。
  • 履歴に加わるのは、前進できたときだけです。壁にぶつかって前進できなかった試行や、方向転換は履歴に含まれません。

FAQ

Q: なぜ座標から文字列の位置を求めるとき、yにwidthを掛けるのですか?
A: 1行下へ進むと、文字列の中ではその行の升の数だけ先へ進むからです。widthが1行分の升の数なので、y行分では 文字進み、さらに行内でx文字進みます。
Q: なぜ左向きの計算に3を足すのですか?
A: 定義順で一つ前の位置を使いたいからです。位置0のNORTHから一つ戻ると負の値になりますが、3を足して4で割った余りなら位置3となり、WESTを選べます。
Q: 壁に向かって前進しようとした方角も履歴に残りますか?
A: 残りません。tryStepForwardは、前方が通路の場合にだけ位置を更新し、履歴に方角を加えます。

関連キーワード: 2次元座標、剰余演算、整数除算、列挙型、リスト

解説を読んでも分からないところは、AIに質問できます。 この問題の本文と解説をふまえて答えます。

この設問をAIに質問する

クイズモードで開きます(AIへの質問は無料の会員登録で使えます)

 プログラム5のαの位置に次の処理を挿入し、実行結果として、図2に示す方角のリストを得た。駒は、開始地点からリストの方角の順に1升ずつ進むと、直前の升に戻る(正反対の方角に向きを変えて進む)ことなく、ゴール地点に至ることができる。に入れる正しい答えを、解答群の中から選べ。   for (int i = e; i < history.size(); i++) {   if (history.get(i - 1) == history.get(i).left().left()) {     history.remove(f);     history.remove(f);     i = i < 2 ? 0 : i - 2;   } }
基本情報技術者試験(令和元年 午後 問11 図2)
eに関する解答群  ア:-1  イ:0  ウ:1   fに関する解答群  ア:i  イ:i + 1  ウ:i - 1

模範解答

e:ウ、f:ウ

解説

解答の導き方

まず、駒がゴールまで進んだときの履歴を考えます。迷路の通路をたどると、履歴には次の方角が順に記録されます。
[SOUTH, EAST, EAST, EAST, NORTH, NORTH, EAST, WEST, SOUTH, SOUTH, EAST, SOUTH, SOUTH, WEST, WEST, WEST, WEST]
この履歴には、進んだあとに同じ道を戻る動きも含まれています。設問では、直前の升に戻る動きを取り除きます。
  1. 2つの方角が正反対なら、取り除けます。
    例えば、EASTに進んだ直後にWESTに進むと、元の升に戻ります。Directionのleftを2回使うと正反対の方角になるため、条件式はこのような組合せを見つけています。
  2. eは1です。
    履歴の位置は0から始まります。隣り合う2つの方角を調べるには、1つ前の位置と現在の位置を比べます。そのため、最初の位置iは1にします。0から始めると、1つ前を表す位置がマイナス1になり、履歴の範囲外を参照してしまいます。
  3. fはi - 1です。
    取り除くのは、位置i - 1と位置iの2つです。1つ目を位置i - 1から削除すると、後ろにあった位置iの要素が位置i - 1に移ります。そこで、同じ位置i - 1をもう一度削除すれば、2つの方角を両方取り除けます。
  4. 削除後は、少し前の位置から調べ直します。
    要素を削除すると、前後にあった方角が新たに隣り合うことがあります。そこで、iを戻してからループを続け、削除によってできた新しい組合せも調べます。
実際に履歴を処理すると、次のようになります。
処理履歴
最初の履歴[SOUTH, EAST, EAST, EAST, NORTH, NORTH, EAST, WEST, SOUTH, SOUTH, EAST, SOUTH, SOUTH, WEST, WEST, WEST, WEST]
iが7のとき、EASTとWESTを削除[SOUTH, EAST, EAST, EAST, NORTH, NORTH, SOUTH, SOUTH, EAST, SOUTH, SOUTH, WEST, WEST, WEST, WEST]
iが6のとき、NORTHとSOUTHを削除[SOUTH, EAST, EAST, EAST, NORTH, SOUTH, EAST, SOUTH, SOUTH, WEST, WEST, WEST, WEST]
iが5のとき、NORTHとSOUTHを削除[SOUTH, EAST, EAST, EAST, EAST, SOUTH, SOUTH, WEST, WEST, WEST, WEST]
最初にEASTとWESTを削除すると、その近くの方角が新たに隣り合います。そのため、iを戻して調べ直す必要があります。最終的に残る履歴は、設問に示された方角のリストになります。

誤りやすいポイント

  • eを0にしないこと
    比較では1つ前の位置も使うため、最初のiは1です。iを0にすると、履歴の範囲外を参照します。
  • 2回目の削除位置をiにしないこと
    1つ目を削除すると後ろの要素が前に詰まります。同じ位置i - 1をもう一度削除することで、隣り合う2つの方角を取り除けます。
  • 削除後に調べ直す位置を見落とさないこと
    要素を削除すると、それまで離れていた方角が隣り合い、正反対の組合せになることがあります。iを戻す処理は、その組合せを見逃さないためにあります。

FAQ

Q: なぜ正反対の方角を2つとも削除できるのですか?
A: その2つの方角に続けて進むと、出発した升に戻るからです。進んだ分と戻った分が打ち消し合います。
Q: なぜ同じ位置を2回削除するのですか?
A: 1つ目を削除すると、後ろの要素がその位置に移るためです。同じ位置を再度削除すると、もう一方も削除できます。
Q: 履歴から要素を削除すると、駒が記録した履歴も変わりますか?
A: 変わりません。getHistoryは履歴のコピーを返すため、ここで削除しているのは、受け取ったリストの内容です。

関連キーワード: リスト、インデックス、列挙型、ループ、状態遷移

解説を読んでも分からないところは、AIに質問できます。 この問題の本文と解説をふまえて答えます。

この設問をAIに質問する

クイズモードで開きます(AIへの質問は無料の会員登録で使えます)

戦国ITクイズ機能

\ せっかくなら /

基本情報技術者を
クイズ形式で学習しませんか?

クイズ画面へ遷移する→

すぐに利用可能!

©︎2026 情報処理技術者試験対策アプリ

このサイトについてブログプライバシーポリシー利用規約特商法表記開発者について