ページ 11

正しく出力されない。ループする。

Posted: 2016年2月10日(水) 18:12
by pazumon_2525
こちらに同じ質問しています。
https://oshiete.goo.ne.jp/qa/9171406.html

内容はこちらと同じですが、必要とする内容は自ら考えました。
以下がそのコードとなります。

実行すると、無限ループあるいはコアダンプが出ます。
まれに出力されますが正しく"・"が表示されません。
何回かデバッグをしましたが、どうしてかわかりません。
よろしくお願いします。デバッグ多いです。

コード:

#include "a.h"
#include<stdio.h>

struct player
{
	int y;  //y座標
	int x;  //x座標
};

struct player dir(int maze[H][W],struct player p);
void solve_maze(int maze[H][W])
{
	int x,y;
	struct player p;
	
	//スタート地点を見つける
	for(y=0;y<H;y++)
	{
		for(x=0;x<W;x++)
		{
			if(maze[y][x] == START)
			{
				printf("[%d][%d]\n",y,x);
				//上 
				if(y == 0 && maze[y][x+1] == WALL && maze[y][x-1] == WALL )
				{
					p.y = y+1;
					p.x = x;
				}
				//左
				else if(x == 0 && maze[y+1][x] == WALL && maze[y-1][x] == WALL )
				{
					p.x = x+1;
					p.y = y;
				}
				//下
				else if(y == H-1 && maze[y][x+1] == WALL && maze[y][x-1] == WALL)
				{
					p.y = y-1;
					p.x = x;
				}
				//右
				else if(x == W-1 && maze[y+1][x] == WALL && maze[y-1][x] == WALL )
				{
					p.x = x-1;
					p.y = y;
				}
			}
		}
	}
	do
	{
		p = dir(maze,p);
	}
	while(maze[p.y][p.x] != GOAL);
}
struct player dir(int maze[H][W],struct player p)
{
	int flg = 0;
	
	while(maze[p.y+1][p.x] == WALL && maze[p.y][p.x+1] != WALL && flg == 0)
	{
		//printf("a\n");
		p.x = p.x+1;
		maze[p.y][p.x] = TRACK;
		
	} 
	if(maze[p.y+1][p.x] != WALL && flg == 0)
	{
		//printf("d\n");
		maze[p.y][p.x] = TRACK;
		p.y = p.y+1;
		flg = 1;
	}
	
	while(maze[p.y][p.x+1] == WALL && maze[p.y-1][p.x] != WALL && flg == 0)
	{
		//printf("b\n");
		p.y = p.y-1;
		maze[p.y][p.x] = TRACK;
	}
	if(maze[p.y][p.x+1] != WALL && flg == 0)
	{
		//printf("c\n");
		maze[p.y][p.x] = TRACK;
		p.x = p.x+1;
		flg = 1;
	}

	while(maze[p.y-1][p.x] == WALL && maze[p.y][p.x-1] != WALL && flg == 0)
	{
		//printf("c\n");
		p.x = p.x-1;
		maze[p.y][p.x] = TRACK;
	}
	if(maze[p.y-1][p.x] != WALL && flg == 0)
	{
		//printf("b\n");
		maze[p.y][p.x] = TRACK;
		p.y = p.y-1;
		flg = 1;
	}
	
	while(maze[p.y][p.x-1] == WALL && maze[p.y+1][p.x] != WALL && flg == 0)
	{
		//printf("d\n");
		p.y = p.y+1;
		maze[p.y][p.x] = TRACK;
	}
	if(maze[p.y][p.x-1] != WALL && flg == 0)
	{
		//printf("a\n");
		maze[p.y][p.x] = TRACK;
		p.x = p.x-1;
		flg = 1;	
	}
	return p;
}

Re: 正しく出力されない。ループする。

Posted: 2016年2月10日(水) 19:41
by みけCAT
マルチポストをする場合は、相互リンクが必要です。

