编写一个扫雷游戏,我们首先要清楚游戏规则

编写一个扫雷游戏,我们首先要清楚游戏规则:
        扫雷就是要把所有非地雷的格子揭开即胜利;踩到地雷格子就算失败。游戏主区域由很多个方格组成。使用鼠标左键随机点击一个方格,方格即被打开并显示出方格中的数字;方格中数字则表示其周围的8个方格隐藏了几颗雷;如果点开的格子为空白格,即其周围有0颗雷,则其周围格子自动打开;如果其周围还有空白格,则会引发连锁反应;在你认为有雷的格子上,点击右键即可标记雷;如果一个已打开格子周围所有的雷已经正确标出,则可以在此格上同时点击鼠标左右键打开其周围剩余的无雷格。
        转化为c语言的东西就是我们用一个字节表示其各种状态,第八位可以表示显示初始化的标识,第七位表示显示雷的标识,第六位表示设置地雷,第五位表示显示数字,剩下的四位就表示身边的地雷数字,为了防止改变比特位的时候把状态也改变了,我们就用到了位与“&”以及位或“|”,而非逻辑与“&&”与逻辑或“|”,通俗点说就是,1与任何值&的结果都是1,0与任何值|的结果都是0。

代码:

#include<stdio.h>
#include<assert.h>
#include<string.h>
#include<stdlib.h>
#include<windows.h>
#include<time.h>

#define INIT_VIEW 0X80  //1000 0000 @
#define MINE_VIEW 0X40  //0100 0000 #//地雷标记
#define MAKE_MINE 0X20  //0010 0000 //地雷
#define MAKE_NUM  0X10  //0001 0000 0 1 2 3雷的个数
#define CLEAR_INIT 0X7F //0111 1111 清除初始化
#define CLEAR_MINE 0XBF //1011 1111 清除雷的显示
#define VIEW_NUM   0X0F //0000 1111 显示数字

#define ROWSIZE 15  //游戏区域
#define COLSIZE 15

#define MINESIZE 64 //雷的个数
typedef unsigned char Grid[ROWSIZE+2][COLSIZE+2];
//行和列多2,方便计算不是累的方格周围的雷数

void Init_ar(Grid ar,int row,int col)
{
    assert(ar !=nullptr);
    for(int r=1;r<=row;++r)
    {
        for(int c=1;c<=col;++c)
        {
            ar[r][c]|=INIT_VIEW;//初始化显示
        }
    }
    int num=0;
    srand((unsigned)time(NULL)); //设置时间种子,以至于每次执行程序的时候地雷的位置不一样   
    while(num<MINESIZE)          //随机设置地雷
    {

        int r=rand()%ROWSIZE+1;
        int c=rand()%COLSIZE+1;
        if(!(ar[r][c]&MAKE_MINE))//如果这个队列不是地雷的话,就设置为雷,直到整个地图有64个雷
        {
            ar[r][c]|=MAKE_MINE;
            ++num;
        }
    }

  
}

void testprint(Grid ar,int row,int col)
{
    printf("  ");
    for(int j=1;j<=col;++j)
    {
        printf("%2d",j);
    }
    printf("\n");
    for(int i=1;i<=row;++i)
    {
        printf("%2d",i);
        for(int j=1;j<=col;++j)
        {
            if(ar[i][j]&MAKE_MINE)
            {
                printf("%2c",'#');
            }
            else
            {
                printf("%2c",'@');
            }
        }printf("\n");

    }printf("\n");

}

void testprint2(Grid ar,int row,int col)
{
    printf("  ");
    for(int j=1;j<=col;++j)
    {
        printf("%2d",j);
    }
    printf("\n");
    for(int i=1;i<=row;++i)
    {
        printf("%2d",i);
        for(int j=1;j<=col;++j)
        {
            if(ar[i][j]&MAKE_NUM)
            {
                printf("%2d",ar[i][j]&VIEW_NUM);
            }
            else if(ar[i][j]&MAKE_MINE)
            {
                printf("%2c",'#');
            }

            else
            {
                printf("%2c",'@');
            }
        }printf("\n");

    }printf("\n");

}
void setminenum(Grid ar,int row,int col)//计算不是雷的方格周围的雷数
{
    assert(ar !=nullptr);
    for(int r=1;r<=row;++r)
    {
        for(int c=1;c<=col;++c)
        {
            if(!(ar[r][c]&MAKE_MINE))//如果这个点不是雷
            {
                unsigned char num=0; 
                for(int i=r-1;i<=r+1;++i)//判断每个点的三行三列
                {
                    for(int j=c-1;j<=c+1;++j)
                    {
                        //如果是雷
                        if(ar[i][j]&MAKE_MINE)
                        {
                            num+=1;
                        }
                    }
                } 
                ar[r][c]|=MAKE_NUM;//数字状态
                ar[r][c]|=(0x0f&num);//周围有几个雷
            }
            
        }
    }

}

