扫雷——Windows上的经典小游戏

前言

利用C/C++实现简易版扫雷,扫雷,一款很多人都玩不明白的游戏,其实这个游戏原理很简单,就是通过你的第一次下坐标排雷(大概率不会被炸死)来说明周围有几颗雷,就是你所下坐标的周边八个位置,1表示有一颗雷,2表示有两颗,以此类推。

扫雷——Windows上的经典小游戏_第1张图片

看到这里可能有的同学已经知道怎么玩这个小游戏了,我这里把游戏获胜的图放出来

扫雷——Windows上的经典小游戏_第2张图片

说了这么多总算是到今天的主角出场了:利用简单的C/C++写出这个小游戏

实现思路

将雷区看作一个n行m列的二维数组,将雷埋在实际雷区中,将玩家输入的坐标与实际雷区中的坐标进行比较,坐标相同则视为踩雷,游戏结束;若不同则视为此坐标排雷成功,通过函数计算出周围雷的数量并将值其赋给镜像雷区,输出给玩家看,起到提示作用,最终通过函数与最开始的预计安全位进行比较,若相等则判定玩家胜利,游戏结束。 所以大概游戏流程为:打印菜单——选择开始——初始化雷区——布置雷——玩家输入坐标——排查雷——结束游戏

同昨天的三子棋一样,使用三个文件,即6_9.c、game2.c、game2.h

文件概述

6_9.c

程序主体,包含main函数、game函数及menu函数,其中srand函数值得注意

game.c

这个源文件主要是实现game函数中的各种功能函数,如初始化雷区函数Rec_board、打印雷区函数Put_board、放置雷函数Put_Boom、判断周围雷数量函数find_boom_num及排雷函数Find_Boom

game.h

自定义的头文件,里面包含了各种声明、各种变量宏定义及各种函数定义

在正式开始之前还是先说明下实际雷区镜像雷区实际雷区就布置雷用的数组,而镜像雷区是给玩家看的数组,两个雷区各司其职,以确保程序正常运行,实际雷区镜像雷区除内容外其他完全一致!

扫雷——Windows上的经典小游戏_第3张图片

代码

6_9.c

#define _CRT_SECURE_NO_WARNINGS 1//屏蔽“scanf 4996”问题

#include"game2.h"//stdio.h包含于此

void menu()

{
  printf("\n$$$$$$$$$$$$$$$$$$$$$$\n");

  printf("$$$$$$  1.Paly  $$$$$$\n");

  printf("$$$$$$  0.Exit  $$$$$$\n");

  printf("$$$$$$$$$$$$$$$$$$$$$$\n\n");

}//菜单

void game()

{
  char mine[ROWS][COLS] = { 0 };//定义数组

  char show[ROWS][COLS] = { 0 };



  Rec_board(mine,ROWS,COLS,'0');//初始化实际雷区为'0'

  Rec_board(show, ROWS, COLS, '*');//初始化镜像雷区为*



  //Put_board(mine, ROW, COL);//测试用

  Put_board(show, ROW, COL);//打印镜像雷区



  //布置雷

  Put_Boom(mine, ROW, COL);

  //Put_board(mine, ROW, COL);//开挂用



  //排查雷

  Find_Boom(mine, show, ROW, COL);

}//游戏本体

int main()

{
  srand((unsigned int)time(NULL));//通过time获取当前时间戳和srand配合,生成随机数

  int input = 0;

  do

  {

    menu();//菜单

    printf("选择:>");

    scanf("%d", &input);

    switch (input)//三种选择结果

    {

    case 1:

        printf("开始游戏!\n");

        game();

        break;

    case 0:

        printf("退出游戏!\n");

        break;

    default:

        printf("输入有误,请重新输入!\n");

        break;

    }

  } while (input);

  return 0;

}

game2.c

#define _CRT_SECURE_NO_WARNINGS 1//屏蔽4996问题

#include"game2.h"

int i = 0;

int j = 0;

void Rec_board(char board[ROWS][COLS], int rows, int cols, char set)

{
  for (i = 0; i < rows; i++)

  {

    for (j = 0; j < cols; j++)

    {

        board[i][j] = set;

    }

  }//棋盘默认为11*11规格,但只用9*9的大小,其他防止寻找周围雷数时越界!

}//初始化雷区,set是雷区或镜像雷区所需要的值,有可能是'0'或*