【追記】
よく見たら、マルチポストと言えるかどうか微妙、むしろ該当しない感じかな…。

Re: 正しく出力されない。ループする。

Posted: 2016年2月10日(水) 19:47
by みけCAT
配列の確保された領域の範囲外にアクセスしてはいけません。
mazeを直接参照するのではなく、添字が範囲外でないかをチェックし、
範囲内ならmazeのその場所の値を返し、範囲外なら適当な値を返す関数を作って利用すると、
この問題は改善しやすいと思います。
(詳しく見ていないので、他にも問題がある可能性を否定できません)

Re: 正しく出力されない。ループする。

Posted: 2016年2月11日(木) 00:08
by pazumon_2525
範囲チェックを関数なしで行うことはできますか?
追加する感じで。

Re: 正しく出力されない。ループする。

Posted: 2016年2月11日(木) 00:24
by みけCAT
pazumon_2525 さんが書きました:範囲チェックを関数なしで行うことはできますか?
はい。
マクロを使うこともできるでしょう。

Re: 正しく出力されない。ループする。

Posted: 2016年2月11日(木) 00:51
by pazumon_2525
あと、範囲外をアクセスしてはいけない。と指摘して頂きましたが、何処で範囲外にアクセスしてしまっておりますでしょうか?
返す値はmaze.pでは駄目ですか?
すみません。よろしくお願いします。

Re: 正しく出力されない。ループする。

Posted: 2016年2月11日(木) 00:57
by みけCAT
pazumon_2525 さんが書きました:あと、範囲外をアクセスしてはいけない。と指摘して頂きましたが、何処で範囲外にアクセスしてしまっておりますでしょうか?
例えばsolve_maze関数でmaze[0][0] == START && maze[0][1] == WALLのとき、25行目で範囲外のmaze[0][-1]へのアクセスが発生します。
他のif文でも同様に範囲外にアクセスする可能性があります。
pazumon_2525 さんが書きました:返す値はmaze.pでは駄目ですか?
このプログラムで使用されているmazeは全て構造体でも共用体でもないので、駄目でしょう。

Re: 正しく出力されない。ループする。

Posted: 2016年2月11日(木) 11:32
by pazumon_2525
方向(4つ分)の関数がないと駄目ですかね?

Re: 正しく出力されない。ループする。

Posted: 2016年2月11日(木) 22:27
by box
pazumon_2525 さんが書きました:方向(4つ分)の関数がないと駄目ですかね?
何々じゃなきゃダメってことはないと思います。設計しだい。

Re: 正しく出力されない。ループする。

Posted: 2016年2月15日(月) 18:33
by pazumon_2525
これまで、アルゴリズムを振り返りましたが、私が書いたプログラムから全然分からなくて困っております。
曲がった際に方向を変えてやるのは分かっておりますが。
よろしくお願い致します。

Re: 正しく出力されない。ループする。

Posted: 2016年2月15日(月) 19:29
by pazumon_2525
すみません。帰宅したらソース貼ります。

Re: 正しく出力されない。ループする。

Posted: 2016年2月15日(月) 21:41
by pazumon_2525
ソースです。
これでもうまく動きません。指摘お願いします。



コード:

#include "a.h"
#include<stdio.h>

#define NORTH 0 //北
#define WEST 1 //西
#define SOUTH 2 //南
#define EAST 3 //東

struct player
{
	int y;  //y座標
	int x;  //x座標
	int dir; //向き     //0:北 1:西 2:南 3;東
};

struct player start(int maze[H][W],struct player p);
struct player north(int maze[H][W],struct player p);
struct player west(int maze[H][W],struct player p);
struct player south(int maze[H][W],struct player p);
struct player east(int maze[H][W],struct player p);

