扫雷游戏C语言实现

用C语言代码实现扫雷游戏

要求:
1.第一次下子,不炸死。
2.坐标周围没雷,可以实现展开。

首先,需要创立一个game.h的头文件,以及game.c的源文件,还有包括主函数的test.c文件,这与三子棋游戏的格式完全一致。
1.创建游戏菜单
扫雷游戏菜单格式与三子棋菜单基本一致,只是名字有所改动而已。可以仿照三子创建菜单。以及建立主函数,在此附上三子棋链接。
三子棋游戏C实现
2.创建game.c文件
2.1.初始化棋盘
利用memset函数进行初始化
(memset函数在<string.h>头文件中,具体用法如下:void *memset( void *dest, int c, size_t count );)
代码如下:

void c_mine(char Mine[ROWS][COLS], int row, int col)            //初始化棋盘
{
 memset(Mine, '0', row*col*sizeof(Mine[0][0]));
}
void c_show(char Mine[ROWS][COLS], int row, int col)
{
 memset(Mine, '*', row*col*sizeof(Mine[0][0]));
}

2.2.打印雷区

void Print(char Mine[ROWS][COLS], int row, int col)//打印雷区
{
 int i = 0;
 int j = 0;
 printf("--------------------\n");
 for ( i = 0; i <=row; i++)
 {
  printf("%d ", i);
 }
 printf("\n");
 for ( i = 1; i <=row; i++)
 {
  printf("%d ", i);
  for (j = 1; j <=col; j++)
  {
   printf("%c ", Mine[i][j]);
  }
  printf("\n");
 }
 printf("--------------------\n");
}

2.3.若第一次踩到雷,将其移走

static void moveMine(char Mine[ROWS][COLS], int x, int y)      //移动第一次踩到的雷
{
 int a = 0;
 int b = 0;
 while (1)
 {
  a = rand() % ROW + 1;
  b = rand() % COL + 1;
  if (Mine[a][b] != '1')
  {
   Mine[a][b] = '1';
   break;
  }
 }
 Mine[x][y] = '0';
}

2.4.随机放置雷
在头文件中可用宏定义设置雷的个数,在下面代码随机放置

void SetMine(char Mine[ROWS][COLS], int row, int col) //放置雷区
{
 int count = MINENUM;
 int x = 0;
 int y = 0;
 while (count!=0)
 {
  x = rand() % row + 1;//[0,9)[1,10)
  y = rand() % col + 1;
  if (Mine[x][y] =='0')
  {
   Mine[x][y] = '1';
   count--;
  }
 }
}

2.5.统计某一点周围的雷数

static int GetMine(char Mine[ROWS][COLS], int x, int y) //统计雷数
{
 //'1'-'0'=1
 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';
}

2.6.若坐标周围没雷,实现展开
利用递归实现,具体代码如下:

static int opeanMine(char Mine[ROWS][COLS], char Show[ROWS][COLS], int x, int y)    //用递归实现展开未知区域
{
 if (GetMine(Mine, x, y) == 0)
 {
  Show[x][y] = '0';
  if ((x - 1) >= 1 && (x - 1) <= ROW && (y - 1) >= 1 && (y - 1) <= COL&&Show[x - 1][y - 1] == '*')
   opeanMine(Mine, Show, x - 1, y - 1);
  if ((x) >= 1 && (x) <= ROW && (y - 1) >= 1 && (y - 1) <= COL&&Show[x][y - 1] == '*')
   opeanMine(Mine, Show, x, y - 1);
  if ((x + 1) >= 1 && (x + 1) <= ROW && (y - 1) >= 1 && (y - 1) <= COL&&Show[x + 1][y - 1] == '*')
   opeanMine(Mine, Show, x + 1, y - 1);
  if ((x + 1) >= 1 && (x + 1) <= ROW && (y) >= 1 && (y) <= COL&&Show[x + 1][y] == '*')
   opeanMine(Mine, Show, x + 1, y);
  if ((x + 1) >= 1 && (x + 1) <= ROW && (y + 1) >= 1 && (y + 1) <= COL&&Show[x + 1][y + 1] == '*')
   opeanMine(Mine, Show, x + 1, y + 1);
  if ((x) >= 1 && (x) <= ROW && (y + 1) >= 1 && (y + 1) <= COL&&Show[x][y + 1] == '*')
   opeanMine(Mine, Show, x, y + 1);
  if ((x - 1) >= 1 && (x - 1) <= ROW && (y + 1) >= 1 && (y + 1) <= COL&&Show[x - 1][y + 1] == '*')
   opeanMine(Mine, Show, x - 1, y + 1);
  if ((x - 1) >= 1 && (x - 1) <= ROW && (y) >= 1 && (y) <= COL&&Show[x - 1][y] == '*')
   opeanMine(Mine, Show, x - 1, y);
 }
 else
 {
  Show[x][y] = GetMine(Mine, x, y) + '0';
 }
 return 0;
}

