C语言——扫雷游戏

简单方法实现扫雷游戏

要求:

1:第一下输入坐标,不炸死。
2:坐标周围没有雷,可以实现展开。


思想:
(一)用一个测试函数test()完成用户的整个游戏体验,放在主函数中。
(二)test()函数中应该完成的内容:菜单选择和游戏部分。
菜单选择即menu()函数;
游戏部分即game()函数;
因为是游戏,所以以用户体验为先,先让用户玩一把。在这应该使用do…while()语句。
!!!
(三)game()函数的具体实现:
同三子棋游戏,给game函数单独创建一个源文件。
扫雷游戏的思想:

首先需要一个雷盘存放雷;
1,雷盘有行和列,因此应该定义一个二维数组。ROW为行,COL为列。
在扫雷的过程中,如果选择一个坐标,则会计算周围坐标的雷数。如果输入坐标为(0,0),则该坐标周围并非都是坐标,无法计算,因此在设计雷盘时应该大一圈。定义为mine[ROWS][COLS],定义ROWS=ROW+2,COLS=COL+2。
雷盘数组——mine[ROWS][COLS]

2,当输入一个坐标时,会计算周围坐标的雷数,如果把计算后的雷数直接放在雷盘中,则下一个坐标计算时就会出错,因此应该定义一个新的数组用来存放雷的信息information[ROWS][COLS]。该数组应该和雷盘数组一样大。
存放雷信息的数组——information[ROWS][COLS]

3,两个数组中都存放字符。
4,给两个数组赋初值。——InItFirst()

5,布雷——SetMine()

6,展示雷盘数组,展示信息数组——Display()

7,排查雷——FimdMine()

排查雷的过程中:
需要一个函数实现计算该坐标周围雷数——MineCount()

输入一个坐标,坐标周围没有雷,实现坐标展开 ——OpenMine()

如果输入的第一个坐标为雷,不能让用户被炸死,转移雷的位置
——FirstMine()



具体代码如下:
1:将所有的重定义,函数声明,引用的头文件放在创建的头文件中

#ifndef  __GAME__H__
#define  __GAME__H__

#define ROW 9
#define COL 9
#define ROWS ROW + 2
#define COLS COL + 2
#define COUNT 10

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void InItFirst(char arr[ROWS][COLS], int rows, int cols,char set);
void SetMine(char mine[ROWS][COLS], int row, int col);
void Display(char arr[ROWS][COLS], int row, int col);
void FimdMine(char mine[ROWS][COLS],char information[ROWS][COLS], int row, int col);
int MineCount(char mine[ROWS][COLS], int x, int y);
void FirstMine(char mine[ROWS][COLS], int i, int j);
void OpenMine(char mine[ROWS][COLS], char information[ROWS][COLS], int x, int y);

#endif  __GAME__H__

2,主函数部分代码如下

#define _CRT_SECURE_NO_WARNINGS
#include "game.h"


//打印菜单
void menu()
{
 printf("*********************\n");
 printf("****** 1. play ******\n");
 printf("****** 0. exit ******\n");
 printf("*********************\n");
}

//游戏部分
void game()
{
 srand((unsigned)time(NULL));
       //需要两个二维数组。一个数组存放雷和非雷。另外一个存放排查之后雷的信息
       //   数组中存放字符,不能存放数字
 char mine[ROWS][COLS] = { 0 };
 char information[ROWS][COLS] = { 0 };
       //给两个数组分别赋初值
 InItFirst(mine, ROWS, COLS,'0');
 InItFirst(information, ROWS, COLS,'*');
       //布雷
 SetMine(mine,ROW,COL);
       //打印雷盘
 Display(mine, ROW, COL);
 Display(information, ROW, COL);
      //排查雷
 FimdMine(mine, information, ROW, COL);
}


//测试函数
void test()
{
 int input = 0;
 do
 {
  menu();
  scanf("%d", &input);
  switch (input)
  {
  case 1:
   game();
   break;
  case 0:
   printf("退出游戏!!!");
   break;
  default:
   break;
  }
 } while (input);
}
int main()
{
 test();
 system("pause");
 return 0;
}

