C语言扫雷游戏

目录

一、游戏介绍

二、程序分析

三、游戏实现

一、打印程序主界面

二、创建数组

三、初始化

四、打印数组

五、随机值创建

六、埋雷

七、排雷

四、完整扫雷代码


一、游戏介绍

今天我们讲解扫雷游戏的制作,这是一个简易的扫雷游戏。

扫雷游戏怎么玩:

格子上的数字代表其周围八个格子中含有的雷的个数。

数字1代表我们点击格子以后显示周围八个格子中含有雷的个数。

我们知道玩法以后,那么我们就开始自己制作一款扫雷游戏吧。

首先如果把代码放入到一个.c文件中的话,不方便阅读,同时逻辑思维能力也会低,我们创建三个文件,test.c、game.c、game.h文件。

test.c文件,包含main函数,负责程序的入口和游戏的整体控制。

game.c:实现扫雷游戏的核心逻辑,如初始化棋盘、布置雷、检查输赢等。

game.h:头文件,包含函数声明和宏定义,用于被其他文件包含。

二、程序分析

在开始写程序时,我们需要分析书写代码的步骤

我们写的扫雷程序是一个简单模式,只需要有9*9的格子。

  1. 设计一个11x11的二维数组来表示棋盘,其中边缘的格子用于避免数组越界的问题。最终打印的话,我们只需要打印9x9的棋盘
  2. 初始化两个二维数组:mine数组用于存储雷的信息,show数组用于显示给玩家看。
  3. 实现一个打印棋盘的函数,用于显示show数组的内容给玩家。
  4. mine数组中随机布置雷。
  5. 实现排雷的逻辑,当玩家点击一个格子时,根据mine数组更新show数组,并显示给玩家。

三、游戏实现

一、打印程序主界面

game.h

#pragma once

#include <stdio.h>

test.c

#include "game.h"

void menu()
{
	printf("***************************\n");
	printf("********* 1、play *********\n");
	printf("********* 0、exit *********\n");
	printf("***************************\n");
}


int main()
{
	int input = 0;
	do
	{
		menu();
		printf("请输入:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			//game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输入错误\n");
			break;
		}
	} while (input);
	return 0;
}

二、创建数组

我们需要创建数组的大小,为了方便修改数组的大小,我们把控制数组的行与宽定义在game.h文件里面,后续也方便我们修改。

game.h

#pragma once

#include <stdio.h>

#define ROW 9          //9行
#define COL 9          //9列
#define ROWS ROW+2     //11行
#define COLS COL+2     //11列

test,c

void game()
{
	char mine[ROWS][COLS];  //设置mine的二维数组
	char show[ROWS][COLS];  //设置show的二维数组
}

三、初始化

我们要把show给里面的元素给换成” * “,mine里面的元素换成” 0 “。

 game.h

#pragma once

#include <stdio.h>

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

//初始化
void InitBoard(char Board[ROWS][COLS], int rows, int cols, char set);  //mine与show函数声明

//打印

//埋雷

//排雷

test.c

void game()
{
    ...............
	//初始化
	InitBoard(mine, ROWS, COLS, '0');   //mine的传参
	InitBoard(show, ROWS, COLS, '*');   //show的传参
	//打印
	 
	//埋雷
	 
	//排雷
}

我们需要设置数组是由字符打印出来的,所以我们把" 0 "跟” * “给传入到InitBoard里面。

我们一次性初始化两行代码,提高了代码编写的效率,无需重复编写代码。

game.c

#define _CRT_SECURE_NO_WARNINGS
#include "game.h"

//初始化
void InitBoard(char Board[ROWS][COLS], int rows, int cols, char set)
{
		int i = 0;
		for (i = 0; i < rows; i++)
		{
			int j = 0;
			for (j = 0; j < cols; j++)
			{
				Board[i][j] = set;   //二维数组等于set设置的字符
			}
		}
}
//打印

//埋雷

//排雷

四、打印数组

game.h

#pragma once

#include <stdio.h>

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

//初始化
    ...............

//打印
void DisplayBoard(char Board[ROWS][COLS], int row, int col);  //函数声明

//埋雷

//排雷

test.c

void game()
{
    ...............
	//初始化
    ...............
	//打印
	DisplayBoard(mine, ROW, COL);  // 把mine二维数组进行函数传参
	DisplayBoard(show, ROW, COL);  // 把show二维数组进行函数传参
	//埋雷
	 
	//排雷

}

game.c

