C语言扫雷控制台版

本期介绍的是通过C语言设计一款控制台版的扫雷游戏,相信各位小伙伴都玩过扫雷,扫雷游戏胜利的条件是:翻开所有不是雷的区域,那么就胜利了,而要是翻开了雷的位置,那么游戏就失败了。

一.设计思想

        通过上面所说的条件,接下来就是制作这款游戏的设计思想了。

        1.设计游戏开始的界面,让玩家选择是否要开始游戏。

        2.初始化棋盘,首先我们要确定棋盘的大小。

        3.布置地雷的位置。

        4..打印棋盘,当我们确定好棋盘大小和雷的位置的时候,需要将棋盘打印出来。

        5.开始排雷。

        6.最后玩家排雷的过程中,我们要判断输赢。

以上就是扫雷游戏的主要设计思想,下面我们来进行分布实现。

二.分布实现

        1.游戏实现的3个模块

              

我将代码分成3个模块完成,main.c主要负责实现游戏整体的逻辑思想,game.h负责每个代码实现过程中的函数声明以及各个头文件的引用,game.c负责具体实现每个部分的游戏代码。

        2.设计游戏界面,判断玩家是否开始游戏

                在主函数中,我们使用do while 循环和switch 语句来判断玩家是否要开始游戏,option函数将把游戏选项打印出来。game()函数负责游戏逻辑的实现

void game()
{
	//初始化棋盘
	char arr1[ROWS][COLS] = { 0 };
	char arr2[ROWS][COLS] = { 0 };
	chessboard(arr1,ROWS,COLS,'#');
	chessboard(arr2,ROWS,COLS,'*');
	//打印棋盘
	printboard(arr2, ROW, COL);
	//布置雷
	putland(arr1, ROW, COL, number);
	//开始排雷
	mineremoval(arr1,arr2 ,ROW, COL);
}
//选择是否开始游戏
void option()
{
	printf("<----------------- 扫雷游戏 --------------->\n");
	printf("<<***************************************>>\n");
	printf("  *******  1. << play 开始游戏>	  *******\n");
	printf("  *******  0. << exit 退出游戏>>  *******\n");
	printf("<<***************************************>>\n");

}
int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		option();
		printf("请选择-->:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("开始游戏\n");
			game();
			break;
		case 0:
			printf("退出游戏成功,欢迎下次游玩\n");
			break;
		default:
			printf("选择错误,请选择有效选项\n");
			break;
		}
	} while (input);
	return 0;
}

 3.确定棋盘的大小     

        首先我们创建一个9*9的数组来表示棋盘

        

根据游戏规则,如果翻开的不是雷,那么就会在那个位置上打印周围9个位置上共有几颗雷,可是如果我们这么设计棋盘的大小,那么边上的位置就不能与中间位置的判断方式一样了,那么该怎么解决呢?

        

这个时候,我们将棋盘的大小扩大为 11*11 的大小,这样边上位置就能够与中间位置的判断方式相同了。但是实际上我们还是在 9*9 大小的棋盘上进行游戏。接下来我们在game.h中使用宏定义的方式定义出实际棋盘的大小和地图的大小。

#define ROW 9//实际棋盘的行数
#define COL 9//实际棋盘的列数
#define ROWS ROW+2//地图的行数
#define COLS COL+2//地图的列数

    4.初始化棋盘

        首先我们在game () 函数中定义2个数组,第一个数组用来存放棋盘中的内容,第二个数组则是呈现在玩家面前的棋盘,这样在后续玩家排雷的过程中,就不会出现不必要的冲突。初始化的过程中,我们用字符#代表不是雷,在后续布置地雷的过程中,用¥(shift+4)代表雷。

//在game()中封装函数
void game()
{
	//初始化棋盘
	char arr1[ROWS][COLS] = { 0 };
	char arr2[ROWS][COLS] = { 0 };
	chessboard(arr1,ROWS,COLS,'#');
	chessboard(arr2,ROWS,COLS,'*');
}
//在game.h中声明chessboard()初始化棋盘函数
void chessboard(char board[ROWS][COLS], int row, int col, char ch);//初始化棋盘
//在game.c中实现初始化函数
void chessboard(char board[ROWS][COLS], int row, int col, char ch)//初始化棋盘
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			board[i][j] = ch;
		}
	}

}

   5.  放置地雷

        当我们初始化好棋盘后,我们需要在9*9的实际棋盘中布置地雷,首先我们要确定好地雷的数量,在game.h中,我们用宏定义的方式定义10个雷,并且在布置雷的过程中,雷的位置是随机的,所以这时候我们就要用到随机数生成函数srand和rand,使用这2个函数需要引用#include<time>,但是如果在同一个位置上布置的多个地雷,那还有意义吗?所以我们还需要判断随机数生成的位置是否已经布置过地雷。如果布置过地雷,那么将重新生成随机数。(这些都是在数组1中实现的)下面看看代码

        

