程序员成长之旅——C语言扫雷

游戏简介

在这里插入图片描述

功能简介

扫雷相信大家并不陌生,而这次我们用C实现的扫雷小游戏具体有以下两个功能:

  • 可以展开一片
  • 第一次踩不到雷

代码实现

跟上一篇讲到的三子棋小游戏思想基本一致。
首先用 printf 打印一个游戏菜单

 void menu()
{
 	printf("**********************\n");
 	printf("*****   1.play    ****\n");
 	printf("*****   0.exit    ****\n");
 	printf("**********************\n");
 }

而这个既然有选项,我们可以用一个函数接收它

void test()
{
  	int input = 0;
  	srand((unsigned int)time(NULL));
  	do
  	{
    		menu();
    		scanf_s("%d", &input);
    	switch (input)
    	{
    	case 1:
    	{
      		game();
      		break;
    	}
    	case 0:
    	{
      		printf("退出游戏\n");
      		break;
    	}
    	default:
    	{
      		printf("选择错误,请重新选择!\n");
      		break;
    	}
   	}
  	} while (input);
}

这些都应该在主函数中实现

int main()
{
  	test();
  	system("pause");
  	return 0;
}

接下来就到了此游戏的重点了,可创建一个game()函数,然后一步一步的实现此游戏

void game()
{

}

程序开始阶段我们可以在头文件引入宏定义,这是方便后续修改

#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define Easy_Count 10

game函数的扩充

void game()
{
	char mine[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };
	Initboard(mine, ROWS, COLS, '0');
	Initboard(show, ROWS, COLS, '*');
	Displayboard(show, ROW, COL);
	Setmine(mine, ROW, COL);
	First_SafeMine(mine, show, ROW, COL);
	Findmine(mine, show, ROW, COL);
}

这就是game函数的扩充内容,接下来我们来看下扩充的这些函数具体是做什么。

  • mine、show 首先我们定义了两个9x9大小棋盘分别为mine以及show,其中一个为真实的棋盘用于系统的判定,我们把其中的参数设置为1和0,其中的1为雷。另外一个棋盘为展示棋盘为我们用户在扫雷的时候看到的棋盘,展开的地方我们用数字表示,隐藏的部分我们用字符’*'来表示。
  • Initboard则是初始化两个棋盘
  • Displayboard则是展示我们想要展示的那个界面
  • Setmine则是用来布置雷的,需要产生随机数组
  • First_SafeMine则是第一次不会踩到雷
  • Findmine则是开始扫雷

上面game函数扩充的实现代码在完整代码有给出,这边我们再来探讨一些扫雷中的这些问题。

  • 在开始之前我们需要说明的是,由于判定以及展开的时候需要对周围八个点进行处理,在处理靠边的点的时候容易发生越界,因此我们将真实棋盘设定为(ROWS)x(COLS),但是我们所看到的仅仅是一个(ROW)x(COL)的棋盘,其余的点我们全部设置为0,这样就避免了错误。
  • 雷需要随机产生,因此引入一个随机语句rand() 而rand()需要引入头文件
    #include<time.h>
    #include<stdlib.h>
    同时还要注意我们坐标是从1-9因此要用rand()%8+1

完整代码

game.h
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>

#define ROW 9
#define COL 9

#define ROWS ROW+2
#define COLS COL+2
#define Easy_Count 10

void Initboard(char board[ROWS][COLS], int rows, int cols, char set);
void Displayboard(char board[ROWS][COLS], int row, int col);
void Setmine(char mine[ROWS][COLS],int row,int col);
void Findmine(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col);
void First_SafeMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
void OpenMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int x, int y);
int get_mine(char mine[ROWS][COLS], int x, int y);
game.c
#include"game.h"

