java递归排雷_C语言实现扫雷小游戏
源代码链接:https://github.com/Sasura321/Minesweeper
扫雷游戏也算是一个简单的小项目,这儿是之前写的代码,来写成博文回顾一下。首先,代码要实现几个功能:
第一下扫雷时,即使踩中了雷也不能直接炸死;
扫雷时,坐标周围没有雷的地方可以实现展开;
统计展开的地方边缘处可能存在的雷的个数;
每次进入游戏,雷分布的地方都是随机的。
1.效果图
1)、程序总的构架:
2)、设计两个棋盘,一个是置放雷的棋盘,在测试中可以查看雷分布在哪些地方,不打印,如果玩家最终失败或者取得胜利,可以打印出来给玩家展示雷的分布。一个是展示给玩家的棋盘,打印,且会不断更新。
3)、游戏效果:
2.菜单
// 菜单
menu()
{
printf("*******************************\n");
printf("**** 欢迎来到扫雷游戏! ****\n");
printf("**** 1.进入游戏 ****\n");
printf("**** 0.退出游戏 ****\n");
printf("*******************************\n");
}
3.初始化棋盘
把棋盘初始化为0:
//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols,char set)
{
memset(board, set, rows*cols*sizeof(board[0][0]));
}
4.打印棋盘
棋盘的打印要用到二维数组的知识,这里会涉及到数组越界的问题,比如我们如果要打印 (10 x 10)的棋盘,我们在设计算法时需要统计周围 8 个方位的雷的个数,那么在统计边界周围雷的个数时就产生了数组越界的问题。为了解决这个问题,在棋盘周围多加一圈,即是如果是10x10,就变成了12x12,多出来的已全部打印出来。
//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf(" ");
for (i = 0; i < row; i++)
{
printf(" %d ", i + 1);
}
printf("\n");
for (j = 0; j < col+1; j++)
{
printf("---|");
}
printf("\n");
for (i = 0; i < row; i++)
{
printf(" %d |", i + 1);
for (j = 0; j < col; j++)
{
printf(" %c |", board[i][j]);
}
printf("\n");
printf(" |", i + 1);
for (j = 0; j < col; j++)
{
printf("---|");
}
printf("\n");
}
printf("\n");
}
5.在棋盘上布雷
利用函数 strand() 函数和 rand() 函数在棋盘上随机地方布置雷,有雷的地方标记为 1 ,没有雷的地方标记为 0。
//布置雷
void ScMinc(char board[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int count = EASY_COUNT;
while (count)
{
x = rand() % 9 + 1;
y = rand() % 9 + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
count--;
}
}
}
6.一次展开周围无雷的地方
扫雷时,坐标周围没有雷的地方展开,并统计展开的地方边缘处可能存在的雷的个数。
先设计一个函数 GetMineCount()用来统计雷周围雷的的数,如果为 0,则排除这个区域即置为 ‘ ’ ,并递归周围的 8 个位置,如果还出现为 0 的情况则继续递归,递归完成后打印展开的地方边缘处可能存在的雷的个数。
//统计周围雷的个数
static 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';
}
//用递归排除周围没有雷的区域
static void NoMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
int ret = GetMineCount(mine, x, y);
if (ret == 0)
{
show[x][y] = ' ';
if ((x-1)>0 && (y-1)>0 && (show[x-1][y-1] == '*'))
NoMine(mine, show, x - 1, y - 1);
if ((x - 1)>0 && (y)>0 && (show[x - 1][y] == '*'))
NoMine(mine, show, x - 1, y);
if ((x - 1)>0 && (y + 1)>0 && (show[x - 1][y + 1] == '*'))
NoMine(mine, show, x - 1, y + 1);
if ((x)>0 && (y - 1)>0 && (show[x][y - 1] == '*'))
NoMine(mine, show, x, y - 1);
if ((x)>0 && (y + 1)>0 && (show[x][y + 1] == '*'))
NoMine(mine, show, x, y + 1);
if ((x + 1)>0 && (y - 1)>0 && (show[x + 1][y - 1] == '*'))
NoMine(mine, show, x + 1, y - 1);
if ((x + 1)>0 && (y)>0 && (show[x + 1][y] == '*'))
NoMine(mine, show, x + 1, y);
if ((x + 1)>0 && (y + 1)>0 && (show[x + 1][y + 1] == '*'))
NoMine(mine, show, x + 1, y + 1);
}
else
show[x][y] = ret + '0';
}
7.排雷
在排雷过程中,用一个循环,如果踩中的不是雷,用 win 来统计非雷个数 ,如果踩中雷,立即炸死,结束循环。在循环结束后,如果非雷个数 win 正好等于使用的棋盘区域个数减去雷的个数的值,则成功排雷。
//排雷
void FindMind(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int win = 0; //统计不是雷的个数
int ret = 0; //统计周围雷的个数
while (win < ROW*COL - EASY_COUNT)
{
int select = 0;
system("CLS"); //清屏,优化界面
DisplayBoard(show, ROW, COL);
printf("----- 1.扫雷 --- 2.标记雷 -----\n");
printf("请选择:>");
scanf("%d", &select);
if (select == 1)
{
printf("请输入要排查的坐标:>");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mine[x-1][y-1] == '0' && show[x-1][y-1] == '*')
{
NoMine(mine, show, x-1, y-1);
DisplayBoard(show, ROW, COL);
win = win + 8;
}
if (mine[x-1][y-1] == '1' && show[x-1][y-1] == '*')
{
show[x-1][y-1] = 'S';
DisplayBoard(show, ROW, COL);
printf("很遗憾,你被炸死了\n\n");
DisplayBoard(mine, row, col);
break;
}
}
else
{
printf("坐标非法\n");
}
}
if (select == 2)
{
printf("请输入要标记雷的坐标:>");
scanf("%d %d", &x, &y);
if (show[x-1][y-1] == '*')
{
show[x-1][y-1] = '@'; //用于玩家标记已经确定的雷
DisplayBoard(show, ROW, COL);
}
else
{
printf("坐标非法\n");
}
}
}
//只剩下有雷的区域(EASY_COUNT:雷的总个数)
if (win = ROW*COL - EASY_COUNT)
{
printf("恭喜你,排雷成功!\n");
DisplayBoard(mine, row, col);
}
}
8.游戏执行
void game()
{
char mine[ROWS][COLS] = { 0 }; //置放雷的棋盘
char show[ROWS][COLS] = { 0 }; //展示给玩家的棋盘
InitBoard(mine, ROWS, COLS,'0');
InitBoard(show, ROWS, COLS, '*');
ScMinc(mine, ROW, COL); //置雷
DisplayBoard(mine, ROW, COL);
DisplayBoard(show, ROW, COL);
FindMind(mine, show, ROW, COL);//排雷
}
void test()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误\n");
}
} while (input);
}
int main()
{
test();
return 0;
}
9.头文件
#ifndef __GAME_H__
#define __GAME_H__
# define _CRT_SECURE_NO_WARNINGS
#include #include #include #include #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 ScMinc(char board[ROWS][COLS], int row, int col);
void FindMind(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
char FistStep(char mine[ROWS][COLS], int row, int col, int x, int y);
#endif __GAME_H__
10.附:game.c 的源码
#include "game.h"
//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols,char set)
{
memset(board, set, rows*cols*sizeof(board[0][0]));
}
//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf(" ");
for (i = 0; i < row; i++)
{
printf(" %d ", i + 1);
}
printf("\n");
for (j = 0; j < col+1; j++)
{
printf("---|");
}
printf("\n");
for (i = 0; i < row; i++)
{
printf(" %d |", i + 1);
for (j = 0; j < col; j++)
{
printf(" %c |", board[i][j]);
}
printf("\n");
printf(" |", i + 1);
for (j = 0; j < col; j++)
{
printf("---|");
}
printf("\n");
}
printf("\n");
}
//布置雷
void ScMinc(char board[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int count = EASY_COUNT;
while (count)
{
x = rand() % 9 + 1;
y = rand() % 9 + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
count--;
}
}
}
//统计周围雷的个数
static 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';
}
//用递归排除周围没有雷的区域
static void NoMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
int ret = GetMineCount(mine, x, y);
if (ret == 0)
{
show[x][y] = ' ';
if ((x-1)>0 && (y-1)>0 && (show[x-1][y-1] == '*'))
NoMine(mine, show, x - 1, y - 1);
if ((x - 1)>0 && (y)>0 && (show[x - 1][y] == '*'))
NoMine(mine, show, x - 1, y);
if ((x - 1)>0 && (y + 1)>0 && (show[x - 1][y + 1] == '*'))
NoMine(mine, show, x - 1, y + 1);
if ((x)>0 && (y - 1)>0 && (show[x][y - 1] == '*'))
NoMine(mine, show, x, y - 1);
if ((x)>0 && (y + 1)>0 && (show[x][y + 1] == '*'))
NoMine(mine, show, x, y + 1);
if ((x + 1)>0 && (y - 1)>0 && (show[x + 1][y - 1] == '*'))
NoMine(mine, show, x + 1, y - 1);
if ((x + 1)>0 && (y)>0 && (show[x + 1][y] == '*'))
NoMine(mine, show, x + 1, y);
if ((x + 1)>0 && (y + 1)>0 && (show[x + 1][y + 1] == '*'))
NoMine(mine, show, x + 1, y + 1);
}
else
show[x][y] = ret + '0';
}
//排雷
void FindMind(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int win = 0; //统计不是雷的坐标数
int ret = 0; //统计周围雷的个数
while (win < ROW*COL - EASY_COUNT)
{
int select = 0;
//system("CLS"); //清屏,优化界面
DisplayBoard(show, ROW, COL);
printf("----- 1.扫雷 --- 2.标记雷 -----\n");
printf("请选择:>");
scanf("%d", &select);
if (select == 1)
{
printf("请输入要排查的坐标:>");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mine[x-1][y-1] == '0' && show[x-1][y-1] == '*')
{
NoMine(mine, show, x-1, y-1);
DisplayBoard(show, ROW, COL);
win = win + 8;
}
if (mine[x-1][y-1] == '1' && show[x-1][y-1] == '*')
{
show[x-1][y-1] = 'S';
DisplayBoard(show, ROW, COL);
printf("很遗憾,你被炸死了\n\n");
DisplayBoard(mine, row, col);
break;
}
}
else
{
printf("坐标非法\n");
}
}
if (select == 2)
{
printf("请输入要标记雷的坐标:>");
scanf("%d %d", &x, &y);
if (show[x-1][y-1] == '*')
{
show[x-1][y-1] = '@'; //用于玩家标记已经确定的雷
DisplayBoard(show, ROW, COL);
}
else
{
printf("坐标非法\n");
}
}
}
if (win > ROW*COL - EASY_COUNT)
{
printf("恭喜你,排雷成功!\n");
DisplayBoard(mine, row, col);
}
}
java递归排雷_C语言实现扫雷小游戏相关推荐
- 【C语言】扫雷小游戏详解
[C语言]扫雷小游戏详解 前言: 还记得大明湖畔的夏雨荷,电脑课上的扫雷吗? ---------------------------是 他 吗--------------------------- 没 ...
- c语言字符游动程序,C语言实现扫雷小游戏详解
本文实例为大家分享了C语言实现扫雷小游戏的具体代码,供大家参考,具体内容如下 一.实现功能 首先显示一个小菜单,选择是否玩游戏.当用户选择退出时,程序运行结束,当用户选择玩游戏时,将提示用户输入扫雷位 ...
- 只用c语言不用图片的游戏,使用C语言实现扫雷小游戏
本文实例为大家分享了C语言实现扫雷小游戏的具体代码,供大家参考,具体内容如下 游戏规则 在一个9*9的地图上一共有十个雷,翻开所有不是雷的位置 游戏即为胜利, 如果踩到雷,游戏结束 设计思路 1.创建 ...
- C语言实现扫雷小游戏(排雷时可展开)
游戏介绍 扫雷想必大家都听说过吧?我们今天写的小游戏就是扫雷,只不过我们只使用C语言写.我们能够做到的就是实现扫雷的基本逻辑,没有图形化界面. 源代码 这次游戏程序的写法和上一次的三子棋的模式很像,也 ...
- C语言实现扫雷小游戏(下)(用递归实现了展开)
穷且益坚,不坠青云之志. 上篇博客实现了鸡肋的扫雷小游戏,不能实现雷盘(场)的展开,体验不是很好,这篇博客对其进行优化了,实现了展开功能. 文章目录 一.新的头文件 二.游戏框架 三.功能函数 ...
- 用C语言实现扫雷小游戏(附上思路+项目展示+源代码)
文章目录 前言 一.扫雷小游戏整体思路讲解. 二.game.c各游戏功能函数的讲解 1.InitBoard 初始化数组函数讲解 2.DisplayBoard 打印格子函数讲解 3.Setmine 电脑 ...
- C语言实现扫雷小游戏 纯小白 非黑窗口
C语言实现一个普通的扫雷小游戏 纯小白所编(含代码非黑窗口!) 扫雷 主要功能 1.创建一个图形界面 2.了解扫雷游戏的原理 3.随机生成雷的位置 4.为整个数组加密,并在雷周围的位置加一 5.导入图 ...
- 用c语言实现扫雷小游戏。
相信小伙伴在学习c语言的时候想做一些小趣事,下面就是用c语言来实现一个扫雷小游戏,不过是简单的实现扫雷(只是通过数组的方式来实现),适合新手学习. 我用的是vs敲的这个代码,大家可以用vs运行(可能有 ...
- C语言编写扫雷小游戏
该博文为原创文章,未经博主同意不得转载,如同意转载请注明博文出处 本文章博客地址:https://cplusplus.blog.csdn.net/article/details/104992377 扫 ...
最新文章
- PMCAFF微课堂(已结束) | 典典养车新媒体负责人亲授:如何运营百万级企业服务号
- golang go mod包管理自定义包及init初始化函数介绍
- python2升级python3后_Centos7 Python2 升级到Python3
- Undefined Reference to Typeinfo
- 0.IT-解决方案-0-VOIP
- A+B and C (64bit)
- 游戏程序中的骨骼插件
- AjaxPro实现方法
- 微服务学习之Hystrix容错保护【Hoxton.SR1版】
- 一个完整的person类
- VMware vSphere 服务器虚拟化之二十七桌面虚拟化之View中使用Thinapp软件虚拟化
- 区块链对人类产生的变革
- CSR867x — 说说什么是ANC、CVC、DSP降噪
- 数据库设计 | 需求分析
- 签名证书(.keystore)生成指南
- 循环双链表的p所指的结点之前插入q所指结点的操作为()
- 【日志分析】Web日志分析
- 【百度地图】城市中心点坐标
- 【Python爬虫】 爬取京东商品图片并下载
- SteamVR使用Curved UI实现与UI的交互
热门文章
- 数据挖掘公司D square nv 完成500万欧元B轮融资
- sublime text3 前端插件介绍
- 如何彻底卸载mysql(xp)
- 小鱼提问1 类中嵌套public修饰的枚举,外部访问的时候却只能Class.Enum这样访问,这是为何?...
- 《虚拟化与云计算》读书感(三)数据中心的概述
- [流水账]毕业?工作?
- CF1148F - Foo Fighters
- 实现nginx上配置免费证书Let's Encrypt
- Zend Framework Mail通过网易免费邮箱发送邮件
- vue-cli 使用小技巧