c语言实现初阶版扫雷游戏

一、基本思路

代码由三部分组成:game.h(头文件以及声明函数)、test.c(主函数以及调用game.c中的函数实现扫雷)、game.c(定义扫雷的4个函数)。

要实现扫雷的功能,game.c中应包含以下功能:①初始化棋盘;②打印棋盘;③布置雷;④排查雷及判断输赢;

在test.c中,首先要打印一个菜单供玩家选择,其次玩家在选择后要实现玩游戏或退出游戏。

二、test.c

在编写主函数时,我们想先在屏幕上输出一个菜单,玩家在看到后可以供玩家选择,写一个menu()函数,主函数调用打印菜单。menu函数

void menu()
{
	printf("########################\n");
	printf("###### 1.进入游戏 ######\n");
	printf("###### 0.退出游戏 ######\n");
	printf("########################\n");
}

在打印完菜单后由玩家选择,do while循环实现,内嵌switch。输入1,玩家进入游戏,调用game()函数,game()函数中有4个其他函数,实现扫雷的功能;输入0,退出循环,玩家退出游戏;输入其他数字,提示有误,重新输入。主函数针对第二行srand()放在后面解释):

int main()
{
	srand((unsigned int)time(NULL));
	int n;
	do {
		menu();
		printf("请玩家选择:> ");
		scanf("%d", &n);
		switch (n) {
		case 1:
			game();
			break;
		case 0:
			printf("玩家退出游戏");
			break;
		default:
			printf("玩家选择有误,请重新选择\n");
			break;
		}
	} while (n);
}

 game()函数设计思路:

可以将棋面想象成一个二维数组,放雷的为一个棋面,排查雷信息的为一个棋面,所以先定义两个二维数组,针对二维数组的行与列以及雷的个数,将其定义为常变量,方便对棋面以及游戏难易程度进行改动。在game()中调用了4个函数,先调用InitalBoard()函数初始化棋面,将布置雷的棋面,字符型二维数组赋值为'0';将雷的信息,字符型二维数组赋值为'*';再调用PrintfBoard()函数,打印雷的信息的棋面;再调用SetMine()函数,在布置雷的棋面上设置相应个数的雷;最后调用LookMine()函数,在打印雷信息的棋面上计算对应坐标周围雷的个数,并判断输赢。

void game()
{
	char a[ROWS][COLS];
	char b[ROWS][COLS];
	//初始化棋面
	InitalBoard(a, ROWS, COLS, '0');
	InitalBoard(b, ROWS, COLS, '*');
	//打印棋面
	//PrintfBoard(a, ROW, COL);   //打印布置好雷的棋面
	PrintfBoard(b, ROW, COL);   //打印雷的信息
	//布置雷
	SetMine(a, ROW, COL);
	//PrintfBoard(a, ROW, COL);   //打印布置好雷的棋面
	//排查雷信息
	LookMine(a, b, ROW, COL);
}

三、game.c

在game.c中主要是定义了InitalBoard()、PrintfBoard()、SetMine()、LookMine() 4个函数。

InitalBoard()函数

将棋面想象成二维数组,布置雷的棋面初始化为'0',显示雷信息的棋面初始化为'*',需要注意的是,在排查雷信息时,对于边界处的坐标,在统计时容易数组出界,所以我们初始化的棋面是在打印棋面上增大了一圈,例如:玩游戏的界面是9×9的,但是在初始化的时候是11×11,布置雷是在9×9棋面上,排查雷是在11×11棋面上,打印雷的信息是9×9的棋面。

void InitalBoard(char a[ROWS][COLS], int rows, int cols, char b)
{
	int i, j;
	for (i = 0; i < rows; i++) {
		for (j = 0; j < cols; j++)
			a[i][j] = b;
	}
}

 PrintfBoard()函数:

打印出初始化的雷信息棋面,元素全为'*',且打印出了每行每列的数字。

void PrintfBoard(char a[ROWS][COLS], int row, int col)
{
	printf("------ 棋面 ------\n");
	int i, j;
	for (j = 0; j <= col; j++) {
		printf("%d ", j);
	}
	printf("\n");
	for (i = 1; i <= row; i++) {
		printf("%d ", i);
		for (j = 1; j <= col; j++) {
			printf("%c ", a[i][j]);
		}
		printf("\n");
	}
}

SetMine()函数:

放置Mine个雷,范围为第一个二维数组中第1行到第ROW行,第1列到第COL列,如何在二维数组中随机产生雷?先创建rand()函数可以产生随机值,而在主函数中使用srand((unsigned int)time(NULL))可以保证每次进入游戏产生的随机值不同,为了使产生的随机值在二维数组范围内,可以使用rand()%row+1,产生1到row1之间的数。while循环判断雷的个数是否达到给定个数,在while循环中使用if语句判断是否重复放置雷。

void SetMine(char a[ROWS][COLS], int row, int col)
{
	int i, j;
	int count = 0;
	while (count < Mine) {
		i = rand() % row + 1;   //产生1到row的随机数
		j = rand() % col + 1;   //产生1到col的随机数
		if (a[i][j] == '0') {
			a[i][j] = '1';
			count++;
		}
	}
}

LookMine()函数

布置好雷后,在第一个二维数组中输入坐标,当输入坐标有误时,会要求玩家重新输入坐标。若刚好开中雷,则游戏结束;若没开中雷,则统计其周围一圈8个元素雷的个数,若有雷,则变量count加1,最终将count变量转为字符,填入对应坐标的第二个数组。当统计雷的信息的元素等于二维数组(行×列-雷的个数)时,游戏结束,玩家取得胜利。

