C语言之扫雷(普通版)

前言:

        扫雷,在那个联网困难的年代,是我们电脑课消遣必玩游戏之一,今天就让我们来自己写一个扫雷小游戏,玩耍一下吧。有了三子棋的经验,我想写扫雷应该会容易一些,在完成扫雷代码之前我们分析一下,扫雷的实现都需要那些功能,第一,我们需要有个雷场提供我们布置雷;第二我们布置完雷之后,当有玩家进行排雷的时候,选定一个坐标进行排雷的话,如果是雷的话,游戏结束,如果不是雷的话,需要以选定坐标为中心,将周围雷的个数显示出来,以便给玩家提供线索,进一步排雷。为了方便,我们需要有个跟布置雷场坐标一一对应的雷盘用来显示雷场。为了防止在计算雷个数的时候数组越界,定义显示雷场的数组应该比布置雷场多出一圈。如下图所示:

 

初始化雷场
布置雷场
显示雷场
显示雷场

 

 

目录

 一、程序框架

二、游戏函数

初始化函数

声明和定义

实现及调用 

布置雷函数

函数声明及调用

函数的实现 

显示函数

函数声明及调用

函数的实现

排雷函数

函数声明及调用

函数的实现

三、整体代码

四、效果演示


 

 一、程序框架

我们像写三子棋一样,将扫雷的程序也分为三个文件编写,分别为test.c用来调用实现不同功能的子程序,game.c用来实现各个子程序的模块,game.h用来放置各个子程序的的声明和定义,让扫雷的代码看起来逻辑清晰,跟我们小时候玩的任何游戏一样 首先进入一个供我们选择的界面,我们选择是否进入游戏,不同的选择对应不同的结果,所以我们要用到case switch结构,游戏不可能只玩一次 所以我们用到循环结构,因为首先进入选择界面 所以我们使用do while 结构 代码如下:

void menu()
{
	printf("*********************************************\n");
	printf("*************** 1.play **********************\n");
	printf("*************** 0.play **********************\n");
	printf("*********************************************\n");
}
void test()
{
	
	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;
}

二、游戏函数

初始化函数

当我们选择进入游戏之后,首先我们应该看到雷盘,所以第一步我们要定义雷场并初始化,布置雷场和显示雷场我们使用的是二维数组,二维数组的大小,根据我们个人喜好来定,为了方便修改,我们在头文件中预处理,设置一下雷盘大小,为了方便观看,我们将布置雷盘初始化为 0 将显示雷场初始化为*具体代码如下:

声明和定义

  我们前面提到,我们要布置雷初步设定是8个雷,为了方便后期修改 我们 预处理一下,用COUNT代替,而且因为是为了方便统计地雷个数,我们将雷盘大小整体扩大一圈,但是布置雷的的范围只可以在ROW 和COL这个范围内,所以我们定义了两个方便修改的常量,如下面代码所示:

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

#define COUNT 8


#define ROW   9
#define COL   9

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



//初始化雷场景
void init_board(char board[ROWS][COLS], char rows,char cols,char set);

实现及调用 

   为了方便,我们封装了初始化函数,因为不同雷盘初始化样子不一样,所以我们多传了一个参数,简便代码,具体如下:

//初始化雷场景函数

void init_board(char board[ROWS][COLS], char rows, char cols,char set)
{
	for (int i = 0; i < rows; i++)
	{
		for (int j = 0; j < cols; j++)
		{
			board[i][j] = set;
		}
	}
}
	char mine[ROWS][COLS];//定义一个布置雷的雷场
	char show[ROWS][COLS];//定义一个显示雷的雷场
   //进行初始化雷场
  // 将布置的雷场全部初始化为字符0
  // 将显示的雷场景全部初始化为字符*
	init_board(mine, ROWS, COLS, '0');
	init_board(show, ROWS, COLS, '*');

布置雷函数

  我们需要将八个雷放置在任意的地方,布置一个减少一个,所以我们用while循环函数,在二维坐标里就是在不越界的情况下,随意生成坐标,所以我们会用到时间戳函数,保证在雷盘内,我们就模一下横、纵坐标之后 加一,另外,在我们布置雷的的时候,需要判断一下,当前坐标有没有已经布置过雷,没有布置的情况下,我们才可以布置,具体代码如下:

函数声明及调用

//开始布置雷
void set_board(char board[ROWS][COLS], char row, char col);
	//布置雷
	set_board(mine, ROW, COL);


int main()

{
	srand((unsigned int)time(NULL));//整一个时间戳
	 test();

函数的实现 

// 布置雷函数
void set_board(char board[ROWS][COLS], char row, char col)
{
	int count = COUNT;

	while (count)
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1;


		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			count--;
		}
		
	}
		
}

显示函数

我们也需要集成一个显示函数,方便我们布置完雷或者排完雷后,显示到界面上,为了显示时候清楚地看到坐标对应的行列方便,我们先利用for循环,显示一行的坐标序号,然后换行后,在利用两层for循环将每个坐标显示出来,为了方便,每行显示之前,加个列坐标序号,具体实现代码如下:

函数声明及调用

//显示雷场景
void display_board(char board[ROWS][COLS], char row, char col);
	display_board(mine, ROW, COL);
	display_board(show, ROW, COL);

函数的实现

