C语言实现简单的扫雷小游戏

 更新时间:2020年10月26日 08:46:29   作者:一只当归  
这篇文章主要为大家详细介绍了C语言实现简单的扫雷小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了C语言实现扫雷小游戏的具体代码,供大家参考,具体内容如下

在编写扫雷小游戏之前,第一,我们应该列出我们想要实现的扫雷小游戏的功能:

1.显示选中的坐标周围的雷的个数。
2.保证第一次选中的坐标不是雷。
3.选中的坐标周围8个格子中没有雷,则展开。

第二,我们应该明白我们需要两个棋盘来实现扫雷游戏:一个棋盘用来展示给玩家,初始界面全为“ * ” (未翻开的格子),这个页面就是我们常见的扫雷页面。另一个棋盘用来给编写者看,棋盘内只有字符‘1'和字符‘0' 。‘1'代表雷,‘0'代表非雷。使用字符‘1'‘0'来代表雷和非雷有利于我们下一步计算坐标周围雷的个数。

1.初始化棋盘

nitboard(show_board, ROWS, COLS,'*'); //‘*'代表未翻开的坐标
 Initboard(mine_board, ROWS, COLS, '0'); //‘0'代表非雷
 void Initboard(char board[ROWS][COLS], int row, int col, char set)
{
 memset(board, set, row*col * sizeof(board[0][0]));
}

2.打印棋盘

void DisPlayboard(char board[ROWS][COLS], int row, int col)
{
 int i = 0;
 int j = 0;
 printf(" ");
 for (i = 1; 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 ", board[i][j]);
 }
 printf("\n");
 }
 printf("\n");
}

3.在棋盘中埋入雷。(因为每一次重新开始游戏雷的位置不能重复,所以选择用随机数来埋雷)

