質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual C++

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

4454閲覧

ドットイートゲーム 敵の移動アルゴリズム を教えてください。

masuter0413

総合スコア50

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual C++

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2017/02/11 02:35

###前提・実現したいこと
こんちには。私は現在パックマンのようなドットイートゲームを作成しています。
まだプログラミングを始めたばかりで、ものすごく簡単ではございますが、基本となるコードはなんとか自分で書くことができました。
しかし、次の問題点がどうしても改善できません。

###発生している問題・エラーメッセージ

敵が壁に当たると全く動かなくなってしまう。

###該当のソースコード

C++

1/////////////////////////////////////////////////////////////// 2// 3// パックマンプログラム pacman2.c 4// 5// 平成29年2月9日 6/////////////////////////////////////////////////////////////// 7#pragma warning(disable:4996) 8#include <stdio.h> 9#include <stdlib.h> // system() 10#include <windows.h> // Sleep() 11#include <conio.h> // kbhit() 12 13#define SIZE 15 // 一辺の長さ 14#define EMPTY 0 // 何もない場所は0 15#define WALL 1 // 壁 16#define FOOD 2 // えさ(ドット) 17#define POWER_FOOD 4 //パワーエサ 18#define PACMAN 3// 主人公 19 20int main() 21{ 22 int wait_time = 300; 23 int x, y, j; 24 int food_count = 0;//エサの個数 25 int power_food_count = 0;//パワーエサの個数 26 int cx, cy;//パックマン 27 int ex, ey;//敵 28 int key; 29 int point = 0; 30 int kx, ky;//自機の座標を保存するための変数 31 int mx, my;//敵の座標を保存するための変数 32 int life = 3;//ライフ 33 34 int field[SIZE][SIZE] = 35 { 36 { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 }, 37 { 1,2,2,2,2,2,2,2,2,2,2,4,2,2,1 }, 38 { 1,2,1,1,1,2,1,1,1,2,1,2,1,2,1 }, 39 { 1,2,1,0,1,2,1,0,1,2,1,2,2,2,1 }, 40 { 1,2,1,1,1,2,1,1,1,2,1,2,1,2,1 }, 41 { 1,2,2,2,2,2,2,2,2,2,2,2,2,2,1 }, 42 { 1,1,1,1,1,0,1,0,1,1,1,0,1,1,1 }, 43 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 44 { 1,1,1,1,1,2,1,2,2,1,1,2,1,1,1 }, 45 { 1,4,2,2,2,2,1,2,1,1,1,2,2,2,1 }, 46 { 1,2,1,1,1,1,0,0,0,0,2,2,1,2,1 }, 47 { 1,2,2,2,0,2,2,1,2,1,2,0,1,2,1 }, 48 { 1,2,1,1,1,0,1,1,2,2,2,1,1,2,1 }, 49 { 1,2,2,2,2,2,2,2,2,1,2,2,2,4,1 }, 50 { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 }, 51 }; 52 53 cx = 7, cy = 7; //パックマンの初期位置 54 ex = 1, ey = 1; //敵の初期位置 55 56 //エサの個数を数える 57 for (y = 0; y < SIZE; y++) 58 { 59 for (x = 0; x < SIZE; x++) 60 { 61 if (field[y][x] == FOOD) 62 food_count++; 63 else if (field[y][x] == POWER_FOOD) 64 power_food_count++; 65 } 66 67 } 68 69 while (1) 70 { 71 // まずはPACMANの動き 72 // キーが押されていたら、キーコードを取得する 73 // 4なら左、6なら右、8なら上、2なら下 74 if (kbhit()) // キーが入力されていれば真 75 { 76 key = getch();//一文字入力、エコーバックなし 77 kx = cx, ky = cy;//パックマンの座標を保存する 78 switch (key) 79 { 80 case '4': 81 cx--; 82 break; 83 case '6': 84 cx++; 85 break; 86 case '2': 87 cy++; 88 break; 89 case '8': 90 cy--; 91 break; 92 } 93 94 cx = (cx + SIZE) % SIZE; //ワープ 95 switch (field[cy][cx]) 96 { 97 case WALL://壁 98 cx = kx, cy = ky; //動けないので cx, cy を元に戻す 99 //壁に当たると自機の座標に元の座標を代入する 100 break; 101 case FOOD: 102 field[cy][cx] = 0;//餌を食べると餌が消える 103 point += 10; //得点加算 104 food_count--; //餌の数を減らしていく 105 break; 106 case POWER_FOOD: 107 field[cy][cx] = 0; //パワーエサを食べると消える 108 life += 1; //LIFE加算 109 power_food_count--;//パワーエサの数を減らしていく 110 break; 111 112 113 } 114 115 } 116 117 118 //ここから敵の動き 119 120 mx = ex; my = ey; //敵の座標を保存する 121 122 if (ex > cx) //敵のx座標 > パックマンのx座標 なら 敵のx座標を減らしてパックマンに近づく。 123 ex--; 124 else if (ex < cx) //敵のx座標 < パックマンのx座標 なら 敵のx座標を増やしてパックマンに近づく。 125 ex++; 126 else if (ey < cy) //敵のy座標 > パックマンのy座標 なら 敵のy座標を減らしてパックマンに近づく。 127 ey++; 128 else if (ey > cy) //敵のy座標 < パックマンのy座標 なら 敵のy座標を増やしてパックマンに近づく。 129 ey--; 130 131 if (field[ey][ex] == WALL) //もし敵が壁に当たったらもとの座標に戻す。 132 { 133 ex = mx; ey = my; 134 135 } 136 137 138 ex = (ex + SIZE) % SIZE; //ワープ 139 140 if (cx == ex && cy == ey) { //もしパックマンと衝突したら マップの真ん中に移動し少し待つ。 141 life--; // そしてLIFE-1 142 ex = 7, ey = 7; 143 Sleep(wait_time); 144 } 145 146 147 // 画面表示 148 for (y = 0; y < SIZE; y++) { 149 for (x = 0; x < SIZE; x++) { 150 if (x == cx && y == cy) 151 printf("C "); 152 else if (x == ex && y == ey) 153 printf("◇"); 154 else if (field[y][x] == FOOD) 155 printf(". "); 156 else if (field[y][x] == WALL) 157 printf("■"); 158 else if (field[y][x] == POWER_FOOD) 159 printf("P "); 160 else 161 printf(" "); 162 } 163 printf("\n"); 164 } 165 166 // すべての場所で field[y][x] の値を元に表示 167 168 169 printf("\n"); 170 printf(" (cx,cy) = (%d, %d)\n", cx, cy); 171 printf(" (ex,ey) = (%d, %d)\n", ex, ey); 172 printf(" point: %d\n", point); 173 printf(" LIFE: %d\n", life); 174 175 if (life == 0) 176 { 177 printf("┏ ┏━┓┏━┓┏┳┓┳━┓ ┏━┓┳ ┳┳━┓┳━┓ ┓\n"); 178 printf("┃ ┃ ┓┣━┫┃┃┃┣┫ ┃ ┃┃ ┃┣┫ ┣┳┛ ┃\n"); 179 printf("┗ ┗━┛┻ ┻┻ ┻┻━┛ ┗━┛┗━┛┻━┛┻┗┛ ┛\n"); 180 Sleep(wait_time); 181 break; 182 } 183 184 if (food_count == 0) //餌を食べきったとき(=CRER)の画面表示 185 { 186 printf("┏ ┏━┓┏━┓┏┳┓┳━┓ ┏━┓ ┳━┓ ┳━┓ ┳━┓ ┓\n"); 187 printf("┃ ┃ ┓┣━┫┃┃┃┣┫ ┃ ┣┳┛ ┣┫ ┣┳┛ ┃\n"); 188 printf("┗ ┗━┛┻ ┻┻ ┻┻━┛ ┗━┛ ┻┗┛ ┻━┛ ┻┗┛ ┛\n"); 189 Sleep(wait_time); 190 break; 191 192 } 193 Sleep(wait_time);// 1秒間(wait_timeミリ秒)何もしない 194 system("cls");// 画面消去 195 } 196 197 return 0; 198} 199

