【C language】扫雷

简介: 【C language】扫雷

1.概要

为了提高C初学者对C语言基本语法的掌控能力,一个极简版的扫雷游戏是十分适合锻炼代码能力的。下面分享仅用数组、函数这些C语言基本语法实现的一个小游戏——“Minesweeper”。

我需要说明的是仅仅是用来练习简单C语言基础语法代码能力的,而并非去尽力完善这个游戏,当然自己有时间有能力也可以去自己完善一下。

2.实现核心思想

用两个二维数组,一个数组用来对外展示,我们称之为show,另一个mine数组记录"雷"与"非雷"。

  • 对于show数组,默认是’*'状态,用来模拟未扫描的区域;倘若已经扫过了,且没有雷我们将其替换为该位置周围雷的数量。
  • 对于mine数组,我们’0’标识非雷,'1’标识雷。

    同时,因为要在下文统计到某个位置周围雷的个数,为了防止数组越界,因而对该棋盘周围多加一圈。

3.实现过程

我们设计的小游戏,整体用三个文件来进行设计的。

  • game.c文件:用来实现具体核心游戏函数
  • game.h文件:用来作为该游戏的小目录,包括一些宏定义和函数声明
  • Test.c文件:用来实现游戏的整体框架以及测试

3.1游戏框架

设计一个很简单的游戏框架是一个游戏设计的开始。该内容没有什么重点,略。

// Test.c文件中
void menu()
{
  printf("---------------------\n");
  printf("-----1.play game-----\n");
  printf("-----0.exit game-----\n");
  printf("---------------------\n");
}
TestGame()
{
  srand((unsigned int)time(0));
  int input = 0;
  do
  {
    menu();
    printf("Input options, please:\n");
    scanf("%d", &input);
    switch (input)
    {
    case 1:
      printf("Minesweeper begins!\n");
      game();
      break;
    case 0:
      printf("Successfully exited the game\n");
      break;
    default:
      printf("The input value is invalid\n");
      break;
    }
  } while (input);
}
int main()
{
  TestGame();
  return 0;
}

实现好了游戏的整体框架,我们要来想一想这个游戏该怎么做了。

3.2游戏逻辑

  • 初始化棋盘:首先我们得准备两个二维数组来当作棋盘,并初始化其值。
  • 打印show棋盘:打印要对外展示的棋盘。
  • 设置雷:在mine棋盘中设置雷,用’1’进行标识
  • 扫雷:玩家输入坐标并接收,然后作出反馈

然后对于我们要在上面框架中写的game(),我们就得出下面游戏逻辑:

#include"game.h"
void game()
{
  char Mine[ROWS_MAX][COLS_MAX];
  char show[ROWS_MAX][COLS_MAX];
  MineInit(Mine, ROWS_MAX, COLS_MAX, '0');
  MineInit(show, ROWS_MAX, COLS_MAX, '*');
  printf("----------Minesweeper interface-----------\n");
  //MinePrint(Mine, ROW_MAX, COL_MAX);
  MinePrint(show, ROW_MAX, COL_MAX);
  SetMines(Mine, ROW_MAX, COL_MAX);
  ClearMines(Mine, show, ROW_MAX, COL_MAX);
}

具体的game.h文件内容如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>
#define ROW_MAX 9
#define COL_MAX 9
#define ROWS_MAX ROW_MAX + 2
#define COLS_MAX COL_MAX + 2
#define MINE_COUNT 5
void MineInit(char(*arr)[COLS_MAX], int rows, int cols, char val);
void MinePrint(char(*arr)[COLS_MAX], int row, int col);
void SetMines(char(*arr)[COLS_MAX], int row, int col);
void ClearMines(char(*Mine)[COLS_MAX], char(*Show)[COLS_MAX], int row, int col);

初始化棋盘 MineInit

那如何进行初始化棋盘呢?因为有两个棋盘,一个需要置0,另一个需要置✳

这里需要指出的是不需要写两个函数哈,只需要把需要初始化的值当作参数传入函数里就可以通过一个函数来处理了。

void MineInit(char(*arr)[COLS_MAX], int rows, int cols, char val)
{
  for (int i = 0; i < rows; i++)
  {
    for (int j = 0; j < cols; j++)
    {
      *(*(arr + i) + j) = val;
    }
  }
}

打印棋盘 MinePrint

对棋盘里的值进行打印即可,双重嵌套循环即可。

其中,第一个循环是为了打印显示中的行号。