2.7.判定赢的条件
若雷被排完,则游戏胜利

static int IsWin(char Mine[ROWS][COLS], int row, int col)        //判断赢
{
 int i = 0;
 int j = 0;
 int count = 0;
 for (i = 1; i <= row; i++)
 {
  for (j = 1; j <= col; j++)
  {
   if (Mine[i][j] == '*')
    count++;
  }
 }
 return count;
}

2.8.找雷过程
且必须判断是否为第一次踩到雷

int FindMine(char Mine[ROWS][COLS], char Show[ROWS][COLS], int row, int col)
{
    int x = 0;
    int y = 0;
    int flag = 1;
    while (MINENUM != IsWin(Show, row, col)) 
    {
         int count = 0;
         printf("请输入坐标:>");
         scanf("%d%d", &x, &y);
         if (x < 1 || x > row || y < 1 || y > col)
         {
             printf("非法坐标,");
         }
         else if (Show[x][y] != '*')
         {
             printf("该地区已被开辟,");
         }
         else if (Mine[x][y] == '1' && flag == 1)
         {
             moveMine(Mine, x, y);
             opeanMine(Mine, Show, x, y);
             system("cls");
             Print(Show, ROW, COL);
             flag = 0;
         }
         else if (Mine[x][y] == '1' && flag == 0)
         {
             printf("游戏结束,你被炸死了\n\n");
             Print(Mine, ROW, COL);
             return 0;
         }
         else if (Mine[x][y] == '0')
         {
             opeanMine(Mine, Show, x, y);
             system("cls");
             Print(Show, ROW, COL);
             flag = 0;
         }
    }
    printf("恭喜你,扫雷成功\n");
    return 0;
}

3.补充头文件
3.1.将game.c中没有被static修饰的函数移入头文件。
3.2.将game.c中没有被static修饰的函数移入test.c的game()函数下。
3.3.在主函数加入随机种子

4.最终所有代码如下

game.h

#pragma once                                    //预防头文件重复引入
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <time.h>

#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define MINENUM 10 //初始10个雷

void SetMine(char Mine[ROWS][COLS], int row, int col);     //设置雷
void c_mine(char Mine[ROWS][COLS], int row, int col);             //初始化
void Print(char Mine[ROWS][COLS], int row, int col);              //打印
void c_show(char Mine[ROWS][COLS], int row, int col);             //初始化
int FindMine(char Mine[ROWS][COLS], char Show[ROWS][COLS], int row, int col);     //找雷

