C语言实现扫雷-遍地开花版!

目录

一、怎么实现?

二、game()主体的构建

三、重点在判输赢!

        判赢函数

四、总体代码


一、怎么实现?

        游戏大体框架构建->菜单、游戏主体->游戏主体用什么实现?->两个数组->一个显示(玩家所见)另外一个用来储存数据(存雷以及数据处理)->看玩家的选择错误与否->提示->主体需要一个循环来实现菜单以及游戏主体的显示->大体框架确认完毕。


void menu()//菜单
{
	printf("--------------------\n");
	printf("|******************|\n");
	printf("|***** 1.play *****|\n");
	printf("|***** 0.exit *****|\n");
	printf("|******************|\n");
	printf("--------------------\n");
}

void game()//游戏本体
{
	char mine[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };
	Initboard(mine, ROWS, COLS,'0');
	Initboard(show, ROWS, COLS, '*');
	Getmine(mine, MINE);
	//Showboard(mine, ROW, COL);
	printf("--------------------\n");
	Showboard(show, ROW, COL);
	win(mine, show, ROW, COL);
}

int main()
{
	srand((unsigned int)time(NULL));
	int input = 0;
	do
	{
		menu();
		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()主体的构建

        构建大体框架->需要什么功能?->初始化->种地雷->查地雷->得到地雷数量的数据->判输赢条件。每次操作都需要判断是否踩到地雷->因此不如初始化存地雷数据的数组为‘1’和‘0’,‘1’代表雷‘0’代表没雷。大体确认完毕

代码如下:


void Initboard(char board[ROWS][COLS],int rows,int cols,char a)//初始化数组为a
{
	for (int i = 0; i < rows; i++)
	{
		for (int j = 0; j < cols; j++)
		{
			board[i][j] = a;
		}
	}
}

void Showboard(char board[ROWS][COLS], int row, int col)//打印扫雷的游戏棋盘
{
	for (int i = 0; i <= col; i++)
	{
		printf("%d ", i);
	}
	printf("\n ———————————————————\n");
	for (int i = 1; i <= row; i++)
	{
		printf("%d|", i);
		for (int j = 1; j <= col; j++)
		{
			if(j!=col)
			printf("%c ", board[i][j]);
			else
				printf("%c|", board[i][j]);

		}
		printf("\n");
	}
	printf(" ———————————————————\n");
}

void Getmine(char board[ROWS][COLS], int mine)//种地雷,种的数量为mine
{
	int count = 0;
	while (count < mine)
	{
		int x = rand() % 9 + 1;
		int y = rand() % 9 + 1;
		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			count++;
		}
	}
}

int Countmine(char board[ROWS][COLS], int row, int col)//数周围的地雷数量
{
	return (board[row - 1][col] + board[row-1][col-1] + board[row][col-1] + board[row+1][col-1] + board[row+1][col] +
		board[row+1][col+1] + board[row][col+1] + board[row-1][col+1] - '0'*8 );
}

void flower(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int* count)//递归查询周围地雷实现地雷游戏的遍地开花
{
	if (row > 0 && row < ROWS && col>0 && col < COLS)//使数组不越距
	{
		if (show[row][col] == '*')//递归结束条件
		{
			if (Countmine(mine, row, col)  == 0)//周围都空遍地开花
			{
				show[row][col] = ' ';//使其显示为空格
				(*count)--;
				flower(mine, show, row - 1, col, count);
				flower(mine, show, row - 1, col - 1, count);
				flower(mine, show, row, col - 1, count);
				flower(mine, show, row + 1, col - 1, count);
				flower(mine, show, row + 1, col, count);
				flower(mine, show, row + 1, col + 1, count);
				flower(mine, show, row, col + 1, count);
				flower(mine, show, row - 1, col + 1, count);
			}
			else//周围不是全空则标出周围地雷数量
			{
				show[row][col] = Countmine(mine, row, col) + '0';
				(*count)--;
			}
		}
	}
	
}

void change(char mine[ROWS][COLS], int row, int col)//就是为了好看点^_^用来游戏结尾显示地雷
{
	for (int i = 1; i <= row; i++)
	{
		for (int j = 1; j <= col; j++)
		{
			if (mine[i][j] == '1')
				mine[i][j] = '$';
		}
	}
}

void win(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)//判断输赢
{
	int a = 0, b = 0;
	int move = 81 - MINE;
	while (move != 0)
	{
		printf("输入扫雷位置(空格隔开):");
		scanf("%d %d", &a, &b);
		if (a >= 1 && a <= row && b >= 1 && b <= col&&show[a][b]=='*')//使数组不越距并且防止选同样的位置
		{
			if (mine[a][b] == '1')
			{
				system("cls");//清屏为了好看
				change(mine, ROW, COL);
				printf("你被炸4了!\n");
				Showboard(mine, row, col);
				break;
			}
			else
			{
					flower(mine, show, a, b, &move);
					system("cls");
					Showboard(show, row, col);
			}
		}
		else
		{
			printf("输入错误!请重新输入! ");
		}
	}
	if (move == 0)
	{
		system("cls");
		printf("恭喜你!扫完了全部雷!\n");
		change(mine, ROW, COL);
		Showboard(mine, row, col);
	}

}

三、重点在判输赢!

        怎么算赢?主要在于玩家扫完所有雷,因此需要定义一个变量move来实现计数,move一开始的数量为9X9-地雷数量,玩家每动一步便-1直到为0跳出循环。重点在于遍地开花(选中的坐标包括周围共8个空位没有地雷)每找到一个就让他为空格,这也算是玩家动作也需让move-1;每多出来一个空以及标明附近地雷数量都要让move-1。

        遍历递归函数

void flower(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int* count)//递归查询周围地雷实现地雷游戏的遍地开花
{
	if (row > 0 && row < ROWS && col>0 && col < COLS)//使数组不越距
	{
		if (show[row][col] == '*')//递归结束条件
		{
			if (Countmine(mine, row, col)  == 0)//周围都空遍地开花
			{
				show[row][col] = ' ';//使其显示为空格
				(*count)--;
				flower(mine, show, row - 1, col, count);
				flower(mine, show, row - 1, col - 1, count);
				flower(mine, show, row, col - 1, count);
				flower(mine, show, row + 1, col - 1, count);
				flower(mine, show, row + 1, col, count);
				flower(mine, show, row + 1, col + 1, count);
				flower(mine, show, row, col + 1, count);
				flower(mine, show, row - 1, col + 1, count);
			}
			else//周围不是全空则标出周围地雷数量
			{
				show[row][col] = Countmine(mine, row, col) + '0';
				(*count)--;
			}
		}
	}
	
}

        判赢函数

void win(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)//判断输赢
{
	int a = 0, b = 0;
	int move = 81 - MINE;
	while (move != 0)
	{
		printf("输入扫雷位置(空格隔开):");
		scanf("%d %d", &a, &b);
		if (a >= 1 && a <= row && b >= 1 && b <= col&&show[a][b]=='*')//使数组不越距并且防止选同样的位置
		{
			if (mine[a][b] == '1')
			{
				system("cls");//清屏为了好看
				change(mine, ROW, COL);
				printf("你被炸4了!\n");
				Showboard(mine, row, col);
				break;
			}
			else
			{
					flower(mine, show, a, b, &move);
					system("cls");
					Showboard(show, row, col);
			}
		}
		else
		{
			printf("输入错误!请重新输入! ");
		}
	}
	if (move == 0)
	{
		system("cls");
		printf("恭喜你!扫完了全部雷!\n");
		change(mine, ROW, COL);
		Showboard(mine, row, col);
	}

}

四、总体代码

game.h

#pragma once

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

#define ROW 9
#define COL 9
#define MINE 10

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

void Initboard(char board[ROWS][COLS], int rows, int cols, char a);//初始化

void Showboard(char board[ROW][COL], int row, int col);//打印

void Getmine(char board[ROWS][COLS],int mine);//种地雷

void win(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);//判赢

game.c

#define _CRT_SECURE_NO_WARNINGS 01

#include"game.h"


void Initboard(char board[ROWS][COLS],int rows,int cols,char a)//初始化数组为a
{
	for (int i = 0; i < rows; i++)
	{
		for (int j = 0; j < cols; j++)
		{
			board[i][j] = a;
		}
	}
}

void Showboard(char board[ROWS][COLS], int row, int col)//打印扫雷的游戏棋盘
{
	for (int i = 0; i <= col; i++)
	{
		printf("%d ", i);
	}
	printf("\n ———————————————————\n");
	for (int i = 1; i <= row; i++)
	{
		printf("%d|", i);
		for (int j = 1; j <= col; j++)
		{
			if(j!=col)
			printf("%c ", board[i][j]);
			else
				printf("%c|", board[i][j]);

		}
		printf("\n");
	}
	printf(" ———————————————————\n");
}

void Getmine(char board[ROWS][COLS], int mine)//种地雷,种的数量为mine
{
	int count = 0;
	while (count < mine)
	{
		int x = rand() % 9 + 1;
		int y = rand() % 9 + 1;
		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			count++;
		}
	}
}

