<数据结构学习>图——连连看游戏

问题描述

《连连看》是由一款益智类游戏。《连连看》只要将相同的两张牌用三根以内的直线连在一起就可以消除,规则简单容易上手。

本题编写程序模拟人进行连连看游戏,电脑模拟人玩连连看的过程如下:

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. 4 5↵
  2. 0 0 0 0 0 0 1 2 0 0 0 0 3 4 0 0 0 0 1 0↵
  3. 1 1↵
  4. 3 3↵
以文本方式显示
  1. TRUE↵
1秒64M0
测试用例 2以文本方式显示
  1. 5 6↵
  2. 0 0 0 0 0 0 0 1 2 3 0 0 3 0 0 0 0 3 0 2 3 4 0 2 0 0 0 2 1 4↵
  3. 1 1↵
  4. 4 4↵
以文本方式显示
  1. TRUE↵
1秒64M0
测试用例 3以文本方式显示
  1. 5 6↵
  2. 0 0 0 0 0 0 0 1 2 3 0 0 3 0 0 0 0 3 0 2 3 4 0 2 0 0 0 2 1 4↵
  3. 3 3↵
  4. 4 5↵
以文本方式显示
  1. FALSE↵
1秒64M0

问题解决

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;
}

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值