扫雷游戏

    • 使用工具
  • 一、基本思路和流程
    • 1. 扫雷游戏的游戏规则
    • 2. 代码实现思路
  • 二、实现步骤(具体步骤)
    • 1. 使用多文件形式
    • 2. 代码实现
      • 定义各个难度等级的棋盘大小和雷的数量
      • 定义全局变量
      • 游戏规则界面
      • 菜单界面
      • 选择实现
      • 选择难度界面
      • 初始化和打印棋盘
        • 棋盘
        • 初始化棋盘
        • 打印棋盘
      • 存放雷
      • 排查放雷
  • 三、整体游戏流程
    • 附上所有代码
      • test.c 文件
      • game.h 文件
      • game.c 文件

使用工具

Visual Studio 2019

一、基本思路和流程

1. 扫雷游戏的游戏规则

1. 在已经准备好的棋盘中,找出所有没有设有雷的位置,找出所有位置后,既获得胜利
2. 该游戏设有三种难度等级,分别是简单、中级和困难模式,每种模式的棋盘大小和 雷的数目都不一样
3. 踩到雷即游戏失败

2. 代码实现思路

1. 游戏规则界面,给玩家讲述该游戏的游戏规则
2. 菜单界面: 玩家可选择开始游戏或退出游戏
3. 选择游戏难度界面,玩家可选择游戏难度
4. 初始化棋盘和打印棋盘
5. 玩家开始选择排雷坐标
6. 玩家落下排雷坐标后打印棋盘,并判断玩家是否踩到雷或者是否已经找出所有非雷位置
7. 若玩家所排位置周围的雷的个数为0,则将该位置改为空格,并利用递归对周围八个位置分别进行排雷
8. 游戏结束后,玩家可选择继续游戏或者退出游戏

二、实现步骤(具体步骤)

1. 使用多文件形式

1. test.c 文件(源文件): 写整个游戏的大致过程
2. game.h 文件(头文件): 引用所需的头文件以及对各个程序所需函数的声明
3. game.c 文件(源文件):定义在game.h 中声明的函数

2. 代码实现

定义各个难度等级的棋盘大小和雷的数量

在game.h文件中,使用宏定义

//简单
#define EASY_ROW 9
#define EASY_COL 9
#define EASY_COUNT 15//中级
#define MID_ROW 15
#define MID_COL 15
#define MID_COUNT 30//困难
#define DIF_ROW 21
#define DIF_COL 21
#define DIF_COUNT 40//简单
#define EASY_ROWS EASY_ROW+2
#define EASY_COLS EASY_COL+2
//中级
#define MID_ROWS MID_ROW+2
#define MID_COLS MID_COL+2
//困难
#define DIF_ROWS DIF_ROW+2
#define DIF_COLS DIF_COL+2

定义全局变量

在test.c 文件中

int ROW = 0;
int COL = 0;
int ROWS = 0;
int COLS = 0;
int count = 0;

游戏规则界面

  • 参考代码如下:
void game_rule()
{printf("***********游戏规则: ***********\n");printf("游戏开始前,你可以选择游戏难度,\n");printf("设有简单,中级,困难三种难度,每\n");printf("种难度棋盘大小和雷的数目都不一样,\n");printf("当你把所有非雷位置找出时,既赢下\n");printf("游戏,祝您游戏愉快\n");printf("\n");printf("\n");
}

菜单界面

  • 代考代码如下:
void menu()
{printf("********************************\n");printf("********   1. play     *********\n");printf("********   0. exit     *********\n");printf("********************************\n");
}

选择实现

  • 参考代码如下
int main()
{game_rule();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);return 0;
}

选择难度界面

  • 参考代码如下
void select_diffcult()
{printf("************难度系数***********\n");printf("**********  1. 简单   *********\n");printf("**********  2. 中级   *********\n");printf("**********  3. 困难   *********\n");int input = 0;do {printf("请选择:>");int select = 0;scanf("%d", &select);switch (select){case 1:ROW = EASY_ROW;COL = EASY_COL;ROWS = EASY_ROWS;COLS = EASY_COLS;count = EASY_COUNT;input = 0;break;case 2:ROW = MID_ROW;COL = MID_COL;ROWS = MID_ROWS;COLS = MID_COLS;count = MID_COUNT;input = 0;break;case 3:ROW = DIF_ROW;COL = DIF_COL;ROWS = DIF_ROWS;COLS = DIF_COLS;count = DIF_COUNT;input = 0;break;default:input = 1;break;}} while (input);
}