int Countmine(char board[ROWS][COLS], int row, int col)//数周围的地雷数量
{
	return (board[row - 1][col] + board[row-1][col-1] + board[row][col-1] + board[row+1][col-1] + board[row+1][col] +
		board[row+1][col+1] + board[row][col+1] + board[row-1][col+1] - '0'*8 );
}

void flower(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int* count)//递归查询周围地雷实现地雷游戏的遍地开花
{
	if (row > 0 && row < ROWS && col>0 && col < COLS)//使数组不越距
	{
		if (show[row][col] == '*')//递归结束条件
		{
			if (Countmine(mine, row, col)  == 0)//周围都空遍地开花
			{
				show[row][col] = ' ';//使其显示为空格
				(*count)--;
				flower(mine, show, row - 1, col, count);
				flower(mine, show, row - 1, col - 1, count);
				flower(mine, show, row, col - 1, count);
				flower(mine, show, row + 1, col - 1, count);
				flower(mine, show, row + 1, col, count);
				flower(mine, show, row + 1, col + 1, count);
				flower(mine, show, row, col + 1, count);
				flower(mine, show, row - 1, col + 1, count);
			}
			else//周围不是全空则标出周围地雷数量
			{
				show[row][col] = Countmine(mine, row, col) + '0';
				(*count)--;
			}
		}
	}
	
}

