数据结构课程设计---迷宫

#include <stdio.h>//包含了printf(),scanf()函数
#include <stdlib.h>//包含了srand(),rand(),system()函数
#include <malloc.h>//包含了malloc()函数
#include <time.h>//包含了time()函数
#include <conio.h>
#define M 50
#define N 50

typedef struct node{
 int row;  //行
 int col;  //列
 struct node * next;
}Mlink;

Mlink * stack;//定义一个栈

int backup[M+2][N+2]; //备份数组

//下面这个函数为我们建立迷宫矩阵
void create(int maze[M+2][N+2] , int maze_row , int maze_col){
 int i , j , k;

 /*我们知道在产生随机数的时候,需要一个叫做种子seed的值作为产生随机数算法的初始值。
 而C/C++库中的srand就是为这一次的随机数生成设置种子。s代表的就是seed的意思。
 time_t time(time_t *time);该函数返回自计算机计时的某个时刻起到现在所过去的秒数。
 一般是返回自1970年1月1日00:00:00以来,到调用函数的时刻所累积的秒数。
 
 这语句的含义就是以自1970年1月1日00:00:00以来,到调用函数的时刻所累积的秒数作为产生随机数算法的种子seed。
  
 没有语句会对程序产生什么影响:
 如果在程序运行时没有自主设置种子的话,用函数rand产生的随机数序列会是一样的。
 而用srand设置随机数种子后,可能产生不同的随机序列(概率很大)。

 之所以说以很大的概率产生不同的随机数序列,是因为从上面的解释可以看到,
 srand是以秒数为单位的。一旦程序多次运行的时间间隔少于1s。那么srand设置种子也没有什么用处。
 所以库函数产生随机数有一定的缺陷。不知道我解释明白了没有!
 */
 srand((unsigned)time(NULL));

 for(i = 0 ; i <= maze_row + 1 ; i++)
  for(j = 0 ; j <= maze_col + 1 ; j++)
   maze[i][j] = 1;//初始化矩阵元素全部为1

 for(i = 1 ; i <= maze_row ; i++)
  for(j = 1 ; j <= maze_col ; j++)
   backup[i][j] = 0;//初始化备份矩阵全部有效元素为0
   
  for(k = 1 ; k <= maze_row * maze_col ; k++){//随机选择位置赋予一个随机的0或1,
            i = (int)(rand() % maze_row) + 1;//rand()会返回一随机数值
   j = (int)(rand() % maze_col) + 1;
   maze[i][j] = (int)(rand() % 2);//随机矩阵这样可以产生更多的"0"即通路
  }

  printf("自动生成中……\n");
  //system就是调用从程序中调用系统命令,system("pause")就是从程序里调用“pause”命令
  //而“pause”这个系统命令的功能很简单,就是在命令行上输出一行"按任意键继续. . ."的字,等待用户按一个键,然后返回。
  system ("pause");

  for(i = 1 ; i <= maze_row ; i++)
   for(j = 1 ; j <= maze_row ; j++)
    backup[i][j] = maze[i][j];//备份数组矩阵
}


//下面这个函数为我们打印迷宫矩阵
void print(int maze[M+2][N+2] , int maze_row , int maze_col){
 int i , j , k;

 printf("\n打印迷宫矩阵如下(0可通,1不可通): \n");
 //在矩阵上方标明列号
 for(k = 1 ; k <= maze_col ; k++){    
  if(k < 10)
      printf("%d  " , k);
     else
         printf("%d " , k);
 }

  //矩阵左方标明行号,并打印矩阵
 for(i = 1 ; i <= maze_row ; i++){
  printf("\n");  
  
  if(i < 10)
   printf("%d  " , i);  
  else
   printf("%d " , i);

  for(j = 1 ; j <= maze_col ; j++)
   printf("%d  " , maze[i][j]);
 }

 printf("\n\n迷宫图形如下(白色可通): \n");
 printf("  ");
 for(k = 1 ; k <= maze_col ; k++){//在图形上方标明列号
  if(k < 10)
      printf("%d " , k);
     else
      printf("%d" , k);
 }

 for(i = 1 ; i <= maze_row ; i++){
  printf("\n");
  if(i < 10)
   printf("%d " , i);  //矩阵左方标明行号
  else
   printf("%d" , i);

  for(j = 1 ; j <= maze_col ; j++){//打印图形
   if(maze[i][j] == 0)
    printf("□");
   if(maze[i][j] == 1)
    printf("■");
  }
 }

}

