C语言小游戏---扫雷

发布于:2022-11-15 ⋅ 阅读:(382) ⋅ 点赞:(0)

目录

1.游戏规则

2.游戏代码的框架

3.游戏函数的一一解析

1。对于一些宏定义,头文件

2.初始化一个棋盘

3.打印棋盘

4.布置雷

5.排雷

1.获得周围的雷的数量

2.主体函数

4.函数主体

1.菜单函数

2.游戏函数

3.test函数

4.main函数

5.代码实现

1.game.h

2.game.c

3.test.c


1.游戏规则


扫雷相信大家都玩过,但是我还是要大概说一下这个游戏的规则。以vs这个运行窗口玩的扫雷,肯定没有正规的软件小程序来的全面,希望大家见谅。就拿简单模式来讲,是一个9*9的方阵内,随机安排10个雷,然后通过对每一个位置的周围一圈的8个位置,判断是否有雷,并将他们的数量统计加起来放在中间的位置。通过不断地推断排雷最终把10个雷排出来。管你听没听懂,看就完啦。

2.游戏代码的框架


  • game.h --- 游戏函数的声明定义
  • test.c  ---  游戏的测试
  • game. c --- 游戏函数的实现

3.游戏函数的一一解析


1。对于一些宏定义,头文件

#include<stdlib.h>
#include<time.h>
这两个头文件是用来生成随机数所必须的。

EASY_COUNT 代表着雷的数量

因为9*9的数组,在边界线的上的数组元素,找他的一周的雷的数量是会出现数组越界的情况,所以需要将数组的行和列设置位11行。

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

#define EASY_COUNT 10

#define ROW 9
#define COL 9

#define ROWS 11
#define COLS 11

2.初始化一个棋盘

初始化棋盘,我们需要初始化两个棋盘,一个给玩家看,一个不给,这样做可以更方便的。mine字符数组代表设置雷区的一个棋盘,show字符数组代表着给玩家展示的棋盘。

这样的一个函数,参数中给到字符数组board,行数列数,还有一个字符。通过for循环将整个数组的元素都赋值set,这个set不同的棋盘给不同的字符。

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;
		}
	}
}

3.打印棋盘

如果直接打印这个9*9的数组的话,会让玩家很难找打要找的位置,所以我们可以给每行每列标上数字,这样可以方便玩家找到需要排雷的位置下标。如图所示的样子。

代码的实现。先打印一行扫雷标志。通过for循环打印第一行的数字提示1-9,然后换行,循环打印每一行的元素,但是在每一行的前面需要打印数字提示,所以打印元素的循环就需要嵌套在内部,因为这个数组的首元素下标是0,二我们给的提示是1,并且玩家输入的也是提示数字,所以for循环需要从下标1开始,循环打印每一个元素,这样就可以打印出一个完整的棋盘,最后也可以再打印扫雷提示的标志。

void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	printf("-------扫雷--------\n");
	for (j = 0; j <= row; j++)
	{
		printf("%d ", j);
	}
	printf("\n");
	for (i = 1; i <= col; i++)
	{
		printf("%d ", i);
		for (j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
	printf("-------扫雷--------\n");
}

4.布置雷

布置雷的思想就是通过生成随机数,作为下标,原本的mine的棋盘是不给玩家展示的,所以可以用1代表有雷,刚开始此棋盘是将所有的位置都赋值0,生成得到的随机下标代表的位置是'0',就可以将其换成'1',直到将10个雷全部布下。

生的随机数%9的话他的余数就是0-8,用它加一就可以得到1-9也就是期盼的下标。通过一个while循环,count的值给到10,每次布置好一颗雷就将这个count减一,直到count等于0的时候,也就说明这个雷已经布置好了。

void SetMine(char mine[ROWS][COLS], int row, int col)
{
	int count = EASY_COUNT;
	while (count)
	{
		int x = rand() % 9 + 1;
		int y = rand() % 9 + 1;
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			count--;
		}
	}
}

5.排雷

1.获得周围的雷的数量

排雷的函数首先需要一个函数来获得周围一圈雷的数量。

这里用一个int 类型的函数,将四周8个位置的元素的字符的ASCII值加起来减去8个'0'的ASCII值,得到的数就是这周围一圈的雷的数量。

int get_mine_count(char mine[ROWS][COLS], int x, int y)
{
	return (mine[x - 1][y] + mine[x - 1][y - 1] + mine[x][y - 1] +
		mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] +
		mine[x][y + 1] + mine[x - 1][y + 1] - 8 * '0');
}

2.主体函数