void MinePrint(char(*arr)[COLS_MAX], int row, int col)
{
  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 ", *(*(arr + i) + j));
    }
    printf("\n");
  }
  printf("----------Minesweeper interface-----------\n");
}

设置雷 SetMines

这里用一个随机数即可,需要注意设置雷的条件是之前不是雷才行,重复设置(同一位置)的不算。

void SetMines(char(*arr)[COLS_MAX], int row, int col)
{
  size_t count = 0;
  while (count < MINE_COUNT)
  {
    int x = rand() % 9 + 1;
    int y = rand() % 9 + 1;
    if (*(*(arr + x) + y) == '0')
    {
      *(*(arr + x) + y) = '1';
      count++;
    }
  }
}

扫雷 ClearMines

扫雷的话要一边展示show信息,一边接收用户输入的行号列号并给出对应的反馈即可。

这里需要注意的是拿到一个位置多少个雷后要用char的形式存入show中,而不是int的形式。

int GetMines(char(*Mine)[COLS_MAX], int x, int y)
{
  return (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');
}
void ClearMines(char (*Mine)[COLS_MAX], char(*Show)[COLS_MAX], int row, int col)
{
  int sum = ROW_MAX * COL_MAX - MINE_COUNT;
  int count = 0;
  while (count < sum)
  {
    //MinePrint(Mine, row, col);
    MinePrint(Show, row, col);
    printf("Enter the coordinates you want to check\n");
    
    int x = 0, y = 0;
    scanf("%d%d", &x, &y);
    if (x >= 1 && y <= 9)
    {
      if (Mine[x][y] == '1')
      {
        printf("Sorry, you were killed.\n");
        printf("Below is the mine layout diagram for this game:\n");
        MinePrint(Mine, row, col);
        //MinePrint(Show, row, col);
        break;
      }
      else
      {
        int z_count = GetMines(Mine, x, y);
        if (Show[x][y] == '*') count++;
        else printf("This location has been scanned and is invalid.\n");
        Sleep(1000);
        Show[x][y] = z_count + '0';
        //MinePrint(Mine, row, col);
        MinePrint(Show, row, col);
      }
    }
    else
    {
      printf("The coordinates you entered are out of bounds\n");
    }
  }
  
  if (count == sum)
  {
    printf("Congratulations, the mine clearance was successful!!!\n");
  }
}

4.总结

整体来说,该游戏是用来复习基本语法知识的,比较简单,游戏逻辑清晰明了,功能单一,适合C初学者。


EOF


相关文章
|
6月前
|
C语言
C语言-------扫雷游戏的代码实现
C语言-------扫雷游戏的代码实现
49 0
|
C语言
【C语言】小游戏--三子棋(下)
【C语言】小游戏--三子棋(下)
|
C语言
【C语言】小游戏--三子棋(上)
【C语言】小游戏--三子棋(上)
|
2月前
|
存储 安全 算法
C 语言——实现扫雷小游戏
本文介绍了使用二维数组创建棋盘并实现扫雷游戏的方法。首先,通过初始化数组创建一个9x9的棋盘,并添加行列标识以便操作。接着,利用随机数在棋盘上布置雷。最后,通过判断玩家输入的坐标来实现扫雷功能,包括显示雷的数量和处理游戏胜利或失败的情况。文中提供了完整的代码实现。
45 1
C 语言——实现扫雷小游戏
|
C语言
C语言小游戏--三子棋
使用C语言来实现儿时玩的小游戏--三子棋,简单易上手,快来试试吧!
98 1
|
程序员
三子棋——so easy!
然后这个test函数里就放一个简易菜单menu()然后再使用do while 这个循环,因为至少要显示一遍如果不想玩才可以关掉。菜单中显示输入1,进入游戏输入0退出游戏。所以我梦需要定义一个变量intput 使用switch(intput)来选择。而注意这个 intput这个变量要放在循环体外面定义。如何在里面定义那么后面while(intput)里面的intput就没有效果。intput的使用范围只在循环体里了。然后你也应该可以看到,这时do while()条件结束也就是intput为0时,这就和上面一致了。好啦基本框架弄好了
88 0
|
Java
hdu2147 kiki's game(巴什博弈java)
意思是一个棋子只能往左面,下面,或者左下走。不能走的那个输。kiki先走。
87 0
|
JavaScript 前端开发 Python
手把手教你使用JavaScript打造一款扫雷游戏
手把手教你使用JavaScript打造一款扫雷游戏
238 0
手把手教你使用JavaScript打造一款扫雷游戏
c语言项目---三子棋
c语言项目---三子棋