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

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

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

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

Q&A

解決済

4回答

251閲覧

ドットイートゲームでループを改善したい

退会済みユーザー

退会済みユーザー

総合スコア0

C

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

0グッド

0クリップ

投稿2019/05/20 04:11

編集2019/05/20 05:35

敵に食べられる前に餌を食べ尽くすために自機を動かすプログラムを作っています。

プレイヤーのソースコード #include <stdio.h> #include <stdlib.h> #include "Info.h" MOVEMENT playerAI(MAPDATA map, POSITION p, POSITION e, int turn) { int len = abs(e.x - p.x) + abs(e.y - p.y); int right, down, left, up, max; right = abs(e.x - p.x + 1) + abs(e.y - p.y); down = abs(e.x - p.x) + abs(e.y + 1 - p.y); left = abs(e.x - p.x - 1) + abs(e.y - p.y); up = abs(e.x - p.x) + abs(e.y - p.y - 1); max = right; if (down > max) max = down; if (left > max) max = left; if (up > max) max = up; if (max == right && map[p.y][p.x + 1] == 1 && !(e.y == p.y && e.x == p.x + 1)) { return RIGHT; } else if (max == down && map[p.y + 1][p.x] == 1 && !(e.y == p.y + 1 && e.x == p.x)) { return DOWN; } else if (max == left && map[p.y][p.x - 1] == 1 && !(e.y == p.y && e.x == p.x - 1)) { return LEFT; } else if (max == up && map[p.y - 1][p.x] == 1 && !(e.y == p.y - 1 && e.x == p.x)) { return UP; } else if (max == right && map[p.y][p.x + 1] == 0 && !(e.y == p.y && e.x == p.x + 1)) { return RIGHT; } else if (max == down && map[p.y + 1][p.x] == 0 && !(e.y == p.y + 1 && e.x == p.x)) { return DOWN; } else if (max == left && map[p.y][p.x - 1] == 0 && !(e.y == p.y && e.x == p.x - 1)) { return LEFT; } else if (max == up && map[p.y - 1][p.x] == 0 && !(e.y == p.y - 1 && e.x == p.x)) { return UP; } else if (map[p.y][p.x + 1] == 1 && !(e.y == p.y && e.x == p.x + 1)) { return RIGHT; } else if (map[p.y + 1][p.x] == 1 && !(e.y == p.y + 1 && e.x == p.x)) { return DOWN; } else if (map[p.y][p.x - 1] == 1 && !(e.y == p.y && e.x == p.x - 1)) { return LEFT; } else if (map[p.y - 1][p.x] == 1 && !(e.y == p.y - 1 && e.x == p.x)) { return UP; } else if (map[p.y][p.x + 1] == 0 && !(e.y == p.y && e.x == p.x + 1)) { return RIGHT; } else if (map[p.y + 1][p.x] == 0 && !(e.y == p.y + 1 && e.x == p.x)) { return DOWN; } else if (map[p.y][p.x - 1] == 0 && !(e.y == p.y && e.x == p.x - 1)) { return LEFT; } else if (map[p.y - 1][p.x] == 0 && !(e.y == p.y - 1 && e.x == p.x)) { return UP; } else { return STAY; } }

マンハッタン距離の最大値を求めて最大値の方向に進むプログラムを組んでいるのですが、同じ場所をぐるぐる逃げ回りループしてしまいます。
ループを改善するにはどのようにすれば良いかアドバイスいただきたいです。

モンスターはプレイヤーに向かって最短距離で移動しようとします。
いずれかの条件を満たすまでゲームが継続します。
・プレイヤーがエサをすべて食べる
・プレイヤーがモンスターに接触する
・1000ターン経過する

 ・返り値としてMOVEMENT型の値を返します。
・引数として以下の変数が与えられる。
map(MAPDATA型):マップの情報(通路・エさ・壁の位置)
p(POSITION型):プレイヤーの位置情報
e(POSITION型):モンスターの位置情報
turn(int型):現在のターン数(最初は0)
ランダムを使う場合はrand関数のみ使用し,srand関数は使わないでください。

