練習 [13] 構造体(4/5)

練習 4(提出プログラム名:p1304a.c)

まず,このプログラム(p1304a.c)ヘッダ(p1304a.h)をダウンロードしなさい.
(ただし,Mac 環境の人はヘッダの中の
#define CLS "cls"

#define CLS "clear"
に書き換えなさい.)
このプログラムは以下に示す仕様の簡単なゲームになっていて,迫ってくる敵(ハンター)から逃げ切ることが目的である.

【逃亡ゲームの仕様】
(ただし,WIDTH, HEIGHT, MAX はいずれもマクロであり,ヘッダの中で定義されている)
(1)プレイヤーとハンターは,X-Y 座標上のいずれかの点(ただし,x, y とも整数)に位置する.
(2)プレイヤーとハンターが動ける範囲はいずれも
  座標 (0,0) を左下,座標 (WIDTH-1, HEIGHT-1) を右上とした四角形の中に限定とする.
(3)プレイヤーとハンターは 1 ターン毎に上下左右のいずれかの方向に 1 マスだけ移動できる.
(4)移動ターンについてはプレイヤーが常に先手であり,それに応じてハンターも動いてくる.
(5)ハンターがプレイヤーと同じ位置に到達したら,プレイヤーの負けである.
(6)捕まることなく MAX ターンが過ぎれば,プレイヤーの勝ちである.
(7)もしも動けない方向へ移動しようとした場合(例えば,座標 (0,0) にいて,左に移動
  しようとした場合)は, そのターンは移動できずにそこに待機となる.

このプログラムでは,プレイヤーを移動させる関数 move が未完成になっている.
現状では「その方向に逃げることはできません」と表示するだけで何もしていない
以下の仕様に従って,この関数を完成させなさい.
なお,関数 move の中では講義資料で説明した p->x」という書き方を用いること.

【関数 move の仕様】
■ 引数 p :プレイヤーの情報が入った構造体へのポインタ
■ 引数 dx, dy :プレイヤーを x, y 方向に移動させる量
■ 動作内容:
 ポインタ p が参照しているプレイヤー(構造体)の x, y 座標を更新する.
 更新する量は dx, dy であり,それぞれ x 座標を dx だけ, y 座標を dy だけ増やす.
 (なお,dx, dy は負の場合もあるが,気にせずに足してよい)
 ただし,移動できる範囲には制限がある(上述した仕様(2))ので,
 移動できない場合は 「その方向には逃げることができません」 とだけ表示して,
 実際は移動させないこと.以下の【ヒント】を参照せよ.

【注意】
この問題では関数 move を完成させるだけであり,他は何も書き換えないこと.
そして, p1304a.c のみを提出しなさい.
なお,プログラムの中でマクロ WIDTH, HEIGHT を使わずに 3 や 2 といったこれらに関する数字を直接書いてはいけません.

【ヒント】
単純に移動させるだけならば
  p->x += dx;
  p->y += dy;
だけで済む
のですが,これだと本来は移動できない領域(マップの外)にも移動できてしまうので,
if 文でチェックする必要があります.
<移動できない4パターン>
①左端にいて(x が 0),左へ移動しようとした.
②右端にいて(x が WIDTH-1),右へ移動しようとした.
③下端にいて(y が 0),下へ移動しようとした.
④上端にいて(y が HEIGHT-1),上へ移動しようとした.

  • 【プログラムの実行例】(その1)赤字は実行時にキーボードから入力する内容
あなたの名前を入力してください:aman
 aman : (0,0)
 hunter : (2,2)
 + --- + ---[H]
 |     |     |
 |     |     |
 + --- + --- +
 |     |     |
 |     |     |
[Y]--- + --- +

 [1 回目]
どの方向に逃げますか?(1:上,2:右,3:下,4:左)
> 1
 aman : (0,1)
 hunter : (1,2)
 + ---[H]--- +
 |     |     |
 |     |     |
[Y]--- + --- +
 |     |     |
 |     |     |
 + --- + --- +

[2 回目]
どの方向に逃げますか?(1:上,2:右,3:下,4:左)
> 3
 aman : (0,0)
 hunter : (1,1)
 + --- + --- +
 |     |     |
 |     |     |
 + ---[H]--- +
 |     |     |
 |     |     |
[Y]--- + --- +

[3 回目]
どの方向に逃げますか?(1:上,2:右,3:下,4:左)
> 2
 aman : (1,0)
 hunter : (1,0)
 + --- + --- +
 |     |     |
 |     |     |
 + --- + --- +
 |     |     |
 |     |     |
 + ---(X)--- +

aman は捕まってしまいました... GAME OVER
  • 【プログラムの実行例】(その2)

(長くなるので実行画面は省略しますが,1 回だけわざと逃げることのできない方向を選んで,1 手だけ無駄にするとクリアできます)

【過去にあったミス(減点となり,やり直しを命じられる)】
実行例を確認せずに提出してしまっている.
■ 関数 move を作っていく中で,上下左右の境界を間違えている.
  x 座標は常に 0 以上 WIDTH 未満でなければなりません.(「以下」ではない
  y 座標は常に 0 以上 HEIGHT 未満でなければなりません.(「以下」ではない
■ 関数 move の中で p->x という書き方をやっていない
 この問題では (*p).x と書いてはいけません
main 関数を書き換えている
インデントに不備がある(VSCode 上でインデントを自動で揃える作業をやっていない).


ミスが無いことを確認したら次の問題へ → [ 練習 5 (p1305a.h) ]