【C语言】实现简易扫雷(仿windows下扫雷)

背景

        个人比较喜欢玩扫雷,恰好又在学习C语言,所以想用自己薄弱的C语言水平实现简单的扫雷小游戏。一来提高自己的编程水平,二来通过编写自己喜欢的游戏,从另一方面获得不一样的成就感。

框架

        实现扫雷不同于我前面写过的三子棋,扫雷的功能更加复杂,更加有逻辑性。

        我首先将我能想到的几个模块都一一列举出来:

               游戏实现函数    菜单    初始化雷区    布置雷区    打印雷区    统计雷区剩余方块    

               无雷方块展开函数    新手保护函数(第一次踩雷不死)

       这里我已将大纲写好, 之后开始编写补充函数内容。

运行效果

                                  

        

        不过想必小伙伴们也看到了,这个小游戏只适合展示,不适合尽情玩耍。(因为实在太费眼睛)

       ( 也请有意改进的小伙伴,关注我接下来对扫雷的完善,我最终会将这个简易版扫雷实现为windows系统下经典扫雷的样式。)

源代码

        下面是我写的代码,如果有不足之处,非常欢迎小伙伴们积极指出。
                        (如果有小伙伴有不懂的地方,欢迎在评论区提问)
       

        头文件

#ifndef __SAOLEI_H__
#define __SAOLEI_H__
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>

#define ROW 10
#define COL 10

void game(void);  //游戏主体

void menu(void);  //菜单

void set_mine(char mine[ROW + 2][COL + 2], int row, int col, int num);  //布雷

int mine_num(char mine[ROW + 2][COL + 2], int x, int y);  //统计某个位置周围雷的个数

int mine_count(char board[ROW + 2][COL + 2], int row, int col);  //统计剩余*的数目

void spread_board(char board[ROW + 2][COL + 2], char mine[ROW + 2][COL + 2], int x, int y);  //展开无雷区

void print_board(char board[ROW + 2][COL + 2], int row, int col);  //打印雷区

void new_help(char mine[ROW + 2][COL + 2], int x, int y);  //新手保护(第一次扫雷不会被炸死)

#endif

        功能函数

#define _CRT_SECURE_NO_WARNINGS

#include "saolei.h"
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>

#define ROW 10
#define COL 10

void print_board(char board[ROW + 2][COL + 2], int row, int col)  //打印雷区
{
	printf("\n");
	int i = 0;
	printf(" 0  1 2 3 4 5 6 7 8 9 10\n");
	for (i = 1; i < (row - 1); i++)
	{
		int j = 0;
		printf("%2d ", i);
		for (j = 1; j < (col - 1); j++)
		{
			printf("%2c", board[i][j]);
		}
		printf("\n");
	}
	printf("\n");
}

int mine_count(char board[ROW + 2][COL + 2], int row, int col)  //统计剩余*的数目
{
	int count = 0;
	for (int i = 1; i < (row - 1); i++)
	{
		for (int j = 1; j < (col - 1); j++)
		{
			if (board[i][j] == '*')
				count++;
		}
	}
	return count;
}

int mine_num(char mine[ROW + 2][COL + 2], int x, int y)  //统计某个位置周围雷的个数
{
	return ((mine[x - 1][y - 1] - '0') + (mine[x - 1][y] - '0')
		+ (mine[x - 1][y + 1] - '0') + (mine[x][y + 1] - '0')
		+ (mine[x + 1][y + 1] - '0') + (mine[x + 1][y] - '0')
		+ (mine[x + 1][y - 1] - '0') + (mine[x][y - 1] - '0'));
}


void spread_board(char board[ROW + 2][COL + 2], char mine[ROW + 2][COL + 2], int x, int y)  //展开无雷区
{
	if ((1 <= x && x <= 10) && (1 <= y && y <= 10) && (mine[x][y] != '1') && (board[x][y] == '*'))
	{
		if (mine_num(mine, x, y) > 0)
		{
			board[x][y] = mine_num(mine, x, y) + '0';
		}
		else
		{
			board[x][y] = ' ';
			spread_board(board, mine, x - 1, y - 1);
			spread_board(board, mine, x - 1, y);
			spread_board(board, mine, x - 1, y + 1);
			spread_board(board, mine, x, y + 1);
			spread_board(board, mine, x + 1, y + 1);
			spread_board(board, mine, x + 1, y);
			spread_board(board, mine, x + 1, y - 1);
			spread_board(board, mine, x, y - 1);
		}
	}
}