void GetBoom(char board[ROWS][COLS], int row, int col) //埋雷
{
 int x = 0;
 int y = 0;
 int sum = 0;
 while(1)
 { 
 x = rand() % row +1; //雷放在1-9的范围里
 y = rand() % col +1;
 if (1)
 {
 board[x][y] = '1';
 sum++;
 if (sum == M) //埋入雷后跳出循环
 {
 break;
 }
 }
 }

4.确保第一次不踩到雷,如果第一次踩到雷,我们就将此位置改为非雷,然后将此处的雷移动到别处未放置雷的位置。 

(还要考虑一种特殊情况,即如果第一次落子就获得胜利的情况时后面函数就不用再执行了,所以此函数要改为有返回值的函数,这样在调用此函数时就可以判断是否为一次就获得胜利的情况)

int Judge_first(char mine_board[ROWS][COLS], char show_board[ROWS][COLS], int row, int col)
{
 int x = 0;
 int y = 0;
 int m;
 int n;
 printf("请输入要排查的坐标:");
 scanf("%d%d", &x, &y);
 while (1)
 {
 if (mine_board[x][y] == '1') //如果第一次踩雷,将此坐标改为非雷
 {
 mine_board[x][y] = '0';
 show_board[x][y] = ' ';
 while (1)
 {
 m = rand() % 9 + 1;
 n = rand() % 9 + 1;
 if (m != x && n != y && mine_board[m][n] != '1')
 {
 mine_board[m][n] = '1';
 }
 Open(mine_board, show_board, x, y);
 if (Full(show_board, ROW, COL) == 1) //展开后判断是否一次获得胜利
 {
 printf("游戏胜利\n");
 DisPlayboard(mine_board, ROW, COL);
 return 2;  //一次获得胜利返回2 不再执行PlayerMove函数
 break;
 }
 DisPlayboard(show_board, row, col);
 break;
 }
 break;
 }
 else if (mine_board[x][y] == '0')
 {
 show_board[x][y] = ' ';
 Open(mine_board, show_board, x, y);
 if (Full(show_board, ROW, COL) == 1)
 {
 printf("游戏胜利\n");
 DisPlayboard(mine_board, ROW, COL);
 return 2;
 break;
 }
 DisPlayboard(show_board, row, col);
 break;
 }
 }
}

5.当坐标周围雷个数为0时,展示周围格子,再以X和Y周围八个坐标分别为中心展开,当坐标周围有雷时不再递归展开,并将雷的个数放在该坐标。

void Open(char mine_board[ROWS][COLS],char show_board[ROWS][COLS], int x, int y)
{
 int ret = 0;
 ret = Num(mine_board, x, y);
 if (ret == 0) //当坐标周围雷个数为0时 打开周围格子 再以X和Y周围八个坐标为中心展开 重复即为递归展开
 {
 show_board[x][y] = ' '; 
 if (x - 1 > 0 && y - 1 > 0 && show_board[x - 1][y - 1] == '*')
 {
 Open(mine_board, show_board, x - 1, y - 1);
 }
 if (x - 1 > 0 && y > 0 && show_board[x - 1][y] == '*')
 {
 Open(mine_board, show_board, x - 1, y);
 }
 if (x - 1 > 0 && y + 1 <= COL && show_board[x - 1][y + 1] == '*')
 {
 Open(mine_board, show_board, x - 1, y + 1);
 }
 if (x > 0 && y + 1 <= COL && show_board[x][y + 1] == '*')
 {
 Open(mine_board, show_board, x, y + 1);
 }
 if (x + 1 < ROW && y + 1 <= COL && show_board[x + 1][y + 1] == '*')
 {
 Open(mine_board, show_board, x + 1, y + 1);
 }
 if (x + 1 <= ROW && y > 0 && show_board[x + 1][y] == '*')
 {
 Open(mine_board, show_board, x + 1, y);
 }
 if (x + 1 <= ROW && y - 1 > 0 && show_board[x + 1][y - 1] == '*')
 {
 Open(mine_board, show_board, x + 1, y - 1);
 }
 if (x > 0 && y - 1 > 0 && show_board[x][y - 1] == '*')
 {
 Open(mine_board, show_board, x, y - 1);
 }
 }
 else if (ret != 0)
 show_board[x][y] = Num(mine_board, x, y) + 48;
}

6.计算坐标周围一圈中所含雷的个数。

int Num(char board[ROWS][COLS], int x, int y)
{
 int sum = 0; //sum为坐标周围雷的个数
 sum = board[x - 1][y - 1]
 + board[x][y - 1] + board[x + 1][y - 1]
 + board[x + 1][y] + board[x + 1][y + 1]
 + board[x][y + 1] + board[x - 1][y + 1]
 + board[x - 1][y] - (8 * '0');
 return sum;
}

7.判断玩家是否排完所有雷。

int Full(char board[ROWS][COLS], int row, int col) 
{
 int i;
 int j;
 int sum = 0; //sum为棋盘未翻开格子的个数
 for (i = 1; i <= row; i++)
 {
 for (j = 1; j <= col; j++)
 {
 if (board[i][j] == '*')
 sum++;
 } 
 }
 if (sum == M) //当未翻开的格子数为雷数时 返回1
 return 1;
}

8.玩家输入坐标扫雷。

void PlayerMove(char mine_board[ROWS][COLS], char show_board[ROWS][COLS], int row, int col)
{
 int x = 0;
 int y = 0;
 int ret = 0;
 while (1)
 {
 if (Full(show_board, ROW, COL) == 1) //棋盘未翻开格子等于雷数时玩家胜利
 {
 printf("游戏胜利\n");
 DisPlayboard(mine_board, ROW, COL);
 break;
 }
 printf("请输入坐标:");
 scanf("%d%d", &x, &y);
 if (x >= 1 && x <= row && y >= 1 && y <= col)
 {
 
 if (mine_board[x][y] == '1') //玩家踩到雷,游戏结束
 {
 printf("游戏结束\n");
 DisPlayboard(mine_board, ROW, COL);
 break;
 }
 ret = Num(mine_board, x, y);
 if (ret == 0) //周围没有雷时,展开周围格子
 {
 Open(mine_board, show_board, x, y);
 DisPlayboard(show_board, ROW, COL);
 }
 else if (ret != 0) //周围有雷时打印雷的个数
 {
 show_board[x][y] = ret + 48;
 DisPlayboard(show_board, ROW, COL);
 }
 }
 else
 printf("输入错误,请重新输入");
 }
}

9.函数声明,宏定义,函数的定义实现,测试。

源文件:test.c //主要负责测试整个代码
头文件:game.h //包含函数各种声明,宏定义
源文件:game.c //包含各种函数的定义

test.c

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

int game()
{
 char show_board[ROWS][COLS] = { 0 };
 char mine_board[ROWS][COLS] = { 0 };
//
 Initboard(show_board, ROWS, COLS,'*'); //初始化数组
 Initboard(mine_board, ROWS, COLS, '0'); 
 printf("游戏开始\n");
 DisPlayboard(show_board, ROW, COL); //打印玩家雷盘
//
 GetBoom(mine_board, ROW, COL); //埋雷
 printf("\n\n\n");
 DisPlayboard(mine_board, ROW, COL); //打印雷盘
//
 if (Judge_first(mine_board, show_board, ROW, COL) == 2) //如果一次胜利,就不再执行PlayerMove函数
 return 2;
// 
 PlayerMove(mine_board, show_board, ROW, COL); 
}

void test()
{
 int n;
 menu();
 do
 {
 printf("请输入选项按钮: ");
 scanf("%d", &n);
 switch (n)
 {
 case 1:
 game();
 break;
 case 0:
 printf("游戏退出\n");
 break;
 default:
 printf("输入错误,请重新输入\n");
 break;
 } 
 }while(1);
}
int main()
{
 srand((unsigned int)time(NULL));
 test();
}

game.c

#include"game.h"
void Initboard(char board[ROWS][COLS], int row, int col, char set)
{
 memset(board, set, row*col * sizeof(board[0][0]));
}
void DisPlayboard(char board[ROWS][COLS], int row, int col)
{
 int i = 0;
 int j = 0;
 printf(" ");
 for (i = 1; 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 ", board[i][j]);
 }
 printf("\n");
 }
 printf("\n");
}

