数组应用之扫雷游戏

一、实现的功能

(1)棋盘可改变大小(利用宏实现)
(2)雷的随机生成,可改变大小(利用宏实现)
(3)棋盘可实现展开,展示周围雷的个数(递归实现)
(4)第一次踩雷不死,改变雷的位置

二、效果截图

菜单:
在这里插入图片描述
游戏过程:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
成功:
在这里插入图片描述
失败(小棋盘容易失败):
在这里插入图片描述

三、代码参考

注意点:
有两个数组分别代表给玩家展示的棋盘和雷盘(放雷的棋盘)
当失败是可以展示雷盘给玩家!

棋盘定义时要多定义两行两列,因为在后期扫雷的时候,要判断一个坐标点的周围8个坐标的雷数,当坐标为(1,1)的时候也可以正常扫雷,如图:
在这里插入图片描述
也就是说我们实际用的棋盘大小是内部的

代码参考:
多文件编写,运行环境是VS2013
注释很详细。可以相互学习,如果有错误的地方请提出来。
main.c

#include "sweep.h"

void Menu(){
	printf("********************************\n");
	printf("   1.开始游戏       2.结束游戏  \n");
	printf("           3.游戏帮助           \n");
	printf("********************************\n");
}

int main(){
	int select = 0;

	do{
		Menu();
		printf("请选择:\n");
		scanf("%d", &select);
		switch (select){
		case 1:
			Game();
			break;
		case 2:
			break;
		case 3:
			printf("(1)实现了棋盘改变大小!雷的个数\n(2)第一次下棋不炸死\n(3)棋盘展开\n");
			break;
		default:
			printf("没有这个选项!\n");
			break;
		}
	} while (select != 2);
	system("pause");
	return 0;
}

sweep.h

#ifndef _SWEEP_H_
#define ROW 10
#define COL 10
#define COUNT 5 //雷的个数

#include <stdio.h>
#include <Windows.h>
#include <time.h>
#pragma warning(disable:4996)

void Game();
//埋雷函数
void MineBoard(char board[][COL], int row, int col);
//扫雷,扩展棋盘
void SweepBoard(char board[][COL], char board0[][COL], int x, int y);
//获得雷的数量
char GetMines(char board[][COL], int x, int y);
//转移雷的地放,只有第一次踩到雷采用到
void ChangeBoard(char board[][COL], int x, int y);
//展示棋盘
void ShowBoard(char board[][COL], int x, int y);
//判断是否踩到雷
int Fail(char board[][COL], int x, int y);
//扫描棋盘,判断是否雷已经扫描完毕
int Win(char board[][COL],int row, int col);
#endif

sweep.c

#include "sweep.h"
void Game(){
	//定义一个棋盘(雷盘)
	char board[ROW][COL] = {'0'};
	//定义一个棋盘(玩家盘)
	char board0[ROW][COL] = {'0'};
	int x = 0;
	int y = 0;
	int result = 0;//结果是0,表示玩家没猜踩到雷,否则踩到雷
	//初始化棋盘(这个棋盘是玩家棋盘)
	int first = 1; //判断是否为第一次下棋
	memset(board0, '*', sizeof(board0));
	//千万要初始化雷盘,而且必须全盘初始化
	memset(board, '0', sizeof(board));
	//埋雷
	MineBoard(board, ROW - 2, COL - 2);
	while (1){
		//展示棋盘
		ShowBoard(board0, ROW - 2, COL - 2);
		printf("请输入坐标:(x,y)\n");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= ROW - 2 && y >= 1 && y <= COL - 2){
			//是第一次就挖到雷的话就转移雷的地方
			if (first == 1 && board[x][y] == '1'){
				board[x][y] = '0';
				ChangeBoard(board, x, y);
				first++;
			}
			first = 0;//无论第一次踩没踩到以后踩到就会结束,所以这里改变first
			result = Fail(board, x, y);
			if (1 == result){
				printf("你踩到雷了,游戏结束\n");
				ShowBoard(board, ROW - 2, COL - 2);
				break;
			}
			else{
				SweepBoard(board, board0, x, y);
				//扫描一遍,棋盘判断是否将雷全部扫除
				if (Win(board0,ROW - 2, COL - 2) == 1){
					ShowBoard(board, ROW - 2, COL - 2);
					printf("扫雷小能手!!!你赢了\n");
					break;
				}
				else{
					//空语句
				}
			}
		}
		else{
			printf("你输入的位置有误请重新输入!\n");
		}
	}
}


void MineBoard(char board[][COL], int row, int col){
	srand((unsigned int)time(NULL));
	int x, y;
	int i = 0;
	int j = 0;
	//埋雷前先将棋盘变为白纸
	for (i = 1; i <= row; i++){
		for (j = 1; j <= col; j++){
			board[i][j] = '0';
		}
	}
	//开始埋雷
	for (i = 0; i < COUNT; i++){
		x = rand() % row + 1;
		y = rand() % col + 1;
		if (board[x][y] == '0'){
			board[x][y] = '1'; //1代表有雷,0代表无雷
		}
		else{
			i--; //这个雷不计数,重新生成一次
		}
	}
}

