扫雷游戏程序的编写

Posted 木木变成林

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了扫雷游戏程序的编写相关的知识,希望对你有一定的参考价值。


在电脑还是Windows xp和Windows 7的时代,想必很多人都一定会接触到一款很经典的游戏,扫雷游戏。简单的界面,易上手的难度,不用上网即可游玩的模式,让它大受欢迎。虽然现在Windows 10系统上已不再默认安装扫雷游戏,但我们却可以通过自己编写代码的方式,来回味我们曾经游玩时的感受。但由于本人目前能力有限,仅能实现由键盘输入的方式,来实现位置的确认。

大概思路

首先,我们需要明确扫雷游戏的规则。我们通过键盘输入坐标的方式,来确定位置排雷,若此位置有雷,则游戏结束,若此位置没有雷,则游戏继续,并显示周围地雷的个数。若我们将所有没有地雷的地方确认后,埋有地雷的所有地方也都知道了,则玩家胜利。
然后,我们可以去思考如何去实现了。因为地雷的数据不能让玩家在游玩时知道,且玩家输入的数据需要存储,同时显示在面板上的数据应该是周围地雷的数量,两者并不相同,基于以上两个原因,我们需要创建两个二维数组,一个用于显示未排雷的地方和周围地雷的数量,命名为show_board,另一个用于存储地雷的位置,命名为mine_board。
但还有个很关键的地方,若我们想展示出一个66的面板,我们是该创建两个66的二维数组吗?这样虽然是最符合我们最直接的想法,但随之而来的问题也有了。若玩家输入的坐标位于面板的边框,如最上面的一行,我们在计算周围地雷数量的时候,则不需要检测上面一行的数据,但若是在最下面一行,则不需要检测下面的一行,甚至若是在左上角,则上面和左边的一行都不需要检测了,这会对我们编写检测周围地雷数的代码有很大的麻烦。因此我们需要在外面再加上一圈,则创建一个8*8的数组,在显示和存储时,都会方便不少。
接着,我们可以编写我们需要的功能函数了。我们需要的功能函数应该有:显示目录的函数Menu,埋下地雷的函数SetMines,显示面板的函数ShowBoard,计算周围地雷数量的函数CountMines,执行游戏相关命令的函数Game。当我们梳理出思路后,便可以上手编写程序了。

功能函数

显示目录的函数Menu

该函数用于向玩家提供游玩或者退出的选项。

void Menu()

	printf("########################\\n");
	printf("# 1. Play       0.Exit #\\n");
	printf("########################\\n");

埋下地雷的函数SetMines

取出两个随机数作为坐标,将其所指向的位置赋值,则为埋下地雷。同时,定义宏定义,将地雷的个数NUM定义为20,方便后期程序维护时修改。

#define NUM 20
static void SetMines(char board[][COL], int row, int col)

	int count = NUM;
	while (count)
		int x = rand() % (row - 2) + 1;
		int y = rand() % (col - 2) + 1;//找到一个随机的位置
		if (board[x][y] == '0')
			board[x][y] = '1';//埋下地雷
			count--;
		
	

显示面板的函数ShowBoard

将show_board中所有值通过循环显示出来。因为每行都要显示出表的下边框,为了方便和美观,单独写一个函数ShowLine来显示出下边框。定义两个宏定义ROW和COL来表示创建的数组的行和列。

#define ROW 8
#define COL 8

static void ShowBoard(char board[][COL], int row, int col)

	printf("     ");
	for (int i = 1; i <= (col - 2); i++)
		printf("%d   ", i);
	
	printf("\\n");
	ShowLine(col);
	for (int i = 1; i <= (row - 2); i++)
		printf("%-3d|", i);
		for (int j = 1; j <= (col - 2); j++)
			printf(" %c |", board[i][j]);
		
		printf("\\n");
		ShowLine(col);
	

static void ShowLine(int col)

	for (int i = 0; i <= (col - 2); i++)
		printf("----");
	
	printf("\\n");

计算周围地雷数量的函数CountMines

此函数则为将所指向的坐标的座位8个位置的数据全部相加,则为周围所有地雷的数量。因为一个位置在没有埋下地雷的时候,其所显示的值为0,在埋下地雷后,显示的值被改为1,将8个位置的值相加,但我们存入的值为char型,所以还需要减去7个‘0’的值,才能真正表示出周围地雷的数量。

static char CountMines(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 + 1][y + 1] + board[x + 1][y] + \\
		board[x + 1][y - 1] + board[x][y - 1] - 7 * '0';

执行游戏相关命令的函数Game

首先我们我们需要向玩家展示出面板,让玩家输入一个坐标,然后判断此坐标是否合法,则判断此坐标是否超出面板限制的范围,和判断是否已被占用,若出现以上两种情况,则需要显示出相关的提示语句。为了玩家查看提示语句方便,则将提示语句放在下一次显示面板钱,同时使用选择语句,来显示不同的提示语句。若坐标合法,则判断此坐标是否有雷,有雷则游戏结束,没有雷则将坐标所只想到的位置赋值。当面板上已无除地雷外的位置时,游戏胜利。

#define ROW 8
#define COL 8
#define STYLE '?'
#define NUM 20

