C语言实现扫雷游戏(含注释详解)

 更新时间:2021年09月10日 15:28:02   作者:3 ERROR(s)  
这篇文章主要为大家详细介绍了C语言实现扫雷游戏,含注释,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了C语言实现扫雷游戏的具体代码,供大家参考,具体内容如下

前言

一、游戏规则介绍

扫雷是一个十分经典的游戏,一张棋盘中有很多个不确定是雷还是安全区域的格子,当点击之后若没有雷则会在该区域显示周围八个格子雷的数目,若有雷则游戏结束。今天我就跟大家分享一下如何用c语言实现初阶版扫雷。

二、基本思路流程介绍

1.创建一个用户交互菜单
2.创建一个Show_Mines棋盘用来埋雷并初始化
3.创建一个Show_Table 棋盘用来和用户交互并初始化
4.玩家选择想要扫描的坐标
5.判定游戏是否结束
6.若没有踩雷则在刚扫描的区域上显示周围八个区域的地雷数目并继续游戏
7.继续扫雷
8.判定游戏是否结束

9.若全部扫描完非雷区域则游戏结束

效果展示

三、代码实现

1.用户交互菜单(Menu函数)

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

2. Game函数

void Game()
{
 srand((unsigned long)time(NULL)); //生成随机数种子

 char show_board[ROW][COL];   
 char mines_board[ROW][COL];

 memset(show_board, WHAT, sizeof(show_board));//生成并且初始化用户显示棋盘
 memset(mines_board, '0', sizeof(mines_board));//生成并且初始化扫雷棋盘

 SetMines(mines_board, ROW, COL);//放雷

 int count = (ROW - 2)*(COL - 2) - NUM;    //若扫完这些次 不触雷则胜利

 while (count){
  system("cls");
  ShowBoard(show_board, ROW, COL);
  printf("请选择你要扫描的区域坐标 ");
  int x = 0;
  int y = 0;
  scanf("%d %d", &x, &y);
  if (x < 1 || x > ROW-2 || y < 1 || y > COL-2){ //非法性输入判断
   printf("输入错误!\n");
   continue;
  }
  if (show_board[x][y] != WHAT){           
   printf("此处已经被扫过了,请从新输出\n");
   continue;
  }
  if (mines_board[x][y] == '1'){
   system("cls");
   ShowBoard(mines_board, ROW, COL);
   printf("踩雷了!游戏结束!\n");
   break;
  }
  
  show_board[x][y] = CountMines(mines_board, x, y);
  count--;
 }

}

1.memset函数直接定义show_board函数并且初始化二维数组为全WHAT宏定义的*。
2.先向用户展示用户展示棋盘,用户输入一个坐标进行非法性判断。
3.把用户输入的坐标拿给放置雷的棋盘中,若该区域有雷则游戏结束,反之则继续
4.游戏胜利条件为扫描完所有非雷区域

3.放雷函数(SetMines函数)

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--;
  }
 }
}

使用随机数种子生成1到 棋盘大小长宽-2的随机数,这些随机数组成的坐标放雷,循环次数就是雷的数目。因为随机数可能生成一样的,所以要进行一次非法性判断,当棋盘这个位置没有雷的情况下才能往里面放雷。

4.扫雷展示面板(ShowBoard函数和ShowLine函数)

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);
 }
}


void ShowLine(int col){  //显示横着的虚线,作为行间隔

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

5.统计周围雷的个数(CountMines函数)

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';//本来减八个零,但是整形转字符加一个‘0'
}

由于数组中存放的是字符'0',周围是8个数字,所以-8*'0'才能返回雷数的int值,为了把数字也能打印出来,所以+‘0',否则打印的是数字作为的ASCLL码的值,最终的结果为-7*‘0'.

6.mine函数

int main()
{
 int quit = 0;
 int select = 0;
 while (!quit){
  Menu();
  printf("请输入 ");
  scanf("%d", &select);
  switch (select){
  case 1:
   Game();
   break;
  case 0:
   quit = 1;
   break;
  default:
   printf("输入错误,请重试!\n");
   break;
  }
 }

 printf("byebye!\n");

 system("pause");
 return 0;
}

四、总代码

#ifndef __Test_H__
#define __Test_H__