void GetBoom(char board[ROWS][COLS], int row, int col) //埋雷
{
 int x = 0;
 int y = 0;
 int sum = 0;
 while(1)
 { 
 x = rand() % row +1; //雷放在1-9的范围里
 y = rand() % col +1;
 if (1)
 {
 board[x][y] = '1';
 sum++;
 if (sum == M) //埋入所需的雷后跳出循环
 {
 break;
 }
 }
 }
}

int Judge_first(char mine_board[ROWS][COLS], char show_board[ROWS][COLS], int row, int col)
{
 int x = 0;
 int y = 0;
 int m;
 int n;
 printf("请输入要排查的坐标:");
 scanf("%d%d", &x, &y);
 while (1)
 {
 if (mine_board[x][y] == '1') //如果第一次踩雷,将此坐标改为非雷
 {
 mine_board[x][y] = '0';
 show_board[x][y] = ' ';
 while (1)
 {
 m = rand() % 9 + 1;
 n = rand() % 9 + 1;
 if (m != x && n != y && mine_board[m][n] != '1')
 {
 mine_board[m][n] = '1';
 }
 Open(mine_board, show_board, x, y);
 if (Full(show_board, ROW, COL) == 1) //展开后判断是否一次获得胜利
 {
 printf("游戏胜利\n");
 DisPlayboard(mine_board, ROW, COL);
 return 2;  //一次获得胜利返回2 不再执行PlayerMove函数
 break;
 }
 DisPlayboard(show_board, row, col);
 break;
 }
 break;
 }
 else if (mine_board[x][y] == '0')
 {
 show_board[x][y] = ' ';
 Open(mine_board, show_board, x, y);
 if (Full(show_board, ROW, COL) == 1)
 {
 printf("游戏胜利\n");
 DisPlayboard(mine_board, ROW, COL);
 return 2;
 break;
 }
 DisPlayboard(show_board, row, col);
 break;
 }
 }
}

