扫雷游戏(C语言)

本文介绍了如何使用C语言制作一个基础的扫雷游戏,包括创建源文件和头文件、初始化棋盘、打印棋盘、布置雷和排查雷的过程,详细展示了关键代码段和逻辑思路。
摘要由CSDN通过智能技术生成

相信大家都玩过扫雷游戏,本人是一名C语言的初学者,下面用一些简单的C语言做一个简单的扫雷游戏并且做出较为详细的思路以及内容介绍。希望可以帮到大家。

(一)创建源文件和头文件

创建一个头文件用来:

(1)放全局变量;(2)函数声明。

创建两个源文件:

test.c用来整理整体思路;game.c用来填充具体函数。

(二)test.c文件做准备工作

#include<stdio.h>
#include"game.h"
void menu()
{
	printf("*********************\n");
	printf("*******1,play********\n");
	printf("*******0.exit********\n");
	printf("*********************\n");
}
void game()//完成扫雷游戏的整个过程
{

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

此处注意:

 while (input);

此语句解析一下,就是input如果是1或者除零以外的其它数则说明需要重新进入循环,而如果是0则退出循环结束游戏。与上面输入内容相呼应。

(三)初始化棋盘

关键点一:我们要创建一个9*9的棋盘,由格式可以看出,最好的方式是创建二维数组;

char mine[LINES][ROWS] = { 0 };//布置雷的信息
char show[LINES][ROWS] = { 0 };//排查出雷的信息

此时需要在"game.h"头文件中加入全局变量(便于更改棋盘大小)的定义:

#define LINE 9
#define ROW 9

#define LINES LINE+2
#define ROWS ROW+2

关键点二:由扫雷游戏的定义可以看出,我们需要记录布置雷的信息(其中1是雷,0不是雷)和排查四周雷的信息(其中翻出的数字就是四周雷的个数)。因此需要两个棋盘(数组);

关键点三:为避免排查棋盘周边的雷时越界(如图中绿色的一圈)我们选择创建一个大一圈(11*11)的数组用来排查雷。(该图是布置雷的信息)

综上,我们在"game.h"文件中声明函数InitBoard:

//棋盘的初始化
void InitBoard(char board[LINES][ROWS], int lines, int rows, char set);

在"game.c"文件中定义函数InitBoard:

//棋盘的初始化
void InitBoard(char board[LINES][ROWS], int lines, int rows, char set)
{
	int i = 0;
	for (i = 0; i < lines; i++)
	{
		int j = 0;
		for (j = 0; j < rows; j++)
		{
			board[i][j] = set;
		}
	}
}

(四)打印棋盘

在"game.h"文件中声明函数DisplayBoard:

//打印棋盘
void DisplayBoard(char board[LINES][ROWS], int line, int row);

在"game.c"文件中定义函数DisplayBoard:

//打印棋盘
void DisplayBoard(char board[LINES][ROWS], int line, int row)
{
	int i = 0;
	printf("--------扫雷---------\n");
	//打印列号
	for (i = 0; i <= line; i++)
	{
		printf("%d ", i);
    }
	printf("\n"); 
	for (i = 1; i <= line; i++)//注意这里从1开始否则会造成坐标错乱
	{
		int j = 0;
		//打印行号
		printf("%d ", i);
		for (j = 1; j <= row; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
}

此时我们的棋盘长这样:

(五)布置雷

关键点一:使用mine[][]数组;

关键点二:只需要在中间的9*9棋盘内布置所以使用的是LINE和ROW而不是LINES和ROWS。

所以在"test.c"文件中使用函数SetMine:

//布置雷
SetMine(mine, LINE, ROW);

在"game.h"文件中定义EASY_COUNT并且声明函数SetMine:

//便于更改雷的个数
#define EASY_COUNT 10
//布置雷
void SetMine(char board[LINES][ROWS], int line, int row);

在"game.c"文件中定义函数SetMine:

//布置雷
void SetMine(char board[LINES][ROWS], int line, int row)
{
	int count = EASY_COUNT;
	while (count)//确定布置的雷一定是10个
	{
		int x = rand() % line + 1;//定义坐标
		int y = rand() % row + 1;
		if (board[x][y] = '0')//为防止布置的雷和上次重复
		{
			board[x][y] = '1';
			count--;
		}
	}
}

(六)排查雷

使用show[][]数组

在"game.h"文件中声明函数FindMind:

//排查雷
void FindMind(char mine[LINES][ROWS], char show[LINES][ROWS],int line,int row);

在"game.c"文件中定义函数FindMind:

//排查雷
void FindMind(char mine[LINES][ROWS], char show[LINES][ROWS], int line, int row)
{
	int x = 0;
	int y = 0;
	int win = 0;
	while (win<row*line-EASY_COUNT)
	{
		printf("请输入要排查的坐标:");
		scanf_s("%d %d", &x, &y);
		if (x >= 1 && x <= line && y >= 1 && y <= row)//防止输入坐标非法
		{
			if (mine[x][y] == '1')
			{
				printf("很遗憾,你被炸死了\n");
				DisplayBoard(mine, LINE, ROW);
				break;
		    }
			else
			{
				if (show[x][y] != '*')
				{
					printf("该坐标已经被排查过了,无需再排查\n");
				}
				else
				{
					//统计mine数组的下x,y坐标轴为八个坐标中有几个雷
					int count = GetMineCount(mine, x, y);
					show[x][y] = count + '0';
					DisplayBoard(show, LINE, ROW);
					win++;
				}
			}
		}
		else
		{
			printf("输入的坐标非法,请重新输入\n");
		}
	}
	if (win == row * line - EASY_COUNT)
	{
		printf("恭喜你,排雷成功\n");
		DisplayBoard(mine, LINE, ROW);
	}
}

在"test.c"文件中使用函数FindMind:

FindMind(mine, show, LINE, ROW);

(七)排查周围雷的个数

上面(六)使用过函数GetMineCount来排查周围雷的个数,下面我们来定义该函数:

int GetMineCount(char mine[LINES][ROWS], 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';

}

思路:

注意:字符0的ASCll码值为48,ASCII码之差就是对应数字之差,例如"0"的ASCII码值为48,"1"的ASCII码值为49;

8*"0"是中间的字符,mine[x - 1][y]等是周围的字符。

综上,该扫雷游戏的代码为:

头文件game.h:

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define EASY_COUNT 10

#define LINE 9
#define ROW 9

#define LINES LINE+2
#define ROWS ROW+2
//棋盘的初始化
void InitBoard(char board[LINES][ROWS], int lines, int rows, char set);
//打印棋盘
void DisplayBoard(char board[LINES][ROWS], int line, int row);
//布置雷
void SetMine(char board[LINES][ROWS], int line, int row);
//排查雷
void FindMind(char mine[LINES][ROWS], char show[LINES][ROWS],int line,int row);

源文件test.c:

#include<stdio.h>
#include"game.h"
void menu()
{
	printf("*********************\n");
	printf("*******1,play********\n");
	printf("*******0.exit********\n");
	printf("*********************\n");
}
void game()//完成扫雷游戏的整个过程
{
	char mine[LINES][ROWS] = { 0 };//布置雷的信息
	char show[LINES][ROWS] = { 0 };//排查出雷的信息
	//下面初始化棋盘
	InitBoard(mine, LINES, ROWS, '0');
	InitBoard(show, LINES, ROWS, '*');
	//观察代码问题
	//DisplayBoard(show, LINE, ROW);
	//以下是布置雷
	SetMine(mine, LINE, ROW);
	DisplayBoard(show, LINE, ROW);
	//观察代码问题
    //DisplayBoard(mine, LINE, ROW);
	//排查雷
	FindMind(mine, show, LINE, ROW);
}
int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		menu();
		printf("请选择->");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
				break;
		default:
			printf("选择错误,重新选择\n");
			break;
		}
		
	} while (input);
		return 0;
}