void DisplayBoard(char Board[ROWS][COLS], int row, int col)
{
	int i = 0;
	printf("--------扫雷游戏-------\n");
	for (i = 0; i <= col; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		printf("%d ", i);
		int j = 0;
		for (j = 1; j <= col; j++)
		{
			printf("%c ", Board[i][j]);  //打印出9*9的二维数组
		}
		printf("\n");
	}
}

输出为:

我们看见在mine数组输出的都是0 0 0 0 ,而show数组输出的是* * * * * * 

在我们游戏过程中,我们只打印出show数组,mine数组是不打印的

如果把 mine数组也打印出来,就是偷看答案了

五、随机值创建

埋雷的话我我们需要使用随机值,把雷给放进到1-9的行列之中。

使用随机值的话,就要使用srand与time。

我们需要创建一个为正数的随机数,就需要使用unsigned类型,srand函数用于初始化随机数生成器,而time函数用于获取当前的时间(以秒为单位),这个时间值可以作为srand函数的种子,从而使得每次运行程序时生成的随机数序列都不同。

所需要包含的头文件如下:game.h

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

test,c

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
    ........
    ........
}

六、埋雷

game.h

//埋雷
void SetMine(char mine[ROWS][COLS],int row,int col);

我们只需要在mine数组中去放雷,所以只需要传送mine数组到函数里面,无需传show数组

test.c

void game()
{

	//初始化
    ...............
	//打印
    ...............
	//埋雷
	SetMine(mine, ROW, COL);  // 传参,在mine二维数组中随机生成炸弹
	//排雷

}

因为数组中字符’1‘是随机生成,有几率生成到同一个位置,所以才使用!=’1‘。

为什么需要使用字符’1‘,而不是整数1,因为我们先前初始化的是字符,而不是整数

game.c

//埋雷
void SetMine(char mine[ROWS][COLS], int row, int col)
{
	int count = 10;
	while (count)
	{
		int x = rand() % row + 1;
		int y = rand() % row + 1; 
		if (mine[x][y] !='1')
		{
			mine[x][y] = '1';
			count--;
		}
	}
}

七、排雷

game.h

//排雷
void FindMine(char mine[ROWS][COLS], char show [ROWS][COLS], int row, int col);
int GetMineCount(char mine[ROWS][COLS], int x, int y); 

FindMine函数是用来检查输入的坐标是雷还是安全的坐标

FindMine函数是用来检查输入坐标的周围八个字符有几个雷

test.c

void game()
{
    ...............
	//初始化
    ...............
	//打印
    ...............
	//埋雷
    ...............
	//排雷
	FindMine(mine, show, ROW, COL);  //把mine跟show都传入进去,我们需要使用两个数组
    int GetMineCount(char mine[ROWS][COLS], int x, int y);  //计算我们输入坐标点周围8个格子中有几个炸弹
}

game.h

void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int win = 0;
	while (win < row * col - 10)
	{
		printf("请输入:");
		scanf("%d%d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (mine[x][y]=='1')
			{
				printf("很遗憾,你被炸死了\n");
				DisplayBoard(mine, ROW, COL);
				break;
			}
			else
			{
				int count = GetMineCount(mine, x, y);  //GetMineCount计算输入坐标周围8个格子炸弹个数。
				show[x][y] = count + '0';
				DisplayBoard(show, ROW, COL);
				win++;
			}

		}
		else
		{
			printf("坐标非法\n");
		}
	}
	if (win == row * col - 10)
	{
		printf("恭喜你,排雷成功\n");
		DisplayBoard(mine, ROW, COL);
	}
}

四、完整扫雷代码

test.c

#define _CRT_SECURE_NO_WARNINGS

#include "game.h"

// 显示菜单
void menu()
{
    printf("***************************\n");
    printf("********* 1、play *********\n");
    printf("********* 0、exit *********\n");
    printf("***************************\n");
}

// 游戏主逻辑
void game()
{
    char mine[ROWS][COLS];  // 存储雷区的棋盘
    char show[ROWS][COLS];  // 存储显示给玩家的棋盘
    // 初始化棋盘
    InitBoard(mine, ROWS, COLS, '0');  // 初始化雷区棋盘
    InitBoard(show, ROWS, COLS, '*');  // 初始化显示棋盘
    // 打印棋盘
    DisplayBoard(mine, ROW, COL);  // 打印雷区棋盘(调试用)
    DisplayBoard(show, ROW, COL);  // 打印显示棋盘
    // 设置雷区
    SetMine(mine, ROW, COL);
    // 查找雷区
    FindMine(mine, show, ROW, COL);
}