void PlayerMove(char mine_board[ROWS][COLS], char show_board[ROWS][COLS], int row, int col)
{
 int x = 0;
 int y = 0;
 int ret = 0;
 while (1)
 {
 if (Full(show_board, ROW, COL) == 1) //棋盘下满玩家胜利
 {
 printf("游戏胜利\n");
 DisPlayboard(mine_board, ROW, COL);
 break;
 }
 printf("请输入坐标:");
 scanf("%d%d", &x, &y);
 if (x >= 1 && x <= row && y >= 1 && y <= col)
 {
 
 if (mine_board[x][y] == '1')
 {
 printf("游戏结束\n");
 DisPlayboard(mine_board, ROW, COL);
 break;
 }
 ret = Num(mine_board, x, y);
 if (ret == 0) //周围没有雷时,展开周围格子
 {
 Open(mine_board, show_board, x, y);
 DisPlayboard(show_board, ROW, COL);
 }
 else if (ret != 0) //周围有雷时打印雷的个数
 {
 show_board[x][y] = ret + 48;
 DisPlayboard(show_board, ROW, COL);
 }
 }
 else
 printf("输入错误,请重新输入");
 }
}

void Open(char mine_board[ROWS][COLS],char show_board[ROWS][COLS], int x, int y)
{
 int ret = 0;
 ret = Num(mine_board, x, y);
 if (ret == 0) //当坐标周围雷个数为0时 打开周围格子 再以X和Y周围八个坐标为中心展开 重复即为递归展开
 {
 show_board[x][y] = ' '; 
 if (x - 1 > 0 && y - 1 > 0 && show_board[x - 1][y - 1] == '*')
 {
 Open(mine_board, show_board, x - 1, y - 1);
 }
 if (x - 1 > 0 && y > 0 && show_board[x - 1][y] == '*')
 {
 Open(mine_board, show_board, x - 1, y);
 }
 if (x - 1 > 0 && y + 1 <= COL && show_board[x - 1][y + 1] == '*')
 {
 Open(mine_board, show_board, x - 1, y + 1);
 }
 if (x > 0 && y + 1 <= COL && show_board[x][y + 1] == '*')
 {
 Open(mine_board, show_board, x, y + 1);
 }
 if (x + 1 < ROW && y + 1 <= COL && show_board[x + 1][y + 1] == '*')
 {
 Open(mine_board, show_board, x + 1, y + 1);
 }
 if (x + 1 <= ROW && y > 0 && show_board[x + 1][y] == '*')
 {
 Open(mine_board, show_board, x + 1, y);
 }
 if (x + 1 <= ROW && y - 1 > 0 && show_board[x + 1][y - 1] == '*')
 {
 Open(mine_board, show_board, x + 1, y - 1);
 }
 if (x > 0 && y - 1 > 0 && show_board[x][y - 1] == '*')
 {
 Open(mine_board, show_board, x, y - 1);
 }
 }
 else if (ret != 0)
 show_board[x][y] = Num(mine_board, x, y) + 48;
}

int Num(char board[ROWS][COLS], int x, int y)
{
 int sum = 0;
 sum = board[x - 1][y - 1]
 + board[x][y - 1] + board[x + 1][y - 1]
 + board[x + 1][y] + board[x + 1][y + 1]
 + board[x][y + 1] + board[x - 1][y + 1]
 + board[x - 1][y] - (8 * '0');
 return sum;
}

