水管工游戏(随机地图版)


/*水管工游戏

  一块快矩形的土地 被分成N*M的单位正方形 现在这个土地上已经买有一些水管
  水管将从(1,1)的左上方 延伸到(N,M)d的矩形下方的右下角右部边缘
水管只有两种 
   "┛","━"

上方的外部方格代表单位正方形  内部的代表水管
每个水管占据一个单位正方形 你要做的就是旋转这些管道
使其可以连接成一个管道通路 即创造一条可以从(1,1)到(N,M)的连通管道
标有树木的方格代表这里没有管道 树木用▲表示
解:为了便于描述 我们用数字代表水管的状态

{"▲","┗","┎","┓","┛","━","┃"}

 0        1     2      3    4      5      6    数字上方与图案对应

   前四个为弯管的四种状态 后两个为直管的两种状态 
  EG:在另一个文件有图片 首先是(1,1)  假设其是直管 则只能用5号管子这种状态
       其次为(1,2) 是弯管 进水口在左边 因此(1,2)的水管有两种方式 上面的第3种和第4种
  先尝试3这种方法  之后到达 (2,2) (2,2)是直管只能是6这种方式。。。。
  就这么尝试下去 直到(N,M+1)结束 便产生一种方案 
  所以用深度遍历的搜索方法来解决比较适合
  我们来用上面的那六种 枚举一下
  对于一个水管 如果是直管 则进水口在左边或右边只能用 5这种方式 如果是在上下两边则直接为6
  而进水口是通过前一个水管来判断的 舍前一个水管为front 
  代码: dfs(int x,int y,int front)//x,y为当前格子的坐标 
  front 为进水口的方向1 2 3 4分别为 左 上 右 下
           2

    1    ✟    3

          4

  当当前的水管为直管:
  if(front==1) //进水口在左边
     dfs(x,y+1,1)
  if(front==2) //进水口在上边
     dfs(x+1,y,2)
  if(front==3) //进水口在右边
     dfs(x,y-1,3)
   if(front==4) //进水口在下边
     dfs(x-1,y,4)
  这个代码直接用 数组来表示会比较好 下面的代码会简化


  当水管是弯管时
   if(front==1) //进水口在左边
  {
     dfs(x+1,y,2) //3号的状态
 dfs(x-1,y,4) //4号的状态
}
if(front==2) //进水口在左边
  {
     dfs(x,y+1,1) //1号的状态
 dfs(x,y-1,3) //4号的状态
}
if(front==3) //进水口在左边
  {
     dfs(x-1,y,4) //1号的状态
 dfs(x+1,y,2) //2号的状态
}
if(front==4) //进水口在左边
  {
     dfs(x,y+1,1) //2号的状态
 dfs(x,y-1,3) //3号的状态
}

*/

下面是改进后的代码,挺好玩:

Windows版 C