###試したこと
敵が壁に当たった時に、一度ランダムに動かそうと思い、

if (field[ey][ex] == WALL) //もし敵が壁に当たったらもとの座標に戻す。
{
ex = mx; ey = my;
j = rand() % 4;
switch (j)
{
case '0':
ex--;
break;
case '1':
ex++;
break;
case '2':
ey++;
break;
case '3':
ey--;
break;
}

}

にしましたが、やはり敵が壁に当たると全く動きません。
###補足情報(言語/FW/ツール等のバージョンなど)
C++
Visual Studio 2015

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

crowmt

2017/02/11 03:35

今の作りですと、パックマンと敵の間に壁があると敵が進まない気がしますが…
crowmt

2017/02/11 03:41

敵の動きで、ダイレクトにパックマンの位置を見るタイミングを、交差点にきたら行うとかにするなどどうでしょうか。
guest

回答2

0

とりあえずの思いつきですが下記みたいなのはどうでしょう?
全く動かさずに書いているので、考え方の参考程度にしてください。

// int ed=0; // edは敵の動く方向を覚えておく変数とする。定義は適当なところで行う // 0:左 1:右 2:上 3:下 //ここから敵の動き mx = ex; my = ey; //敵の座標を保存する md = ed; //敵の動く方向を保存する while(1) { switch(ed) { case 0: ex--; break; case 1: ex++; break; case 2: ey--; break; case 3: ey++; break; } if (field[ey][ex] == WALL) //移動先が壁の場合 { //とりあえず移動元に位置を戻して ex = mx; ey = my; //次に進む方向を決定する switch(md) { case 0: if (ed == 0) { //左に進んでいるときに壁に当たった場合 //進める方向は上か下になる //そこで自機のY座標と比較して方向を決める if (ey > cy) { ed = 2; } else { ed = 3; } } else if (ed == 2) { //ここに来るということは、現在の位置の上が壁だったので下に方向を変える ed = 3; } else if (ed == 3) { //ここに来るということは、現在の位置の下が壁だったので上に方向を変える ed = 2; } break; case 1: //0の場合を参考に break; case 2: //0の場合を参考に break; case 3: //0の場合を参考に break; } } else { // 移動先が壁ではない場合、敵の位置を決定するループから抜ける break; } }