给到一个整型变量win,while循环的条件是win<9*9-10,先进入循环,输入需要排查的坐标,首先坐标要合理也就是x >= 1 && x <= row &&y >= 1 && y <= col。然后判断show棋盘中的字符,show棋盘的初始化字符是'*',所以当棋盘中是这个字符时就是没有被排查过,然后判断这个字符,如果时'1'的话就是代表此处是雷,那么游戏就结束了,玩家就被炸死了。如果不是的话,那就需要用到上面的get_mine_count这个函数,获得周围一圈的雷的数量,并且将这个值赋给这个位置。最后如果都不是的话那就是输入的坐标错误,会提示输入错误,重新输入,然后再回到之前的while循环入口,不断进行这样的操作,直到while判断条件的值小于等于10,也就是所有的雷都被排除,也就获得了游戏的胜利。

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("输入需要排查的坐标:>");
		scanf("%d%d", &x, &y);
		if (x >= 1 && x <= row &&y >= 1 && y <= col)
		{
			if (show[x][y] != '*')
			{
				printf("该坐标已被排查过\n");
				continue;
			}
			if (mine[x][y] == '1')
			{
				printf("简单模式都能被炸死,没用!!\n");
				DisplayBoard(mine, ROW, COL);
				break;
			}
			else
			{
				int n = get_mine_count(mine, x, y);
				show[x][y] = n + '0';
				DisplayBoard(show, ROW, COL);
				win++;
			}
		}
		else
		{
			printf("输入错误,请重新输入\n");
		}
	}
	if (win == (row * col) - EASY_COUNT)
	{
		printf("恭喜你,扫雷成功!!\n");
		DisplayBoard(mine, ROW, COL);
	}
}

4.函数主体

1.菜单函数

首先给到一个菜单函数,在之前的游戏中都有涉及,就不过多作解释了。

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

2.游戏函数

游戏函数的话就是将之前的函数合理的放在一起,使得游戏能够进行。

代码如下,也很简单,看看就能明白,要注意的各个函数调用的顺序,不然容易出错。

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);
	DisplayBoard(mine, ROW, COL);
	FindMine(mine,show, COL, ROW);
}

3.test函数

test函数就是整个游戏运行的大体思路,将所有的函数相互配合,完成游戏。

首先就是srand函数,来获得随机数。运行后的界面是菜单函数的界面,所以需要输入一个值,后来用do-while语句,它的条件就是输入值为真。while语句内部用的是switch语句,选择0,1中的一个,要么是进行游戏,执行game函数,不然就是输入0退出游戏,当输入1后,并且完成了游戏可以继续此游戏,直到输入0时才会结束。当输入的值不是0也不是1时,就会提示输入错误,需要重新输入。

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

4.main函数

这就是函数主题,就没东西。

int main()
{
	test();
	return 0;
}

5.代码实现

1.game.h

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

#define EASY_COUNT 10

#define ROW 9
#define COL 9

#define ROWS 11
#define COLS 11

//初始化棋盘
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);

2.game.c

#define _CRT_SECURE_NO_WARNINGS 1
#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 (j = 0; j <= row; j++)
	{
		printf("%d ", j);
	}
	printf("\n");
	for (i = 1; i <= col; 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 x = rand() % 9 + 1;
		int y = rand() % 9 + 1;
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			count--;
		}
	}
}
//获得周围一圈雷的数量

int get_mine_count(char mine[ROWS][COLS], int x, int y)
{
	return (mine[x - 1][y] + mine[x - 1][y - 1] + mine[x][y - 1] +
		mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] +
		mine[x][y + 1] + mine[x - 1][y + 1] - 8 * '0');
}

//排雷
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("输入需要排查的坐标:>");
		scanf("%d%d", &x, &y);
		if (x >= 1 && x <= row &&y >= 1 && y <= col)
		{
			if (show[x][y] != '*')
			{
				printf("该坐标已被排查过\n");
				continue;
			}
			if (mine[x][y] == '1')
			{
				printf("简单模式都能被炸死,没用!!\n");
				DisplayBoard(mine, ROW, COL);
				break;
			}
			else
			{
				int n = get_mine_count(mine, x, y);
				show[x][y] = n + '0';
				DisplayBoard(show, ROW, COL);
				win++;
			}
		}
		else
		{
			printf("输入错误,请重新输入\n");
		}
	}
	if (win == (row * col) - EASY_COUNT)
	{
		printf("恭喜你,扫雷成功!!\n");
		DisplayBoard(mine, ROW, COL);
	}
}

3.test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"

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

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);
	DisplayBoard(mine, ROW, COL);
	FindMine(mine,show, COL, ROW);
}

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

以上就是扫雷的全部解析啦。

本文含有隐藏内容,请 开通VIP 后查看