int Mazepath(int maze[M+2][N+2] , int x1 , int x2 , int y1 , int y2){
 Mlink * p;

 if(maze[x1][y1] == 0){
    p = (Mlink *)malloc(sizeof(Mlink));
    p -> row = x1;
    p -> col = y1;
    p -> next = NULL;
       stack = p;          //将入口放入堆栈
    maze[stack -> row][stack -> col] = 1;//标志入口已访问

 while((!(stack->row==NULL&&stack->col==NULL))&&(!(stack->row==x2&&stack->col==y2)))//未找到出口并且堆栈不空
  {
   if(maze[stack->row+1][stack->col]==0)  //下面可通
   {
    p=(Mlink *)malloc(sizeof(Mlink));
    p->row=stack->row+1;
    p->col=stack->col;
    p->next=stack;         //入栈
    stack=p;
    maze[stack->row][stack->col]=1; //标记已访问
   }
   else if(maze[stack->row][stack->col+1]==0)  //右面位置可通
   {
    p=(Mlink *)malloc(sizeof(Mlink));
    p->row=stack->row;
    p->col=stack->col+1;
    p->next=stack;           //入栈
    stack=p;
    maze[stack->row][stack->col]=1;//标记已访问
   }
   else if(maze[stack->row-1][stack->col]==0)  //左面可通
   {
    p=(Mlink *)malloc(sizeof(Mlink));
    p->row=stack->row-1;
    p->col=stack->col;
    p->next=stack;        //入栈
    stack=p;
    maze[stack->row][stack->col]=1;//标记已访问
   }
   else if(maze[stack->row][stack->col-1]==0)//上面可通
   {
    p=(Mlink *)malloc(sizeof(Mlink));
    p->row=stack->row;
    p->col=stack->col-1;
    p->next=stack;       //入栈
    stack=p;
    maze[stack->row][stack->col]=1;//标记已访问

   }
   else   //不可通 返回上一点
   {
    if (stack->next!=NULL)
    {            //堆栈里布置一个顶点则出栈并返回循环
       p=stack;
       stack=stack->next;   //出栈
       free(p);  //释放空间
    }
    else                   //堆栈里只有一个顶点即入口,此时若释放空间出栈会使循环
    {                      //控制语句无法比较(因为stack->col,stack->row都已不存在,)
       stack->row=NULL;
          stack->col=NULL;
       stack->next=NULL;
    }
   }
  
  }
  if (stack->row==x2&&stack->col==y2) return (1);
   else return (0);

 }
 else return(0);
}

/****************************输出坐标通路*******************/
void printonglu1()
{
 Mlink *q;
 int i=1;
 printf("其中的一条通道为:\n");
     q=stack; 
     printf("  出口<--");
     while (q!=NULL)
     {
      if(i%5==0)
       printf("\n");
      printf("[%d%3d]<--",q->row,q->col);
      q=q->next;
      i++;
     }
     printf("入口\n");
}
/*******************************分割线**********************/


/**********************输出图形通路**************************/

//2时输出↑,3时输出←,4时输出→,5时输出↓

void printonglu2(int a,int b)
{
 printf("图形通路如下:\n");
 int z;
 printf("  ");
 for(z=1;z<=b;z++)  //图形上方标明列号
 {if(z<10)
  printf("%d ",z);
  else
   printf("%d",z);
 }
 int i,j;
 Mlink *p;
 p=stack;
 backup[p->row][p->col]=6;
 while (p->next!=NULL)
 {
  if(p->next->col!=NULL)
  {
   if( p->row > p->next->row ) backup[p->next->row][p->next->col]=5;//下一节点在下
   else if(p->row<p->next->row) backup[p->next->row][p->next->col]=2;//下一节点在上
   else if(p->col>p->next->col) backup[p->next->row][p->next->col]=4;//下一节点在右
   else backup[p->next->row][p->next->col]=3;//下一节点在左
  }
  else ;
  p=p->next;
 }
 for(i=1;i<=a;i++)
 {
  printf("\n");
   if(i<10) printf("%d ",i);  //图形左方标明行号
  else printf("%d",i);
  for(j=1;j<=b;j++)
  {
   if(backup[i][j]==0)
    printf("□");
   if(backup[i][j]==1)
    printf("■");
   if(backup[i][j]==2)
    printf("↑");
   if(backup[i][j]==3)
    printf("←");
   if(backup[i][j]==4)
    printf("→");
   if(backup[i][j]==5)
    printf("↓");
   if(backup[i][j]==6)
    printf("㊣");
  }
 }
}


/*
颜色属性由两个十六进制数字指定 -- 第一个为背景,第二个则为
前景。每个数字可以为以下任何值之一:

0 = 黑色       8 = 灰色
1 = 蓝色       9 = 淡蓝色
2 = 绿色       A = 淡绿色
3 = 湖蓝色     B = 淡浅绿色
4 = 红色       C = 淡红色
5 = 紫色       D = 淡紫色
6 = 黄色       E = 淡黄色
7 = 白色       F = 亮白色
*/