//在main.c中的game()函数中封装putland()函数
void game()
{
	//初始化棋盘
	char arr1[ROWS][COLS] = { 0 };
	char arr2[ROWS][COLS] = { 0 };
	chessboard(arr1,ROWS,COLS,'#');
	chessboard(arr2,ROWS,COLS,'*');
    //布置雷
    putland(arr1, ROW, COL, number);
}
//在game.h中声明putland函数
void putland(char board[ROWS][COLS], int row, int col, int count);//放置地雷
//在game.c中实现putland()函数
void putland(char board[ROWS][COLS], int row, int col, int count)//放置地雷

{
	
	while (count)
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (board[x][y] == '#')
			{
				board[x][y] = '@';
				count--;
				
			}
		}
	}


}

6.打印棋盘

        这时候就该打印出棋盘了,上述说到的第二个数组就是我们打印的对象,否则我们打印数组1的话,雷的位置就暴露了,那这个游戏就没有意义了。所以我们打印数组2,数组2中的  字符* 就表示没有被翻开的位置。

        

//在main.c中封装printboard函数
void game()
{
	//初始化棋盘
	char arr1[ROWS][COLS] = { 0 };
	char arr2[ROWS][COLS] = { 0 };
	chessboard(arr1,ROWS,COLS,'#');
	chessboard(arr2,ROWS,COLS,'*');
	//布置雷
	putland(arr1, ROW, COL, number);
    //打印棋盘
	printboard(arr2, ROW, COL);
}

        

//在game.h中声明printboard函数
void printboard(char board[ROWS][COLS], int row, int col);//打印棋盘
//在game.c中实现printboard函数
void printboard(char board[ROWS][COLS], int row, int col)//打印棋盘
{
	printf("--------扫雷-------\n");
	for (int i = 0; i <= col; i++)
	{
		printf("%d ", i);
	}
	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");
	}
	printf("--------扫雷-------\n");
}

7.玩家开始下棋和判断输赢

        接下来就是玩家开始下棋和判断游戏输赢了,玩家输入下棋的坐标,输入坐标后会通过数组1中初始化好的棋盘中判断玩家有没有踩到雷,如果踩到雷,那么游戏结束玩家排雷失败,如果玩家没有踩到雷,那就判断该坐标周围有多少颗雷,最后传给数组2 ,由数组2打印出新的棋盘样式,让玩家继续排雷,如果玩家输入翻开过的坐标,那么就会提示,该位置你已经排过了请重新排雷,如果玩家输入了错误的坐标,则提示输入坐标错误,请重新输入!那么什么时候玩家获胜呢?当棋盘中被翻开的位置数量 等于 棋盘总位置减去雷的数量,那么玩家就获胜了,扫雷成功(被翻开的数量我们用一个变量count记录,每翻开一个不是雷的位置,我们就进行累加,被翻开的数量=9*9 减去雷的数量)接下来看看代码吧

        

//判断输入坐标周围的雷
int findmine(char board[ROWS][COLS], int x, int y)
{
	int count = 0;
	for (int i = x - 1; i <= x + 1; i++)
	{
		for (int j = y - 1; j <= y + 1; j++)
		{
			if (board[i][j] == '@')
			{
				count++;
			}
		}
	}
	return count;
}
//开始排雷
void mineremoval(char board[ROWS][COLS], char board2[ROWS][COLS], int row, int col)
{
	int count = 0;
	while (1)
	{
		int x = 0;
		int y = 0;
		printf("请输入你要排雷的位置-->:");
	a:
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (board[x][y] == '@')
			{
				printf("很遗憾你被炸死了!\n");
				printboard(board, ROW, COL);
				printf("\n");
				printf("\n");
				printf("\n");
				break;
			}
			else
			{
				if (board2[x][y] != '*')
				{
					printf("该位置你已经排过了,请重新排雷-->:");
					goto a;
				}
				else
				{
					int r = findmine(board, x, y);
					board2[x][y] = r + '0';
					system("cls");
					printboard(board2, ROW, COL);
					count++;
					if (count == row * col - number)
					{
						printf("恭喜你,排雷成功!\n");
						printboard(board, ROW, COL);
						break;
					}

				}
			}
		}
		else
		{
			printf("输入坐标错误,请重新输入-->:");
			goto a;
		}
	}

}

