(資料結構作業)用C語言寫的一個迷宮
阿新 • • 發佈:2019-02-07
編譯環境:win8.1+VS2015
說明:這是資料結構學完棧和佇列寫的作業。利用隨機數生成一張迷宮圖,然後用佇列找出最短路徑,用棧輸出之。可以動態顯示最短路徑喔~~~最後,這個作業用了檔案分離寫(標頭檔案宣告,.cpp檔案定義)。
Last but not least:輸入的行數和列數都不能太大(12以下)。因為:佇列中找最短路徑的時候要儲存很多位置,當圖太大的時候位置就變多了不是,這時候佇列就會溢位的(也就是佇列裝不下那麼多位置資訊了)。
===========上程式碼了=================
//file name:stack.h
#ifndef STACK_H
#define STACK_H
#include "queue.h"
#define MAXSIZE 10000
typedef int Status; /*返回狀態值*/
typedef struct
{
int i, j;/*座標值*/
int next;/*前一個位置在佇列中的序號*/
}SElemType;
/*佇列結構*/
typedef struct {
int top;
SElemType elem[MAXSIZE];
}SqStack;
Status InitStack(SqStack *); //構造一個空棧
Status StackEmpty(SqStack);//若棧為空,返回TRUE,否則返回FALSE
Status Push(SqStack *, ElemType);//插入元素作為新的棧頂元素
Status Pop(SqStack *, SElemType *);//若棧不空,刪除棧頂元素,用e返回其值
#endif // !STACK_H
//file name:stack.cpp
#include<stdio.h>
#include"stdlib.h"
#include"stack.h"
#include"queue.h"
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define INFEASIBLE -1
#define OVERFLOW -2
Status InitStack(SqStack *S) //構造一個空棧
{
S->top = -1;
return OK;
}//InitStack
Status StackEmpty(SqStack S)//若棧為空,返回TRUE,否則返回FALSE
{
if (S.top == -1)
return TRUE;
else
return FALSE;
}//StackEmpty
Status Push(SqStack *S, ElemType e)//插入元素作為新的棧頂元素
{
if(S->top>=MAXSIZE-1){//棧滿
printf("The stack is full!\n");
return ERROR;
}
++S->top;
S->elem[S->top].i = e.i;
S->elem[S->top].j = e.j;
S->elem[S->top].next = e.pre;
return OK;
}//Push
Status Pop(SqStack *S, SElemType *e)//若棧不空,刪除棧頂元素,用e返回其值
{
if (S->top == -1)
{
printf("Empty stack!\n");
return ERROR;
}
e->i = S->elem[S->top].i;
e->j = S->elem[S->top].j;
e->next = S->elem[--S->top].next;
return OK;
}//Pop
//file name:queue.h
#ifndef QUEUE_H
#define QUEUE_H
#define MAXSIZE 10000
typedef int Status; /*返回狀態值*/
/*佇列中資料元素型別*/
typedef struct
{
int i, j;/*座標值*/
int pre;/*前一個位置在佇列中的序號*/
}ElemType;
/*佇列結構*/
typedef struct {
int front, rear;
ElemType elem[MAXSIZE];
}SqQueue;
Status InitQueue(SqQueue *); /*構造一個空佇列Q*/
int QueueLength(SqQueue); /*返回佇列Q的元素個數,即佇列的長度*/
Status EnQueue(SqQueue *, ElemType);/*插入元素e為Q的新的隊尾元素*/
Status DeQueue(SqQueue *, ElemType *); /*若佇列不為空,則刪除Q的隊頭元素,用e返回其值*/
Status QueueEmpty(SqQueue);/*若佇列為空,則返回真*/
Status GetHead(SqQueue, ElemType *); /*若佇列不空,用e返回隊頭元素*/
#endif // !QUEUE_H
//file name:queue.cpp
#include<stdio.h>
#include<stdlib.h>
#include "queue.h"
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OVERFLOW -2
Status InitQueue(SqQueue *Q) /*構造一個空佇列Q*/
{
Q->front = Q->rear = 0;
return OK;
}//InitQueue
Status EnQueue(SqQueue *Q, ElemType e)/*插入元素e為Q的新的隊尾元素*/
{
if (QueueLength(*Q) >= MAXSIZE - 1) {//隊滿
printf("Queue is full!Can not continue to find the way...\n");
exit(OVERFLOW);
}
else {
Q->elem[Q->rear].i = e.i;
Q->elem[Q->rear].j = e.j;
Q->elem[Q->rear].pre = e.pre;
Q->rear++;
}
return OK;
}//Enqueue
int QueueLength(SqQueue Q) /*返回佇列Q的元素個數,即佇列的長度*/
{
return Q.rear;
}//QueueLength
Status DeQueue(SqQueue *Q, ElemType *e) /*若佇列不為空,則刪除Q的隊頭元素,用e返回其值*/
{
if (QueueEmpty(*Q))
return ERROR;
e->i = Q->elem[Q->front].i;
e->j = Q->elem[Q->front].j;
e->pre = Q->elem[Q->front].pre;
Q->front++;
return OK;
}//DeQueue
Status QueueEmpty(SqQueue Q) /*若佇列為空,則返回真*/
{
if (Q.front == Q.rear)
return TRUE;
else
return FALSE;
}//QueueEmpty
Status GetHead(SqQueue Q, ElemType *e) /*若佇列不空,用e返回隊頭元素*/
{
if (QueueEmpty(Q)) {//如果隊空
printf("The queue is empty!\n");
return ERROR;
}
*e = Q.elem[Q.front];
return OK;
}//GetHead
//file name:maze.h
#ifndef MAZE_H
#define MAZE_H
#include "queue.h"
#define M 12
#define N 12
#define SUCCESS 1
#define FAIL 0
typedef int Status;
typedef struct {
int x, y;
}DType;
Status ProduceArray(int ***, int, int); //動態生成一個二維陣列
Status ProduceMap(int **, int, int);//利用0 1隨機數生成一張圖(1為牆)
Status PrintMap(int **, int, int, int, int);//列印迷宮圖
Status FindPath(int**, const int, const int); //尋找路線
Status ShowShortPath(int**, int, int, SqQueue); //列印最短路
#endif // !MAZE_H
//file name:maze.cpp
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<Windows.h>
#include"maze.h"
#include"stack.h"
Status ProduceArray(int ***array, int row, int col)
{
int i;
*array = (int **)malloc((row + 2) * sizeof(int *));
for (i = 0; i < (row + 2); i++) {
(*array)[i] = (int *)malloc((col + 2) * sizeof(int *));
}
return SUCCESS;
}
/*生成一張圖*/
Status ProduceMap(int **MAZE,int row,int col)
{
int i, j;
srand((unsigned)(time(NULL))); //隨機種子
for (i = 0; i <= row + 1; i++) {
for (j = 0; j <= col + 1; j++)
{
/*圍牆的處理*/
if (i == 0 || j == 0 || i == (row + 1) || j == (col + 1))
MAZE[i][j] = 1;
else {
MAZE[i][j] = ((rand() % 10) > 6 ? 1 : 0);/*產生隨機數,控制產生的概率*/
}
}
}
/*入口和出口*/
MAZE[1][1] = MAZE[row][col] = 0;
return SUCCESS;
}//ProduceMap
Status PrintMap(int **MAZE, int row, int col,int cur_x,int cur_y)
{
system("cls");
int i, j;
const char *BAR = "▓"; //障礙物圖案"▓"
const char *OBJ = "㊣"; //物體位置圖案"㊣"
for (i = 0; i <= row + 1; i++) {
for (j = 0; j <= col + 1; j++) {
if (MAZE[i][j] == 1) { //障礙物
printf(BAR);
}
else if (i == cur_x&&j == cur_y) { //移動物件
printf(OBJ);
}
else if (MAZE[i][j] == 0) //可通位置,2個空格
printf(" ");
}
printf("\n");
}
printf("Current position:(%d,%d)\n\n", cur_x, cur_y);
return SUCCESS;
}//PrintMap
Status FindPath(int **MAZE, int row, int col) //尋找路線
{
ElemType head, e;
int x, y, i, j, k;
SqQueue Q;//佇列
static int **MARK;//標記陣列
const DType Direction[8] = { { -1,-1 },{ -1,0 },{ -1,1 },{ 0,1 },
{ 1,1 },{ 1,0 },{ 1,-1 },{ 0,-1 } };
ProduceArray(&MARK, row, col);
MARK[0][0] = 0;//初始化為零
InitQueue(&Q);//佇列的初始化
e.i = 1, e.j = 1, e.pre = -1;//起點位置
EnQueue(&Q, e);//將起點放入佇列
MARK[1][1] = 1;//標記陣列將起點標記為已通過
while(!QueueEmpty(Q)){//當佇列不為空時
GetHead(Q, &head);//取出隊頭元素給head
x = head.i, y = head.j;
for (k = 0; k < 8; k++) { //依次探查各個方向
i = x + Direction[k].x;
j = y + Direction[k].y;
if (MAZE[i][j] == 0 && MARK[i][j] != 1) {//未通過且可行路
e.i = i, e.j = j, e.pre = Q.front;
EnQueue(&Q, e);//將新的路放到隊尾
MARK[x][y] = 1;//標記已走路
}
if (i == row&&j == col) {//如果到達出口
ShowShortPath(MAZE, row, col, Q);
return SUCCESS;
}
}//for end
DeQueue(&Q, &head);
}//while end
//無法通過
return FAIL;
}//FindPath
Status ShowShortPath(int **MAZE,int row,int col,SqQueue Q) //列印最短路線
{
SqStack S;
InitStack(&S);
SElemType e;
int cur_x, cur_y;
int count = 0;
DType Way[100];
int i = Q.rear - 1;
while (i != -1)
{
Push(&S, Q.elem[i]);
i = Q.elem[i].pre;
}
printf(">>>>One of the shortest way:\n");
while (!StackEmpty(S))
{
Pop(&S, &e);
cur_x = e.i, cur_y = e.j;
Way[count].x = cur_x, Way[count++].y = cur_y;
PrintMap(MAZE, row, col, cur_x, cur_y);
Sleep(1000);
}
for (i = 0; i < count; i++) {
printf("(%d,%d)\t", Way[i].x, Way[i].y);
if ((i+1) % 5 == 0)
printf("\n");
}
printf("\n>>>>the shortest way need: %d steps\n\n",count);
return SUCCESS;
}//ShowShortPath
//file name:main.cpp
#include<stdio.h>
#include<windows.h>
#include"maze.h"
int main()
{
int row, col;
int **MAZE;
/*輸入行和列生成迷宮圖*/
printf("\n>>>Input the maze's row and column(row<11,column<11): ");
scanf("%d%d", &row, &col);
while (row <= 0 || row>10 || col <= 0 || col>10) {
printf("Dataes error!Please input suitable dataes\n");
printf("\n>>>Input the maze's row and column: ");
scanf("%d%d", &row, &col);
}
printf("\n>>>>>>>>>>A map is being created...\n");
Sleep(500);
ProduceArray(&MAZE, row, col);//動態生成一個二維陣列
ProduceMap(MAZE,row, col);//生成一張迷宮圖
PrintMap(MAZE, row, col, 1, 1);//列印迷宮
printf("\n============>Finding the ways...\n");
printf(">>>Caculating the shortest way...\n");
Sleep(1000);
if (FindPath(MAZE, row, col) == 0) {
printf("Can not arrive!\n");
}
system("pause");
return 0;
}
最後說幾句:1、個人覺得這個演算法挺好的,當時老師要求的是自己定義幾張圖來測試有路和沒有路的情況,但是通過這個來控制障礙物的方法只需要調一下產生的概率就好了如下面的“6”可以改大或改小,試試就知道了=_=
MAZE[i][j] = ((rand() % 10) > 6 ? 1 : 0);/產生隨機數,控制產生的概率/
2、這是用檔案分離寫的,直接複製貼上不能執行!