C语言实现扫雷游戏

简介: C语言实现扫雷游戏

和我们之前的三子棋一样,扫雷的核心思想也是二维数组的利用

今天我们就来试着利用数组的知识来实现扫雷游戏

1.扫雷实现的逻辑

跟三子棋一样,我们首先创建三个文件:game.h , game.c , test.c

  • 1.用define定义常量,定义数组的行和列,这样改变数组行列不需要整个修改代码,只需要改变define后面定义常量的值;
  • 2.需要一个菜单来供我们选择进入游戏还是退出游戏,menu函数;
  • 3.玩游戏肯定不止玩一局,所以需要设置循环do...while;
  • 4.需要俩个数组,一个用来设置雷(mine),存放雷的信息;一个用来让玩家排查雷(show),存放玩家输入的坐标信息;
  • 5.需要初始化俩个数组,我们把要埋雷的数组初始化为’0‘,要排雷的数组初始化为’*‘;
  • 6.需要打印棋盘让玩家来排雷;
  • 7.需要设置雷和排雷函数;

2.游戏的实现

2.1打印菜单

定义一个menu()函数来打印菜单

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

2.2玩家选择

我们在main()中采取do-while循环来实现重复游戏,用switch()来获取玩家的选择

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

目前我们的实现效果是这样的

2.3游戏实现扫雷的逻辑

1.布置雷的逻辑

假设我们实现一个9*9的棋盘,上面布置十个雷

这样我们就需要一个9*9的数组来存放雷

假设这是我们的棋盘

最开始每个位置都放0;0表示非雷

当我们布置雷的时候,把雷放成1

2.排雷的第一种情况

假设我们在排这个绿色坐标的时候,它不是雷,这时候我们需要统计它周围红圈中8个坐标的雷的个数;像上面这种情况,我们需要显示1;但是这个1会与我们表示雷的1冲突,为了解决这个问题,我们再单独给他一个数组,全部放成 ‘ * ’ ;

这个时候,我们在 ‘ * ’ 棋盘中,对应的位置显示‘1’表示这个坐标周围的八个坐标里有一个雷;我们给玩家展示的时候,展示第2个数组

  • 第一个棋盘存雷和非雷的信息
  • 第二个棋盘存玩家排查出来的雷的信息

3.排雷的第二种情况

假设我们要排查边缘的这个坐标,这个是超出了我们9*9的数组范围

这个时候为了防止越界,我们再把这个数组扩充,即在设置存雷的数组的时候,范围设置成11*11

像这样

这个时候,就不存在越界行为了

为了便于计算,我们的展示棋盘同样扩大到11*11(严丝合缝);

2.4棋盘的初始化

我们定一个InitBoard()函数来初始化棋盘

定义两个11*11的数组

这个数组用来放布置好的雷的信息(11*11)

这个数组用来放排查出的雷的信息(11*11)

为了保证两个数组严格的统一,包括元素类型也要统一,我们定义为char数组

game.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);

game.c

//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
  int i = 0, j = 0;
  for (i = 0; i < rows; i++) {
    for (j = 0; j < cols; j++) {
      board [i][j] = set;
    }
  }
}

test.c

void game() {
  char mine[ROWS][COLS] = { 0 };
  char show[ROWS][COLS] = { 0 };
  InitBoard(mine, ROWS, COLS, '0');
  InitBoard(show, ROWS, COLS, '*');
}

2.5打印棋盘

我们定义一个DisplayBoard()函数来打印棋盘

在打印的时候,我们可以打印出坐标

1.代码

game.c

//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col) {
  int i = 0, j = 0;
  for (i = 0; i <= col; i++) {
    printf("%d ", i);
  }
  printf("\n");
  for (i = 1; i <= row; i++) {
    printf("%d ", i);
    for (j = 1; j <= col; j++){
      printf("%c ", board[i][j]);
    }
    printf("\n");
  }
}

test.c

void game() {
  char mine[ROWS][COLS] = { 0 };
  char show[ROWS][COLS] = { 0 };
  InitBoard(mine, ROWS, COLS, '0');
  InitBoard(show, ROWS, COLS, '*');
  DisplayBoard(mine, ROW, COL);
  DisplayBoard(show, ROW, COL);
}

2.打印效果

2.6布置雷

我们定义一个setMine()函数来布置雷

假设我要布置十个雷

  • 随机布置
  • 用1表示雷

这里我们又要用到我们的随机数函数rand(),使用rand函数必然需要在main()函数中调用srand();

//布置雷
void setMine(char mine[ROWS][COLS], int row, int col) {
  int count = EASY_COUNT;
  while (count) {
    int x = rand() % row + 1;
    int y = rand() % col + 1;
    if (mine[x][y] == '0') {
      mine[x][y] = '1';
      count--;
    }
  }
}

2.7排雷

排查雷的逻辑是:

  1. 如果这个位置不是雷,就计算这个位置周围八个坐标有几个雷,并显示雷的个数
  2. 如果这个位置是雷,就炸死了,游戏结束
  3. 如果把不是雷的位置都找出来了,那么游戏也结束,玩家胜利

在扫雷的过程中,我们还需要计算周围雷的个数

定义一个GetMineCount()函数来统计周围雷的个数

int GetMineCount(char mine[ROWS][COLS], int x, int y) {
  return(mine[x - 1][y] +
    mine[x - 1][y - 1] +
    mine[x][y - 1] +
    mine[x + 1][y - 1] +
    mine[x + 1][y] +
    mine[x + 1][y + 1] +
    mine[x][y + 1] +
    mine[x - 1][y + 1] - 8 * '0');
}