void set_mine(char mine[ROW + 2][COL + 2], int row, int col, int num)  //布雷
{
	int i = 0;
	srand((unsigned)time(NULL));
	for (i = 0; i < num; i++)
	{
		int x = rand() % (row - 2) + 1;
		int y = rand() % (col - 2) + 1;
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
		}
		else
		{
			i--;
		}
	}
}

void new_help(char mine[ROW+2][COL+2], char board[ROW+2][COL+2])  //新手保护(第一次扫雷不会被炸死)
{
	int x = 0;
	int y = 0;

	srand((unsigned)time(NULL));
	
	while (1)
	{ 
		//输入排雷坐标(同时判断坐标合法性)
		printf("请输入坐标(X,Y):>");
		scanf("%d,%d", &x, &y);

		if ((1 <= x && x <= 10) && (1 <= y && y <= 10))
		{
			if (mine[x][y] == '1')
			{
				mine[x][y] = '0';
				while (1)
				{
					int m = rand() % ROW + 1;
					int n = rand() % COL + 1;
					if ((m != x) && (n != y) && (mine[m][n] == '0'))
					{
						mine[m][n] = '1';
						spread_board(board, mine, x, y);
						print_board(board, (ROW + 2), (COL + 2));
						break;
					}
				}
			}
			else
			{
				spread_board(board, mine, x, y);
				print_board(board, (ROW + 2), (COL + 2));
			}
			break;
		}
		else
		{
			printf("你输入的坐标可能指向其他星系。\n\n");
		}
	}
}

void menu(void)  //菜单
{
	printf("*********************\n");
	printf("**   1.开始游戏    **\n");
	printf("**   0.退出游戏    **\n");
	printf("*********************\n");
	printf("请选择要进行的动作:>");
}

void game(void)  //游戏主体
{
	int x = 0;
	int y = 0;
	int count = 0;  //定义剩余雷数
	int num = 0;
	//定义雷区,迷雾区
	char mine[ROW + 2][COL + 2];
	char board[ROW + 2][COL + 2];

	//初始化雷区,迷雾区
	memset(mine, '0', sizeof(mine));
	memset(board, '*', sizeof(board));
	//布雷
	printf("请输入地雷数(建议10~30) : >");
	scanf("%d", &num);
	set_mine(mine, (ROW + 2), (COL + 2), num);
	//打印迷雾区
	print_board(board, (ROW + 2), (COL + 2));
	//新手保护
	new_help(mine, board);

	while (1)
	{
		//判断是否胜利
		count = mine_count(board, (ROW + 2), (COL + 2));
		if (count == num)
		{
			printf("恭喜你,你成功的排掉了所有雷!\n\n");
			break;
		}
		//输入排雷坐标(同时判断坐标合法性)
		printf("请输入坐标(X,Y):>");
		scanf("%d,%d", &x, &y);

		if ((1 <= x && x <= 10) && (1 <= y && y <= 10))
		{
			if (mine[x][y] == '1')
			{
				printf("哦!你踩到雷了,再接再厉吧!!!\n\n");
				break;
			}
			else
			{
				spread_board(board, mine, x, y);
				print_board(board, (ROW + 2), (COL + 2));
			}
		}
		else
		{
			printf("你输入的坐标可能指向其他星系。\n");
		}
	}
}

        主体函数

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include "saolei.h"


int main()
{
	int input = 0;
	do
	{
		menu();
		scanf("%d", &input);
		switch (input)
		{
		case 1: game();
			break;
		case 0: printf("\n退出游戏。\n\n");
			break;
		default: printf("\n输入错误!\n\n请重新输入。\n\n");
			break;
		}
	} while (input);
	return 0;
}





猜你喜欢

转载自blog.csdn.net/qq_41866437/article/details/79974365