新手小练习——扫雷游戏(c语言实现)

目录

一,基本思路

二,排雷整体实现(含空白展开功能)

三,排雷的细节讲解


一,基本思路

1.使用两个棋盘(也就是要求创建两个二维数组),一个用以存放雷的位置,一个用以展示给玩家看

2.明确要实现的几个主要功能:1)把棋盘打印到屏幕,展示给玩家

                                                  2)玩家进行排雷,给出玩家所排点周围雷的个数

                                                  3)设置失败的触发条件:玩家踩雷

                                                  4)设置成功的触发条件:玩家排雷次数已达到上限值

                                                (上限值=棋盘总格数 - 玩家设置的雷的个数) 

二,排雷整体实现(含空白展开功能)

本人小白哈哈,刚玩扫雷的时候并没有注意这个空白展开的功能,后来补加上去的,比较赶,并未做太多的算法优化,请见谅哈哈🤣🤣🤣

下面是总代码,接着会有细节的讲述

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void chushihua(char a[11][11],char p);
void print_board(char b[11][11]);
int pailei(char a[11][11],char b[11][11]);
void setbomb(char a[11][11],int n);
void kaipi(char a[11][11],char b[11][11],int x,int y);
int countlei(char a[11][11],int x,int y);
int pan(char b[11][11],int x,int y);
int pan2(char b[11][11]);
int x1=0,y1=0;



int main()
{
	again:
	printf("请输入1或2\n1为开始游戏  2为退出游戏");
	int u,n;
	scanf("%d",&u);
	switch (u) 
	{
	case 1:
	printf("游戏开始\n设置雷的数量\n");
	scanf("%d",&n);
	char a[11][11];//用以存放雷的位置,其中'0'为无雷区,其中'1'为雷区
	char b[11][11];//用以展示给玩家,其中'*'表示未被探索区域
	chushihua(a,'0');
	chushihua(b,'*');
	setbomb(a,n);
    while(1)//利用循环实现多次下棋
	{
		int k=1;
		print_board(b);
		k=pailei(a,b);
        if(k==2)
        {
            kaipi(a,b,x1,y1);
        }
	    if(k==0)
		{
			print_board(a);
			printf("You Lost!你被炸死了");
			break;
		}
		if(pan2(b)==n)
		{
			printf("You Win!");
			break;
		}
	}
	break;


	case 2:
	printf("游戏已退出");
	break;


	default:
	printf("输入错误,请重新输入\n");
	goto again;
	}
	return 0;
}



//函数定义
void chushihua(char a[11][11],char p)
{
	for(int i=0;i<=10;i++)
	{
		for(int j=0;j<=10;j++)
		{
			a[i][j]=p;
		}

	}

}

void print_board(char b[11][11])
{
	for(int i=0;i<=9;i++)
	{
		printf("%d ",i);
	}
	printf("\n");
	for(int i=1;i<=9;i++)
	{
		printf("%d ",i);
		for(int j=1;j<=9;j++)
		{
			printf("%c ",b[i][j]);
		}
		printf("\n");
	}

}

void setbomb(char a[11][11],int n)
{
	int x,y,z,r,count=0;
	srand((unsigned)time(NULL));
     while(1)
     {
          z = rand();
          r = rand();
          x=z%9+1;
          y=r%9+1;
         if(a[x][y]=='0')
         {
              a[x][y]='1';
			  count++;
         }
		 if(count==n)
		 {
			 break;
		 }
     }     
}

int countlei(char a[11][11],int x,int y)
{
    int count=a[x-1][y-1]+a[x-1][y]+a[x-1][y+1]+a[x][y-1]+a[x][y+1]+a[x+1][y-1]+a[x+1][y]+a[x+1][y+1]-8*'0';
    return count;
}
  

int pailei(char a[11][11],char b[11][11])//返回值为0时,被炸死
{
	int x,y,count=0;
	while(1)
	{
	printf("输入需要排查的坐标\n");
	scanf("%d %d",&x,&y);
	if(x<1||x>9||y<1||y>9||b[x][y]!='*')
	{
		continue;
	}

	if(a[x][y]=='1')
	{
		return 0;
	}
	count=a[x-1][y-1]+a[x-1][y]+a[x-1][y+1]+a[x][y-1]+a[x][y+1]+a[x+1][y-1]+a[x+1][y]+a[x+1][y+1]-8*'0';
	b[x][y]='0'+count;
    if(count==0)
    {
        x1=x;
        y1=y;
        return 2;
    }
    
    return 1;
	}
}

void kaipi(char a[11][11],char b[11][11],int x,int y)
{

    for(int i=-1;i<=1;i++)
    {
        for(int j=-1;j<=1;j++)
        {
            if(i!=0||j!=0)
            {
                b[x+i][y+j]=countlei(a, x+i, y+j)+'0';
            }
        }
    }
 for(int i=-1;i<=1;i++)
    {
        for(int j=-1;j<=1;j++)
        {
	            if(b[x+i][y+j]=='0'&& pan(b,x+i,y+j)==1)
                {
                  kaipi(a,b,x+i,y+j);
				}
		}
	}			 
}


int pan(char b[11][11],int x,int y)//有*号返回1
{
	 for(int i=-1;i<=1;i++)
    {
        for(int j=-1;j<=1;j++)
        {
			if(i!=0||j!=0)
			{
				if(b[x+i][y+j]=='*')
				{
					return 1;
				}
			}
		}
	} 
	return 0;
}

int pan2(char b[11][11])//计算b数组中的*数
{
	int count=0;
	for(int i=1;i<=9;i++)
	{
		for(int j=1;j<=9;j++)
		{
			if(b[i][j]=='*')
			{
				count++;
			}
		}
	}
	return count;
}




三,排雷的细节讲解

1.首先,我们先看代码的函数声明部分(解释见图)

 

2.接着,看代码躯干(main函数部分)

 

 

3.最后,我们看各个函数的定义

1)初始化

2)打印棋盘

 3)电脑随机在a盘中布置雷,雷记为'*'

 4)数坐标为(x,y)的位置周围的雷的数量,返回值即雷的数量

 5)玩家排雷(返回值为0时,被炸死;返回值为2时,说明周围无雷,可以进行空白的开辟)

 6)周围无雷,进行空白的开辟(利用函数递归),其中if(b[x+i][y+j]=='0'&& pan(b,x+i,y+j)==1)的递归的边界条件极为重要i

条件1:该位置周围无雷;

条件2:该位置周围的区域并未被翻开

 7)看坐标为(x,y)处周围是否有*,为kaipi函数的函数递归做边界条件

 8)计算b中’*‘的数量,即未排查区的数量,当未排除区为0,玩家即可获得胜利

 

以上就是我关于扫雷的一些实现,小白新人,如有错误,感谢各位大佬的指正啦~~😁😁😘😝

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值