递归算法实现扫雷


//扫雷游戏
#include<iostream>
#include<iomanip> //输出 对齐 (manipulator操纵器) setw(n)
using namespace std;
#include<stdlib.h>
#include<time.h>
#define M1 10        //行
#define M2 8        //列     

#define MYN 8    //雷个数
int arr1[M1+2][M2+2]; //arr1用于布雷,arr2用于扫雷显示
char arr2[M1+2][M2+2];

int E1[8]={-1,0,1,1,1,0,-1,-1};//搜索规则
int E2[8]={-1,-1,-1,0,1,1,1,0};

//初始化
void initiate()
{
    for(int i=0;i<M1+2;i++)
    {
        for(int j=0;j<M2+2;j++)
        {
            if(i==0||j==0||i==M1+1||j==M2+1)
                arr2[i][j]='#';  //边界墙  --对*操作时不影响
            else
            {
                arr1[i][j]=0;
                arr2[i][j]='*'; //开始界面全是*
            }
        }
    }
}

//布雷和数字
void putLandmine ()
{
    srand((unsigned int)time(NULL));
    
    for(int k=0;k<MYN;k++)  //随机下标布置地雷
    {
        int i=1+rand()%(M1-1);
        int j=1+rand()%(M2-1);
        arr1[i][j]=-1;
    }
    //计算数字 :
    int temp=0;
    for(int i=1;i<=M1;i++)
    {
        for(int j=1;j<=M2;j++)
        {
            if(arr1[i][j]!=-1)
            {
                temp=0;
                for(int k=0;k<8;k++)
                if(arr1[i+E1[k]][j+E2[k]]==-1)  //如果四周有雷,计数并放在(i,j)位置上
                    temp++;
                arr1[i][j]=temp;
            }
        }
    }
}

//打印1
void view()
{
    for(int i=0;i<M1+2;i++)
    {
        for(int j=0;j<M2+2;j++)
        {
            cout<<setw(3)<<arr1[i][j];//setw(n) 保证输出宽度为n
        }
        cout<<endl;
    }
}
//打印arr2面向用户
void view2()
{
    
    for(int i=0;i<M1+2;i++)
    {
        for(int j=0;j<M2+2;j++)
        {
            if(i==0&&j!=(M2+1))  //打印列数
            {
                cout<<setw(3)<<j;
            }
            else if(j==0&&i!=(M1+1)) //打印行数
            {
                cout<<setw(3)<<i;
            }
            else
            {
                cout<<setw(3)<<arr2[i][j];
            }
        }
        cout<<endl;
    }
}

void defeat() //打印失败时的界面
{
    for(int i=0;i<M1+2;i++)
    {
        for(int j=0;j<M2+2;j++)
        {
            if(arr1[i][j]==-1)
                arr2[i][j]='U'; //U表示雷
        }
    }
    view2();
}

void set(int x,int y)    //是0则递归展开
{
    
    if(arr1[x][y]==0)  //数字是0的位置周围一定没雷
    {
        arr2[x][y]=' ';
        for(int k=0;k<8;k++)
        {
            if(x+E1[k]>=0&&x<=(M1+2)&&y+E2[k]>=0&&y<=(M2+2)&&arr2[x+E1[k]][y+E2[k]]=='*')
            {
                set(x+E1[k],y+E2[k]);
            }
        }
    }
    else
    {
        arr2[x][y]=arr1[x][y]+'0';//按字符存到arr2中
    }
}

int LmGame(int x,int y) //扫雷过程  踩雷返回0,否则返回1
{
    if(arr1[x][y]==-1) //踩着雷了
    {
        defeat();
        cout<<"踩着雷了!!"<<endl;
        return 0;    //直接返回
    }
    set(x,y);
    view2();
    cout<<"很棒!继续扫雷"<<endl;
    return 1;
}

int succeed()//判断全部扫完 若是返回1 否则返回0
{
    int count=0;
    for(int i=1;i<=M1;i++)
    {
        for(int j=1;j<=M2;j++)
        {
            if(arr2[i][j]=='*')
            {
                count+=1;
            }
        }
    }
    if(count==MYN) //成功条件 剩余个数刚好是雷的个数
        return 1;
    else
        return 0;
}

int allow(char ca[],int& x,int& y)   //误输入? 判断
{
    x=0;y=0;
    
    for(int i=0;ca[i]!='\0';i++)
    {
        if(ca[i]==' ')
        {
            for(int j=0;j<i;j++)
            {
                x=x*10;
                x+=(int)ca[j]-48;
            }
            for(int k=i+1;ca[k]!='\0';k++)
            {
                y=y*10;
                y+=(int)ca[k]-48;
            }
            system("cls");
            return 1;
        }
    }
    system("cls");
    return 0;
}
int main()
{
    cout<<"开始扫雷游戏"<<endl;
    initiate();
    putLandmine ();
    view();         //查看部署
    view2();        //用户界面
    char ca[10];    //输入
    int x,y,p,s;
    
    do{
        cout<<"输入坐标:";
        gets(ca);                 //输入字符串:数字空格数字
        int ret=allow(ca,x,y);
        if(ret==0||x<1||x>M1||y<1||y>M2) //误输入? 判断
        {    
            view2();
            cout<<"请输入你要扫雷的下标x y:(1~9)" <<endl;
            cout<<"你的输入有误,重新输入"<<endl;
        }
        else if(arr2[x][y]!='*')
        {
            view2();
            cout<<"请输入你要扫雷的下标x y:(1~9)" <<endl;
            cout<<"这里已经扫过,重新输入"<<endl;
        }
        else
        {    
            system("cls"); //清屏
            p=LmGame(x,y);    //扫雷
            s=succeed();    //是否成功
        }
    }while(p&&!s||x<1||x>M1||y<1||y>M2);
    // p==1单步没有踩雷、且s==0整体没有扫完---继续
    // 误输入---继续
    
    if(s==1)  cout<<"哇哦,扫完了!原来你就是扫雷大神"<<endl;
    else cout<<"游戏结束,再接再厉" <<endl;
    system("pause");
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值