初始化和打印棋盘

棋盘
  • 使用二维数组,由于定于数组设置大小只能用常量,所有为了避免越界,我们将棋盘大小设置为三种游戏模式中棋盘最大的那一类
  • 为了方便后续打印,我们将设置两个一样大小的数组,一个用来存放雷,一个用来打印
 char mine[DIF_ROWS][DIF_COLS];//存放雷char show[DIF_ROWS][DIF_COLS];
初始化棋盘

mine[DIF_ROWS][DIF_COLS] 和 show[DIF_ROWS][DIF_COLS]都需要进行初始化

  • 参考代码如下
void InitBoard(char board[DIF_ROWS][DIF_COLS], int rows, int cols, char ch)
{int i = 0;for (i = 0; i < rows; i++){int j = 0;for (j = 0; j < cols; j++){board[i][j] = ch;}}
}
打印棋盘
  • 参考代码如下
void DisPlayBoard(char board[DIF_ROWS][DIF_COLS], int row, int col)
{int i = 0;printf("   ");for (i = 1; i <= row; i++){printf("%2d ", i);}printf("\n");printf("  |");for (i = 1; i <= row; i++){printf("---");}printf("\n");for (i = 1; i <= row; i++){printf("%2d|", i);int j = 0;for (j = 1; j <= col; j++){printf(" %c ", board[i][j]);}printf("\n");}
}
  • 实现后效果

存放雷

  • 存放雷可能出现的问题

1. 随机生成雷的过程中,需要判断雷的位置是否已被占用

可以使用时间戳生成随机数,随机生成雷的坐标,利用循环解决位置是否被占用的问题

  • 参考代码如下
//cnt是雷的数量
void SetMine(char mine[DIF_ROWS][DIF_COLS], int row, int col, int cnt)
{while (cnt > 0){int x = 0;int y = 0;x = rand() % row + 1;y = rand() % col + 1;if (mine[x][y] == '0'){mine[x][y] = '1';cnt--;}}
}

排查放雷

如果玩家排查的位置的周围雷的数量为0, 那么久要利用递归来对周围的八个位置进行排查,为了防止递归的栈溢出问题,需要将已经排查过得位置进行标记

  • 参考代码如下