void Game()

	srand((unsigned long)time(NULL));

	char show_board[ROW][COL];
	char mine_board[ROW][COL];

	memset(show_board, STYLE, sizeof(show_board));
	memset(mine_board, '0', sizeof(mine_board));//初始化show_board和mine_board

	SetMines(mine_board, ROW, COL);

	int count = (ROW - 2)*(COL - 2) - NUM;//计算除地雷外位置的总数
	int error = 0;
	while (count)
		system("cls");
		if (error == 1)
			printf("Postion Error!\\n");
		//玩家输入的坐标超出范围
		else if(error == 2)
			printf("Postion Is not *\\n");
		//玩家输入的坐标已被占用
		ShowBoard(show_board, ROW, COL);
		printf("Please Enter Your Postion<x,y># ");
		int x = 0;
		int y = 0;
		scanf("%d %d", &x, &y);
		if (x < 1 || x > ROW - 2 || y < 1 || y > COL - 2)
			error = 1;
			continue;
		
		if (show_board[x][y] != STYLE)
			error = 2;
			continue;
		
		if (mine_board[x][y] == '1')
			printf("game over!\\n");
			ShowBoard(mine_board, ROW, COL);
			break;//排雷失败,结束游戏
		
		error = 0;
		show_board[x][y] = CountMines(mine_board, x, y);
		count--;
	
	if (!count)
		printf("You win!\\n");//排雷成功
	

主调函数main

先显示目录,让玩家输入其想执行的操作,并执行相应的命令。

int main()

	int quit = 0;
	int select = 0;
	while (!quit)
		Menu();
		printf("Please Enter# ");
		scanf("%d", &select);
		switch (select)
		case 1:
			Game();
			break;
		case 0:
			quit = 1;
			break;
		default:
			printf("Postion Error, Try Again!\\n");
			break;
		
	

	printf("byebye!\\n");

	system("pause");
	return 0;

至此,所有三子棋的程序都已经编写完毕,后面为将前面所有代码合在一起的结果。

合集

合集中game.h文件中,主要为宏定义和函数的声明;game.c文件中为所有功能函数的编写;main.c文件中为主调函数的编写。

clear_mine.h文件

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1

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

#define ROW 8
#define COL 8
#define STYLE '?'
#define NUM 20

extern void Game();
extern void Menu();

clear_mine.c文件

#include "clear_mine.h"

void Menu()

	printf("########################\\n");
	printf("# 1. Play       0.Exit #\\n");
	printf("########################\\n");


static void SetMines(char board[][COL], int row, int col)

	int count = NUM;
	while (count)
		int x = rand() % (row - 2) + 1;
		int y = rand() % (col - 2) + 1;
		if (board[x][y] == '0')
			board[x][y] = '1';
			count--;
		
	


static void ShowLine(int col)

	for (int i = 0; i <= (col - 2); i++)
		printf("----");
	
	printf("\\n");


static void ShowBoard(char board[][COL], int row, int col)

	printf("     ");
	for (int i = 1; i <= (col - 2); i++)
		printf("%d   ", i);
	
	printf("\\n");
	ShowLine(col);
	for (int i = 1; i <= (row - 2); i++)
		printf("%-3d|", i);
		for (int j = 1; j <= (col - 2); j++)
			printf(" %c |", board[i][j]);
		
		printf("\\n");
		ShowLine(col);
	


static char CountMines(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 + 1][y + 1] + board[x + 1][y] + \\
		board[x + 1][y - 1] + board[x][y - 1] - 7 * '0';


void Game()

	srand((unsigned long)time(NULL));

	char show_board[ROW][COL];
	char mine_board[ROW][COL];

	memset(show_board, STYLE, sizeof(show_board));
	memset(mine_board, '0', sizeof(mine_board));

	SetMines(mine_board, ROW, COL);

	int count = (ROW - 2)*(COL - 2) - NUM;
	int error = 0;
	while (count)
		system("cls");
		if (error == 1)
			printf("Postion Error!\\n");
		
		else if(error == 2)
			printf("Postion Is not *\\n");
		
		ShowBoard(show_board, ROW, COL);
		printf("Please Enter Your Postion<x,y># ");
		int x = 0;
		int y = 0;
		scanf("%d %d", &x, &y);
		if (x < 1 || x > ROW - 2 || y < 1 || y > COL - 2)
			error = 1;
			continue;
		
		if (show_board[x][y] != STYLE)
			error = 2;
			continue;
		
		if (mine_board[x][y] == '1')
			printf("game over!\\n");
			ShowBoard(mine_board, ROW, COL);
			break;
		
		error = 0;
		show_board[x][y] = CountMines(mine_board, x, y);
		count--;
	
	if (!count)
		printf("You win!\\n");
	

main.c文件

#include "clear_mine.h"
int main()

	int quit = 0;
	int select = 0;
	while (!quit)
		Menu();
		printf("Please Enter# ");
		scanf("%d", &select);
		switch (select)
		case 1:
			Game();
			break;
		case 0:
			quit = 1;
			break;
		default:
			printf("Postion Error, Try Again!\\n");
			break;
		
	

	printf("byebye!\\n");
	system("pause");
	return 0;

以上是关于扫雷游戏程序的编写的主要内容,如果未能解决你的问题,请参考以下文章

扫雷游戏程序的编写

编写扫雷游戏提高 Bash 技巧

扫雷(初级)游戏程序编写(C语言版)

详细解读用C语言编写的 “扫雷”程序

Java练习(模拟扫雷游戏)

扫雷游戏 c语言