//   显示雷场景函数
void display_board(char board[ROWS][COLS], char row, char col)
{
	printf("************扫雷游戏******************\n");
	for (int j = 0; j <= col; j++)
	{
		printf("%d ",j);
	}
	printf("\n");
	for (int i = 1; i <= row; i++)
	{
		printf("%d ", i );
		for (int j = 1; j <= col; j++)
		{
			
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}


}

初始化完成后,我们将,雷盘打印出来看一下 

 


排雷函数

   我们的目的是把雷场上除了地雷的位置都给挖掘出来,当我们给定一个坐标之后,跟雷场坐标进行比较,如果是雷,那游戏结束,如果不是雷,我们还需要再进一步判断这个坐标有没有被排除过,如果没有,那我们就可以进行周围雷个数的计数了,只有进入计数这一步,雷盘上的总坐标才会减少1,当 厂上的坐标个数和雷的个数相同时候那么我们就赢了。具体实现代码如下:

函数声明及调用

//开始排雷
void get_board(char mine[ROWS][COLS], char show[ROWS][COLS], char row, char col);
	//排雷
	get_board(mine,show, ROW, COL);

函数的实现

需要提的一点是,坐标上显示的是数字字符,所以我们在统计周围雷个数的时候,可以将周围所有的字符数加起来 减去 8 乘以‘0’,这样函数返回的就是数字个数,在加上字符零就又可以显示数字字符例如:

 

排雷函数

// 排雷函数
void get_board(char mine[ROWS][COLS], char show[ROWS][COLS], char row, char col)
{
	int x = 0;
	int y = 0;
	int win = 0;
	while (win < row * col - 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");
				display_board(mine, ROW, COL);
				break;
			}
			else
			{

				int ret = count_mine(mine,x,y);
				show[x][y] = ret + '0';
				display_board(show, ROW, COL);
				win++;
			}
		}
		else
		{
			printf("坐标非法,请重新输入\n");
		}
		if (win == row * col - COUNT)
		{
			printf("恭喜你,通关\n");
			display_board(mine, ROW, COL);
		}
	}

}

统计雷数

//统计这个点周围有几个雷,并显示出来
int count_mine(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');

}

三、整体代码

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"

// ***********************扫雷游戏******************************//
void menu()
{
	printf("*********************************************\n");
	printf("*************** 1.play **********************\n");
	printf("*************** 0.play **********************\n");
	printf("*********************************************\n");
}

void game()
{
	char mine[ROWS][COLS];//定义一个布置雷的雷场
	char show[ROWS][COLS];//定义一个显示雷的雷场
   //进行初始化雷场
  // 将布置的雷场全部初始化为字符0
  // 将显示的雷场景全部初始化为字符*
	init_board(mine, ROWS, COLS, '0');
	init_board(show, ROWS, COLS, '*');

	//将初始化好场景显示出来
	//display_board(mine, ROW, COL);
	//display_board(show, ROW, COL);

	//布置雷
	set_board(mine, ROW, COL);
	display_board(mine, ROW, COL);

	//排雷
	get_board(mine,show, ROW, COL);



}
void test()
{
	
	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()

{
	srand((unsigned int)time(NULL));//整一个时间戳
	 test();

	return 0;
}

game.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "game.h"


//初始化雷场景函数

void init_board(char board[ROWS][COLS], char rows, char cols,char set)
{
	for (int i = 0; i < rows; i++)
	{
		for (int j = 0; j < cols; j++)
		{
			board[i][j] = set;
		}
	}
}
//   显示雷场景函数
void display_board(char board[ROWS][COLS], char row, char col)
{
	printf("************扫雷游戏******************\n");
	for (int j = 0; j <= col; j++)
	{
		printf("%d ",j);
	}
	printf("\n");
	for (int i = 1; i <= row; i++)
	{
		printf("%d ", i );
		for (int j = 1; j <= col; j++)
		{
			
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}


}
// 布置雷函数
void set_board(char board[ROWS][COLS], char row, char col)
{
	int count = COUNT;

	while (count)
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1;


		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			count--;
		}
		
	}
		
}

//统计这个点周围有几个雷,并显示出来
int count_mine(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 get_board(char mine[ROWS][COLS], char show[ROWS][COLS], char row, char col)
{
	int x = 0;
	int y = 0;
	int win = 0;
	while (win < row * col - 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");
				display_board(mine, ROW, COL);
				break;
			}
			else
			{

				int ret = count_mine(mine,x,y);
				show[x][y] = ret + '0';
				display_board(show, ROW, COL);
				win++;
			}
		}
		else
		{
			printf("坐标非法,请重新输入\n");
		}
		if (win == row * col - COUNT)
		{
			printf("恭喜你,通关\n");
			display_board(mine, ROW, COL);
		}
	}

}

game.h

#pragma once

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

#define COUNT 8


#define ROW   9
#define COL   9

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



//初始化雷场景
void init_board(char board[ROWS][COLS], char rows,char cols,char set);
//显示雷场景
void display_board(char board[ROWS][COLS], char row, char col);
//开始布置雷
void set_board(char board[ROWS][COLS], char row, char col);
//开始排雷
void get_board(char mine[ROWS][COLS], char show[ROWS][COLS], char row, char col);

四、效果演示

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值