void main(){
 //背景为黑色,前景为绿色
  system("color 02"); 
  //a为迷宫的行数,b为迷宫的列数
  int k = 1 , maze_row , maze_col;
  //迷宫矩阵
  int maze[M+2][N+2];
  //备份数组以重复使用迷宫
  int back_up[M+2][N+2] , p , q; 

  printf("我们开始建立迷宫!\n");
  printf("请输入迷宫矩阵的行数: maze_row = ");
  scanf("%d" , &maze_row);
  printf("请输入迷宫矩阵的列数: maze_col = ");
  scanf("%d" , &maze_col);

  //下面这个函数为我们建立迷宫矩阵
  create(maze , maze_row , maze_col);  

  for(p = 0 ; p <= maze_row + 2 ; p++)
    for(q = 0 ; q <= maze_col + 2 ; q++)
    back_up[p][q] = maze[p][q];

  while(k != 0){ 
     int x , x1 , x2 , y1 , y2; 

  //下面这个函数为我们打印迷宫矩阵
     print(maze , maze_row , maze_col);

     printf("\n\n输入迷宫入口(横坐标x1,纵坐标y1): \n");
     scanf("%d%d" , &x1 ,&y1);
     printf("输入迷宫出口(横坐标x2,纵坐标y2): \n");
     scanf("%d%d" , &x2 , &y2);  

     x = Mazepath(maze , x1 , x2 , y1 , y2);

     if(x==1)        //迷宫可通
    {
     printonglu1(); //打印坐标通路
     printonglu2(maze_row , maze_col);//打印图形通路
     printf("\n");
    }
    else
    {
     printf("无通路! \n");//不可通
     getch();
     system("cls");
     main();
    }
    for(p=0;p<=maze_row+2;p++)
     for(q=0;q<=maze_col+2;q++){
    backup[p][q]=back_up[p][q];
    maze[p][q]=back_up[p][q];
     }
    printf("输入任意键返回首页:\n"); 
    getch();
    system("cls");
    main();

  }
}

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,走迷宫游戏是一个非常有意思的课程设计,需要用到许多数据结构和算法。以下是一个简单的实现思路: 1. 将迷宫地图存储在一个二维数组中,其中 0 表示可以通过的路,1 表示墙壁。 2. 使用栈来实现迷宫的深度优先搜索,从起点开始,不断往前走,直到遇到墙壁或者到达终点。 3. 如果遇到墙壁,则将当前位置出栈,并回溯到上一个位置,继续搜索。 4. 如果到达终点,则输出路径并结束程序。 下面是一个简单的实现代码: ```python class Maze: def __init__(self, maze_map): self.maze_map = maze_map self.width = len(maze_map[0]) self.height = len(maze_map) def get_neighbors(self, pos): x, y = pos neighbors = [] if x > 0 and self.maze_map[y][x-1] == 0: neighbors.append((x-1, y)) if y > 0 and self.maze_map[y-1][x] == 0: neighbors.append((x, y-1)) if x < self.width-1 and self.maze_map[y][x+1] == 0: neighbors.append((x+1, y)) if y < self.height-1 and self.maze_map[y+1][x] == 0: neighbors.append((x, y+1)) return neighbors def find_path(self, start, end): stack = [start] visited = set() while stack: pos = stack[-1] if pos == end: return stack if pos not in visited: visited.add(pos) neighbors = self.get_neighbors(pos) for neighbor in neighbors: if neighbor not in visited: stack.append(neighbor) else: stack.pop() return None maze_map = [ [0, 1, 0, 0, 0, 0, 0, 0], [0, 1, 0, 1, 1, 1, 1, 0], [0, 0, 0, 0, 0, 0, 1, 0], [1, 1, 1, 1, 1, 0, 1, 0], [0, 0, 0, 0, 0, 0, 1, 0], [0, 1, 1, 1, 1, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0], ] maze = Maze(maze_map) start = (0, 0) end = (7, 6) path = maze.find_path(start, end) if path: print(path) else: print("No path found") ``` 这里我们使用了一个 Maze 类来存储迷宫地图和实现搜索算法。其中 get_neighbors 方法用来获取一个位置的所有邻居节点,find_path 方法用来实现深度优先搜索。我们首先将起点压入栈中,然后不断从栈中取出最后一个节点进行搜索,如果当前节点是终点,则返回路径;否则将当前节点的所有邻居节点压入栈中。如果当前节点没有邻居节点或者所有邻居节点都已经被访问过,则将当前节点出栈,回溯到上一个节点。 这个实现还比较简单,如果需要实现更高效的算法,可以考虑使用广度优先搜索或者A*算法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值