void show_ar(Grid ar,int row,int col)
{
    //system("cls");
    printf("  ");
    for(int j=1;j<=col;++j)
    {
        printf("%2d",j);
    }
    printf("\n");
    for(int i=1;i<=row;++i)
    {
        printf("%2d",i);
        for(int j=1;j<=col;++j)
        {
            if(ar[i][j]&INIT_VIEW) //初始化显示
            {
                printf("%2c",'@');
            } 
            else if(ar[i][j]&MINE_VIEW)//雷的显示
            {
                printf("%2c",'#');
            }
            else{         //显示数字
                printf("%2d",ar[i][j]&VIEW_NUM);
            }
        }
        printf("\n");

    }printf("\n");
}
int main()
{
    Grid ar={0};
    Init_ar(ar,ROWSIZE,COLSIZE);
    //testprint(ar,ROWSIZE,COLSIZE);
    setminenum(ar,ROWSIZE,COLSIZE);
    //testprint2(ar,ROWSIZE,COLSIZE);
    int num=0,tag=0;
    int r,c;
    char ch;
    while(tag!=0||num<MINE_VIEW)
    {
        printf("%d\n",tag);//测试用,设置标记错误的雷的个数,不是雷,标记成雷+1,取消标记-1
/*        for(r=1;r<=ROWSIZE;++r)
        {
            for(c=1;c<=COLSIZE;++c)
            {
                //Sleep(200);
                ch='#';
*/
        show_ar(ar,ROWSIZE,COLSIZE);
        printf("输入行列\n");
        scanf("%d %d %c",&r,&c,&ch);
        if(r>=1&&r<=ROWSIZE&&c>=1&&c<=COLSIZE)
        {   if(ch=='0')
            {
                if(ar[r][c]&MAKE_MINE)//将雷标记成不是雷
                {
                    printf("雷炸了\n");
                    break;
                }                      
                else
                {
                    if(ar[r][c]&MINE_VIEW)//0100 0000如果是雷的视图
                {

                    ar[r][c]&=CLEAR_MINE;//1011 1111清除雷的标记
                    //ar[r][c]|=INIT_VIEW;//1000 0000初始化显示
                    tag=tag-1;
                }
                ar[r][c]&=CLEAR_INIT;//0111 1111清除初始化

                }            
            }
            else if(ch=='#')
            {

                if(ar[r][c]&MAKE_MINE)//是地雷
                {
                    num=num+1;
                }
                else{tag=tag+1;}
                ar[r][c]&=CLEAR_INIT;//清除初始化
                ar[r][c]|=MINE_VIEW;//雷视图 
                //tag=tag+1;
                //printf("tag=%d",tag);
                //if(tag>64)
                //{
                    //printf("标记雷的个数等于64,但是还没有寻找完成\n");
                   // break;
                //}
            }
            else if(ch=='@')
            {
                if(ar[r][c]&MAKE_MINE)//是地雷
                {
                    num=num-1;
                }
                else
                {
                    if(ar[r][c]&MINE_VIEW)//0100 0000如果是雷的视图
                    {
                    tag=tag-1;
                    }
                }
                ar[r][c]&=CLEAR_MINE;//1011 1111清除雷的标记
                ar[r][c]|=INIT_VIEW;//1000 0000初始化显示
            }       
        }
        else{printf("输入错误\n");}
    }        /*    }
        }*/
    if(num>=MINESIZE)
    {
        printf("胜利\n");
    }
    if(tag>64)
    {
        printf("超出最大雷个数,没有找到所有雷,失败\n");
    }
    return 0;
}
//问题:标记完雷,直接标记不是雷,无法操作//已实现

结果:

0
   1 2 3 4 5 6 7 8 9101112131415      
 1 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
 2 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
 3 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
 4 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
 5 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
 6 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
 7 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
 8 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
 9 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
10 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
11 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
12 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
13 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
14 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @
15 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      

输入行列
1 1 #
0
   1 2 3 4 5 6 7 8 9101112131415      
 1 # @ @ @ @ @ @ @ @ @ @ @ @ @ @      
 2 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
 3 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
 4 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
 5 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
 6 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
 7 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
 8 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @
 9 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
10 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
11 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
12 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
13 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
14 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
15 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      

输入行列
1 1 @
0
   1 2 3 4 5 6 7 8 9101112131415      
 1 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
 2 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
 3 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
 4 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
 5 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
 6 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
 7 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
 8 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
 9 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
10 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
11 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @
12 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
13 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
14 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      
15 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @      

输入行列
1 1 0
雷炸了

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值