IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> C语言实现扫雷小游戏(初级版) -> 正文阅读

[游戏开发]C语言实现扫雷小游戏(初级版)

C语言实现扫雷小游戏

勤奋出天才,实践出真知。因此,为了检验自己最近一段时间的学习成果,今天用C语言实现了一个初级版的扫雷小游戏。

成果展示

哈哈,话不多说,先展示一下我的成果!!!

********************************
************ 1. play ***********
************ 0. exit ***********
********************************
请输入您的选择>:1
0  | 1   2   3   4   5   6   7   8   9
---------------------------------------
1  | * | * | * | * | * | * | * | * | *
   |---|---|---|---|---|---|---|---|---
2  | * | * | * | * | * | * | * | * | *
   |---|---|---|---|---|---|---|---|---
3  | * | * | * | * | * | * | * | * | *
   |---|---|---|---|---|---|---|---|---
4  | * | * | * | * | * | * | * | * | *
   |---|---|---|---|---|---|---|---|---
5  | * | * | * | * | * | * | * | * | *
   |---|---|---|---|---|---|---|---|---
6  | * | * | * | * | * | * | * | * | *
   |---|---|---|---|---|---|---|---|---
7  | * | * | * | * | * | * | * | * | *
   |---|---|---|---|---|---|---|---|---
8  | * | * | * | * | * | * | * | * | *
   |---|---|---|---|---|---|---|---|---
9  | * | * | * | * | * | * | * | * | *


请输入你要排查的坐标:>1 1
0  | 1   2   3   4   5   6   7   8   9
---------------------------------------
1  | 1 | * | * | * | * | * | * | * | *
   |---|---|---|---|---|---|---|---|---
2  | * | * | * | * | * | * | * | * | *
   |---|---|---|---|---|---|---|---|---
3  | * | * | * | * | * | * | * | * | *
   |---|---|---|---|---|---|---|---|---
4  | * | * | * | * | * | * | * | * | *
   |---|---|---|---|---|---|---|---|---
5  | * | * | * | * | * | * | * | * | *
   |---|---|---|---|---|---|---|---|---
6  | * | * | * | * | * | * | * | * | *
   |---|---|---|---|---|---|---|---|---
7  | * | * | * | * | * | * | * | * | *
   |---|---|---|---|---|---|---|---|---
8  | * | * | * | * | * | * | * | * | *
   |---|---|---|---|---|---|---|---|---
9  | * | * | * | * | * | * | * | * | *

请输入你要排查的坐标:>5 1
0  | 1   2   3   4   5   6   7   8   9
---------------------------------------
1  | 1 | 1 |   |   |   |   |   | 1 | *
   |---|---|---|---|---|---|---|---|---
2  | * | 1 |   |   |   | 1 | 1 | 2 | *
   |---|---|---|---|---|---|---|---|---
3  | 1 | 1 |   |   |   | 1 | * | * | *
   |---|---|---|---|---|---|---|---|---
4  |   |   |   |   |   | 1 | 2 | * | *
   |---|---|---|---|---|---|---|---|---
5  |   | 1 | 2 | 2 | 1 |   | 2 | * | *
   |---|---|---|---|---|---|---|---|---
6  |   | 1 | * | * | 1 |   | 2 | * | *
   |---|---|---|---|---|---|---|---|---
7  | 1 | 2 | * | 2 | 1 |   | 1 | 1 | 1
   |---|---|---|---|---|---|---|---|---
8  | * | * | * | 1 |   |   |   |   |
   |---|---|---|---|---|---|---|---|---
9  | * | * | * | 1 |   |   |   |   |

请输入你要排查的坐标:>2 1
很遗憾,您被炸死了!
0  | 1   2   3   4   5   6   7   8   9
---------------------------------------
1  | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
   |---|---|---|---|---|---|---|---|---
2  | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1
   |---|---|---|---|---|---|---|---|---
3  | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0
   |---|---|---|---|---|---|---|---|---
4  | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
   |---|---|---|---|---|---|---|---|---
5  | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0
   |---|---|---|---|---|---|---|---|---
6  | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 0
   |---|---|---|---|---|---|---|---|---
7  | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
   |---|---|---|---|---|---|---|---|---
8  | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0
   |---|---|---|---|---|---|---|---|---
9  | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0

********************************
************ 1. play ***********
************ 0. exit ***********
********************************
请输入您的选择>:0
退出游戏
请按任意键继续. . .

实现功能介绍

玩过扫雷的小伙伴都知道,我们的任务是找出所有没有地雷的方格,才算完成游戏。要扫雷,首先我们得先有一个雷盘用来存放我们的地雷,扫雷时如果该格子周围八个格子都没有雷,该格子就会被清空;踩到雷,游戏结束。整理好思路以后,我们就开始实现。

  1. 创建雷盘
  2. 初始化雷盘
  3. 打印雷盘
  4. 随机布置10颗雷
  5. 第一次排雷时不会被炸死
  6. 展开式排雷