//排查位置周围雷的数量
int MineCount(char mine[DIF_ROWS][DIF_COLS], int x, int y)
{int cnt = mine[x - 1][y - 1] +mine[x - 1][y] +mine[x - 1][y + 1] +mine[x][y - 1] +mine[x][y + 1] +mine[x + 1][y - 1] +mine[x + 1][y] +mine[x + 1][y + 1] - 8 * '0';return cnt;}
//对排查位置周围八个位置进行排查
void Expend(char mine[DIF_ROWS][DIF_COLS], char show[DIF_ROWS][DIF_COLS], int x, int y, int visted[DIF_ROWS][DIF_COLS])
{//visted[x][y] == 1;int vist[DIF_ROWS][DIF_COLS] = { 0 };int cnt = MineCount(mine, x, y);if (cnt > 0)show[x][y] = cnt + '0';else{show[x][y] = ' ';if (visted[x - 1][y - 1] == 0){vist[x    - 1][y - 1] = 1;visted[x - 1][y - 1] = 1;}if (visted[x - 1][y] == 0){vist[x - 1][y] = 1;visted[x - 1][y] = 1;}if (visted[x - 1][y + 1] == 0){vist[x - 1][y + 1] = 1;visted[x - 1][y + 1] = 1;}if (visted[x][y - 1] == 0){vist[x][y - 1] = 1;visted[x][y - 1] = 1;}if (visted[x][y + 1] == 0){vist[x ][y + 1] = 1;visted[x][y + 1] = 1;}if (visted[x + 1][y - 1] == 0){vist[x + 1][y - 1] = 1;visted[x + 1][y - 1] = 1;}if (visted[x + 1][y] == 0){vist[x + 1][y] = 1;visted[x + 1][y] = 1;}if (visted[x + 1][y + 1] == 0){vist[x + 1][y + 1] = 1;visted[x + 1][y + 1] = 1;}if (vist[x - 1][y - 1] == 1){Expend(mine, show, x - 1, y - 1, visted);}if (vist[x - 1][y] == 1){Expend(mine, show, x - 1, y, visted);}if (vist[x - 1][y + 1] == 1){Expend(mine, show, x - 1, y + 1, visted);}if (vist[x][y - 1] == 1){Expend(mine, show, x, y - 1, visted);}if (vist[x][y + 1] == 1){Expend(mine, show, x, y + 1, visted);}if (vist[x + 1][y - 1] == 1){Expend(mine, show, x + 1, y - 1, visted);}if (vist[x + 1][y] == 1){Expend(mine, show, x + 1, y, visted);}if (vist[x + 1][y + 1] == 1){Expend(mine, show, x + 1, y + 1, visted);}}
}
//排查雷
void FindMine(char mine[DIF_ROWS][DIF_COLS], char show[DIF_ROWS][DIF_COLS], int row, int col, int cnt, int visted[DIF_ROWS][DIF_COLS])
{while (1){int x = 0;int y = 0;printf("请输入:>");scanf("%d%d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col){if (1 == visted[x][y]){printf("该位子已被占用\n");}else if (mine[x][y] == '1'){show[x][y] = '$';DisPlayBoard(show, row, col);printf("你踩到雷了\n");break;}else{visted[x][y] == 1;Expend(mine, show, x, y, visted);DisPlayBoard(show, row, col);}}else{printf("超出范围\n");}int count = 0;int i = 0;for (i = 1; i <= row; i++){int j = 0;for (j = 1; j <= col; j++){if (show[i][j] == '*'){count++;}}}if (count == cnt){printf("恭喜你,你赢了\n");break;}}
}

三、整体游戏流程

  • 参考代码如下
void game()
{select_diffcult();char mine[DIF_ROWS][DIF_COLS];char show[DIF_ROWS][DIF_COLS];int visted[DIF_ROWS][DIF_COLS];int i = 0;for (i = 0; i < ROWS; i++){int j = 0;for (j = 0; j < COLS; j++){if (i == 0)visted[i][j] = 1;else if (j == 0)visted[i][j] = 1;else if (i == ROWS - 1)visted[i][j] = 1;else if (j == COLS - 1)visted[i][j] = 1;elsevisted[i][j] = 0;}}//初始化棋盘InitBoard(mine, ROWS, COLS, '0');InitBoard(show, ROWS, COLS, '*');//打印棋盘DisPlayBoard(show, ROW, COL);//存放雷SetMine(mine, ROW, COL, count);//排查雷FindMine(mine, show, ROW, COL, count, visted);
}

附上所有代码

test.c 文件

#include "game.h"int ROW = 0;
int COL = 0;
int ROWS = 0;
int COLS = 0;
int count = 0;void game_rule()
{printf("***********游戏规则: ***********\n");printf("游戏开始前,你可以选择游戏难度,\n");printf("设有简单,中级,困难三种难度,每\n");printf("种难度棋盘大小和雷的数目都不一样,\n");printf("当你把所有非雷位置找出时,既赢下\n");printf("游戏,祝您游戏愉快\n");printf("\n");printf("\n");
}void menu()
{printf("********************************\n");printf("********   1. play     *********\n");printf("********   0. exit     *********\n");printf("********************************\n");
}void select_diffcult()
{printf("************难度系数***********\n");printf("**********  1. 简单   *********\n");printf("**********  2. 中级   *********\n");printf("**********  3. 困难   *********\n");int input = 0;do {printf("请选择:>");int select = 0;scanf("%d", &select);switch (select){case 1:ROW = EASY_ROW;COL = EASY_COL;ROWS = EASY_ROWS;COLS = EASY_COLS;count = EASY_COUNT;input = 0;break;case 2:ROW = MID_ROW;COL = MID_COL;ROWS = MID_ROWS;COLS = MID_COLS;count = MID_COUNT;input = 0;break;case 3:ROW = DIF_ROW;COL = DIF_COL;ROWS = DIF_ROWS;COLS = DIF_COLS;count = DIF_COUNT;input = 0;break;default:input = 1;break;}} while (input);
}
void game()
{select_diffcult();char mine[DIF_ROWS][DIF_COLS];char show[DIF_ROWS][DIF_COLS];int visted[DIF_ROWS][DIF_COLS];int i = 0;for (i = 0; i < ROWS; i++){int j = 0;for (j = 0; j < COLS; j++){if (i == 0)visted[i][j] = 1;else if (j == 0)visted[i][j] = 1;else if (i == ROWS - 1)visted[i][j] = 1;else if (j == COLS - 1)visted[i][j] = 1;elsevisted[i][j] = 0;}}//初始化棋盘InitBoard(mine, ROWS, COLS, '0');InitBoard(show, ROWS, COLS, '*');//打印棋盘DisPlayBoard(show, ROW, COL);//存放雷SetMine(mine, ROW, COL, count);//排查雷FindMine(mine, show, ROW, COL, count, visted);
}int main()
{game_rule();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);return 0;
}

game.h 文件

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>//简单
#define EASY_ROW 9
#define EASY_COL 9
#define EASY_COUNT 15//中级
#define MID_ROW 15
#define MID_COL 15
#define MID_COUNT 30//困难
#define DIF_ROW 21
#define DIF_COL 21
#define DIF_COUNT 40//简单
#define EASY_ROWS EASY_ROW+2
#define EASY_COLS EASY_COL+2
//中级
#define MID_ROWS MID_ROW+2
#define MID_COLS MID_COL+2
//困难
#define DIF_ROWS DIF_ROW+2
#define DIF_COLS DIF_COL+2//初始化棋盘
extern void InitBoard(char board[DIF_ROWS][DIF_COLS], int rows, int cols,char ch);
//打印棋盘
extern void DisPlayBoard(char board[DIF_ROWS][DIF_COLS], int row, int col);
//存放雷
extern void SetMine(char mine[DIF_ROWS][DIF_COLS], int row, int col, int cnt);
//排查雷
extern void FindMine(char mine[DIF_ROWS][DIF_COLS], char show[DIF_ROWS][DIF_COLS], int row, int col, int cnt, int visted[DIF_ROWS][DIF_COLS]);
extern int MineCount(char mine[DIF_ROWS][DIF_COLS], int x, int y);
extern void Expend(char mine[DIF_ROWS][DIF_COLS], char show[DIF_ROWS][DIF_COLS], int x, int y, int visted[DIF_ROWS][DIF_COLS]);

game.c 文件

#include "game.h"void InitBoard(char board[DIF_ROWS][DIF_COLS], int rows, int cols, char ch)
{int i = 0;for (i = 0; i < rows; i++){int j = 0;for (j = 0; j < cols; j++){board[i][j] = ch;}}
}void DisPlayBoard(char board[DIF_ROWS][DIF_COLS], int row, int col)
{int i = 0;printf("   ");for (i = 1; i <= row; i++){printf("%2d ", i);}printf("\n");printf("  |");for (i = 1; i <= row; i++){printf("---");}printf("\n");for (i = 1; i <= row; i++){printf("%2d|", i);int j = 0;for (j = 1; j <= col; j++){printf(" %c ", board[i][j]);}printf("\n");}
}void SetMine(char mine[DIF_ROWS][DIF_COLS], int row, int col, int cnt)
{while (cnt > 0){int x = 0;int y = 0;x = rand() % row + 1;y = rand() % col + 1;if (mine[x][y] == '0'){mine[x][y] = '1';cnt--;}}
}int MineCount(char mine[DIF_ROWS][DIF_COLS], int x, int y)
{int cnt = mine[x - 1][y - 1] +mine[x - 1][y] +mine[x - 1][y + 1] +mine[x][y - 1] +mine[x][y + 1] +mine[x + 1][y - 1] +mine[x + 1][y] +mine[x + 1][y + 1] - 8 * '0';return cnt;}void Expend(char mine[DIF_ROWS][DIF_COLS], char show[DIF_ROWS][DIF_COLS], int x, int y, int visted[DIF_ROWS][DIF_COLS])
{//visted[x][y] == 1;int vist[DIF_ROWS][DIF_COLS] = { 0 };int cnt = MineCount(mine, x, y);if (cnt > 0)show[x][y] = cnt + '0';else{show[x][y] = ' ';if (visted[x - 1][y - 1] == 0){vist[x    - 1][y - 1] = 1;visted[x - 1][y - 1] = 1;}if (visted[x - 1][y] == 0){vist[x - 1][y] = 1;visted[x - 1][y] = 1;}if (visted[x - 1][y + 1] == 0){vist[x - 1][y + 1] = 1;visted[x - 1][y + 1] = 1;}if (visted[x][y - 1] == 0){vist[x][y - 1] = 1;visted[x][y - 1] = 1;}if (visted[x][y + 1] == 0){vist[x ][y + 1] = 1;visted[x][y + 1] = 1;}if (visted[x + 1][y - 1] == 0){vist[x + 1][y - 1] = 1;visted[x + 1][y - 1] = 1;}if (visted[x + 1][y] == 0){vist[x + 1][y] = 1;visted[x + 1][y] = 1;}if (visted[x + 1][y + 1] == 0){vist[x + 1][y + 1] = 1;visted[x + 1][y + 1] = 1;}if (vist[x - 1][y - 1] == 1){Expend(mine, show, x - 1, y - 1, visted);}if (vist[x - 1][y] == 1){Expend(mine, show, x - 1, y, visted);}if (vist[x - 1][y + 1] == 1){Expend(mine, show, x - 1, y + 1, visted);}if (vist[x][y - 1] == 1){Expend(mine, show, x, y - 1, visted);}if (vist[x][y + 1] == 1){Expend(mine, show, x, y + 1, visted);}if (vist[x + 1][y - 1] == 1){Expend(mine, show, x + 1, y - 1, visted);}if (vist[x + 1][y] == 1){Expend(mine, show, x + 1, y, visted);}if (vist[x + 1][y + 1] == 1){Expend(mine, show, x + 1, y + 1, visted);}}
}void FindMine(char mine[DIF_ROWS][DIF_COLS], char show[DIF_ROWS][DIF_COLS], int row, int col, int cnt,int visted[DIF_ROWS][DIF_COLS])
{while (1){int x = 0;int y = 0;printf("请输入:>");scanf("%d%d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col){if (1 == visted[x][y]){printf("该位子已被占用\n");}else if (mine[x][y] == '1'){show[x][y] = '$';DisPlayBoard(show, row, col);printf("你踩到雷了\n");break;}else{visted[x][y] == 1;Expend(mine, show, x, y, visted);DisPlayBoard(show, row, col);}}else{printf("超出范围\n");}int count = 0;int i = 0;for (i = 1; i <= row; i++){int j = 0;for (j = 1; j <= col; j++){if (show[i][j] == '*'){count++;}}}if (count == cnt){printf("恭喜你,你赢了\n");break;}}
}

C语言实现扫雷游戏(一步步教你如何写扫雷)相关推荐

  1. python扫雷游戏实验分析_用python写扫雷游戏实例代码分享

    扫雷是一个非常经典的WIN游戏,我们教给大家用python语言来写出这个游戏,以下是全部实例代码: #!/usr/bin/python #coding:utf-8 #python 写的扫雷游戏 imp ...

  2. 如何用python编一个扫雷游戏_用 Python 做一个 Windows 扫雷游戏

    原标题:用 Python 做一个 Windows 扫雷游戏 本文代码基于 python3.6 和 pygame1.9.4. Windows XP 上的扫雷是无数80/90后的集体回忆,今天我们就用 P ...

  3. 如何用C语言做PONG游戏,[Unity 3d] 如何优雅的写一个PingPong效果

    PingPong效果在 Unity 真的是随处可见:来回运动啦,呼吸灯啦,活塞运动啦,渐隐渐显啦,今天笔者就用两种方式教大家写下这个简单而常见的动画效果. 1. DoTween 借助Dotween,我 ...

  4. 很不错的教程一步步教你如何写Makefile

    [转载:原文地址:http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=408225] 陈皓 概述 -- 什么是makefile?或许很多 ...

  5. c语言扫雷游戏构成原理,扫雷游戏的C语言实现

    在学习C语言初期,我们可以找一些平常玩的游戏进行简单的C语言实现.今天就和大家分享一下关于windows中扫雷游戏的实现. 在正式写代码前,简单说一下对这个游戏的分析: 1.先提示的应该是一个简单的m ...

  6. C语言 —— 扫雷游戏

    ▏扫雷是款极其经典的游戏,以下就来描述用C语言实现初级扫雷游戏(9*9)的实现  ▏ 目录 写这个游戏的思路 玩法介绍 思考过程 实现过程 主函数 游戏函数 游戏函数的头文件  写这个游戏的思路  玩 ...

  7. C语言编写扫雷游戏【W5+字详细教学版,包教包会】

    目录 前言 一.扫雷游戏 二.整体分析 三.游戏的实现 1.实现test文件 2.实现game.h文件 3.实现game.c文件 3.1 初始化棋盘 3.2 打印棋盘 3.3 埋放地雷 3.4 判断行 ...

  8. [安全攻防进阶篇] 一.什么是逆向分析、逆向分析应用及经典扫雷游戏逆向

    从2019年7月开始,我来到了一个陌生的专业--网络空间安全.初入安全领域,是非常痛苦和难受的,要学的东西太多.涉及面太广,但好在自己通过分享100篇"网络安全自学"系列文章,艰难 ...

  9. 一文教你从零开始设计并实现一个Java扫雷游戏

    背景:扫雷这款游戏有着很长的历史,从扫雷被开发出来到现在进行了无数次的优化,这款游戏变得越来越让人爱不释手了,简单的玩法在加上一个好看的游戏界面,每一处的细节都体现了扫雷的魅力.以JAVA语言作为开发 ...

最新文章

  1. 计算机视觉系统学习书籍/综述汇总
  2. Linux内核自旋锁使用笔记
  3. 中移动TD终端资助或只限五洋巨头
  4. 计算机组成原理 — FPGA 现场可编程门阵列
  5. 自考进行时--2018.10.21
  6. 底部菜单_css实现移动端底部导航菜单隆起效果
  7. java selenium 定位frame_webdriver 定位frameset中的frame
  8. Elasticsearch基础教程ES
  9. PHP7 serialize_precision 配置不当导致 json_encode() 浮点小数溢出错误
  10. Snipaste在Window运行后遇到提示计算机中丢失 api-ms-win-crt-runtime-l1-1-0.dll 错误
  11. POJ 1328 Radar Installation【贪心】
  12. java过载保护_微服务过载保护原理与实战
  13. matlab画图命令
  14. 利用python更改图片格式和分辨率
  15. 当你在追梦的路上抱怨生活太累快要放弃的时候,不妨看看我的这篇文章
  16. 境外服务器停机:原因、影响以及如何预防
  17. 【R语言】时间序列案例:住宅销量预测的乘法季节模型
  18. 大数据运维架构师培训(1):Zookeeper,Hadoop(HDFS,MR,Yarn)
  19. 2021-04-10 仿牛客网第六章
  20. HCNA-Telnet

热门文章

  1. Java数据 定义规则脱敏实现
  2. 数字信号处理|用Matlab画复指数序列的实部、虚部、幅值、相位图
  3. vue项目--open打开0.0.0.0网址如何修改
  4. 怎么把heic图片格式转换jpg格式呢?
  5. 大规模点云的弱监督语义分割
  6. EF框架实现登录(记住密码+首页欢迎)+列表功能(增删改查)+过滤器
  7. 数据库sql server 2008 r2 RTM版本升级到sql server 2012 r2
  8. 采购单ME21N增强控制行文本必输
  9. sql2008质疑处理方法
  10. 百度编辑器UEditor 如何屏蔽‘本地保存成功‘提示?