int Full(char board[ROWS][COLS], int row, int col)
{
 int i;
 int j;
 int sum = 0;
 for (i = 1; i <= row; i++)
 {
 for (j = 1; j <= col; j++)
 {
 if (board[i][j] == '*')
 sum++;
 } 
 }
 if (sum == M)
 return 1;
}

game.h

#define _CRT_SECURE_NO_WARNINGS
#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 M 10 //所需雷的个数

void test();
int game();
void Initboard(char board[ROWS][COLS], int row, int col, int set); //初始化数组
void DisPlayboard(char board[ROWS][COLS], int row, int col); //打印雷盘
void GetBoom(char board[ROWS][COLS], int row, int col); //安放炸弹
int Judge_first(char mine_board[ROWS][COLS], char show_board[ROWS][COLS], int row, int col); //保证第一次不是雷
void PlayerMove(char mine_board[ROWS][COLS], char show_board[ROWS][COLS], int row, int col); //玩家排雷
void Open(char mine_board[ROWS][COLS],char show_board[ROWS][COLS], int x, int y); //展开函数
int Num(char mine_board[ROWS][COLS], int x, int y); //计算坐标周围雷的数量
int Full(char board[ROWS][COLS], int row, int col); //判断雷是否下满

更多有趣的经典小游戏实现专题,分享给大家:

C++经典小游戏汇总

python经典小游戏汇总

python俄罗斯方块游戏集合

JavaScript经典游戏 玩不停

java经典小游戏汇总

javascript经典小游戏汇总

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • C++实践Time类中的运算符重载参考方法

    C++实践Time类中的运算符重载参考方法

    今天小编就为大家分享一篇关于C++实践Time类中的运算符重载参考方法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-02-02
  • C++中const用于函数重载的示例代码

    C++中const用于函数重载的示例代码

    这篇文章主要介绍了C++中const用于函数重载的相关资料,需要的朋友可以参考下
    2017-09-09
  • C语言实现万年历源码

    C语言实现万年历源码

    这篇文章主要为大家详细介绍了C语言实现万年历源码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-10-10
  • 简述c++ 发展史

    简述c++ 发展史

    这篇文章主要介绍了c++ 发展的过程,帮助大家更好的了解和学习c++,感兴趣的朋友可以了解下
    2020-08-08
  • C++实现LeetCode(167.两数之和之二 - 输入数组有序)

    C++实现LeetCode(167.两数之和之二 - 输入数组有序)

    这篇文章主要介绍了C++实现LeetCode(167.两数之和之二 - 输入数组有序),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • C++进程共享数据封装成类实例

    C++进程共享数据封装成类实例

    这篇文章主要介绍了C++进程共享数据封装成类的方法,以实例形式讲述了其封装代码与具体用法,具有一定的实用价值,需要的朋友可以参考下
    2014-10-10
  • C语言之复杂链表的复制方法(图示详解)

    C语言之复杂链表的复制方法(图示详解)

    下面小编就为大家带来一篇C语言之复杂链表的复制方法(图示详解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-07-07
  • C++合并二叉树的思路与示例代码

    C++合并二叉树的思路与示例代码

    二叉树大家应该都不陌生,但是合并二叉树呢?这篇文章主要给大家介绍了关于C++合并二叉树的相关资料,文中给出了两种解决的方法,大家可以根据需要选择对应的方法,需要的朋友可以参考下
    2021-08-08
  • 在C语言中比较两个字符串是否相等的方法

    在C语言中比较两个字符串是否相等的方法

    这篇文章主要介绍了在C语言中比较两个字符串是否相等的方法,分别介绍了strcmp()函数和strcasecmp()函数,注意功能区分,需要的朋友可以参考下
    2015-08-08
  • 一些C语言中字符串的算法问题解决实例小结

    一些C语言中字符串的算法问题解决实例小结

    这篇文章主要介绍了一些C语言中字符串的算法问题解决实例小结,包括将字符串转化为int类型的数及旋转字符串等操作,需要的朋友可以参考下
    2016-03-03

最新评论