定义一个FindMine()函数来排查雷

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 - EASY_COUNT) {
    printf("请输入要排查雷的坐标:");
    scanf("%d %d", &x, &y);
    if (x >= 1 && x <= row && y >= 1 && y <= col) {
      if (show[x][y] == '*') {
        if (mine[x][y] == '1') {
          printf("很遗憾,你被炸死了\n");
          DisplayBoard(show, ROW, COL);
          break;
        }
        else {
          int count = GetMineCount(mine, x, y);
          show[x][y] = count + '0';
          DisplayBoard(show, ROW, COL);
          win++;
        }
      }
      else {
        printf("该坐标已经被排查了\n");
      }
    }
    else {
      printf("非法坐标,请重新输入\n");
    }
  }
  if (win == row * col - EASY_COUNT) {
    printf("恭喜你,排雷成功\n");
    DisplayBoard(mine, ROW, COL);
  }
}

2.8game()函数

void game() {
  char mine[ROWS][COLS] = { 0 };
  char show[ROWS][COLS] = { 0 };
  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);
}

3.源代码

game.h

#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define EASY_COUNT 10//十个雷
//初始化棋盘
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 1
#include"game.h"
//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
  int i = 0, j = 0;
  for (i = 0; i < rows; i++) {
    for (j = 0; j < cols; j++) {
      board [i][j] = set;
    }
  }
}
//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col) {
  int i = 0, j = 0;
  printf("--------扫雷--------\n");
  for (i = 0; i <= col; i++) {
    printf("%d ", i);
  }
  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 setMine(char mine[ROWS][COLS], int row, int col) {
  int count = EASY_COUNT;
  while (count) {
    int x = rand() % row + 1;
    int y = rand() % col + 1;
    if (mine[x][y] == '0') {
      mine[x][y] = '1';
      count--;
    }
  }
}
//扫雷
int GetMineCount(char mine[ROWS][COLS], int x, int y) {
  return(mine[x - 1][y] +
    mine[x - 1][y - 1] +
    mine[x][y - 1] +
    mine[x + 1][y - 1] +
    mine[x + 1][y] +
    mine[x + 1][y + 1] +
    mine[x][y + 1] +
    mine[x - 1][y + 1] - 8 * '0');
}
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 - EASY_COUNT) {
    printf("请输入要排查雷的坐标:");
    scanf("%d %d", &x, &y);
    if (x >= 1 && x <= row && y >= 1 && y <= col) {
      if (show[x][y] == '*') {
        if (mine[x][y] == '1') {
          printf("很遗憾,你被炸死了\n");
          DisplayBoard(show, ROW, COL);
          break;
        }
        else {
          int count = GetMineCount(mine, x, y);
          show[x][y] = count + '0';
          DisplayBoard(show, ROW, COL);
          win++;
        }
      }
      else {
        printf("该坐标已经被排查了\n");
      }
    }
    else {
      printf("非法坐标,请重新输入\n");
    }
  }
  if (win == row * col - EASY_COUNT) {
    printf("恭喜你,排雷成功\n");
    DisplayBoard(mine, ROW, COL);
  }
}

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu() {
  printf("******************\n");
  printf("***** 1.play *****\n");
  printf("***** 0.exit *****\n");
  printf("******************\n");
}
void game() {
  char mine[ROWS][COLS] = { 0 };
  char show[ROWS][COLS] = { 0 };
  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() {
  srand((unsigned int)time(NULL));
  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;
}

4.总结

这就是扫雷的全部过程了,希望对各位有帮助4

今天我们练习写出了扫雷游戏,这是一个不错的进步,对数组有了更多的理解

小杜跟各位小伙伴在一起成长,祝我们都能成为大牛!

                                                                                                                               //小杜的成长之路

相关文章
|
2月前
|
C语言
扫雷游戏(用C语言实现)
扫雷游戏(用C语言实现)
106 0
|
28天前
|
C语言 Windows
C语言课设项目之2048游戏源码
C语言课设项目之2048游戏源码,可作为课程设计项目参考,代码有详细的注释,另外编译可运行文件也已经打包,windows电脑双击即可运行效果
32 1
|
2月前
|
编译器 C语言
猜数字游戏实现#C语言
猜数字游戏实现#C语言
87 1
|
2月前
|
存储 C语言
揭秘C语言:泊舟的猜数字游戏
揭秘C语言:泊舟的猜数字游戏
|
2月前
|
存储 算法 安全
C语言实现扫雷游戏
C语言实现扫雷游戏
|
2月前
|
C语言
初学者指南:使用C语言实现简易版扫雷游戏
初学者指南:使用C语言实现简易版扫雷游戏
39 0
|
2月前
|
C语言
C语言扫雷游戏(详解)
C语言扫雷游戏(详解)
42 0
|
2月前
|
程序员 C语言
初识C语言之三子棋游戏
初识C语言之三子棋游戏
37 0
|
2月前
|
C语言
初识C语言3——函数(以猜数字游戏为例)
初识C语言3——函数(以猜数字游戏为例)
71 0
|
2月前
|
存储 编译器 C语言
【C语言篇】数组和函数的实践:扫雷游戏(附源码)
【C语言篇】数组和函数的实践:扫雷游戏(附源码)
39 0