扫雷游戏的实现

目录

一、实现思路

二、实现代码

1、头文件中常量以及自定义函数的声明

2、main函数

3、game函数

4、初始化函数

5、棋盘展示函数

6、布置地雷函数

7、发现地雷函数

8、代码的实现效果

三、后续改进


一、实现思路

需要完成的游戏逻辑

①、引导用户选择是否开始游戏;

②、设置棋盘(二维数组);

③、初始化棋盘(二维数组),并展示;

④、在棋盘(二维数组)中埋入地雷;

⑤、引导用户输入坐标;

⑥、以用户所选坐标为中心,统计九宫格内地雷的数量,并于该坐标上显示,若选择的坐标上刚好有地雷,则显示 "game over" ,用户重新跳回游戏界面

二、实现代码

1、头文件中常量以及自定义函数的声明

#pragma once
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define ROWS  ROW+2					//用define定义便于整个代码的复编译,因此后续所有的自定义函数中,都带了这个几个变量
#define COLS  COL+2					//用define定义便于整个代码的复编译,因此后续所有的自定义函数中,都带了这个几个变量
#define ROW  9						//用define定义便于整个代码的复编译,因此后续所有的自定义函数中,都带了这个几个变量
#define COL  9						//用define定义便于整个代码的复编译,因此后续所有的自定义函数中,都带了这个几个变量
									
#define easy_count 10				//用define定义便于整个代码的复编译


//为使test.c中能够正常调用所有的自定义函数,需要在头文件中,对所有自定义函数进行声明,
//注:头文件的声名格式应当与函数定义格式相同?
void init_board(char board[ROWS][COLS], int rows, int cols, char set);	//原则上,init_board 只需一个数组作为函数变量,用一个变量来接收mine 和 show,在test.c中调用两次即可
																		
void display_board(char show[ROWS][COLS], int row, int col);			//原则上,display_board 只需一个数组作为函数变量,即,只需要展示 show 即可,游戏中展示 mine 属于作弊行为
																		
void set_mine(char mine[ROWS][COLS], int row, int col);					//原则上,set_mine 只需一个数组作为函数变量,因为只有在mine中埋入地雷

void find_mine(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col);	//find_mine 之所以需要两个形参数组作为函数,一是需要知道所选择坐标的周围范围内存在多少个地雷,其次还要将统计的个数																		
																				// 由此可推:数字 + 数字字符'0' = 数字字符

2、main函数

主函数:

#inculde "game.h"

int main()
{
    test();//跳转至自定义函数test
    return 0;
}

为了引导用户进入游戏,编写自定义函数test:

void test()                                
{
    int input = 0;                         //使用do while 循环来实现程序
    
    do {
        printf("请选择是否开始游戏\n");
        menu();
        scanf("%d", &input);
        switch (input)
        {
        case 0:
        {
            printf("退出游戏\n");
            break;
        }
        case 1:
        {
            printf("开始游戏\n");
            game();                        //跳转至自定义函数game
            break;
        }
        default:
        {
            printf("输入有误,重新输入\n");
            break;
        }
        }
    } while (input);
}

3、game函数

void game()
{    
    

	char mine [ROWS][COLS] = {0};	//为便于实现,需要定义两个数组,其中一个用于布置地雷
	char show [ROWS][COLS] = {0};	//还有一个用于显示
    //之所以选用11*11二维数组是因为,在初始化棋盘后,mine数组中内所有元素均为字符'0'
    //这样在后续统计地雷数时,可以避免用户选择边缘位置时而出现错误,同时也便于代码的实现

	//初始化游戏,同时展示show棋盘
	init_board(mine, ROWS, COLS, '0');	//mine中全部设为字符'0'
	init_board(show, ROWS, COLS, '*');	//show中全部设为字符'*

	//向玩家展示内部9*9的大小的棋盘
	display_board(show, ROW, COL);

	//在mine中设置地雷,其中字符'1'表示地雷,字符'0',表示非雷,同样的,因为玩家只需要在9*9的区域
	//内排雷,所以雷只要设置在9*9范围内
	set_mine(mine, ROW, COL);

	//发现雷,选定坐标,以该坐标为中心,统计周围八个格子中雷的个数,因为数组设置的是11*11大小,
	//且所有单元格都初始化为字符0,所以不会存在溢出和多算的情况。每次发现完后
	find_mine(mine,show, ROW, COL);
}