void solve_maze(int maze[H][W])
{
	int x,y;
	struct player p;
	
	//スタート地点を見つける
	for(y=0;y<H;y++)
	{
		for(x=0;x<W;x++)
		{
			if(maze[y][x] == START)
			{
				printf("[%d][%d]\n",y,x);
				//上 
				if(y == 0 && maze[y][x+1] == WALL && maze[y][x-1] == WALL )
				{
					p.y = y+1;
					p.x = x;
					p.dir = SOUTH;
				}
				//左	return 0;
				else if(x == 0 && maze[y+1][x] == WALL && maze[y-1][x] == WALL )
				{
					p.x = x+1;
					p.y = y;
					p.dir = WEST;
				}
				//下
				else if(y == H-1 && maze[y][x+1] == WALL && maze[y][x-1] == WALL)
				{
					p.y = y-1;
					p.x = x;
					p.dir = NORTH;
				}
				//右
				else if(x == W-1 && maze[y+1][x] == WALL && maze[y-1][x] == WALL )
				{
					p.x = x-1;
					p.y = y;
					p.dir = EAST;
				}
			}
		}
	}
	do
	{
		p = start(maze,p);
		maze[p.y][p.x] = TRACK;
		system("clear");
		print_maze(maze);
		usleep(500000);
	}
	while(maze[p.y][p.x] != GOAL);
}

struct player start(int maze[H][W],struct player p)
{
	if(p.dir == NORTH)
	{
		north(maze, p);
	}
	else if(p.dir == WEST)
	{
		west(maze, p);
	}
	else if(p.dir == SOUTH)
	{
		south(maze, p);
	}
	else if(p.dir == EAST)
	{
		east(maze, p);
	}
	
	return p;
}

struct player north(int maze[H][W],struct player p)
{
	int flg = 0;
	
	/* 東が前で南が右 */
	while(p.x<W-1 && maze[p.y+1][p.x] == WALL && maze[p.y][p.x+1] != WALL && flg == 0)
	{
		p.x = p.x+1;
		maze[p.y][p.x] = TRACK;
		
	} 
	if(maze[p.y+1][p.x] != WALL && flg == 0)
	{
		maze[p.y][p.x] = TRACK;
		p.y = p.y+1;
		flg = 1;
	}
	
	/* 北が前で東が右 */
	while(p.y>0 && maze[p.y][p.x+1] == WALL && maze[p.y-1][p.x] != WALL && flg == 0)
	{
		p.y = p.y-1;
		maze[p.y][p.x] = TRACK;
	}
	if(maze[p.y][p.x+1] != WALL && flg == 0)
	{
		maze[p.y][p.x] = TRACK;
		p.x = p.x+1;
		flg = 1;
	}

	/* 西が前で北が右*/
	while(p.x>0 && maze[p.y-1][p.x] == WALL && maze[p.y][p.x-1] != WALL && flg == 0)
	{
		p.x = p.x-1;
		maze[p.y][p.x] = TRACK;
	}
	if(maze[p.y-1][p.x] != WALL && flg == 0)
	{
		maze[p.y][p.x] = TRACK;
		p.y = p.y-1;
		flg = 1;
	}
	
	/* 南が前で西が右 */
	while(p.y<H-1 && maze[p.y][p.x-1] == WALL && maze[p.y+1][p.x] != WALL && flg == 0)
	{
		p.y = p.y+1;
		maze[p.y][p.x] = TRACK;
	}
	if(maze[p.y][p.x-1] != WALL && flg == 0)
	{
		maze[p.y][p.x] = TRACK;
		p.x = p.x-1;
		flg = 1;	
	}
	
	return p;
}

struct player west(int maze[H][W],struct player p)
{
	int flg = 0;
	
	/* 南が前で西が右 */
	while(p.y<H-1 && maze[p.y][p.x-1] == WALL && maze[p.y+1][p.x] != WALL && flg == 0)
	{
		p.y = p.y+1;
		maze[p.y][p.x] = TRACK;
	}
	if(maze[p.y][p.x-1] != WALL && flg == 0)
	{
		maze[p.y][p.x] = TRACK;
		p.x = p.x-1;
		flg = 1;	
	}
	