3,游戏部分代码如下

//扫雷游戏
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"

//赋初值
void InItFirst(char arr[ROWS][COLS], int rows, int cols, char set)
{
 int i = 0;
 int j = 0;
 for (i = 0; i < rows; i++)
 {
  for (j = 0; j < cols; j++)
  {
   arr[i][j] = set;
  }
 }
}

//布雷
void SetMine(char mine[ROWS][COLS], int row, int col)
{
 int count = COUNT;
 while (count > 0)
 {
  int i = rand() % row + 1;
  int j = rand() % col + 1;
  if (i >= 1 && i <= row && j >=1 && j <= col)
  {
   if ('0' == mine[i][j])
   {
    mine[i][j] = '1';
    count--;
   }
  }
 }
}

//展示布局,可展示雷盘,也可展示信息盘,根据情况而定
void Display(char arr[ROWS][COLS], int row, int col)
{
 int i = 0;
 int 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 ", arr[i][j]);
  }
  printf("\n");
 }
}

//保证第一下不被炸死,如果输入的第一个坐标是雷,则交换雷的位置,将一个非雷与雷交换
void FirstMine(char mine[ROWS][COLS], int i, int j)
{
 int x = rand() % ROW + 1;
 int y = rand() % COL + 1;
 mine[i][j] = '0';
 while (1)
 {
  if (x >= 1 && x <= ROW && y >= 1 && y <= COL)
  {
   if ('0' == mine[x][y])
   {
    mine[x][y] = '1';
    break;
   }
  }
 }
}

//计算该坐标周围雷的个数
int MineCount(char mine[ROWS][COLS], 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';
}

//若输入坐标周围雷数为0,则展开周围一周,直至雷数为0
void OpenMine(char mine[ROWS][COLS],char information[ROWS][COLS], int x, int y)
{
 int i = 0;
 int j = 0;
 if (x >= 1 && x <= ROW && y >= 1 && y <= COL)
 {
  if (MineCount(mine,x,y) == 0)
  {
   information[x][y] = '0';
   for (i = x - 1; i <= x + 1; i++)
   {
    for (j = y - 1; j <= y + 1; j++)
    {
     if (information[i][j] == '*')
     {
      OpenMine(mine, information, i, j);
     }
    }
   }
  }
  else
  {
   information[x][y] = MineCount(mine, x, y)+'0';
  }
 }
}

//排查雷
void FimdMine(char mine[ROWS][COLS], char information[ROWS][COLS], int row, int col)
{
 int ret = 0;
 int allcount = 0;
       //如何判断游戏成功
 while (1)
 {
  int win = 0;
  int i = 0;
  int j = 0;
        //int count = 0;
  allcount++;
  printf("请输入坐标:>");
  scanf("%d%d", &i, &j);
       //判断坐标是否有效
  if (i >= 1 && i <= row && j >= 1 && j <= col)
  {
         //判断该坐标是否为雷
   if ('1' == mine[i][j])
   {
    if (allcount == 1)
    {
           //如果输入的第一个坐标为雷,则交换一个非雷到该位置
     FirstMine(mine, i, j);
     continue;;
    }
    else
    {
     printf("你被炸死了!!!游戏结束!\n");
     Display(mine, row, col);
     break;
    }
   }
   else
   {
    OpenMine(mine, information, i, j);
    for (i = 1; i <= row; i++)
    {
     for (j = 1; j <= col; j++)
     {
      if (information[i][j] != '*')
      {
       win++;
      }
     }
    }
    Display(information, ROW, COL);
   }
  }
  else
  {
   printf("输入的坐标无效!请重新输入!!!\n");
  }
  if (win == row*col - COUNT)
  {
   printf("恭喜你!游戏成功!!!\n");
   break;
  }
 }
}

猜你喜欢

转载自blog.csdn.net/xmfjmcwf/article/details/83450462