问题描述
《连连看》是由一款益智类游戏。《连连看》只要将相同的两张牌用三根以内的直线连在一起就可以消除,规则简单容易上手。
本题编写程序模拟人进行连连看游戏,电脑模拟人玩连连看的过程如下:
1、分析本局游戏,将本局游戏转化成一个二位数组。0表示空白区域,数字表示该游戏牌为出现在游戏中的第几类游戏牌。
2、利用广度优先搜索算法,判断两个游戏牌是否可以消除。
3、程序模拟人点击可以消除的一对游戏牌进行消除。
对某局游戏转化成二维数组如下:
0 0 0 0 0
0 1 2 0 0
0 0 3 4 0
0 0 0 1 0
输入二位数组的行、列,二位数组、起始元素的的坐标、终止元素的坐标,判断起始游戏牌和终止游戏牌是否可以消除。
对上例输入:
4 5
0 0 0 0 0 0 1 2 0 0 0 0 3 4 0 0 0 0 1 0
1 1
3 3
输出:TRUE
测试输入 | 期待的输出 | 时间限制 | 内存限制 | 额外进程 | |
---|---|---|---|---|---|
测试用例 1 | 以文本方式显示
| 以文本方式显示
| 1秒 | 64M | 0 |
测试用例 2 | 以文本方式显示
| 以文本方式显示
| 1秒 | 64M | 0 |
测试用例 3 | 以文本方式显示
| 以文本方式显示
| 1秒 | 64M | 0 |
问题解决
int map[100][100]; //保存地图
int visited[100][100];//记录转了几条边了
struct Vec //保存每个点的信息
{
int x,y; //坐标信息
int direct; //方向信息,如下turn数组
int edge; //已经转了几条边了
};
int turn[4][4]={{0,-1},{0,1},{-1,0},{1,0}};//上0下1左2右3
int n,m; //行数和列数
int beginx,beginy,endx,endy; //起点和终点坐标
int BFS()
{
Vec p,t,s;
queue<Vec> q; //建立一个队列保存每轮遍历到的一层上的点
for(int i=0;i<4;i++) //起点向周围四个方向走动一步
{
t.x=beginx+turn[i][0];
t.y=beginy+turn[i][1];
t.direct=i; //方向改变
t.edge=1; //转动边数+1
visited[t.x][t.y]=t.edge; //当前这个点的转动次数
q.push(t); //入队
}
while(q.size()>0) //队列非空时
{
p=q.front(); //取队首
q.pop(); //立即弹出队首
if(p.x==endx&&p.y==endy) //如果此点恰好是终点,输出能找到,返回1
{
cout<<"TRUE"<<endl;
return 1;
}
for(int i=0;i<4;i++) //若不是终点,向此点四周走动一步
{
s.x=p.x+turn[i][0];
s.y=p.y+turn[i][1];
s.direct=i; //改变方向
if(s.direct!=p.direct) s.edge=p.edge+1; //方向若改换转动边数要增加
else s.edge=p.edge;
if(s.x>n-1||s.y>m-1||s.x<0||s.y<0||s.edge>3) continue;
//若坐标越界或转动边数>3直接跳过
else if(map[s.x][s.y]!=0&&map[s.x][s.y]!=map[endx][endy]) continue;
//若地图上是其他点也直接跳过
else if(visited[s.x][s.y]==0||visited[s.x][s.y]>=s.edge)
{ //若此点未访问或转动边数大于当前转动边数(说明曾经遍历过但没找到终点,
但改变方向走或许还有机会)
visited[s.x][s.y]=s.edge; //改变转动变数加入队列重新遍历
q.push(s);
}
}
}
return 0;
}
int main() //main函数,输入行列数、地图、起点和终点
{
cin>>n>>m;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
cin>>map[i][j];
}
}
cin>>beginx>>beginy;
cin>>endx>>endy;
int judge=1;
judge=BFS();
if(judge==0) cout<<"FALSE"<<endl; //若有解BFS函数会返回1,返回0说明无解,输出FALSE
return 0;
}
完整代码:
#include <iostream>
#include<queue>
using namespace std;
int map[100][100];
int visited[100][100];//记录转了几条边了
struct Vec
{
int x,y;
int direct;
int edge;
};
int turn[4][4]={{0,-1},{0,1},{-1,0},{1,0}};//上0下1左2右3
int n,m;
int beginx,beginy,endx,endy;
int BFS()
{
Vec p,t,s;
queue<Vec> q;
for(int i=0;i<4;i++)
{
t.x=beginx+turn[i][0];
t.y=beginy+turn[i][1];
t.direct=i;
t.edge=1;
visited[t.x][t.y]=t.edge;
q.push(t);
}
while(q.size()>0)
{
p=q.front();
q.pop();
if(p.x==endx&&p.y==endy)
{
cout<<"TRUE"<<endl;
return 1;
}
for(int i=0;i<4;i++)
{
s.x=p.x+turn[i][0];
s.y=p.y+turn[i][1];
s.direct=i;
if(s.direct!=p.direct) s.edge=p.edge+1;
else s.edge=p.edge;
if(s.x>n-1||s.y>m-1||s.x<0||s.y<0||s.edge>3) continue;
else if(map[s.x][s.y]!=0&&map[s.x][s.y]!=map[endx][endy]) continue;
else if(visited[s.x][s.y]==0||visited[s.x][s.y]>=s.edge)
{
visited[s.x][s.y]=s.edge;
q.push(s);
}
}
}
return 0;
}
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
cin>>map[i][j];
}
}
cin>>beginx>>beginy;
cin>>endx>>endy;
int judge=1;
judge=BFS();
if(judge==0) cout<<"FALSE"<<endl;
return 0;
}