4、初始化函数

void init_board(char board[ROWS][COLS], int rows, int cols, char set)//ROWS和COLS是 define定义过的,所以形参中不能再次使用ROWS,COLS
{
	int i = 0;
	for (i = 0; i < rows; i++)
	{
		//int j = 0;
		for (int j = 0; j < cols; j++)
		{
			board[i][j] = set;	//在自定义函数 game 中,该自定义函数被调用了两次,将mine和show分别进行初始化
		}
	}
}

5、棋盘展示函数

//棋盘展示
//扫雷游戏在编写过程中,只需要将中间9*9的部分展示给玩家,所以行列分别为 ROW 和 COL 而不是 ROWS和COLS
//同时使用形参 row 和 col 来接收 实参 ROW 和 COL
void display_board(char show[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i <= row; i++)              
	{
		printf("%d ", i);                 //便于用户确定横坐标
	}
	printf("\n");

	for (i = 1; i <= row; i++)
	{
		printf("%d ", i);                 //便于用户确定纵坐标
		for (j = 1; j <= col; j++)
		{	
			printf("%c ", show[i][j]);    //展示棋盘
		}
		printf("\n");
	}
}

代码实现的结果:

6、布置地雷函数

//在初始化完毕,以及初次打印棋盘后,就要给棋盘中偷偷买入地雷,这一过程玩家是看不见的,但是是实际存在的
//我们所要做的就是在原11*11的数组中,在其中间9*9的部分随机埋入10个地雷,
void set_mine(char mine[ROWS][COLS], int row, int col)
{
	int count = easy_count;			//easy_count是define定义的变量,不能直接用于+-运算,
	while (count>0)					//循环埋入地雷,直至埋入10个为止
	{
		int x = rand() % row +1;	//随机埋入
		int y = rand() % col +1;
		if (mine[x][y] != '1')		//该条语句用于确保不会重复埋雷而浪费字数,
		{							//开是所产生的随机数x y 以及对应的单元格 mine[x][y]肯定满足
			mine[x][y] = '1';		//mine[x][y] != '1',因此if语句能够顺利执行,
			count--;				//同时确保后面不会重复埋雷
		}
	}
	//display_board(mine, row, col);	//作弊器
}

7、发现地雷函数

//找地雷,同时打印棋盘结果
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int win = row * col - easy_count;//胜利条件
	
	while (win)
	{
		printf("请输入坐标\n");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)//为确保游戏的正常进行,
		{										 //需要对输入的坐标是否有效进行判断
			if (mine[x][y] == '1')//判断输入坐标是否为雷
			{
				printf("game over\n");
				break;
			}
			else
			{
				int count = get_mine(mine, x, y);//不是则将自定义函数get_mine中的值返回到count中
				show[x][y] = count + '0';//数字转字符 ,最终以数字字符输出到字符数组中
				display_board(show, row, col);//展示棋盘
				win--;
			}
		}
		else
		{
		printf("输入有误,请重新输入\n");
		}
		
	}
	if (!win)
	{
		printf("you win\n");
	}
}

自定义函数get_mine的实现方式

注:该自定义函数在find_mine 函数前,如果在find_mine 函数后面,则在使用时,需要在find_mine函数前定义该函数

//该函数用于确定以某单元格为中心,周围八个位置有多少个雷
int get_mine(char mine[ROWS][COLS], int x, int y)
{
	int count = 0;
	for (int i = -1; i <= 1; i++)
	{
		for (int j = -1; j <= 1; j++)
		{
			count += mine[x+i][y+j] - '0';//字符转数字
		}
	}
	return count;
}

8、代码的实现效果

