c言語の迷路の最短経路を求めるプログラムでキューのアンダーフローが起きてしまいます。どなたかアドバイスをお願いします。
Posted: 2014年11月07日(金) 15:21
大学で出た演習問題です。自分でもそれなりに頑張ってみたのですがうまくいきません。以下に問題とソースを記すので、どなたかアドバイスをお願いします。
左上の座標を(0,0) とするマス目でできたNxNマスの迷路があり、
’*’ は壁で、’ ’ は空きマスの通路とする。
このような迷路において、指定したスタートS からゴールG まで、
下記の手順で最短距離を求めるプログラムをつくれ。
手順1: スタート位置の座標=(sx,sy) と距離=0 をキューに記録する
手順2: キューが空になるまで以下を繰り返す。
手順2-1: キューから位置と距離を取り出し、現在の位置と距離とする。
手順2-2: もしその位置がゴールG ならば繰返しを抜ける。
手順2-3: 現在の位置の上下左右を調べ、空きマスならば(現在の距離+1) を
そのマスの距離として座標とともにキューに保存する。
手順3: ゴールに到達していれば距離を出力して終了する。
• N は7 とする。
• 一度通った道を記録するように工夫することで、効率よく計算することもできる。
#include<stdio.h>
#include<stdlib.h>
#define N 7
#define QUEUESIZE 1000000
typedef char elementtype;
struct queue {
int front, rear;
elementtype elements[QUEUESIZE];
};
void initqueue(struct queue *q){
q->front = q->rear = 0;
}
int queueempty(struct queue *q){
return ( q->front==q->rear );
}
void putq(struct queue *q, elementtype x){
q->elements[q->rear]=x;
q->rear++;
if(q->rear>= QUEUESIZE) q->rear=0;
if(q->rear==q->front){
printf("queue overflow"); exit(1);
}
}
elementtype getq(struct queue *q){
elementtype wk;
if(q->front==q->rear){
printf("queue underflow"); exit(1);
}
else {
wk=q->elements[q->front];
q->front++;
if(q->front>=QUEUESIZE) q->front=0;
return wk;
}
}
int main(void) {
#define BUFSIZE (N*2)
char buf[BUFSIZE];
char maze[N][N];
int i, j, sx, sy, gx, gy;
struct queue queue;
initqueue(&queue);
/* 迷路を読み込み、maze にセットする。*/
for (i = 0; i < N; i++) {
fgets(buf, BUFSIZE, stdin);
for (j = 0; j < N && (buf[j] != '\n' && buf[j] != '\0'); j++) {
if (buf[j] == 'S') {
sx = j; sy = i;
} else if (buf[j] == 'G') {
gx = j; gy = i; buf[j] = ' ';
}
maze[j] = buf[j];
}
}
int x=sx,y=sy,c=0;
putq(&queue,x); putq(&queue,y); putq(&queue,c);
while (queue.elements!=NULL) {
x=getq(&queue); y=getq(&queue); c=getq(&queue); //ここでアンダーフローが起きてしまうようです。
if (x==gx && y==gy) {break;}
if (maze[x+1][y]==' ') {
putq(&queue,x+1); putq(&queue,y); putq(&queue,c+1);
maze[x+1][y]='*';
}
if (maze[x-1][y]==' ') {
putq(&queue,x-1); putq(&queue,y); putq(&queue,c+1);
maze[x-1][y]='*';
}
if (maze[x][y+1]==' ') {
putq(&queue,x); putq(&queue,y+1); putq(&queue,c+1);
maze[x][y+1]='*';
}
if (maze[x][y-1]==' ') {
putq(&queue,x); putq(&queue,y-1); putq(&queue,c+1);
maze[x][y-1]='*';
}
}
/* 最短距離を表示する。*/
printf("%d\n", c);
return 0;
}
左上の座標を(0,0) とするマス目でできたNxNマスの迷路があり、
’*’ は壁で、’ ’ は空きマスの通路とする。
このような迷路において、指定したスタートS からゴールG まで、
下記の手順で最短距離を求めるプログラムをつくれ。
手順1: スタート位置の座標=(sx,sy) と距離=0 をキューに記録する
手順2: キューが空になるまで以下を繰り返す。
手順2-1: キューから位置と距離を取り出し、現在の位置と距離とする。
手順2-2: もしその位置がゴールG ならば繰返しを抜ける。
手順2-3: 現在の位置の上下左右を調べ、空きマスならば(現在の距離+1) を
そのマスの距離として座標とともにキューに保存する。
手順3: ゴールに到達していれば距離を出力して終了する。
• N は7 とする。
• 一度通った道を記録するように工夫することで、効率よく計算することもできる。
#include<stdio.h>
#include<stdlib.h>
#define N 7
#define QUEUESIZE 1000000
typedef char elementtype;
struct queue {
int front, rear;
elementtype elements[QUEUESIZE];
};
void initqueue(struct queue *q){
q->front = q->rear = 0;
}
int queueempty(struct queue *q){
return ( q->front==q->rear );
}
void putq(struct queue *q, elementtype x){
q->elements[q->rear]=x;
q->rear++;
if(q->rear>= QUEUESIZE) q->rear=0;
if(q->rear==q->front){
printf("queue overflow"); exit(1);
}
}
elementtype getq(struct queue *q){
elementtype wk;
if(q->front==q->rear){
printf("queue underflow"); exit(1);
}
else {
wk=q->elements[q->front];
q->front++;
if(q->front>=QUEUESIZE) q->front=0;
return wk;
}
}
int main(void) {
#define BUFSIZE (N*2)
char buf[BUFSIZE];
char maze[N][N];
int i, j, sx, sy, gx, gy;
struct queue queue;
initqueue(&queue);
/* 迷路を読み込み、maze にセットする。*/
for (i = 0; i < N; i++) {
fgets(buf, BUFSIZE, stdin);
for (j = 0; j < N && (buf[j] != '\n' && buf[j] != '\0'); j++) {
if (buf[j] == 'S') {
sx = j; sy = i;
} else if (buf[j] == 'G') {
gx = j; gy = i; buf[j] = ' ';
}
maze[j] = buf[j];
}
}
int x=sx,y=sy,c=0;
putq(&queue,x); putq(&queue,y); putq(&queue,c);
while (queue.elements!=NULL) {
x=getq(&queue); y=getq(&queue); c=getq(&queue); //ここでアンダーフローが起きてしまうようです。
if (x==gx && y==gy) {break;}
if (maze[x+1][y]==' ') {
putq(&queue,x+1); putq(&queue,y); putq(&queue,c+1);
maze[x+1][y]='*';
}
if (maze[x-1][y]==' ') {
putq(&queue,x-1); putq(&queue,y); putq(&queue,c+1);
maze[x-1][y]='*';
}
if (maze[x][y+1]==' ') {
putq(&queue,x); putq(&queue,y+1); putq(&queue,c+1);
maze[x][y+1]='*';
}
if (maze[x][y-1]==' ') {
putq(&queue,x); putq(&queue,y-1); putq(&queue,c+1);
maze[x][y-1]='*';
}
}
/* 最短距離を表示する。*/
printf("%d\n", c);
return 0;
}