# include <stdio.h>
# include <stdlib.h>
# include <windows.h>
# include <time.h>
# define N 14  //地图的行数
# define M 16  //地图的列数
int Flag=0,BOOK[N+1][M+1]={0},S[N+2][M+2]={0},top=0,SUM=0,K,MAX[2];
const int NEXT[][2]={{0,0},{0,1},{1,0},{0,-1},{-1,0}};//用数组代替上面的判断
const int A[][3]={{0,0,0},{1,0,2},{0,1,1},{-1,0,4},{0,1,1}};//同上
const int B[][3]={{0,0,0},{-1,0,4},{0,-1,3},{1,0,2},{0,-1,3}};//同上
const char G[][3]={"▲","┗","┏","┓","┛","━","┃","进","出"};//数字对应的水管形状 或树木
const  int T[][2]={{1,2},{4,3},{3,2},{4,1},{2,3},{1,4},{2,1},{3,4},{1,1},{3,3},{2,2},{4,4}};//弯的水管的进出方向1 2 3 4分别为 左 上 右 下
//const char Q[][3]={"┓","┓","┎","┎","┛","┛","┗","┗","━","━","┃","┃"};
const int  LL[]={3,3,2,2,4,4,1,1,5,5,6,6};//可以用■ 代替上面的 G数组中的▲
char stack[M*N][3]={0};            //用二维数组模拟栈
void dfs(int X,int Y,int front);
int print(int num);
int main(){
	int i,j;
		do{
	printf("输出路径坐标请按1 否则按0:");
	scanf("%d",&K);
	while(getchar()!='\n');
    }while(K<0||K>1);
	do{
	S[1][0]=7;S[N][M+1]=8;
	printf("原水管分布图:");
		srand(time(NULL));//产生随机种子
		for(i=0;i<=N+1;i++)         //输出地图
	{
		printf("\n");
		for(j=0;j<=M+1;j++)
		{
		   if(i&&j&&i!=N+1&&j!=M+1)
             S[i][j]=rand()%7;
			printf("%s",G[S[i][j]]);
		}
	}
	printf("\n");
	dfs(1,1,1);               //深度遍历
	printf("当前地图%s能接通!\n",Flag?"\0":"不");
	if(Flag)
	{
		printf("共%d种连接方式,已全显示 向上翻\n",SUM);
		printf("最大步数%d  是第%d种\n",MAX[0],MAX[1]);
		system("pause");
	}
	else
	{
		Sleep(1200);
		system("cls");
	}
	}while(!Flag);
    return 0;
}
int print(int num)
{
    int i;
	for(i=0;i<12;i++)                                     //   2                                                 // 1   3
		      if(stack[num][2]==T[i][0]&&stack[num+1][2]==T[i][1])
				  return  LL[i];  //输出Q对应的水管形状
	return -1;
}
void dfs(int X,int Y,int front)
{
	int i,j;
   if(X==N&&Y==M+1)//如果方案找到 输出 信息
   {
	   stack[top+1][2]=1;
	  for(Flag=1;Flag<=top;Flag++)   //输出路径坐标
	  {
	    if(K)
		printf("(%2d,%2d)\t",stack[Flag][0],stack[Flag][1]);
		S[stack[Flag][0]][stack[Flag][1]]=print(Flag);
	  }
	    printf("\n连接好之后[左上<入口>->右下<出口>]第%d种:\n共%d步\n",++SUM,top);
        if(top>=MAX[0])
		{
		    MAX[0]=top;
			MAX[1]=SUM;
		}
		 for(i=0;i<=N+1;i++)
		 {
		    for(j=0;j<=M+1;j++)
		   printf("%s",G[S[i][j]]);
			printf("\n");
		 }
	  return ;
   }
    if(X<1||Y<1||X>N||Y>M||BOOK[X][Y])
		return ;
    BOOK[X][Y]=1;
	stack[++top][0]=X;
	stack[top][1]=Y;
	if(S[X][Y]>=5&&S[X][Y]<=6)
	{
			  stack[top][2]=front;
	  dfs(X+NEXT[front][0],Y+NEXT[front][1],front);//在上一个程序里有解释
	}
	if(S[X][Y]>=1&&S[X][Y]<=4)
	{
	   stack[top][2]=front;
	   dfs(X+A[front][0],Y+A[front][1],A[front][2]);//在上一个程序里有解释
	   dfs(X+B[front][0],Y+B[front][1],B[front][2]);
	}
	BOOK[X][Y]=0;//消除当前坐标的标记
	top--;    //将当前坐标出栈
	return ;
}

手机的C4droid版本 TCC:

