1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > java递归排雷_C语言实现扫雷小游戏

java递归排雷_C语言实现扫雷小游戏

时间:2022-03-19 20:33:54

相关推荐

java递归排雷_C语言实现扫雷小游戏

源代码链接:/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);

}

}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。