功能实现

今天我们依旧采取多文件形式来进行实现。
vs2013创建一个新的工程文件,里面包含头文件 game.h,test.c,game.c三个文件。

头文件game.h

game.h包含了:库函数头文件的引用,宏定义的常量,以及功能函数的声明。

#ifndef __GAME_H__
#define __GAME_H__

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

#define ROW  9
#define COL  9

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

#define MINE_COUNT 10 //炸弹个数

//初始化雷盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char ch);

//打印雷盘信息
void PrintBoard(char board[ROWS][COLS], int row, int col);

//布置雷
void SetMine(char board[ROWS][COLS], int row, int col);

//排雷
void SearchMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

#endif

源文件 test.c

用来测试游戏的。
游戏菜单的实现,让玩家通过菜单选择进入或者退出游戏。

#include "game.h"

void menu()
{
	printf("********************************\n");
	printf("************ 1. play ***********\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,'*');//初始化存放排查出来的雷的棋盘信息

	PrintBoard(show, ROW, COL);//打印棋盘信息
	//布置雷
	SetMine(mine, ROW, COL);

	//排雷
	SearchMine(mine,show,ROW,COL);
}
int main(void)
{
	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);
	return 0;
}

源文件game.c

这个文件里面是各个游戏功能函数的实现。

  1. 创建雷盘

由于雷的位置和排查出来的雷的信息需要分开统计,因此这里我们选择两个二维数组作为棋盘;棋盘大小设计为9X9,如图箭头所指的红格子所示。在这里插入图片描述
如果棋盘大小设计为9X9,后期我们在统计一些边上和角落的棋子周围的雷的个数时,会比较麻烦,因此我们让棋盘大上一圈,选择用11X11的棋盘,但是我们只用其中9x9的格子,用来布置雷。
在这里插入图片描述

char mine[ROWS][COLS] = { 0 };//用来存放雷的位置
char show[ROWS][COLS] = { 0 };//用来存放排查出来的雷的信息
  1. 初始化棋盘

我们知道数组mine用来存放雷的位置,用字符‘1’表示该位置为雷,用字符‘0’表示该位置非雷。因此初始化mine数组时,数组元素全部置为‘1’,表示还没有布置雷。
为了给玩家保留一点神秘感,show数组全部初始化为‘*’。

//初始化数组
void InitBoard(char board[ROWS][COLS], int rows, int cols, char ch)
{
	int i = 0;
	for (i = 0; i < rows; i++)
	{
		int j = 0;
		for (j = 0; j < cols; j++)
		{
			board[i][j] = ch;
		}
	}
}
  1. 打印雷盘

为了让玩家在屏幕上看到这个雷盘,因此这里封装了了一个打印函数。

void PrintBoard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	//列号打印
	for (i = 0; i < row + 1; i++)
	{
		if (i == 0)
		{
			printf(" %d |", i);
		}
		else
		{
			printf(" %d  ", i);
		}
	}
	printf("\n");
	printf("---------------------------------------\n");

	for (i = 1; i < row + 1; i++)
	{
		int j = 0;
		printf(" %d |", i);//行号打印
		for (j = 1; j < col + 1; j++)
		{
			printf(" %c ", board[i][j]);
			if (j < col)
			{
				printf("|");
			}
		}
		printf("\n");
		if (i < row)
		{
			printf("   |");
			for (j = 1; j < col + 1; j++)
			{
				printf("---");
				if (j < col)
				{
					printf("|");
				}
			}
			printf("\n");
		}
	}
	printf("\n");
}

打印到屏幕上的效果大概就是下面这个样子:

  1. 打印雷盘

雷用字符‘1’表示,布置在中间9X9的格子里。

