ドットイートゲーム 敵の表示ができません

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
けいすけ

ドットイートゲーム 敵の表示ができません

#1

投稿記事 by けいすけ » 8年前

前回質問させていただいたプログラムでまた違う質問をさせて頂きます。
皆さんのおかげで、少しづつ完成に近づいていっているのですが、肝心な[敵]の表示がうまくできません。
先生はとりあえず一体でいいからと言われたので、まずは一体表示させたいところなんですが、
次のようにコードをかきました。
[code=C]
//////////////////////////////////////////////////////////////////////
//
// パックマンプログラム pacman.c
//
//
// 高等専門学校 情報工学科 
// 平成29年1月26日
//
//////////////////////////////////////////////////////////////////////
#pragma warning(disable:4996)
#include <stdio.h>
#include <stdlib.h> // system()
#include <windows.h> // Sleep()
#include <conio.h> // kbhit()

#define SIZE 15 // 一辺の長さ
#define EMPTY 0 // 何もない場所は0
#define WALL 1 // 壁
#define FOOD 2 // えさ(ドット)
#define PACMAN 3// 主人公
int main()
{
int wait_time = 300;
int x, y;
int food_count = 0;//エサの個数
int cx, cy;//パックマン
int ex, ey;//敵機の座標
int key;
int r;
int point = 0;
int kx, ky;//自機の座標を保存するための変数
int mx, my;//敵機の座標を保存するための変数
// 最も重要なデータ 1 は壁、えさは2、空白は 0
// field[y][x]となるので注意!
int field[SIZE][SIZE] =
{
{ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
{ 1,2,2,2,2,2,2,2,2,2,2,2,2,2,1 },
{ 1,2,1,1,1,2,1,1,1,2,1,2,1,2,1 },
{ 1,2,1,0,1,2,1,0,1,2,1,2,2,2,1 },
{ 1,2,1,1,1,2,1,1,1,2,1,2,1,2,1 },
{ 1,2,2,2,2,2,2,2,2,2,2,2,2,2,1 },
{ 1,1,1,1,1,0,1,0,1,1,1,0,1,1,1 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 1,1,1,1,1,2,1,2,2,1,1,2,1,1,1 },
{ 1,2,2,2,2,2,1,2,1,1,1,2,2,2,1 },
{ 1,2,1,1,1,1,0,0,0,0,2,2,1,2,1 },
{ 1,2,2,2,0,2,2,1,2,1,2,0,1,2,1 },
{ 1,2,1,1,1,0,1,1,2,2,2,1,1,2,1 },
{ 1,2,2,2,2,2,2,2,2,1,2,2,2,2,1 },
{ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
};

//まずはゲーム開始前の処理
cx = 7, cy = 7; // パックマンを初期位置に配置
ex = 6, ey = -6;//敵を初期位置に配置
//エサの個数を数える
for (y = 0; y < SIZE; y++)
{
for (x = 0; x < SIZE; x++)
{
if (field[y][x] == FOOD)
food_count++;
}

}

while (1)
{
// まずはPACMANの動き
// キーが押されていたら、キーコードを取得する
// 4なら左、6なら右、8なら上、2なら下
if (kbhit()) // キーが入力されていれば真
{
key = getch();//一文字入力、エコーバックなし
kx = cx, ky = cy;//自機の座標を保存する
mx = ex, my = ey;
switch (key)
{
case '4':
cx--;
break;
case '6':
cx++;
break;
case '2':
cy++;
break;
case '8':
cy--;
break;
}
cx = (cx + SIZE) % SIZE; //ワープ

      //敵機の動き
      r = rand() % 3; //3分の1の確率で自機をおいかける
      if (r == 0) {
 if (mx > cx)  //敵機のx座標が自機のx座標より大きければx座標を減らして自機に向かう ex--;
 if (mx < cx) //敵機のx座標が自機のx座標より小さければx座標を増やして自機に向かう
ex++;
 if (my > cy) //敵機のy座標が自機のx座標より大きければy座標を減らして自機に向かう
ey--;
 if (my < cy) //敵機のy座標が自機のx座標より小さければy座標を増やして自機に向かう
  ey++;
}
switch (field[cy][cx])
{
case WALL://壁
cx = kx, cy = ky; //動けないので cx, cy を元に戻す
//壁に当たると自機の座標に元の座標を代入する
break;
case FOOD:
field[cy][cx] = 0;//餌を食べると餌が消える
point += 10; //得点加算
food_count--; //餌の数を減らしていく
break;
}
switch (field[ey][ex])
{
case WALL://壁
ex = mx, ey = my; //動けないので cx, cy を元に戻す
//壁に当たると自機の座標に元の座標を代入する
break;
}
}
// ここまでPACMANの動き

// 画面表示
for (y = 0; y < SIZE; y++) {
for (x = 0; x < SIZE; x++) {
if (x == cx && y == cy)
printf("C "); //注意するのは文字は半角2文字分にすること。じゃないと壁が動く。
else if (x == ex && y == ey)//敵の表示
printf("◇");
else if (field[y][x] == FOOD)
printf(". ");
else if (field[y][x] == WALL)
printf("■");
else
printf(" ");
}
printf("\n");
}

// すべての場所で field[y][x] の値を元に表示


printf("\n");
printf(" (cx,cy) = (%d, %d)\n", cx, cy);
printf(" (cx,cy) = (%d, %d)\n", ex, ey);
printf(" point: %d\n", point);
if (food_count == 0) //餌を食べきったとき(=CRER)の画面表示
{
printf("┏ ┏━┓┏━┓┏┳┓┳━┓ ┏━┓ ┳━┓ ┳━┓ ┳━┓ ┓\n");
printf("┃ ┃ ┓┣━┫┃┃┃┣┫ ┃ ┣┳┛ ┣┫ ┣┳┛ ┃\n");
printf("┗ ┗━┛┻ ┻┻ ┻┻━┛ ┗━┛ ┻┗┛ ┻━┛ ┻┗┛ ┛\n");
Sleep(wait_time);
break;

}
Sleep(wait_time);// 1秒間(wait_timeミリ秒)何もしない
system("cls");// 画面消去
}
return 0;
}

[/code]

自分ではどこが間違っているのかわかりません。どなたか教えてください。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: ドットイートゲーム 敵の表示ができません

#2

投稿記事 by みけCAT » 8年前

とりあえず実行せずにコードを読んだ感じでは、
  • 敵の初期位置が画面外である上、eyやexの値をチェックせずにfield[ey][ex]を読んでいるので、範囲外へのアクセスにより未定義動作になる
  • 敵が斜めに移動する場合がある (仕様?)
という問題がありそうですね。
けいすけ さんが書きました:肝心な[敵]の表示がうまくできません。
「うまくできません」だけでなく、具体的にどんな動きをさせたくて、どうなってしまうのかを書いてください。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

けいすけ

Re: ドットイートゲーム 敵の表示ができません

#3

投稿記事 by けいすけ » 8年前

みけCAT さんが書きました:とりあえず実行せずにコードを読んだ感じでは、
  • 敵の初期位置が画面外である上、eyやexの値をチェックせずにfield[ey][ex]を読んでいるので、範囲外へのアクセスにより未定義動作になる
  • 敵が斜めに移動する場合がある (仕様?)
という問題がありそうですね。
けいすけ さんが書きました:肝心な[敵]の表示がうまくできません。
「うまくできません」だけでなく、具体的にどんな動きをさせたくて、どうなってしまうのかを書いてください。
すいません。説明不足でした。まず敵の動きは基本的に、自機と同じ仕様にしたいです。また、自機に近づいてくるようにプログラムしたつもりです。
そして、申し上げたように敵が表示されないのを改善して、まずは敵をちゃんと表示したいです。

けいすけ

Re: ドットイートゲーム 敵の表示ができません

#4

投稿記事 by けいすけ » 8年前

けいすけ さんが書きました:
みけCAT さんが書きました:とりあえず実行せずにコードを読んだ感じでは、
  • 敵の初期位置が画面外である上、eyやexの値をチェックせずにfield[ey][ex]を読んでいるので、範囲外へのアクセスにより未定義動作になる
  • 敵が斜めに移動する場合がある (仕様?)
という問題がありそうですね。
けいすけ さんが書きました:肝心な[敵]の表示がうまくできません。
「うまくできません」だけでなく、具体的にどんな動きをさせたくて、どうなってしまうのかを書いてください。
すいません。説明不足でした。まず敵の動きは基本的に、自機と同じ仕様にしたいです。また、自機に近づいてくるようにプログラムしたつもりです。
そして、申し上げたように敵が表示されないのを改善して、まずは敵をちゃんと表示したいです。
いま、敵の初期位置を変えると、表示されました。
しかし、うごきません。
なぜでしょう?

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: ドットイートゲーム 敵の表示ができません

#5

投稿記事 by みけCAT » 8年前

けいすけ さんが書きました:いま、敵の初期位置を変えると、表示されました。
しかし、うごきません。
なぜでしょう?
  • キーを押していない
  • 敵のy座標が自機のy座標と同じ
という原因が考えられます。
まず、kbhit()が真のときしか敵の移動処理をしていないので、キーを押さなければ敵は動きません。
さらに、コメントを取り除いて分かりやすいように{}を補うと

コード:

if (mx > cx) {
	if (mx < cx) {
		ex++;
	}
}
というコードになっているので、mx > cxとmx < cxは同時に成立せず、キーを押しても敵のx座標は変わりません。
みけCAT さんが書きました:敵が斜めに移動する場合がある (仕様?)
というのは誤りでした。
オフトピック
対応していないコンパイラがあるので、文字列でもコメントでもない場所に全角スペースを入れるべきではありません。
そもそも、インデントが崩れて表示される原因になるので、インデントにタブとスペースを混ぜるのはよくありません。
Emacsとかいうエディタの初期設定だとタブとスペースを混ぜてくるんだよ、あのクソが…
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

けいすけ

Re: ドットイートゲーム 敵の表示ができません

#6

投稿記事 by けいすけ » 8年前

みけCAT さんが書きました:
けいすけ さんが書きました:いま、敵の初期位置を変えると、表示されました。
しかし、うごきません。
なぜでしょう?
  • キーを押していない
  • 敵のy座標が自機のy座標と同じ
という原因が考えられます。
まず、kbhit()が真のときしか敵の移動処理をしていないので、キーを押さなければ敵は動きません。
さらに、コメントを取り除いて分かりやすいように{}を補うと

コード:

if (mx > cx) {
	if (mx < cx) {
		ex++;
	}
}
というコードになっているので、mx > cxとmx < cxは同時に成立せず、キーを押しても敵のx座標は変わりません。
みけCAT さんが書きました:敵が斜めに移動する場合がある (仕様?)
というのは誤りでした。
オフトピック
対応していないコンパイラがあるので、文字列でもコメントでもない場所に全角スペースを入れるべきではありません。
そもそも、インデントが崩れて表示される原因になるので、インデントにタブとスペースを混ぜるのはよくありません。
Emacsとかいうエディタの初期設定だとタブとスペースを混ぜてくるんだよ、あのクソが…
敵の表示はうまくいきました!!アドバイス本当にありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る