int main()
{
    int input = 0;  // 用户输入
    srand((unsigned int)time(NULL));  // 随机数种子
    do
    {
        menu();  // 显示菜单
        printf("请输入:");
        scanf("%d", &input);  // 获取用户输入
        switch (input)
        {
        case 1:
            game();  // 开始游戏
            break;
        case 0:
            printf("退出游戏\n");
            break;
        default:
            printf("输入错误\n");
            break;
        }
    } while (input);  // 输入0时退出循环
    return 0;
}

game.h

#pragma once

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

// 定义棋盘的大小
#define ROW 9
#define COL 9
#define ROWS ROW+2  // 包含边界的行数
#define COLS COL+2  // 包含边界的列数

// 初始化棋盘
void InitBoard(char Board[ROWS][COLS], int rows, int cols, char set);

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

// 设置雷区
void SetMine(char mine[ROWS][COLS], int row, int col);

// 查找雷区
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

// 获取雷数
int GetMineCount(char mine[ROWS][COLS], int x, int y);

game.c

#define _CRT_SECURE_NO_WARNINGS
#include "game.h"

// 初始化棋盘
void InitBoard(char Board[ROWS][COLS], int rows, int cols, char set)
{
    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < cols; j++)
        {
            Board[i][j] = set;  // 设置每个格子的初始值
        }
    }
}

// 打印棋盘
void DisplayBoard(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");
    }
}

// 设置雷区
void SetMine(char mine[ROWS][COLS], int row, int col)
{
    int count = 10;  // 设置雷的数量
    while (count)
    {
        int x = rand() % row + 1;
        int y = rand() % row + 1;
        if (mine[x][y] != '1')  // 确保不会重复设置雷
        {
            mine[x][y] = '1';  // 设置雷
            count--;
        }
    }
}

// 获取指定位置周围的雷数
int GetMineCount(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++)
        {
            if (mine[x + i][y + j] == '1')  // 检查周围8个格子
            {
                count++;  // 如果有雷,计数器加1
            }
        }
    }
    return count;
}

// 查找雷区
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
    int x = 0;
    int y = 0;
    int win = 0;
    while (win < row * col - 10)  // 没有排完所有雷前循环
    {
        printf("请输入:");
        scanf("%d%d", &x, &y);  // 输入排雷坐标
        if (x >= 1 && x <= row && y >= 1 && y <= col)
        {
            if (mine[x][y] == '1')  // 如果踩到雷
            {
                printf("很遗憾,你被炸死了\n");
                DisplayBoard(mine, ROW, COL);  // 显示所有雷区
                break;
            }
            else
            {
                int count = GetMineCount(mine, x, y);  // 获取周围雷数
                show[x][y] = count + '0';  // 显示周围雷数
                DisplayBoard(show, ROW, COL);  // 打印当前棋盘
                win++;
            }
        }
        else
        {
            printf("坐标非法\n");  // 输入非法坐标提示
        }
    }
    if (win == row * col - 10)  // 如果赢得游戏
    {
        printf("恭喜你,排雷成功\n");
        DisplayBoard(mine, ROW, COL);  // 显示所有雷区
    }
}

  • 29
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
C语言扫雷游戏排行榜是一个用于记录玩家在扫雷游戏中的得分和排名的榜单。在C语言中,我们可以使用数组和结构体来实现这个排行榜。 首先,我们可以创建一个结构体来表示每个玩家的信息,如玩家的姓名和得分。结构体的定义可以像这样: ``` struct Player { char name[20]; int score; }; ``` 然后,我们创建一个数组来存储多个玩家的信息,数组的大小可以根据需要进行调整。例如: ``` struct Player leaderboard[10]; ``` 接下来,我们可以编写函数来实现对排行榜的操作,如添加玩家、更新得分和显示排行榜等。 添加玩家的函数可以接受玩家的姓名和得分,并将其添加到排行榜中。例如: ``` void addPlayer(char name[20], int score) { // 找到排行榜中得分低于当前得分的位置,并将其后的玩家信息依次后移一位 // 将当前玩家信息插入到空出的位置 } ``` 更新得分的函数可以接受玩家的姓名和新得分,并根据姓名找到对应的玩家并更新其得分。例如: ``` void updateScore(char name[20], int newScore) { // 根据姓名找到对应的玩家,并更新其得分 } ``` 最后,我们可以编写显示排行榜的函数,按照得分从高到低的顺序显示玩家信息。例如: ``` void showLeaderboard() { // 对排行榜中的玩家根据得分进行排序,并输出玩家信息 } ``` 以上是用C语言实现扫雷游戏排行榜的基本思路,具体的实现细节可以根据实际需求进行调整和完善。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值