game.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void c_mine(char Mine[ROWS][COLS], int row, int col)            //初始化棋盘
{
 memset(Mine, '0', row*col*sizeof(Mine[0][0]));
}
void c_show(char Mine[ROWS][COLS], int row, int col)
{
 memset(Mine, '*', row*col*sizeof(Mine[0][0]));
}
void Print(char Mine[ROWS][COLS], int row, int col)                //打印雷区
{
 int i = 0;
 int j = 0;
 printf("--------------------\n");
 for ( i = 0; i <=row; i++)
 {
  printf("%d ", i);
 }
 printf("\n");
 for ( i = 1; i <=row; i++)
 {
  printf("%d ", i);
  for (j = 1; j <=col; j++)
  {
   printf("%c ", Mine[i][j]);
  }
  printf("\n");
 }
 printf("--------------------\n");
}
static void moveMine(char Mine[ROWS][COLS], int x, int y)      //移动第一次踩到的雷
{
 int a = 0;
 int b = 0;
 while (1)
 {
  a = rand() % ROW + 1;
  b = rand() % COL + 1;
  if (Mine[a][b] != '1')
  {
   Mine[a][b] = '1';
   break;
  }
 }
 Mine[x][y] = '0';
}
void SetMine(char Mine[ROWS][COLS], int row, int col) //放置雷区
{
 int count = MINENUM;
 int x = 0;
 int y = 0;
 while (count!=0)
 {
  x = rand() % row + 1;//[0,9)[1,10)
  y = rand() % col + 1;
  if (Mine[x][y] =='0')
  {
   Mine[x][y] = '1';
   count--;
  }
 }
}
static int GetMine(char Mine[ROWS][COLS], int x, int y) //统计雷数
{
 //'1'-'0'=1
 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';
}
static int opeanMine(char Mine[ROWS][COLS], char Show[ROWS][COLS], int x, int y)    //用递归实现展开未知区域
{
 if (GetMine(Mine, x, y) == 0)
 {
  Show[x][y] = '0';
  if ((x - 1) >= 1 && (x - 1) <= ROW && (y - 1) >= 1 && (y - 1) <= COL&&Show[x - 1][y - 1] == '*')
   opeanMine(Mine, Show, x - 1, y - 1);
  if ((x) >= 1 && (x) <= ROW && (y - 1) >= 1 && (y - 1) <= COL&&Show[x][y - 1] == '*')
   opeanMine(Mine, Show, x, y - 1);
  if ((x + 1) >= 1 && (x + 1) <= ROW && (y - 1) >= 1 && (y - 1) <= COL&&Show[x + 1][y - 1] == '*')
   opeanMine(Mine, Show, x + 1, y - 1);
  if ((x + 1) >= 1 && (x + 1) <= ROW && (y) >= 1 && (y) <= COL&&Show[x + 1][y] == '*')
   opeanMine(Mine, Show, x + 1, y);
  if ((x + 1) >= 1 && (x + 1) <= ROW && (y + 1) >= 1 && (y + 1) <= COL&&Show[x + 1][y + 1] == '*')
   opeanMine(Mine, Show, x + 1, y + 1);
  if ((x) >= 1 && (x) <= ROW && (y + 1) >= 1 && (y + 1) <= COL&&Show[x][y + 1] == '*')
   opeanMine(Mine, Show, x, y + 1);
  if ((x - 1) >= 1 && (x - 1) <= ROW && (y + 1) >= 1 && (y + 1) <= COL&&Show[x - 1][y + 1] == '*')
   opeanMine(Mine, Show, x - 1, y + 1);
  if ((x - 1) >= 1 && (x - 1) <= ROW && (y) >= 1 && (y) <= COL&&Show[x - 1][y] == '*')
   opeanMine(Mine, Show, x - 1, y);
 }
  else
 {
  Show[x][y] = GetMine(Mine, x, y) + '0';
 }
 return 0;
}
static int IsWin(char Mine[ROWS][COLS], int row, int col)        //判断赢
{
 int i = 0;
 int j = 0;
 int count = 0;
 for (i = 1; i <= row; i++)
 {
  for (j = 1; j <= col; j++)
  {
   if (Mine[i][j] == '*')
    count++;
  }
 }
 return count;
}
int FindMine(char Mine[ROWS][COLS], char Show[ROWS][COLS], int row, int col)
{
    int x = 0;
    int y = 0;
    int flag = 1;
    while (MINENUM != IsWin(Show, row, col)) 
    {
         int count = 0;
         printf("请输入坐标:>");
         scanf("%d%d", &x, &y);
         if (x < 1 || x > row || y < 1 || y > col)
         {
             printf("非法坐标,");
         }
         else if (Show[x][y] != '*')
         {
             printf("该地区已被开辟,");
         }
         else if (Mine[x][y] == '1' && flag == 1)
         {
             moveMine(Mine, x, y);
             opeanMine(Mine, Show, x, y);
             system("cls");
             Print(Show, ROW, COL);
             flag = 0;
         }
         else if (Mine[x][y] == '1' && flag == 0)
         {
             printf("游戏结束,你被炸死了\n\n");
             Print(Mine, ROW, COL);
             return 0;
         }
         else if (Mine[x][y] == '0')
         {
             opeanMine(Mine, Show, x, y);
             system("cls");
             Print(Show, ROW, COL);
             flag = 0;
         }
    }
    printf("恭喜你,扫雷成功\n");
    return 0;
}

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void Menu()
{
 printf("****************************\n");
 printf("*****欢迎来到扫雷小游戏*****\n");
 printf("***********1.paly***********\n");
 printf("***********0.exit***********\n");
 printf("****************************\n");
}
void game()
{
 char mine[ROWS][COLS] = { 0 };
 char show[ROWS][COLS] = { 0 };
 c_mine(mine, ROWS, COLS);      //初始化雷区
 SetMine(mine, ROW, COL);       //放置雷
 c_show(show, ROWS, COLS);      //初始化show
 //Print(mine, ROW, COL);       //打印雷区
 Print(show, ROW, COL);
 FindMine(mine, show, ROW, COL);
}
int main()
{
 int input = 0;
 srand((unsigned)time(NULL));
 do
 {
  Menu();
  printf("请输入你的操作:>");
  scanf("%d", &input);
  switch (input)
  {
  case 1:
   game();
   break;
  case 0:
   break;
  default:printf("输入错误,请重新输入\n");
   break;
  }
 } while (input);
 return 0;
}

这样就完成了扫雷游戏。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值