*MOVEMENT型
プレイヤーやモンスターの移動方向を示す型。
STAY,UP,LEFT,RIGHT,DOWNの5種類の値がある。
*MAPDATA型
マップ上の通路・エサ・壁の位置の情報を示す型です。
0~255の値を持つ,22×19の二次元配列として扱うことができます。
0:通路
1:エサ
2:壁
*POSITION型
プレイヤーやモンスターの位置情報を示す型。
x座標とy座標を取り出すことが出来る。
(例)プレイヤーのx座標:p.x,モンスターのy座標:e.y
また,以下の値が定義されています。
MAP_WIDTH:マップの横幅 (19)
MAP_HEIGHT:マップの縦幅 (22)

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

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

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

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

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

y_waiwai

2019/05/20 05:08

このままではコードが見づらいので、質門を編集し、<code>ボタンで、出てくる’’’の枠の中にコードを貼り付けてください
jimbe

2019/05/20 08:56

この場合マークダウンにしても見難いですね...
guest

回答4

0

ベストアンサー

ループを改善するにはどのようにすれば良いか

ぐるぐるしているのを見て, shunshunx0906 さんがそのプレイヤーを操作する人だったら, どの時にどのように判断してどこに進むでしょうか.
それを組み込めば良いかと思います.

投稿2019/05/20 09:14

jimbe

総合スコア12696

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

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

退会済みユーザー

退会済みユーザー

2019/05/20 10:19

そこが問題ですね... 例えば、if文でループ情態に入ったらランダム関数で壁のない方向に進むようにしたいのですが、ループ状態に入ったことを認識するためのプログラムが思いつきません...
jimbe

2019/05/20 11:26

AI の開発は, 単に人工的に頭脳を作るというだけでなく, その過程において, 「人間の思考はどのように行われているのか」を知ることでもあります. プログラムが「同じ所をぐるぐる回っている」と判断するにはどのような情報が必要なのか, ご自身が道に迷った時, もし同じ所をぐるぐる回っていると判断されるとしたら, それは何によってでしょうか. 想像してそれをコード化することこそ, まさしく開発のような気がします.
guest

0

回答ではないですが、

if (max == right && map[p.y][p.x + 1] == 1 && !(e.y == p.y && e.x == p.x + 1)) { return RIGHT; }

else if (max == down && map[p.y + 1][p.x] == 1 && !(e.y == p.y + 1 && e.x == p.x)) { return DOWN; }

if文でreturnしてしまうのなら、以降のelseは削除できますね

if (max == right && map[p.y][p.x + 1] == 1 && !(e.y == p.y && e.x == p.x + 1)) { return RIGHT; }
if (max == down && map[p.y + 1][p.x] == 1 && !(e.y == p.y + 1 && e.x == p.x)) { return DOWN; }
~~~
return STAY;

投稿2019/05/20 07:01

y_waiwai

総合スコア87784

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

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

退会済みユーザー

退会済みユーザー

2019/05/20 08:18

アドバイスありがとうございます。 明日削除したものと見比べてみたいと思います。
guest

0

left, right, up, down の式は間違ってませんか?
例えば,rightについては

right = abs(e.x - p.x + 1) + abs(e.y - p.y);

↓こうでは?
right = abs(e.x - (p.x + 1)) + abs(e.y - p.y);

投稿2019/05/20 06:48

fana

総合スコア11675

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

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

退会済みユーザー

退会済みユーザー

2019/05/20 08:15

指摘ありがとうございます。 明日動作の確認してみたいと思います。
guest

0

これが原因かはわかりませんが、少なくともif文の条件式でmax=で代入しているのはおかしいですね。

C

1if (max = right && map[p.y][p.x + 1] == 1 && !(e.y == p.y && e.x == p.x + 1)) { return RIGHT; } 23if (max == right && map[p.y][p.x + 1] == 1 && !(e.y == p.y && e.x == p.x + 1)) { return RIGHT; }

8箇所あるので修正してみてください。

投稿2019/05/20 04:31

ttyp03

総合スコア16998

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

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

退会済みユーザー

退会済みユーザー

2019/05/20 04:47

代入になってましたね... ありがとうございます! ループは別の要因ありそうです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問