麻将游戏

简介: Description  在一种”麻将”游戏中,游戏是在一个有W*H格子的矩形平板上进行的。每个格子可以放置一个麻将牌,也可以不放(如图所示)。玩家的目标是将平板上的所有可通过一条路径相连的两张相同的麻将牌,从平板上移去。

Description

  在一种”麻将”游戏中,游戏是在一个有W*H格子的矩形平板上进行的。每个格子可以放置一个麻将牌,也可以不放(如图所示)。玩家的目标是将平板上的所有可通过一条路径相连的两张相同的麻将牌,从平板上移去。最后如果能将所有牌移出平板,则算过关。 
  这个游戏中的一个关键问题是:两张牌之间是否可以被一条路径所连接,该路径满足以下两个特性: 
  1. 它由若干条线段组成,每条线段要么是水平方向,要么是垂直方向。 
  2. 这条路径不能横穿任何一个麻将牌 (但允许路径暂时离开平板)。 
  这是一个例子: 

       在(1,3)的牌和在(4, 4)的牌可以被连接。(2, 3)和(3, 4)不能被连接。 
  你的任务是编一个程序,检测两张牌是否能被一条符合以上规定的路径所连接。

Input

  输入文件的第一行有两个整数w,h (1<=w,h<=75),表示平板的宽和高。接下来h行描述平板信息,每行包含w个字符,如果某格子有一张牌,则这个格子上有个’X’,否则是一个空格。平板上最左上角格子的坐标为(1,1),最右下角格子的坐标为(w,h)。接下来的若干行,每行有四个数x1, y1, x2, y2 ,且满足1<=x1,x2<=w,1<=y1,y2<=h,表示两张牌的坐标(这两张牌的坐标总是不同的)。如果出现连续四个0,则表示输入结束。

Output

  输出文件中,对于每一对牌输出占一行,为连接这一对牌的路径最少包含的线段数。如果不存在路径则输出0。

Sample Input

5 4 
XXXXX 
X X 
XXX X 
XXX 
2 3 5 3 
1 3 4 4 
2 3 3 4 
0 0 0 0 

Sample Output

4

3

0

算法分析:

这道题可以参考上一篇文章:最少转弯数

最少转弯数这一道题计算出发点到目的点的最少转弯数,本题计算两个点之间的路径的线段的段数。这个段数其实就是转弯数加1.所以可以按照上一篇文章的做法求解。这一题当中,麻将牌可以离开平板,所以在表示平板的0/1矩阵地图周围构造一个环形通路,也就是外面有一圈0,以便广搜时可以走这一条路。

大体的思路就是在广搜时,对每一个可以前进的方向都一直前进直到不可行走为止,然后再从下一个方向继续广搜。具体描述见最少转弯数这篇文章的分析和代码注释。

 

PS:本题部分资料整理自下面两篇文章。

http://blog.csdn.net/SSL_ZZY/article/details/53856843

http://www.cnblogs.com/A1269180380/p/6340704.html

 