最后附上源码

        main.c文件中代码:

        

#define  _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void game()
{
	//初始化棋盘
	char arr1[ROWS][COLS] = { 0 };
	char arr2[ROWS][COLS] = { 0 };
	chessboard(arr1,ROWS,COLS,'#');
	chessboard(arr2,ROWS,COLS,'*');
	//布置雷
	putland(arr1, ROW, COL, number);
	//打印棋盘
	printboard(arr2, ROW, COL);
	//开始排雷
	mineremoval(arr1,arr2 ,ROW, COL);
}

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		option();
		printf("请选择-->:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("开始游戏\n");
			game();
			break;
		case 0:
			printf("退出游戏成功,欢迎下次游玩\n");
			break;
		default:
			printf("选择错误,请选择有效选项\n");
			break;
		}
	} while (input);
	return 0;
}

        game.h文件中的代码

        

#pragma once
#include<stdio.h>
#include<Windows.h>
#include<time.h>
#include<stdlib.h>
#define ROW 9//实际棋盘的行数
#define COL 9//实际棋盘的列数
#define ROWS ROW+2//地图的行数
#define COLS COL+2//地图的列数
#define number 10



//最后设计的时钟



void option();//选择是否开始游戏

void chessboard(char board[ROWS][COLS], int row, int col, char ch);//初始化棋盘

void printboard(char board[ROWS][COLS], int row, int col);//打印棋盘

void putland(char board[ROWS][COLS], int row, int col, int count);//放置地雷

void mineremoval(char board[ROWS][COLS], char board2[ROWS][COLS], int row, int col);//开始排雷

game .c文件中的代码

        

#define  _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
//选择是否开始游戏
void option()
{
	printf("<----------------- 扫雷游戏 --------------->\n");
	printf("<<***************************************>>\n");
	printf("  *******  1. << play 开始游戏>	  *******\n");
	printf("  *******  0. << exit 退出游戏>>  *******\n");
	printf("<<***************************************>>\n");

}
//初始化棋盘
void chessboard(char board[ROWS][COLS], int row, int col, char ch)
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			board[i][j] = ch;
		}
	}

}
//打印棋盘
void printboard(char board[ROWS][COLS], int row, int col)
{
	printf("--------扫雷-------\n");
	for (int i = 0; i <= col; i++)
	{
		printf("%d ", i);
	}
	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");
	}
	printf("--------扫雷-------\n");
}//
//放置地雷
void putland(char board[ROWS][COLS], int row, int col, int count)

{
	
	while (count)
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (board[x][y] == '#')
			{
				board[x][y] = '@';
				count--;
				
			}
		}
	}


}
//开始排雷
void mineremoval(char board[ROWS][COLS], char board2[ROWS][COLS], int row, int col)
{
	int count = 0;
	while (1)
	{
		int x = 0;
		int y = 0;
		printf("请输入你要排雷的位置-->:");
	a:
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (board[x][y] == '@')
			{
				printf("很遗憾你被炸死了!\n");
				printboard(board, ROW, COL);
				printf("\n");
				printf("\n");
				printf("\n");
				break;
			}
			else
			{
				if (board2[x][y] != '*')
				{
					printf("该位置你已经排过了,请重新排雷-->:");
					goto a;
				}
				else
				{
					int r = findmine(board, x, y);
					board2[x][y] = r + '0';
					system("cls");
					printboard(board2, ROW, COL);
					count++;
					if (count == row * col - number)
					{
						printf("恭喜你,排雷成功!\n");
						printboard(board, ROW, COL);
						break;
					}

				}
			}
		}
		else
		{
			printf("输入坐标错误,请重新输入-->:");
			goto a;
		}
	}

}
//判断输入坐标周围的雷
int findmine(char board[ROWS][COLS], int x, int y)
{
	int count = 0;
	for (int i = x - 1; i <= x + 1; i++)
	{
		for (int j = y - 1; j <= y + 1; j++)
		{
			if (board[i][j] == '@')
			{
				count++;
			}
		}
	}
	return count;
}

以上就是本期扫雷控制台版的全部内容,感兴趣的小伙伴可以动手试试哦。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值