void change(char mine[ROWS][COLS], int row, int col)//就是为了好看点^_^用来游戏结尾显示地雷
{
	for (int i = 1; i <= row; i++)
	{
		for (int j = 1; j <= col; j++)
		{
			if (mine[i][j] == '1')
				mine[i][j] = '$';
		}
	}
}

void win(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)//判断输赢
{
	int a = 0, b = 0;
	int move = 81 - MINE;
	while (move != 0)
	{
		printf("输入扫雷位置(空格隔开):");
		scanf("%d %d", &a, &b);
		if (a >= 1 && a <= row && b >= 1 && b <= col&&show[a][b]=='*')//使数组不越距并且防止选同样的位置
		{
			if (mine[a][b] == '1')
			{
				system("cls");//清屏为了好看
				change(mine, ROW, COL);
				printf("你被炸4了!\n");
				Showboard(mine, row, col);
				break;
			}
			else
			{
					flower(mine, show, a, b, &move);
					system("cls");
					Showboard(show, row, col);
			}
		}
		else
		{
			printf("输入错误!请重新输入! ");
		}
	}
	if (move == 0)
	{
		system("cls");
		printf("恭喜你!扫完了全部雷!\n");
		change(mine, ROW, COL);
		Showboard(mine, row, col);
	}

}

text.c

#define _CRT_SECURE_NO_WARNINGS 01

#include"game.h"

void menu()//菜单
{
	printf("--------------------\n");
	printf("|******************|\n");
	printf("|***** 1.play *****|\n");
	printf("|***** 0.exit *****|\n");
	printf("|******************|\n");
	printf("--------------------\n");
}

void game()//游戏本体
{
	char mine[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };
	Initboard(mine, ROWS, COLS,'0');
	Initboard(show, ROWS, COLS, '*');
	Getmine(mine, MINE);
	//Showboard(mine, ROW, COL);
	printf("--------------------\n");
	Showboard(show, ROW, COL);
	win(mine, show, ROW, COL);
}

int main()
{
	srand((unsigned int)time(NULL));
	int input = 0;
	do
	{
		menu();
		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;
}

猜你喜欢

转载自blog.csdn.net/weixin_64038246/article/details/130589915