先贴一张效果图
扫雷的基本思路
1.首先对棋盘初始化,并印出棋盘。
2.对棋盘进行埋雷。
3.输入坐标进行排雷。
4.编写函数统计当前位置周围的雷数,当周围8个位置都没有雷时进行递归展开。
5.统计棋盘中未展开的坐标数是否与雷数相等来判断输赢。
棋盘
首先对棋盘具体分析,应该创建两个棋盘,在一个棋盘中记录雷的位置,另一个棋盘打印出来给用户查看。
因为后面要统计当前位置周围的雷数,当位置在边角时,统计位置时会造成溢出,所以我们可以考虑把棋盘大上一圈,比如99的棋盘我们可以创建成1111的。
如图所示,黑色框为打印给用户看到的棋盘,红色框里面的实际创建的大小,(上下左右均比棋盘大一个)这样就可以避免在统计图中红色部分是造成越界访问了。
初始化
对雷盘和棋盘进行初始化
void InitBoard(char board[ROWS][COLS], int row, int col, char val)
{
int i = 0;
for (int i = 0; i < row; i++)
{
int j = 0;
for (int j = 0; j < col; j++)
{
board[i][j] = val;
}
}
}
生成随机雷
在对棋盘初始化完成后,我们应该通过生成随机数来步骤雷,代码如下:
void CreateMine(char board[ROWS][COLS], int row, int col, int size)
{
int count = size;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (board[x][y] != '1')
{
board[x][y] = '1';
count--;
}
}
}
}
打印棋盘
完成布置雷后,接下来我们就可以打印出棋盘来了
void PrinBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
printf("_________________________________\n");
for (i = 0; i <= row; i++)
printf(" %d", i);
printf("\n");
for (i = 1; i <= row; i++)
{
int j = 1;
printf("%2d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
printf("_________________________________\n");
}
开始扫雷
通过对用户输入的坐标进行判断当前位置是否有雷,没有雷的话就要统计当前位置周围8个格子的雷数,如果周围8个位置没有雷,就要对周围8个格子进行递归展开。反之则被炸死,游戏结束。当每次统计完 判断当前状态是否胜利。
判断输赢
通过统计棋盘中未排查的坐标个数与雷数是否相等来判断是否输赢,当与雷数相同是,排雷成功游戏结束。
void PlayerMove(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col)
{
int x, y;
PrinBoard(show, ROW, COL);
while (1)
{
printf("输入需要排查的坐标>");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col && show[x][y] == '*')
{
if (mine[x][y] == '1')
{
printf("您被炸死了\n");
show[x][y] = '1';
PrinBoard(show, ROW, COL);
break;
}
else
{
Open(show, mine, x, y);
PrinBoard(show, ROW, COL);
}
}
else
{
printf("您当前输入的坐标不合法,请重新输入\n");
}
int i = 0, flag = 0;
for (i = 1; i <= ROW; i++)
{
int j = 0;
for (j = 1; j <= COL; j++)
{
if (show[i][j] == '*')
flag++;
}
}
if (flag == MINES)
{
printf("玩家获胜\n");
break;
}
}
}
展开函数
void Open(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col)
{
if (row > 0 && row <= ROW && col > 0 && col <= COL)
{
int count = Get_Mine_Count(mine, row, col);
if (count != 0)
show[row][col] = '0' + count;
else if (show[row][col] != ' ')
{
show[row][col] = ' ';
int i = 0;
for (int i = row - 1; i <= row + 1; i++)
{
int j = 0;
for (j = col - 1; j <= col + 1; j++)
{
Open(show, mine, i, j);
}
}
}
else
{
//show[row][col]!=' '递归停止
return ;
}
}
}
统计周围雷数
int Get_Mine_Count(char board[ROWS][COLS], int row, int col)
{
int i = 0, count = 0;
for (i = row - 1; i <= row + 1; i++)
{
int j = 0;
for (j = col-1; j <= col + 1; j++)
{
if (board[i][j] == '1')
count++;
}
}
return count;
}
完整代码如下
text.c
#include"game.h"
void menu()
{
printf("******************************\n");
printf("******** 1.play *********\n");
printf("******** 0.EXIT *********\n");
printf("******************************\n");
}
void game()
{
int size = MINES;
char mine[ROWS][COLS];
char show[ROWS][COLS];
//初始化棋盘
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
//布置雷
CreateMine(mine, ROW, COL, size);
PlayerMove(show, mine, ROW, COL);
}
int main()
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
menu();
printf("请选择>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出\n");
break;
default:
printf("输入错误\n");
break;
}
} while (input);
return 0;
}
game.c
#include"game.h"
void InitBoard(char board[ROWS][COLS], int row, int col, char val)
{
int i = 0;
for (int i = 0; i < row; i++)
{
int j = 0;
for (int j = 0; j < col; j++)
{
board[i][j] = val;
}
}
}
void PrinBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
printf("_________________________________\n");
for (i = 0; i <= row; i++)
printf(" %d", i);
printf("\n");
for (i = 1; i <= row; i++)
{
int j = 1;
printf("%2d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
printf("_________________________________\n");
}
void CreateMine(char board[ROWS][COLS], int row, int col, int size)
{
int count = size;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (board[x][y] != '1')
{
board[x][y] = '1';
count--;
}
}
}
}
int Get_Mine_Count(char board[ROWS][COLS], int row, int col)
{
int i = 0, count = 0;
for (i = row - 1; i <= row + 1; i++)
{
int j = 0;
for (j = col-1; j <= col + 1; j++)
{
if (board[i][j] == '1')
count++;
}
}
return count;
}
void Open(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col)
{
if (row > 0 && row <= ROW && col > 0 && col <= COL)
{
int count = Get_Mine_Count(mine, row, col);
if (count != 0)
show[row][col] = '0' + count;
else if (show[row][col] != ' ')
{
show[row][col] = ' ';
int i = 0;
for (int i = row - 1; i <= row + 1; i++)
{
int j = 0;
for (j = col - 1; j <= col + 1; j++)
{
Open(show, mine, i, j);
}
}
}
else
{
//show[row][col]!=' '递归停止
return ;
}
}
}
void PlayerMove(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col)
{
int x, y;
PrinBoard(show, ROW, COL);
while (1)
{
printf("输入需要排查的坐标>");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col && show[x][y] == '*')
{
if (mine[x][y] == '1')
{
printf("您被炸死了\n");
show[x][y] = '1';
PrinBoard(show, ROW, COL);
break;
}
else
{
Open(show, mine, x, y);
PrinBoard(show, ROW, COL);
}
}
else
{
printf("您当前输入的坐标不合法,请重新输入\n");
}
int i = 0, flag = 0;
for (i = 1; i <= ROW; i++)
{
int j = 0;
for (j = 1; j <= COL; j++)
{
if (show[i][j] == '*')
flag++;
}
}
if (flag == MINES)
{
printf("玩家获胜\n");
break;
}
}
}
game.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
enum
{
ROW = 10,
COL = 10,
ROWS = ROW + 2,
COLS = COL + 2,
MINES = 5 //雷数
};
void InitBoard(char board[ROWS][COLS], int row, int col, char val);
void PrinBoard(char board[ROWS][COLS], int row, int col);
void CreateMine(char board[ROWS][COLS], int row, int col, int size);
void PlayerMove(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col);
int Get_Mine_Count(char board[ROWS][COLS], int row, int col);
void Open(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col);