下面的代码是由最少转弯数的代码修改而来:

  1 #include<cstdio>  
  2 #include<cstring>  
  3 #include<queue>  
  4 using namespace std;
  5 
  6 const int dx[]={0,1,0,-1};//右下左上
  7 const int dy[]={1,0,-1,0};
  8 struct point
  9 {
 10     int x,y,turn;
 11 }_begin,_end,p;
 12 
 13 queue<point> q;
 14 int n,m,_map[101][101];
 15 bool used[101][101];  
 16 
 17 int fun();//统计从 _begin到达 _end的最少拐弯数。拐弯数加1就是线段数。 
 18 
 19 int main()
 20 {
 21     freopen("MAHJONG_data/MAHJONG7.in","r",stdin);
 22     freopen("MAHJONG_data/MAHJONG7.ans","w",stdout);
 23     int w,h,i,j,x1,y1,x2,y2;
 24     char ch;
 25     scanf("%d%d",&w,&h);getchar();//吸收行末尾回车符
 26     n=h;m=w; // n行,m列 
 27     
 28     //下面构造地图,把原来的字符矩阵转换为0/1矩阵表示的地图 
 29     //构造地图周围的环形通路 
 30     for(i=0;i<=n+1;i++) {  _map[i][0]=0;  _map[i][m+1]=0; }
 31     for(j=0;j<=m+1;j++) {  _map[0][j]=0;  _map[n+1][j]=0; }
 32     //for(j=0;j<=m+2;j++) _map[n+2][j]=1;  构造矩阵底部围墙 
 33     //for(i=0;i<=n+2;i++) _map[i][m+2]=1;  构造矩阵右侧围墙 
 34     for(i=1;i<=n;i++)//输入地图,把地图转换为0/1矩阵 
 35     {
 36         for(j=1;j<=m;j++)
 37         {
 38             ch=getchar();
 39             if(ch==' ') _map[i][j]=0; //0表示可以行走 
 40             else _map[i][j]=1;        //1表示不可以行走 
 41         }
 42         getchar();//吸收行末尾回车符
 43     }
 44     n++; m++;//因为环形通路的存在,行和列数目都增加 1。
 45     
 46     /*for(i=0;i<=n;i++)
 47     {
 48         for(j=0;j<=m;j++) printf("%d",_map[i][j]);
 49         printf("\n");
 50     }
 51     printf("\n-----------\n");*/
 52     
 53     while(scanf("%d%d%d%d",&x1,&y1,&x2,&y2)!=EOF)
 54     {
 55         if(x1==0&&x2==0&&y1==0&&y2==0) break;
 56         else
 57         {
 58             _begin.x=y1;
 59             _begin.y=x1;
 60             _end.x=y2;
 61             _end.y=x2;
 62             
 63             _map[y2][x2]=0;//要使得目的地可以到达 
 64             fun();
 65             _map[y2][x2]=1;//还原地图 
 66         }
 67     }
 68     
 69     return 0;
 70 }
 71 int fun()
 72 {
 73     memset(used,0,sizeof(used));
 74     while(!q.empty()) q.pop();//清空队列
 75      
 76     q.push(_begin);
 77     q.front().turn=0;  
 78     while(!q.empty())
 79     {
 80         for(int i=0;i<4;i++)
 81         {
 82             p.x=q.front().x+dx[i];  
 83             p.y=q.front().y+dy[i];
 84             //从队头出发往dx[i]和dy[i]方向一直走,直到遇到边界或高山则停止,再从原队头换下一个方向走 
 85             while(p.x>=0&&p.x<=n&&p.y>=0&&p.y<=m&&!_map[p.x][p.y]) //环形通路也是可以行走的 
 86             {
 87                 if(!used[p.x][p.y])
 88                 {
 89                     if(p.x==_end.x&&p.y==_end.y)
 90                     {
 91                         printf("%d\n",q.front().turn+1);//注意输出的是当前队头的转弯次数。 
 92                         return 0;  
 93                     }  
 94                     used[p.x][p.y]=1;  
 95                     p.turn=q.front().turn+1;  
 96                     q.push(p);  
 97                 }
 98                 p.x+=dx[i];
 99                 p.y+=dy[i];
100             }  
101         }  
102         q.pop();//当前队头元素已经不能再扩展,可以删除队头 
103     }
104     printf("0\n");//假如广搜无法到达目的地,那么输出0 
105 }

 

相关文章
|
4月前
|
人工智能 黑灰产治理 开发者
虚拟模特,一键生成高颜值AI模特!活动震撼来袭,快来生成你的高颜值模特大片!
体验”通义万相-虚拟模特“,晒出属于你的高颜值AI模特大片,在活动页面提交作品以及使用反馈,即有机会获得反馈奖哦!
346 2
虚拟模特,一键生成高颜值AI模特!活动震撼来袭,快来生成你的高颜值模特大片!
|
7月前
|
存储 前端开发 JavaScript
中秋佳节,万家团圆:中秋拼图小游戏。
前言:提前预祝各位开发者、各行各业的工作人员,中秋佳节!国庆节~身体健康,阖家欢乐!!! 在这个拼图游戏中,我们会展示一张月饼图片,然后将它分割成多个小方块。我们需要拖拽这些小方块,使它们重新排列,最
|
11月前
|
安全 程序员
学做游戏最重要的是学什么
解决问题的能力是一个人的最核心的技能,也是判断一个人游戏开发水平高低的决定性因素。你在做任何事情,尤其是刚接触一个新领域时,一定会遇到各种各样的问题,而其中大部分的问题你都从来没有遇到过。这个时候咋办呢? 最好最快的方式莫过于有一个有经验的老师可以带一带你,他可以指导一些方法和经验,回答你的一些疑问,告诉你哪里可能有“坑”......(小蚂蚁目前做的就是这些事情)。
74 0
P1000 超级玛丽游戏
P1000 超级玛丽游戏
76 0
10:超级玛丽游戏
10:超级玛丽游戏
77 0
|
存储 前端开发 开发者
「用前端重返童年🥤」为黑神话悟空定制红白机版游戏开始动画
「用前端重返童年🥤」为黑神话悟空定制红白机版游戏开始动画
142 0
复刻经典童年游戏扫雷之运营大大们来捉迷藏了
复刻经典童年游戏扫雷之运营大大们来捉迷藏了
161 0
复刻经典童年游戏扫雷之运营大大们来捉迷藏了
益智游戏软件
本文研究全球及中国市场益智游戏软件现状及未来发展趋势,侧重分析全球及中国市场的主要企业,同时对比北美、欧洲、中国、日本、东南亚和印度等地区的现状及未来发展趋势
|
人工智能 算法 云计算
捏脸太强!MetaHuman随心创造虚拟人类,给你一个「上帝的玩具」
近日,Unreal Engine开发的全新工具MetaHuman Creator。这款产品一经推出,便引起了轰动,原因是它可以用最短时间、最简单方式「捏」高保真的数字人类。不禁让人惊叹智人时代的来临!当数字人类无限接近真人,甚至比真人还完美,我们该兴奋还是恐惧?
417 0
捏脸太强!MetaHuman随心创造虚拟人类,给你一个「上帝的玩具」