# include <stdio.h>  
# include <stdlib.h>  
# include <unistd.h>  
# include <time.h>  
# define N 14  //地图的行数  
# define M 16  //地图的列数  
int Flag=0,BOOK[N+1][M+1]={0},S[N+2][M+2]={0},top=0,SUM=0,K,MAX[2];  
const int NEXT[][2]={{0,0},{0,1},{1,0},{0,-1},{-1,0}};//用数组代替上面的判断  
const int A[][3]={{0,0,0},{1,0,2},{0,1,1},{-1,0,4},{0,1,1}};//同上  
const int B[][3]={{0,0,0},{-1,0,4},{0,-1,3},{1,0,2},{0,-1,3}};//同上  
const char G[][4]={"♡","┗","┏","┓","┛","━","┃","♡","♡"};//数字对应的水管形状 或树木  
const  int T[][2]={{1,2},{4,3},{3,2},{4,1},{2,3},{1,4},{2,1},{3,4},{1,1},{3,3},{2,2},{4,4}};//弯的水管的进出方向1 2 3 4分别为 左 上 右 下  
//const char Q[][3]={"┓","┓","┎","┎","┛","┛","┗","┗","━","━","┃","┃"};  
const int  LL[]={3,3,2,2,4,4,1,1,5,5,6,6};//可以用■ 代替上面的 G数组中的■ ▲  
char stack[M*N][3]={0};            //用二维数组模拟栈  
void dfs(int X,int Y,int front);  
int print(int num);  
int main(){  
    int i,j;  
        do{  
    printf("输出路径坐标请按1 否则按0:");  
    scanf("%d",&K);  
    while(getchar()!='\n');  
    }while(K<0||K>1);  
    do{  
    S[1][0]=7;S[N][M+1]=8;  
    printf("原水管分布图:");  
        srand(time(NULL));//产生随机种子  
        for(i=0;i<=N+1;i++)         //输出地图  
    {  
        printf("\n");  
        for(j=0;j<=M+1;j++)  
        {  
           if(i&&j&&i!=N+1&&j!=M+1)  
             S[i][j]=rand()%7;  
            printf("%s",G[S[i][j]]);  
        }  
    }  
    printf("\n");  
    dfs(1,1,1);               //深度遍历  
    printf("当前地图%s能接通!\n",Flag?"\0":"不");  
    if(Flag)  
    {  
        printf("共%d种连接方式,已全显示 向上翻\n",SUM);  
        printf("最大步数%d  是第%d种\n请按任意键继续……",MAX[0],MAX[1]);  
        getchar();
    }  
    else  
    {  
        sleep(1);  
       system("clear");  
    }  
    }while(!Flag);  
    return 0;  
}  
int print(int num)  
{  
    int i;  
    for(i=0;i<12;i++)                                     //   2                                                 // 1   3  
              if(stack[num][2]==T[i][0]&&stack[num+1][2]==T[i][1])  
                  return  LL[i];  //输出Q对应的水管形状  
    return -1;  
}  
void dfs(int X,int Y,int front)  
{  
    int i,j;  
   if(X==N&&Y==M+1)//如果方案找到 输出 信息  
   {  
       stack[top+1][2]=1;  
      for(Flag=1;Flag<=top;Flag++)   //输出路径坐标  
      {  
        if(K)  
        printf("(%2d,%2d)\t",stack[Flag][0],stack[Flag][1]);  
        S[stack[Flag][0]][stack[Flag][1]]=print(Flag);  
      }  
        printf("\n连接好之后[左上<入口>->右下<出口>]第%d种:\n共%d步\n",++SUM,top);  
        if(top>=MAX[0])  
        {  
            MAX[0]=top;  
            MAX[1]=SUM;  
        }  
         for(i=0;i<=N+1;i++)  
         {  
            for(j=0;j<=M+1;j++)  
           printf("%s",G[S[i][j]]);  
            printf("\n");  
         }  
      return ;  
   }  
    if(X<1||Y<1||X>N||Y>M||BOOK[X][Y])  
        return ;  
    BOOK[X][Y]=1;  
    stack[++top][0]=X;  
    stack[top][1]=Y;  
    if(S[X][Y]>=5&&S[X][Y]<=6)  
    {  
              stack[top][2]=front;  
      dfs(X+NEXT[front][0],Y+NEXT[front][1],front);//在上一个程序里有解释  
    }  
    if(S[X][Y]>=1&&S[X][Y]<=4)  
    {  
       stack[top][2]=front;  
       dfs(X+A[front][0],Y+A[front][1],A[front][2]);//在上一个程序里有解释  
       dfs(X+B[front][0],Y+B[front][1],B[front][2]);  
    }  
    BOOK[X][Y]=0;//消除当前坐标的标记  
    top--;    //将当前坐标出栈  
    return ;  
}  
VM ubuntu 版  GCC
# include <stdio.h>  
# include <stdlib.h>  
# include <unistd.h>  
# include <time.h>  
# define N 14  //地图的行数  
# define M 26  //地图的列数  
int Flag=0,BOOK[N+1][M+1]={0},S[N+2][M+2]={0},top=0,SUM=0,K,MAX[2];  
const int NEXT[][2]={{0,0},{0,1},{1,0},{0,-1},{-1,0}};//用数组代替上面的判断  
const int A[][3]={{0,0,0},{1,0,2},{0,1,1},{-1,0,4},{0,1,1}};//同上  
const int B[][3]={{0,0,0},{-1,0,4},{0,-1,3},{1,0,2},{0,-1,3}};//同上  
const char G[][5]={"▲","┗","┏","┓","┛","━","┃","★","★"};//数字对应的水管形状 或树木  
const  int T[][2]={{1,2},{4,3},{3,2},{4,1},{2,3},{1,4},{2,1},{3,4},{1,1},{3,3},{2,2},{4,4}};//弯的水管的进出方向1 2 3 4分别为 左 上 右 下  
//const char Q[][3]={"┓","┓","┎","┎","┛","┛","┗","┗","━","━","┃","┃"};  
const int  LL[]={3,3,2,2,4,4,1,1,5,5,6,6};//可以用■ 代替上面的 G数组中的▲  
char stack[M*N][3]={0};            //用二维数组模拟栈  
void dfs(int X,int Y,int front);  
int print(int num);  
int main(){  
    int i,j;  
        do{  
    printf("输出路径坐标请按1 否则按0:");  
    scanf("%d",&K);  
    while(getchar()!='\n');  
    }while(K<0||K>1);  
    do{  
    S[1][0]=7;S[N][M+1]=8;  
    printf("原水管分布图:");  
        srand(time(NULL));//产生随机种子  
        for(i=0;i<=N+1;i++)         //输出地图  
    {  
        printf("\n");  
        for(j=0;j<=M+1;j++)  
        {  
           if(i&&j&&i!=N+1&&j!=M+1)  
             S[i][j]=rand()%7;  
            printf("%s",G[S[i][j]]);  
        }  
    }  
    printf("\n");  
    dfs(1,1,1);               //深度遍历  
    printf("当前地图%s能接通!\n",Flag?"\0":"不");  
    if(Flag)  
    {  
        printf("共%d种连接方式,已全显示 向上翻\n",SUM);  
        printf("最大步数%d  是第%d种\n",MAX[0],MAX[1]);  
        //pause();
       getchar();
    }  
    else  
    {  
        sleep(1);  
        system("clear");  
    }  
    }while(!Flag);  
    return 0;  
}  
int print(int num)  
{  
    int i;  
    for(i=0;i<12;i++)                                     //   2                                                 // 1   3  
              if(stack[num][2]==T[i][0]&&stack[num+1][2]==T[i][1])  
                  return  LL[i];  //输出Q对应的水管形状  
    return -1;  
}  
void dfs(int X,int Y,int front)  
{  
    int i,j;  
   if(X==N&&Y==M+1)//如果方案找到 输出 信息  
   {  
       stack[top+1][2]=1;  
      for(Flag=1;Flag<=top;Flag++)   //输出路径坐标  
      {  
        if(K)  
        printf("(%2d,%2d)\t",stack[Flag][0],stack[Flag][1]);  
        S[stack[Flag][0]][stack[Flag][1]]=print(Flag);  
      }  
        printf("\n连接好之后[左上<入口>->右下<出口>]第%d种:\n共%d步\n",++SUM,top);  
        if(top>=MAX[0])  
        {  
            MAX[0]=top;  
            MAX[1]=SUM;  
        }  
         for(i=0;i<=N+1;i++)  
         {  
            for(j=0;j<=M+1;j++)  
           printf("%s",G[S[i][j]]);  
            printf("\n");  
         }  
      return ;  
   }  
    if(X<1||Y<1||X>N||Y>M||BOOK[X][Y])  
        return ;  
    BOOK[X][Y]=1;  
    stack[++top][0]=X;  
    stack[top][1]=Y;  
    if(S[X][Y]>=5&&S[X][Y]<=6)  
    {  
              stack[top][2]=front;  
      dfs(X+NEXT[front][0],Y+NEXT[front][1],front);//在上一个程序里有解释  
    }  
    if(S[X][Y]>=1&&S[X][Y]<=4)  
    {  
       stack[top][2]=front;  
       dfs(X+A[front][0],Y+A[front][1],A[front][2]);//在上一个程序里有解释  
       dfs(X+B[front][0],Y+B[front][1],B[front][2]);  
    }  
    BOOK[X][Y]=0;//消除当前坐标的标记  
    top--;    //将当前坐标出栈  
    return ;  
}  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值