源文件game.c:

#include"game.h"
#include<stdio.h>
void InitBoard(char board[LINES][ROWS], int lines, int rows, char set)
{
	int i = 0;
	for (i = 0; i < lines; i++)
	{
		int j = 0;
		for (j = 0; j < rows; j++)
		{
			board[i][j] = set;
		}
	}
}
void DisplayBoard(char board[LINES][ROWS], int line, int row)
{
	int i = 0;
	printf("--------扫雷---------\n");
	//打印列号
	for (i = 0; i <= line; i++)
	{
		printf("%d ", i);
    }
	printf("\n"); 
	for (i = 1; i <= line; i++)
	{
		int j = 0;
		//打印行号
		printf("%d ", i);
		for (j = 1; j <= row; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
}
//布置雷
void SetMine(char board[LINES][ROWS], int line, int row)
{
	int count = EASY_COUNT;
	while (count)
	{
		int x = rand() % line + 1;
		int y = rand() % row + 1;
		if (board[x][y] = '0')
		{
			board[x][y] = '1';
			count--;
		}
	}
}
int GetMineCount(char mine[LINES][ROWS], 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 FindMind(char mine[LINES][ROWS], char show[LINES][ROWS], int line, int row)
{
	int x = 0;
	int y = 0;
	int win = 0;
	while (win<row*line-EASY_COUNT)
	{
		printf("请输入要排查的坐标:");
		scanf_s("%d %d", &x, &y);
		if (x >= 1 && x <= line && y >= 1 && y <= row)
		{
			if (mine[x][y] == '1')
			{
				printf("很遗憾,你被炸死了\n");
				DisplayBoard(mine, LINE, ROW);
				break;
		    }
			else
			{
				if (show[x][y] != '*')
				{
					printf("该坐标已经被排查过了,无需再排查\n");
				}
				else
				{
					//统计mine数组的下x,y坐标轴为八个坐标中有几个雷
					int count = GetMineCount(mine, x, y);
					show[x][y] = count + '0';
					DisplayBoard(show, LINE, ROW);
					win++;
				}
			}
		}
		else
		{
			printf("输入的坐标非法,请重新输入\n");
		}
	}
	if (win == row * line - EASY_COUNT)
	{
		printf("恭喜你,排雷成功\n");
		DisplayBoard(mine, LINE, ROW);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

乐茵.

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

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

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

打赏作者

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

抵扣说明:

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

余额充值