	/* 東が前で南が右 */
	while(p.x<W-1 && maze[p.y+1][p.x] == WALL && maze[p.y][p.x+1] != WALL && flg == 0)
	{
		p.x = p.x+1;
		maze[p.y][p.x] = TRACK;
	} 
	if(maze[p.y+1][p.x] != WALL && flg == 0)
	{
		maze[p.y][p.x] = TRACK;
		p.y = p.y+1;
		flg = 1;
	}
	/* 北が前で東が右 */
	while(p.y>0 && maze[p.y][p.x+1] == WALL && maze[p.y-1][p.x] != WALL && flg == 0)
	{
		p.y = p.y-1;
		maze[p.y][p.x] = TRACK;
	}
	if(maze[p.y][p.x+1] != WALL && flg == 0)
	{
		maze[p.y][p.x] = TRACK;
		p.x = p.x+1;
		flg = 1;
	}
	/* 西が前で北が右*/
	while(p.x>0 && maze[p.y-1][p.x] == WALL && maze[p.y][p.x-1] != WALL && flg == 0)
	{
		p.x = p.x-1;
		maze[p.y][p.x] = TRACK;
	}
	if(maze[p.y-1][p.x] != WALL && flg == 0)
	{
		maze[p.y][p.x] = TRACK;
		p.y = p.y-1;
		flg = 1;
	}
	return p;
}

struct player south(int maze[H][W],struct player p)
{
	int flg = 0;
	
	/* 西が前で北が右*/
	while(p.x>0 && maze[p.y-1][p.x] == WALL && maze[p.y][p.x-1] != WALL && flg == 0)
	{
		p.x = p.x-1;
		maze[p.y][p.x] = TRACK;
	}
	if(maze[p.y-1][p.x] != WALL && flg == 0)
	{
		maze[p.y][p.x] = TRACK;
		p.y = p.y-1;
		flg = 1;
	}
	
	/* 南が前で西が右 */
	while(p.y<H-1 && maze[p.y][p.x-1] == WALL && maze[p.y+1][p.x] != WALL && flg == 0)
	{
		p.y = p.y+1;
		maze[p.y][p.x] = TRACK;
	}
	if(maze[p.y][p.x-1] != WALL && flg == 0)
	{
		maze[p.y][p.x] = TRACK;
		p.x = p.x-1;
		flg = 1;	
	}
	
	/* 東が前で南が右 */
	while(p.x<W-1 && maze[p.y+1][p.x] == WALL && maze[p.y][p.x+1] != WALL && flg == 0)
	{
		p.x = p.x+1;
		maze[p.y][p.x] = TRACK;
		
	} 
	if(maze[p.y+1][p.x] != WALL && flg == 0)
	{
		maze[p.y][p.x] = TRACK;
		p.y = p.y+1;
		flg = 1;
	}
	
	/* 北が前で東が右 */
	while(p.y>0 && maze[p.y][p.x+1] == WALL && maze[p.y-1][p.x] != WALL && flg == 0)
	{
		p.y = p.y-1;
		maze[p.y][p.x] = TRACK;
	}
	if(maze[p.y][p.x+1] != WALL && flg == 0)
	{
		maze[p.y][p.x] = TRACK;
		p.x = p.x+1;
		flg = 1;
	}
	
	return p;
}

struct player east(int maze[H][W],struct player p)
{
	int flg = 0;
	
	/* 北が前で東が右 */
	while(p.y>0 && maze[p.y][p.x+1] == WALL && maze[p.y-1][p.x] != WALL && flg == 0)
	{
		p.y = p.y-1;
		maze[p.y][p.x] = TRACK;
	}
	if(maze[p.y][p.x+1] != WALL && flg == 0)
	{
		maze[p.y][p.x] = TRACK;
		p.x = p.x+1;
		flg = 1;
	}
	
