源代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <time.h>
#include <ctime>
#include <string.h>
//宏定义
#define UP 8
#define RIGHT 6
#define DOWN 5
#define LEFT 4
#define TRUE 1
#define cell_empty(a) (!(a)->up && !(a)->right && !(a)->down && !(a)->left)
//下一个元素没有被访问,且验证前一个被访问过
//全局变量
int width, height;
typedef struct {
unsigned int up : 1;
unsigned int right : 1;
unsigned int down : 1;
unsigned int left : 1;
unsigned int path : 1;
unsigned int visited : 1;
} cell_t;
typedef cell_t *maze_t;
//函数声明
void MazeOptions (); //主菜单选项
void SubOptions (); //次菜单选项
void CheckOptionM (); //检查主菜单输入选项合法性
void CheckOptionS (); //检查次菜单输入选项合法性
void ContinueMaze (); //按任意键继续
void CreateMaze (maze_t maze, int width, int height); //创建迷宫
void SolveMaze (maze_t maze, int width, int height); //解迷宫
void PrintMaze (maze_t maze, int width, int height); //显示迷宫
void RandomGenMaze (); //自动生成
void ManualGenMaze (); //手动生成
void PrintTitle(); //显示标题印象
void PrintMainMenu (); //显示主菜单印象
void PrintSubMenu(); //显示次菜单印象
void PrintAboutMaze (); //显示关于印象
//void PrintMGMenu (); //显示手动生成迷宫提示
//void PrintAGMenu (); //显示自动生成迷宫提示
int main ()
{
PrintTitle();
MazeOptions ();
return 1;
}//主函数
void MazeOptions ()
{
char strm[256];
PrintMainMenu();
printf ("\n Which option do you want to choose? (Enter '1' or '2' or '3' or '4')");
scanf("%s", strm);
if(strlen(strm)>1)
{
CheckOptionM ();
return;
}
switch (strm[0])
{
case '1': ManualGenMaze ();
break;
case '2': RandomGenMaze ();
break;
case '3': PrintAboutMaze ();
break;
case '4': exit (EXIT_SUCCESS);
break;
default : CheckOptionM ();
break;
}
}//主菜单选项
void SubOptions ()
{
char strs[256];
PrintSubMenu ();
printf ("\n Which option do you want to choose? (Enter '1' or '2' or '3'or '4')");
scanf("%s", strs);
if(strlen(strs)>1)
{
CheckOptionS ();
return;
}
switch (strs[0])
{
case '1': MazeOptions ();
break;
case '2': RandomGenMaze ();
break;
case '3': ManualGenMaze ();
break;
case '4': exit (EXIT_SUCCESS);
break;
default : CheckOptionS ();
}
}//次菜单选项
void CheckOptionM ()
{
printf ("\n Error! Illegal option number! Did you input a wrong integer number?\n");
ContinueMaze ();
MazeOptions ();
}//检查主菜单输入选项合法性
void CheckOptionS ()
{
printf ("\n Error! Illegal option number! Did you input a wrong integer number?\n");
ContinueMaze ();
SubOptions ();
}//检查次菜单输入选项合法性
void ContinueMaze ()
{
printf ("\n Press any key to continue...");
getch();
}//按任意键继续
void CreateMaze (maze_t maze, int width, int height) //创建迷宫
{
maze_t mp, maze_top;
char paths [4];
int visits,directions;
visits = width * height - 1;
mp = maze;
maze_top = mp + (width * height) - 1;
while (visits)
{
directions = 0;
if ((mp - width) >= maze && cell_empty (mp - width))
paths [directions++] = UP;
if (mp < maze_top && ((mp - maze + 1) % width) && cell_empty (mp + 1))
paths [directions++] = RIGHT;
if ((mp + width) <= maze_top && cell_empty (mp + width))
paths [directions++] = DOWN;
if (mp > maze && ((mp - maze) % width) && cell_empty (mp - 1))
paths [directions++] = LEFT;
if (directions)
{
visits--;
directions = ((unsigned) rand () % directions);
switch (paths [directions])
{
case UP:
mp->up = TRUE;
(mp -= width)->down = TRUE;
break;
case RIGHT:
mp->right = TRUE;
(++mp)->left = TRUE;
break;
case DOWN:
mp->down = TRUE;
(mp += width)->up = TRUE;
break;
case LEFT:
mp->left = TRUE;
(--mp)->right = TRUE;
break;
default:
break;
}
}
else
{
do
{
if (++mp > maze_top)
mp = maze;
} while (cell_empty (mp));
}
}
}//创建迷宫
void SolveMaze (maze_t maze, int width, int height) //解迷宫
{
maze_t *stack, mp = maze;
int sp = 0;
stack = (maze_t *) calloc (width * height, sizeof (maze_t));
if (stack == NULL)
{
(void) fprintf (stderr, "Cannot allocate memory!\n");
exit (EXIT_FAILURE);
}
(stack [sp++] = mp)->visited = TRUE;
while (mp != (maze + (width * height) - 1))
{
if (mp->up && !(mp - width)->visited)
stack [sp++] = mp - width;
if (mp->right && !(mp + 1)->visited)
stack [sp++] = mp + 1;
if (mp->down && !(mp + width)->visited)
stack [sp++] = mp + width;
if (mp->left && !(mp - 1)->visited)
stack [sp++] = mp - 1;
if (stack [sp - 1] == mp)
--sp;
(mp = stack [sp - 1])->visited = TRUE;
}
while (sp--)
if (stack [sp]->visited)
stack [sp]->path = TRUE;
free (stack);
}//解迷宫
void PrintMaze (maze_t maze, int width, int height) //显示迷宫
{
int w, h;
char *line, *lp;
line = (char *) calloc ((width + 1) * 2 * 2, sizeof (char));
if (line == NULL)
{
(void) fprintf (stderr, "Cannot allocate memory!\n");
exit (EXIT_FAILURE);
}
maze->up = TRUE;
(maze + (width * height) - 1)->down = TRUE;
for (lp = line, w = 0; w < width; w++)
{
strcpy(lp,"■"),lp+=2;
if ((maze + w)->up)
if((maze + w)->path) strcpy(lp,"◎"),lp+=2;
else strcpy(lp," "),lp+=2;
else
strcpy(lp,"■"),lp+=2;
}
strcpy(lp,"■"),lp+=2;
(void) puts (line);
for (h = 0; h < height; h++)
{
for (lp = line, w = 0; w < width; w++)
{
if ((maze + w)->left)
if((maze + w)->path && (maze + w - 1)->path)
strcpy(lp,"◎"),lp+=2;
else strcpy(lp," "),lp+=2;
else
strcpy(lp,"■"),lp+=2;
if((maze + w)->path)
strcpy(lp,"◎"),lp+=2;
else strcpy(lp," "),lp+=2;
}
strcpy(lp,"■"),lp+=2;
(void) puts (line);
for (lp = line, w = 0; w < width; w++)
{
strcpy(lp,"■"),lp+=2;
if ((maze + w)->down)
if((maze + w)->path && (h == height - 1
||(maze + w + width)->path))
strcpy(lp,"◎"),lp+=2;
else strcpy(lp," "),lp+=2;
else
strcpy(lp,"■"),lp+=2;
}
strcpy(lp,"■"),lp+=2;
(void) puts (line);
maze += width;
}
free (line);
}//显示迷宫
void RandomGenMaze () //自动生成
{
maze_t maze;
//PrintAGMenu ();
srand((unsigned)time(0));
width = rand()%19; //randomly generate weight, from 0-19
height = rand()%19; //randomly generate height, from 0-19
if (width <= 0 || height <= 0)
{
RandomGenMaze (); //if '0' is generate out redo RandomGenMaze founction
}
maze = (maze_t) calloc (width * height, sizeof (cell_t));
if (maze == NULL)
{
(void) fprintf (stderr, "Cannot allocate memory!\n");
exit (EXIT_FAILURE);
} //check value validity and allocate meomory
printf ("The randomly generated maze looks as below:\n('■'=block)\n\n");
CreateMaze (maze, width, height);
PrintMaze (maze, width, height);
(void) putchar ('\n');
printf ("And follow the dot-line you'll find the solution:\n('■'=block, '◎'=path-print)\n\n");
SolveMaze (maze, width, height);
PrintMaze (maze, width, height);
free(maze);
printf ("══════════════════════════════════════ \n");
ContinueMaze ();
SubOptions ();
}//自动生成
void ManualGenMaze() //手动生成
{
maze_t maze;
//PrintMGMenu ();
printf (" Now you can input its width value('18' is recommended):");
scanf ("%d", &width);
if (!width || width <= 0) // 大于100 出现死循环
{
printf(" Error, illegel width value, press any key to back.");
getch();
ManualGenMaze(); //MazeOptions(); 应该可以用while 语句
}
printf (" And its height value('18' is recommended):");
scanf ("%d", &height);
if (!height|| height <= 0)
{
printf(" Error, illegel height value, press any key to back.");
getch();
MazeOptions();
}
maze = (maze_t) calloc (width * height, sizeof (cell_t));
if (maze == NULL)
{
(void) fprintf (stderr, "Cannot allocate memory!\n");
exit (EXIT_FAILURE);
} //check value validity and allocate meomory
printf ("\n The randomly generated maze which was declared manually looks as below:\n ('■'=block)\n\n");
CreateMaze (maze, width, height);
PrintMaze (maze, width, height);
(void) putchar ('\n');
printf (" And follow the dot-line you'll find the solution:\n ('■'=block, '◎'=path-print)\n\n");
SolveMaze (maze, width, height);
PrintMaze (maze, width, height);
free(maze);//print maze
printf ("══════════════════════════════════════ \n");
ContinueMaze ();
SubOptions ();
}//手动生成
void PrintTitle()
{
printf("* * * * * * * * * * * * * * * * * * * * * * * *");
printf("\n-----------------------------------------------\n");
printf("\n* 迷宫游戏 *\n");
printf("\n-----------------------------------------------\n");
printf("* * * * * * * * * * * * * * * * * * * * * * * *");
}
//显示标题印象
void PrintMainMenu()
{
printf("\n\n* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n");
printf(" --------------主菜单-------------- \n");
printf(" 1 ------- manually generate maze------\n");
printf(" 2 ------- randomly generate a mase by computer-------\n");
printf(" 3 ------- about---------\n");
printf(" 4 ------- exit ---------\n");
printf("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n");
}//显示主菜单印象
void PrintSubMenu()
{
printf("\n\n* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n");
printf(" 1 ------- 回主菜单------\n");
printf(" 2 ------- RandomGenMaze -------\n");
printf(" 3 ------- ManualGenMaze ---------\n");
printf(" 4 ------- exit ---------\n");
printf("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n");
}//显示次菜单印象
void PrintAboutMaze ()
{
printf(" \n 游戏说明 暂时没写 \n");
ContinueMaze ();
SubOptions ();
}//显示关于印象