注:为便于验证,此处将头文件中 game.h 内的常量 ROW COL 设置为2,easy_count 设置为1

胜利:

失败:

退出游戏:

三、后续改进

1、若中心坐标周围没有雷,递归展开。//这需要用到递归函数,暂时为学
2、能否像游戏一样,标记某个坐标为雷?
 

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个简单的 Java 扫雷游戏实现,你可以参考一下: ```java import java.util.Random; import java.util.Scanner; public class MineSweeperGame { private static final int ROWS = 10; // 行数 private static final int COLS = 10; // 列数 private static final int MINES = 10; // 雷数 private static final int MINE = -1; // 雷的标记 private static final int COVERED = 0; // 覆盖的标记 private static final int UNCOVERED = 1; // 已经被翻开的标记 private int[][] board; // 存储游戏状态的二维数组 private boolean gameOver; // 游戏是否结束 private int remaining; // 剩余未翻开的格子数 public MineSweeperGame() { board = new int[ROWS][COLS]; gameOver = false; remaining = ROWS * COLS - MINES; initBoard(); placeMines(); } // 初始化游戏面板 private void initBoard() { for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { board[i][j] = COVERED; } } } // 随机放置雷 private void placeMines() { Random random = new Random(); int count = 0; while (count < MINES) { int row = random.nextInt(ROWS); int col = random.nextInt(COLS); if (board[row][col] != MINE) { board[row][col] = MINE; count++; } } } // 显示游戏面板 private void displayBoard() { System.out.println(" 0 1 2 3 4 5 6 7 8 9"); System.out.println(" ---------------------"); for (int i = 0; i < ROWS; i++) { System.out.print(i + "| "); for (int j = 0; j < COLS; j++) { if (board[i][j] == COVERED) { System.out.print(". "); } else if (board[i][j] == UNCOVERED) { // 如果是已经被翻开的格子,显示数字 int count = countAdjacentMines(i, j); if (count > 0) { System.out.print(count + " "); } else { System.out.print(" "); } } else { System.out.print("* "); } } System.out.println("|" + i); } System.out.println(" ---------------------"); System.out.println(" 0 1 2 3 4 5 6 7 8 9"); } // 获取相邻的格子中雷的数量 private int countAdjacentMines(int row, int col) { int count = 0; for (int i = Math.max(0, row - 1); i <= Math.min(ROWS - 1, row + 1); i++) { for (int j = Math.max(0, col - 1); j <= Math.min(COLS - 1, col + 1); j++) { if (board[i][j] == MINE) { count++; } } } return count; } // 翻开格子 private void uncover(int row, int col) { if (board[row][col] == UNCOVERED) { return; } if (board[row][col] == MINE) { gameOver = true; return; } board[row][col] = UNCOVERED; remaining--; if (countAdjacentMines(row, col) == 0) { // 如果相邻的格子中没有雷,就翻开它们 for (int i = Math.max(0, row - 1); i <= Math.min(ROWS - 1, row + 1); i++) { for (int j = Math.max(0, col - 1); j <= Math.min(COLS - 1, col + 1); j++) { if (board[i][j] == COVERED) { uncover(i, j); } } } } } // 运行游戏 public void run() { Scanner scanner = new Scanner(System.in); while (!gameOver) { displayBoard(); System.out.print("Enter row and column (separated by a space): "); int row = scanner.nextInt(); int col = scanner.nextInt(); if (row < 0 || row >= ROWS || col < 0 || col >= COLS) { System.out.println("Invalid row or column!"); continue; } if (board[row][col] == UNCOVERED) { System.out.println("The cell has already been uncovered!"); continue; } uncover(row, col); if (remaining == 0) { System.out.println("Congratulations! You have won!"); break; } } displayBoard(); System.out.println("Game over!"); } public static void main(String[] args) { MineSweeperGame game = new MineSweeperGame(); game.run(); } } ``` 这个实现比较简单,只有基本的游戏逻辑,有些细节可能还需要完善。你可以根据自己的需求进行修改和扩展。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值