void SetMine(char board[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int count = MINE_COUNT;//布置的雷的个数
	while (count)
	{
		x = rand() % row + 1;//随机行号范围1~row
		y = rand() % col + 1;//随机列号范围1~col
		//判断这个位置有没有雷
		if (board[x][y] != '1')
		{
			board[x][y] = '1';//布置雷
			count--;
		}
	}
	printf("\n");
}

布置完成以后,我们这里打印一下雷盘,大致看一下雷的分布情况:

  1. .扫雷

玩家输入一个坐标,如果是雷(为了增加游戏的可玩性,如果玩家第一次踩到雷了,我们把雷移走,在雷盘上重新找个非雷的位置,把雷布置在那里。
),游戏结束;如果不是雷,展开一片。游戏继续,直所有非雷的位置全部排完。

int ConutMine(char show[ROWS][COLS], int row, int col)
{
	int count = 0;
	int i = 0;
	for (i = 1; i <= row; i++)
	{
		int j = 0;
		for (j = 1; j <= col; j++)
		{
			if (show[i][j] == '*')
			{
				count++;
			}
		}
	}
	return count;
}

void SearchMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int i = 1;//表示第一次排雷
	int count = ConutMine(show,row,col);//还有多少个位置没有排
	while (count != MINE_COUNT)
	{
		printf("请输入你要排查的坐标:>");
		scanf("%d%d", &x, &y);
		if ((x > 0 && x < 10) && (y > 0 && y < 10))//判断玩家输入坐标合法性
		{
			if (mine[x][y] == '1')//踩到雷
			{
				if (i == 1)//表示第一次排雷不被炸死
				{
					mine[x][y] = '0';
					x = rand() % row + 1;
					y = rand() % col + 1;
					while (1)
					{
						x = rand() % row + 1;
						y = rand() % col + 1;
						if (mine[x][y] != '1')
						{
							mine[x][y] = '1';
							break;
						}
					}
					Spread(mine, show, x, y);
					PrintBoard(show, ROW, COL);//打印棋盘信息
					count = ConutMine(show, row, col);
				}
				else
				{
					printf("很遗憾,您被炸死了!\n");
					PrintBoard(mine, ROW, COL);
					break;
				}
			}
			else
			{
				Spread(mine,show,x,y);//展开式排雷
				PrintBoard(show, ROW, COL);//打印棋盘信息
				count = ConutMine(show, row, col);
			}
			i = 2;//至少排雷一次
		}
		else
		{
			printf("您输入的坐标不合法,请重新输入你要排查的坐标!\n");
		}
	}
	if (count == MINE_COUNT)
	{
		printf("恭喜您,排雷成功!\n");
	}
}

注:当游戏中排到一个周围一圈都无雷的位置时,运用递归,实现扩展展开周围的一片无雷区。

//排查该坐标附近雷的个数
int MineCount(char board[ROWS][COLS], int x, int y)
{
	return (board[x - 1][y - 1] + board[x - 1][y] + board[x - 1][y + 1] + 
			board[x][y - 1] + board[x][y + 1] + board[x + 1][y - 1] + 
			board[x + 1][y] + board[x + 1][y + 1] - 8 * '0');
}

void Spread(char mine[ROWS][COLS], char show[ROWS][COLS],int x, int y)
{
	int count_number = MineCount(mine, x, y);//排查该坐标附近雷的个数
	if (count_number == 0)
	{
		show[x][y] = ' ';
		if ((x - 1 > 0 && x - 1 < 10) && (y - 1 > 0 && y - 1 < 10) && show[x - 1][y - 1] == '*')
		{
			Spread(mine, show, x - 1, y - 1);
		}
		if ((x - 1 > 0 && x - 1 < 10) && (y  > 0 && y < 10) && show[x - 1][y] == '*')
		{
			Spread(mine, show, x - 1, y );
		}
		if ((x - 1 > 0 && x - 1 < 10) && (y + 1 > 0 && y + 1 < 10) && show[x - 1][y + 1] == '*')
		{
			Spread(mine, show, x - 1, y + 1);
		}
		if ((x  > 0 && x < 10) && (y - 1 > 0 && y - 1 < 10) && show[x][y - 1] == '*')
		{
			Spread(mine, show, x , y - 1);
		}
		if ((x > 0 && x < 10) && (y + 1 > 0 && y + 1 < 10) && show[x][y + 1] == '*')
		{
			Spread(mine, show, x, y + 1);
		}
		if ((x + 1 > 0 && x + 1 < 10) && (y - 1 > 0 && y - 1 < 10) && show[x + 1][y - 1] == '*')
		{
			Spread(mine, show, x + 1, y - 1);
		}
		if ((x + 1 > 0 && x + 1 < 10) && (y > 0 && y < 10) && show[x + 1][y] == '*')
		{
			Spread(mine, show, x + 1, y);
		}
		if ((x + 1 > 0 && x + 1 < 10) && (y + 1 > 0 && y + 1 < 10) && show[x + 1][y + 1] == '*')
		{
			Spread(mine, show, x + 1, y + 1);
		}
	}
	else
	{
		show[x][y] = count_number + '0';
	}
}

写在后面

以上程序还有很多可以完善的地方,比如增加计时功能,标记雷的位置的功能等,这些问题等到日后学习到了更多知识以后再来完善它。至此这篇关于C语言实现扫雷小游戏的文章到这里就告一段落了。

若本篇内容对您有所帮助,请三连点赞,关注,收藏支持下。

创作不易,白嫖不好,各位的支持和认可,就是我创作的最大动力,我们下篇文章见!

如果本篇博客有任何错误,请批评指教,不胜感激 !

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2021-08-05 17:40:59  更:2021-08-05 17:41:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/6 8:26:24-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码