void LookMine(char a[ROWS][COLS], char b[ROWS][COLS], int row, int col)
{
	int x, y;
	int count = 0;
	int k = 0;
	while (k < (row * col) - Mine)
	{
		printf("请输入坐标,用空格隔开:");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (a[x][y] == '1')
			{
				printf("很遗憾你开中了雷,游戏结束\n");
				PrintfBoard(a, ROW, COL);
				break;
			}
			else
			{
				int i, j;
				for (i = x - 1; i <= x + 1; i++) {
					for (j = y - 1; j <= y + 1; j++) {
						if (a[i][j] == '1')
							count++;
					}
				}
				b[x][y] = count + '0';
				count = 0;
				k++;
				PrintfBoard(b, ROW, COL);   //打印雷的信息

			}
		}
		else
			printf("输入坐标有误,需重新输入");

	}
	if (k == (row * col) - Mine)
		printf("恭喜你,游戏成功!!!\n");
}

四、game.h 

 game.h中主要放需要用到的头文件以及game.c中4个函数的声明,c语言的标志头文件#include<stdio.h>,调用rand()函数用到头文件#include<stdlib.h>,在主函数srand()函数中调用time()函数,用到头文件#include<time.h>,定义棋盘行数、列数以及雷的个数为常变量,用到头文件#define

#pragma once
#include<stdio.h>
#include <stdlib.h>;
#include <time.h>;
#define COL 9
#define ROW 9
#define COLS COL+1
#define ROWS ROW+1
#define Mine 10
//初始化棋盘函数声明
void InitalBoard(char a[ROWS][COLS], int rows, int cols, char b);
//打印棋盘函数声明
void PrintfBoard(char a[ROWS][COLS], int row, int col);
//布置雷函数声明
void SetMine(char a[ROWS][COLS], int row, int col);
//排查雷信息函数
void LookMine(char a[ROWS][COLS], char b[ROWS][COLS], int row, int col);

五、完整代码

game.h:

#pragma once
#include<stdio.h>
#include <stdlib.h>;
#include <time.h>;
#define COL 9
#define ROW 9
#define COLS COL+1
#define ROWS ROW+1
#define Mine 10
//初始化棋盘函数声明
void InitalBoard(char a[ROWS][COLS], int rows, int cols, char b);
//打印棋盘函数声明
void PrintfBoard(char a[ROWS][COLS], int row, int col);
//布置雷函数声明
void SetMine(char a[ROWS][COLS], int row, int col);
//排查雷信息函数
void LookMine(char a[ROWS][COLS], char b[ROWS][COLS], int row, int col);

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu()
{
	printf("########################\n");
	printf("###### 1.进入游戏 ######\n");
	printf("###### 0.退出游戏 ######\n");
	printf("########################\n");
}
void game()
{
	char a[ROWS][COLS];
	char b[ROWS][COLS];
	//初始化棋面
	InitalBoard(a, ROWS, COLS, '0');
	InitalBoard(b, ROWS, COLS, '*');
	//打印棋面
	//PrintfBoard(a, ROW, COL);   //打印布置好雷的棋面
	PrintfBoard(b, ROW, COL);   //打印雷的信息
	//布置雷
	SetMine(a, ROW, COL);
	//PrintfBoard(a, ROW, COL);   //打印布置好雷的棋面
	//排查雷信息
	LookMine(a, b, ROW, COL);
}
int main()
{
	srand((unsigned int)time(NULL));
	int n;
	do {
		menu();
		printf("请玩家选择:> ");
		scanf("%d", &n);
		switch (n) {
		case 1:
			game();
			break;
		case 0:
			printf("玩家退出游戏");
			break;
		default:
			printf("玩家选择有误,请重新选择\n");
			break;
		}
	} while (n);
}

game.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
//初始化棋盘函数定义
void InitalBoard(char a[ROWS][COLS], int rows, int cols, char b)
{
	int i, j;
	for (i = 0; i < rows; i++) {
		for (j = 0; j < cols; j++)
			a[i][j] = b;
	}
}
//打印棋盘函数定义
void PrintfBoard(char a[ROWS][COLS], int row, int col)
{
	printf("------ 棋面 ------\n");
	int i, j;
	for (j = 0; j <= col; j++) {
		printf("%d ", j);
	}
	printf("\n");
	for (i = 1; i <= row; i++) {
		printf("%d ", i);
		for (j = 1; j <= col; j++) {
			printf("%c ", a[i][j]);
		}
		printf("\n");
	}
}
//放雷函数定义
void SetMine(char a[ROWS][COLS], int row, int col)
{
	int i, j;
	int count = 0;
	while (count < Mine) {
		i = rand() % row + 1;   //产生1到row的随机数
		j = rand() % col + 1;   //产生1到col的随机数
		if (a[i][j] == '0') {
			a[i][j] = '1';
			count++;
		}
	}
}
//排查雷信息函数定义
void LookMine(char a[ROWS][COLS], char b[ROWS][COLS], int row, int col)
{
	int x, y;
	int count = 0;
	int k = 0;
	while (k < (row * col) - Mine)
	{
		printf("请输入坐标,用空格隔开:");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (a[x][y] == '1')
			{
				printf("很遗憾你开中了雷,游戏结束\n");
				PrintfBoard(a, ROW, COL);
				break;
			}
			else
			{
				int i, j;
				for (i = x - 1; i <= x + 1; i++) {
					for (j = y - 1; j <= y + 1; j++) {
						if (a[i][j] == '1')
							count++;
					}
				}
				b[x][y] = count + '0';
				count = 0;
				k++;
				PrintfBoard(b, ROW, COL);   //打印雷的信息

			}
		}
		else
			printf("输入坐标有误,需重新输入");

	}
	if (k == (row * col) - Mine)
		printf("恭喜你,游戏成功!!!\n");
}

六、运行结果 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ambition…

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

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

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

打赏作者

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

抵扣说明:

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

余额充值