//展开原则:遇到雷就停止开展
void SweepBoard(char board[][COL], char board0[][COL], int x, int y){
	if (board[x][y] == '0' && x >= 1 && x <= (ROW-2) && y >= 1 && y <= (COL-2) && board0[x][y] == '*'){
		board0[x][y] = GetMines(board,x,y);
	}
	if (board[x - 1][y - 1] == '0' && x-1 >= 1 && x-1 <= (ROW - 2) && y-1 >= 1 && y-1 <= (COL - 2) && board0[x - 1][y - 1] == '*'){
		board0[x - 1][y - 1] = GetMines(board, x - 1, y - 1);
		if (GetMines(board, x - 1, y - 1) == '0'){
			SweepBoard(board, board0, x - 1, y - 1);
		}
	}
	if (board[x - 1][y] == '0' && x-1 >= 1 && x-1 <= (ROW - 2) && y >= 1 && y <= (COL - 2) && board0[x - 1][y] == '*'){
		board0[x - 1][y] = GetMines(board, x - 1, y);
		if (GetMines(board, x - 1, y) == '0'){
			SweepBoard(board, board0, x - 1, y);
		}
	}
	if (board[x - 1][y + 1] == '0' && x-1 >= 1 && x-1 <= (ROW - 2) && y+1 >= 1 && y+1 <= (COL - 2) && board0[x - 1][y + 1] == '*'){
		board0[x - 1][y + 1] = GetMines(board, x - 1, y + 1);
		if (GetMines(board, x - 1, y + 1) == '0'){
			SweepBoard(board, board0, x - 1, y + 1);
		}
	}
	if (board[x][y - 1] == '0' && x >= 1 && x <= (ROW - 2) && y-1 >= 1 && y-1 <= (COL - 2) && board0[x][y - 1] == '*'){
		board0[x][y - 1] = GetMines(board, x, y - 1);
		if (GetMines(board, x, y - 1) == '0'){
			SweepBoard(board, board0, x, y - 1);
		}
	}
	if (board[x][y + 1] == '0' && x >= 1 && x <= (ROW - 2) && y+1 >= 1 && y+1 <= (COL - 2) && board0[x][y + 1] == '*'){
		board0[x][y + 1] = GetMines(board, x, y + 1);
		if (GetMines(board, x, y + 1) == '0'){
			SweepBoard(board, board0, x, y + 1);
		}
	}
	if (board[x + 1][y - 1] == '0' && x+1 >= 1 && x+1 <= (ROW - 2) && y-1 >= 1 && y-1 <= (COL - 2) && board0[x + 1][y - 1] == '*'){
		board0[x + 1][y - 1] = GetMines(board, x + 1, y - 1);
		if (GetMines(board, x + 1, y - 1) == '0'){
			SweepBoard(board, board0, x + 1, y - 1);
		}
	}
	if (board[x + 1][y] == '0' && x + 1 >= 1 && x + 1 <= (ROW - 2) && y >= 1 && y <= (COL - 2) && board0[x + 1][y] == '*'){
		board0[x + 1][y] = GetMines(board, x + 1, y);
		if (GetMines(board, x + 1, y) == '0'){
			SweepBoard(board, board0, x + 1, y);
		}
	}
	if (board[x + 1][y + 1] == '0' && x + 1 >= 1 && x + 1 <= (ROW - 2) && y + 1 >= 1 && y + 1 <= (COL - 2) && board0[x + 1][y + 1] == '*'){
		board0[x + 1][y + 1] = GetMines(board, x + 1, y + 1);
		if (GetMines(board, x + 1, y + 1) == '0'){
			SweepBoard(board, board0, x + 1, y + 1);
		}
	}
}

char GetMines(char board[][COL], 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] - 7 * '0';
}
//转移雷
void ChangeBoard(char board[][COL], int x, int y){
	int i = 0;
	int j = 0;
	srand((unsigned int)time(NULL));
	while (1){
		i = rand() % (ROW - 2) + 1;
		j = rand() % (COL - 2) + 1;
		if (board[i][j] == '0' && i != x && j != y){
			board[i][j] = '1';
			break;
		}
	}
}

void ShowBoard(char board[][COL], int row, int col){
	int i = 0;
	int j = 0;
	int i0 = 0;
	//最顶层的线
	for (i = 1; i <= col; i++){
		printf("///", i);
	}
	printf("\n");
	printf("     \\");
	//列坐标提示
	for (i = 1; i <= col; i++){
		if (i >= 10){
			printf("  %d  ", i);
		}
		else{
			printf("   %d  ", i);
		}
	}
	for (i = 1; i <= row; i++){
		printf("\n");
		//行坐标提示
		printf("       ");
		for (i0 = 1; i0 <= col; i0++){
			printf("------", i0);
		}
		printf("\n");
		if (i < 10){
			printf(" ");
		}
		printf("  %d  |", i);
		//打印内容
		for (j = 1; j <= col; j++){
			printf("  %c  |", board[i][j]);
		}
	}
	printf("\n");
	//最底层的线
	for (i = 1; i <= col; i++){
		printf("-------", i);
	}
	printf("\n");
}

//返回1说明踩到雷了,否则继续游戏
int Fail(char board[][COL], int x, int y){
	if (board[x][y] == '1'){
		return 1;
	}
	else{
		return 0;
	}
}

int Win(char board[][COL],int row, int col){
	int i, j;
	int count = 0;
	for (i = 1; i <= row; i++){
		for (j = 1; j <= col; j++){
			if (board[i][j] == '*'){
				count++;
			}
		}
	}
	if (count > COUNT){
		//雷没有扫完,返回0继续游戏
		return 0;
	}
	else{
		//*总不能比雷少吧,只能等于了
		return 1;
	}
}

参考声明:

扫雷扩展棋盘的时候遇到不懂的地方,百度到了一个大佬的博客,参考了一下!
链接:大佬博客

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值