とりあえず、移動先が壁の場合の次の方向の決定方法を変更すれば、いろいろ性格がでると思います。
また、移動する前に分岐点があるかチェックして、そこを曲がるかどうかの処理を入れればいいと思います。

投稿2017/02/11 09:09

編集2017/02/11 13:56
YAmaGNZ

総合スコア10258

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

私はプログラミング初心者かつRubyしかわからない人間です。
移動先が壁かどうかを調べてから移動するというのは
どうでしょうか。
fieldの8つめの配列は
[ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ]ですが
こちらの都合で
[ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,1 ]に
変更しました。
以下のプログラムでは敵が階段状の壁に当たると
引っかかります。(自機を動かすとまた動くようになります。)
移動先が壁かどうかを先に調べる以外は
質問に書いてあったことを書き換えただけなので
もしかしたらそちらの言語でも移動先が壁かどうかを
先に調べるようにすれば動くかもしれません。

Ruby

1#encoding : utf-8 2require"dxruby" 3 4@map = [[ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 ], 5 [ 1,2,2,2,2,2,2,2,2,2,2,4,2,2,1 ], 6 [ 1,2,1,1,1,2,1,1,1,2,1,2,1,2,1 ], 7 [ 1,2,1,0,1,2,1,0,1,2,1,2,2,2,1 ], 8 [ 1,2,1,1,1,2,1,1,1,2,1,2,1,2,1 ], 9 [ 1,2,2,2,2,2,2,2,2,2,2,2,2,2,1 ], 10 [ 1,1,1,1,1,0,1,0,1,1,1,0,1,1,1 ], 11 [ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,1 ], 12 [ 1,1,1,1,1,2,1,2,2,1,1,2,1,1,1 ], 13 [ 1,4,2,2,2,2,1,2,1,1,1,2,2,2,1 ], 14 [ 1,2,1,1,1,1,0,0,0,0,2,2,1,2,1 ], 15 [ 1,2,2,2,0,2,2,1,2,1,2,0,1,2,1 ], 16 [ 1,2,1,1,1,0,1,1,2,2,2,1,1,2,1 ], 17 [ 1,2,2,2,2,2,2,2,2,1,2,2,2,4,1 ], 18 [ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 ]] 19 20@map_tile = [] 21@map_tile[0] = Image.new(30, 30, C_BLACK) #何もない 22@map_tile[1] = Image.new(30, 30, C_WHITE) #壁 23@map_tile[2] = Image.new(30, 30, C_BLACK) 24@map_tile[3] = Image.new(30, 30, C_GREEN) #自機 25@map_tile[4] = Image.new(30, 30, C_BLACK) 26@map_tile[5] = Image.new(30, 30, C_RED) #敵 27 28Window.width = 450 29Window.height = 450 30 31start_count = 0 32 33cx = 7 34cy = 7 35 36ex = 1 37ey = 1 38 39enemy_count = 0 40 41game_overcount = 0 42next_count = 0 43font = Font.new(55) 44 45Window.loop do 46 #初期位置の指定 47 if start_count == 0 then 48 @map[cx][cy] = 3 49 @map[ex][ey] = 5 50 start_count = 1 51 end 52 53 #自機の操作 54 if Input.keyPush?(K_W) then 55 if @map[cx - 1][cy] != 1 && @map[cx - 1][cy] != 5 then 56 @map[cx][cy] = 0 57 @map[cx -= 1][cy] = 3 58 start_count = 2 59 end 60 end 61 if Input.keyPush?(K_S) then 62 if @map[cx + 1][cy] != 1 && @map[cx + 1][cy] != 5 then 63 @map[cx][cy] = 0 64 @map[cx += 1][cy] = 3 65 start_count = 2 66 end 67 end 68 if Input.keyPush?(K_D) then 69 if @map[cx][cy + 1] != 1 && @map[cx][cy + 1] != 5 then 70 @map[cx][cy] = 0 71 @map[cx][cy += 1] = 3 72 start_count = 2 73 end 74 end 75 if Input.keyPush?(K_A) then 76 if @map[cx][cy - 1] != 1 && @map[cx][cy - 1] != 5 then 77 @map[cx][cy] = 0 78 @map[cx][cy -= 1] = 3 79 start_count = 2 80 end 81 end 82 83 84 #敵 85 if start_count == 2 86 if ex > cx 87 if @map[ex - 1][ey] != 1 then 88 @map[ex][ey] = 0 89 @map[ex -= 1][ey] = 5 90 end 91 end 92 if ex < cx 93 if @map[ex + 1][ey] != 1 then 94 @map[ex][ey] = 0 95 @map[ex += 1][ey] = 5 96 end 97 end 98 if ey > cy 99 if @map[ex][ey - 1] != 1 then 100 @map[ex][ey] = 0 101 @map[ex][ey -= 1] = 5 102 end 103 end 104 if ey < cy 105 if @map[ex][ey + 1] != 1 then 106 @map[ex][ey] = 0 107 @map[ex][ey += 1] = 5 108 end 109 end 110 start_count = 1 111 end 112 113 Window.draw_tile(0, 0, @map, @map_tile, 0, 0, 15, 15) 114 115 if @map[cx][cy] == 5 116 Window.draw(0, 0, Image.new(450, 450, C_RED)) 117 Window.draw_font(90, 150, "Game Over", font) 118 next_count += 1 119 if next_count >= 180 then 120 break 121 end 122 end 123end

投稿2017/02/11 06:24

編集2017/02/11 06:24
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問