	/* 西が前で北が右*/
	while(p.x>0 && maze[p.y-1][p.x] == WALL && maze[p.y][p.x-1] != WALL && flg == 0)
	{
		p.x = p.x-1;
		maze[p.y][p.x] = TRACK;
	}
	if(maze[p.y-1][p.x] != WALL && flg == 0)
	{
		maze[p.y][p.x] = TRACK;
		p.y = p.y-1;
		flg = 1;
	}
	/* 南が前で西が右 */
	while(p.y<H-1 && maze[p.y][p.x-1] == WALL && maze[p.y+1][p.x] != WALL && flg == 0)
	{
		p.y = p.y+1;
		maze[p.y][p.x] = TRACK;
	}
	if(maze[p.y][p.x-1] != WALL && flg == 0)
	{
		maze[p.y][p.x] = TRACK;
		p.x = p.x-1;
		flg = 1;	
	}
	
	/* 東が前で南が右 */
	while(p.x<W-1 && maze[p.y+1][p.x] == WALL && maze[p.y][p.x+1] != WALL && flg == 0)
	{
		p.x = p.x+1;
		maze[p.y][p.x] = TRACK;
		
	} 
	if(maze[p.y+1][p.x] != WALL && flg == 0)
	{
		maze[p.y][p.x] = TRACK;
		p.y = p.y+1;
		flg = 1;
	}
	
	return p;
}		
		

Re: 正しく出力されない。ループする。

Posted: 2016年2月15日(月) 22:23
by hoge
36行目の if(y == 0 && maze[y][x+1] == WALL && maze[y][x-1] == WALL )は[0][W-1]の場合[0][W]となり範囲外アクセスが発生しますね。

gooの投稿を見る限り、スタートとゴールは外周上にのみ存在するようなので、スタートの位置(0なりW-1なり...)から向きを決めるといいかもしれません。
オフトピック
ex9.h...課題9ですかね

Re: 正しく出力されない。ループする。

Posted: 2016年2月15日(月) 22:34
by pazumon_2525
struct player startでスタート位置から向きを指定しています。
これではダメですか?

Re: 正しく出力されない。ループする。

Posted: 2016年2月16日(火) 14:17
by pazumon_2525
範囲外チェックはどうしたらよいですか?

Re: 正しく出力されない。ループする。

Posted: 2016年2月16日(火) 14:38
by pazumon_2525
コンパイルすると右に壁がなかったときに止まってしまうんですよね。

Re: 正しく出力されない。ループする。

Posted: 2016年2月16日(火) 16:29
by hoge
pazumon_2525 さんが書きました:範囲外チェックはどうしたらよいですか?
範囲外を参照しなければ大丈夫です。

どうしたらいいのかを聞くのではなく、なにがどのように分からないのかを言ってください。
オフトピック
ex9.h変更されてるし学校の課題だったのかな。
学校の課題だったら担当の教授なり先生なりに聞くのが早いと思うんだけどなぁ

Re: 正しく出力されない。ループする。

Posted: 2016年2月16日(火) 16:56
by usao
オフトピック
このトピックって,「何の話なの?」っていうのが明確な状況なのですか?

明確な問題設定や,
それに対してどういう方法(アルゴリズム)を実装しようとしているのか等に関しての
説明等も見つけることができませんし,
>ex9.h
がどうのとかいう話も一体何の話をしているのか全く謎……


リンク先を見ても

>ランダムなSからGまで・をたどっていくようにしたいです

とかいう,ものすごく曖昧な一文しか無いわけですが.
この一文を読むと
「入力データには少なくとも{ 'S', 'G', '・' }が含まれていて,
 複数の '・' が,'S'から'G'までの道筋を示す形に連なって分布している」
という状況を思い浮かべますが,そういう感じでもなさそうだし……?