void Put_board(char board[ROWS][COLS], int row, int col)

{
  printf("-------扫雷-------\n");

  for (j = 0; j <= col; j++)//打印纵坐标

    printf("%d ", j);

  printf("\n");

  for (i = 1; i <= row;i++)

  {

    printf("%d ", i);//打印横坐标

    for (j = 1; j <= col; j++)

    {

        printf("%c ",board[i][j]);

    }

    printf("\n");

  }

  printf("-------扫雷-------\n");

}//打印镜像雷区,跟三子棋差不多的逻辑

void Put_Boom(char board[ROWS][COLS], int row, int col)

{
  int count = Boom;

  int i = 0;

  while (count)

  {

        int x = rand() % row + 1;//+1是因为,要用到1到9的雷区,如果不+1,只能得到0到8的雷区

        int y = rand() % col + 1;//同理

        if (board[x][y] == '0')

        {

            board[x][y] = '1';// '1'代表雷

            count--;//布置成功一颗 -1

        }//只有雷布置成功了。count才--,才能跳出while

  }

}//放置雷

int find_boom_num(char board[ROWS][COLS], 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][y + 1] + board[x + 1][y - 1] + board[x + 1][y] + board[x + 1][y + 1] - 8 * '0';

}//判断周围有几颗雷

void Find_Boom(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)

{

  int count = 0;//记录周边雷数

  while (count < row * col - Boom)

  {
    int x = 0;

    int y = 0;

    int input = 0;
    printf("请输入一个坐标用以排雷:>");
  
    scanf("%d %d", &x, &y);

  if (mine[x][y] == '1')

   {

    printf("\n扫雷失败,你被炸死了!\n");

    Put_board(mine, ROW, COL);

    printf("\n\n\n请选择是否重新开始\n\n\n");

    break;

   }//失败情况

  else if (mine[x][y] != '1')

   {

    int num = find_boom_num(mine, x, y);

    show[x][y] = num + '0';

    Put_board(show, ROW, COL);

    count++;

   }//成功情况,主要是获取周围雷数,然后将其赋给镜像雷区



  if (count == row * col - Boom)

   {

    printf("\n恭喜排雷成功!\n");

    Put_board(show, ROW, COL);

   }//排雷成功的情况

  }

}

game2.h

#pragma once//自定义头文件自己生成的

#include

#include//srand和rand的头文件

#include//time函数的头文件

#define ROW 9//宏定义行

#define COL 9//宏定义列

#define ROWS ROW+2//“缓冲区”

#define COLS COL+2//“缓冲区”

#define Boom 10//宏定义雷数

void Rec_board(char board[ROWS][COLS], int rows, int cols, char set);

//初始化雷区和镜像雷区

void Put_board(char board[ROWS][COLS], int row, int col);

//主要打印镜像雷区,实际雷区处于隐藏状态

void Put_Boom(char board[ROWS][COLS], int row, int col);

//放置雷

void Find_Boom(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col);

//排查雷

代码实现页面

扫雷——Windows上的经典小游戏_第4张图片

这是个代码间的关系

扫雷——Windows上的经典小游戏_第5张图片

这是初始运行页面

扫雷——Windows上的经典小游戏_第6张图片

首次坐标输入界面

扫雷——Windows上的经典小游戏_第7张图片

一不注意就被炸死了

扫雷——Windows上的经典小游戏_第8张图片

扫雷成功界面,不建议用9*9的盘玩,因为界面、功能不完善,很难获胜

因为行ROW和列COL是全局宏定义的变量,因此可以轻而易举的更改达到扩大雷区的效果

扫雷——Windows上的经典小游戏_第9张图片

在这里更改

扫雷——Windows上的经典小游戏_第10张图片

看看5*5超小页面

总结

扫雷游戏跟三子棋游戏本质上是一样的,都有三个必要条件初始化棋盘(雷区)、玩家输入坐标、电脑生成随机坐标。回看整个代码,无非就是各种函数模块的拼接,难点也不过是理解数组内元素的比较与更换,总的来说,这些小游戏都是提前练手的好选择,在成为大牛的路上努力,加油吧!各位同学!

鸣谢

感谢比特鹏哥关于扫雷两个小时的讲解!

你可能感兴趣的:(C语言杂谈,c语言,c++)