#include<stdio.h>
#include<Windows.h>
#include <stdlib.h>
#include <time.h>
#define WHAT '*'
#define NUM  20
#define COL  10
#define ROW  10
void Game();
#pragma warning(disable:4996)
#endif       //以上都是头文件

int main()
{
 int quit = 0;
 int select = 0;
 while (!quit){
  Menu();
  printf("请输入 ");
  scanf("%d", &select);
  switch (select){
  case 1:
   Game();
   break;
  case 0:
   quit = 1;
   break;
  default:
   printf("输入错误,请重试!\n");
   break;
  }
 }

 printf("byebye!\n");

 system("pause");
 return 0;
}


void Game()
{
 srand((unsigned long)time(NULL)); //生成随机数种子

 char show_board[ROW][COL];   
 char mines_board[ROW][COL];

 memset(show_board, WHAT, sizeof(show_board));
 memset(mines_board, '0', sizeof(mines_board));

 SetMines(mines_board, ROW, COL);

 int count = (ROW - 2)*(COL - 2) - NUM;    //若扫完这些次 不触雷则胜利

 while (count){
  system("cls");
  ShowBoard(show_board, ROW, COL);
  printf("请选择你要扫描的区域坐标 ");
  int x = 0;
  int y = 0;
  scanf("%d %d", &x, &y);
  if (x < 1 || x > ROW-2 || y < 1 || y > COL-2){ //非法性输入判断
   printf("输入错误!\n");
   continue;
  }
  if (show_board[x][y] != WHAT){           
   printf("此处已经被扫过了,请从新输出\n");
   continue;
  }
  if (mines_board[x][y] == '1'){
   system("cls");
   ShowBoard(mines_board, ROW, COL);
   printf("踩雷了!游戏结束!\n");
   break;
  }
  
  show_board[x][y] = CountMines(mines_board, x, y);
  count--;
 }
}


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';//本来减八个零,但是整形转字符加一个‘0'
}

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);
 }
}

oid 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--;
  }
 }
}
void ShowLine(int col){

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

Menu(){   //用户交互函数
 printf("########################\n");
 printf("# 1. Play       0.Exit #\n");
 printf("########################\n");
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • 详解C++编程中的vector类容器用法

    详解C++编程中的vector类容器用法

    vector是一个标准库中的容器,使用时需要包含#include <vector>头文件,也可以说vector是一个类模板而不是一种数据类型,对它的定义,需要指定类型,需要的朋友可以参考下
    2016-05-05
  • C++ 中 socket编程实例详解

    C++ 中 socket编程实例详解

    这篇文章主要介绍了C++ 中 socket编程实例详解的相关资料,需要的朋友可以参考下
    2017-06-06
  • c++用指针交换数组的实例讲解

    c++用指针交换数组的实例讲解

    下面小编就为大家分享一篇c++用指针交换数组的实例讲解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-11-11
  • C语言实现红黑树的实例代码

    C语言实现红黑树的实例代码

    这篇文章主要介绍了C语言实现红黑树的实例代码,有需要的朋友可以参考一下
    2013-12-12
  • C++使用GDAL库实现Tiff文件的读取

    C++使用GDAL库实现Tiff文件的读取

    这篇文章主要为大家详细介绍了C++使用GDAL库实现Tiff文件的读取的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-03-03
  • C语言连续生成多个随机数实现可限制范围

    C语言连续生成多个随机数实现可限制范围

    这篇文章主要介绍了C语言连续生成多个随机数实现可限制范围,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • C语言 一级指针与二级指针详细介绍

    C语言 一级指针与二级指针详细介绍

    这篇文章主要介绍了C语言 一级指针与二级指针详细介绍的相关资料,需要的朋友可以参考下
    2016-10-10
  • c语言B树深入理解

    c语言B树深入理解

    B树是为磁盘或其他直接存储设备设计的一种平衡查找树,本文将详细介绍c语言B树,需要的朋友可以参考下
    2012-11-11
  • C语言模拟实现memmove的示例代码

    C语言模拟实现memmove的示例代码

    memmove函数用于拷贝字节,如果目标区域和源区域有重叠的话,memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中,但复制后源内容会被更改。本文主要介绍了C语言模拟实现memmove的示例代码,需要的可以参考一下
    2022-12-12
  • C++冒泡排序及其优化算法

    C++冒泡排序及其优化算法

    这篇文章主要为大家介绍了C++冒泡排序及其优化算法示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2021-11-11

最新评论