void Initboard(char board[ROWS][COLS], int rows, int cols, char set)
{
 	int i = 0;
 	int j = 0;
 	for (i = 0; i < rows; i++)
 	{
  		for (j = 0; j < cols; j++)
  	{
   		board[i][j] = set;
  	}
 	}
}
void Displayboard(char board[ROWS][COLS], int row, int col)
{
 	int i = 0;
 	int j = 0;
 	printf("------------------------\n");
 	for (i = 0; i <= col; i++)
 	{
 		printf("%d ", i);
 	}
 	printf("\n");
 	for (i = 1; i <= row; i++)
 	{
  		printf("%d ", i);
  	for (j = 1; j <= col; j++)
  	{
   		printf("%c ", board[i][j]);
  	}
  	printf("\n");
 	}
 	printf("------------------------\n");
}
void Setmine(char mine[ROWS][COLS], int row, int col)
{
 	int count = Easy_Count;
 	while (count)
 	{
  		int i=rand() % row+1;
  		int j=rand() % col+1;
  		if (mine[i][j] == '0')
  		{
   			mine[i][j] = '1';
   			count--;
  		}
 	}
}
int get_mine(char mine[ROWS][COLS], int x, int y)
{
 	return mine[x - 1][y - 1] +
  	mine[x - 1][y] +
  	mine[x - 1][y + 1] +
  	mine[x][y + 1] +
  	mine[x][y - 1] +
  	mine[x + 1][y - 1] +
  	mine[x + 1][y] +
  	mine[x + 1][y + 1]-8*'0';
}
void OpenMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int x, int y)//展开一片
{
 	int ret = 0;
 	ret = get_mine(mine, x, y);
 	if (ret == 0)
 	{
  		show[x][y] = '0';
  		if (x > 0 && y + 1 <= col && show[x][y + 1] == '*')
   		OpenMine(mine, show, row, col, x, y + 1);
  		if (x - 1 > 0 && y + 1 <= col && show[x - 1][y + 1] == '*')
   		OpenMine(mine, show, row, col, x - 1, y + 1);
  		if (x - 1 > 0 && y > 0 && show[x - 1][y] == '*')
   		OpenMine(mine, show, row, col, x - 1, y);
  		if (x - 1 > 0 && y - 1 > 0 && show[x - 1][y - 1] == '*')
  		OpenMine(mine, show, row, col, x - 1, y - 1);
  		if (x > 0 && y - 1 > 0 && show[x][y - 1] == '*')
   		OpenMine(mine, show, row, col, x, y - 1);
  		if (x + 1 <= row && y - 1 > 0 && show[x + 1][y - 1] == '*')
   		OpenMine(mine, show, row, col, x + 1, y - 1);
  		if (x + 1 <= row && y > 0 && show[x + 1][y] == '*')
   		OpenMine(mine, show, row, col, x + 1, y);
  		if (x + 1 <= row && y + 1 <= col && show[x + 1][y + 1] == '*')
   		OpenMine(mine, show, row, col, x + 1, y + 1);
 	}
 	else
 	{
  		show[x][y] = get_mine(mine, x, y) + '0';
 	}
}
void First_SafeMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)//确保第一个不踩雷
{
 	int x = 0;
 	int y = 0;
 	int ret = 1;
 	int count = 0;
 	printf("请输入要排查的坐标:");
 	scanf_s("%d%d", &x, &y);
 	if (mine[x][y] == '1')//如果为雷,则改为没有雷
 	{
  		mine[x][y] = '0';
  		count = get_mine(mine, x, y);
  		show[x][y] = count + '0';
  		while (ret)//随机生成一个雷
  	{
   		x = rand() % ROW + 1;
   		y = rand() % COL + 1;
   		if (mine[x][y] == '0')
   	{
    		mine[x][y] = '1';
   	}
   	ret--;
  	}
 	}
 	OpenMine(mine, show, row, col, x, y);
 	Displayboard(show, row, col);
}
void Findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
 	int x = 0;
 	int y = 0;
 	int win = 0;
 	while (win < row * col - Easy_Count)
 	{
  		printf("请输入坐标\n");
  		scanf_s("%d%d", &x, &y);
  	if (x >= 1 && x <= row && y >= 1 && y <= col)
  	{
   	if (mine[x][y] == '1')
   	{
    		printf("你被炸死了,游戏结束\n");
    		Displayboard(mine, ROW, COL);
    		break;
   	}
   	else
   	{
    		//统计x,y周围有多少个雷
    		int count = get_mine(mine, x, y);
    		show[x][y] = count + '0';
    		OpenMine(mine, show, row, col, x, y);
    		Displayboard(show, ROW, COL);
    		win++;
	   	}
	 }
  	else
  	{
   	printf("输入的坐标非法,请重新输入!\n");
  	}
 	}
 	if (win == row * col - Easy_Count)
 	{
  		printf("恭喜你,扫雷成功\n");
  		Displayboard(mine, ROW, COL);
 	}
}
test.c
#include"game.h"

void game()
{
 	char mine[ROWS][COLS] = { 0 };
 	char show[ROWS][COLS] = { 0 };
 	//初始化棋盘
 	Initboard(mine, ROWS, COLS, '0');
 	Initboard(show, ROWS, COLS, '*');
 	//打印棋盘
 	/*Displayboard(mine, ROW, COL);*/
 	Displayboard(show, ROW, COL);
 	//布置雷
 	Setmine(mine, ROW, COL);
 	/*Displayboard(mine, ROW, COL);*/

	First_SafeMine(mine, show, ROW, COL);
 	//扫雷
 	Findmine(mine, show, ROW, COL);
 }
 void menu()
{
 	printf("**********************\n");
 	printf("*****   1.play    ****\n");
 	printf("*****   0.exit    ****\n");
 	printf("**********************\n");
}
void test()
{
 	int input = 0;
 	srand((unsigned int)time(NULL));
 	do
 	{
  		menu();
  		scanf_s("%d", &input);
  		switch (input)
  		{
  		case 1:
  		{
   			game();
   			break;
  		}
  		case 0:
  		{
   			printf("退出游戏\n");
   			break;
  		}
  		default:
  		{
   			printf("选择错误,请重新选择!\n");
   			break;
  		}
  	}
 	} while (input);
}
int main()
{
 	test();
 	system("pause");
 	return 0;
}

运行结果

在这里插入图片描述

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

从零出发——

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值