编程记录,关于B站上鹏哥C语言课程中的练习记录
记录内容:C语言实现扫雷(关于数组)
-
思路
test.c 测试逻辑
game.h 存储声明
game.c 编写运行函数 -
用循环使游戏多次执行(do-while循环)
-
打印菜单
-
switch选择语句,测试用户输入和测试逻辑(同三子棋和猜数字)
-
编写函数game()实现扫雷游戏
游戏规则,是雷:游戏失败;不是雷:显示当前一周有几个雷存在。
1.布置雷(使用二维数组存储相关信息)(2个)
存放雷的棋盘,无雷是0,有雷是1,这样会和排查雷产生歧义2.排查雷,另设置一个数组,专门存放排查雷的信息
为了实现神秘初始化设置为*,所以数组使用字符类型,使用字符1/0
为了避免越界,实现9×9的棋盘要保存11×11的数组大小
mine[11][11] show[11][11]
为了实现机动性,不使用具体数字,使用生命,9和11(9+2)都需要声明 -
编写函数初始化棋盘,布置盘是‘0’,排查盘是*(两个数组均需要初始化)
-
编写函数打印棋盘(增加行号和列号用于方便用户判断位置)
-
编写函数完成布置雷(随机坐标在9×9中)(布置10个雷)(while循环)
-
编写函数完成排查雷(从mine中排查信息放入show数组)
判断坐标合法性(用死循环直到合法,不合法反复输入) -
编写函数统计周围坐标雷的数目(将数字结果变为字符)(数字结果+’0’)
同理,将各个坐标相加再减去字符0×8个,即为周围雷的个数,因此该函数仅需要一个return
可以在前面增加static,该函数只能在该源文件看到,其他源文件看不到,因为该函数只需要满足该源文件中排查雷函数的功能,这样该函数不会和其他源文件中的函数发生冲突。 -
增加变量,当所有非雷都成功排出,则跳出循环,并且给出成功提示,并显示当前棋盘
-
优化内容,当该坐标不是雷且该坐标周围也没有雷,显示当前坐标一周的排查雷情况
可以使用递归的方式。
增加标记雷的功能
优化内容未实现
代码如下:
game.h
//程序所需要的头文件
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>
//程序所需要的数据
//为了能获取一周的数据,棋盘为9*9,则实际棋盘为11*11
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
//本次游戏的埋雷个数
#define NUM 10
//初始化二维数组
void InitBoard(char board[ROWS][COLS], int row, int col , char x);
//打印二维数组
void DisplayBoard(char board[ROWS][COLS], int row, int col);
//布置雷
void Arrange(char board[ROWS][COLS], int row, int col);
//排查雷
int FindMine(char board1[ROWS][COLS],char board2[ROWS][COLS], int row, int col);
game.c
#include "game.h"
//二维数组初始化
void InitBoard(char board[ROWS][COLS], int row, int col, char x)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = x;
}
}
}
//棋盘打印
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf( "--------------------\n" );
for (i = 0; i <= row; i++)
{
for (j = 0; j <= col; j++)
{
if (0 == i)
{
printf("%d ", j);
}
else if (0 == j)
{
printf("%d ", i);
}
else
{
printf("%c ", board[i][j]);
}
}
printf("\n");
}
printf("--------------------\n");
}
//布置雷
void Arrange(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
int count = 0;
while (count != NUM)
{
i = rand() % row + 1;
j = rand() % col + 1;
//if ((strcmp(board[i][j],'0'))==0) 会报错
if(board[i][j] == '0')
{
board[i][j] = '1';
count++;
}
}
}
//返回周围一周雷的个数
int RetNum(char board[ROWS][COLS], int i, int j)
{
return board[i - 1][j - 1] + board[i - 1][j] + board[i - 1][j + 1] + board[i][j - 1] + board[i][j + 1]
+ board[i + 1][j - 1] + board[i + 1][j] + board[i + 1][j + 1] - 8 * '0';
}
//排查雷
//若当前坐标恰好是雷:输出玩家失败
//若当前坐标不是雷:显示当前坐标一周的雷的个数
int FindMine(char board1[ROWS][COLS], char board2[ROWS][COLS], int x, int y)
{
if (board1[x][y] == '1')
{
printf("爆炸!玩家失败!!!\n");
printf("爆炸!玩家失败!!!\n");
printf("爆炸!玩家失败!!!\n");
return 0;
}
else {
int ret = 0;
ret = RetNum(board1, x, y)+48;
//printf("%d\n", ret);
board2[x][y] = (char)ret;
return 1;
}
}
test.c
#include "game.h"
void menu()
{
printf("####################\n");
printf("##### 1 play #####\n");
printf("##### 2 exit #####\n");
printf("####################\n");
}
void game()
{
//为了达到初始不可见的要求,用*存放,则存放数组应为char类型
//使用两个数组,一个存放布置雷的数据,一个存放排查雷的数据
char board1[ROWS][COLS] = { 0 }; //布置雷
char board2[ROWS][COLS] = { 0 }; //排查雷
//初始化二维数组
InitBoard(board1, ROWS, COLS, '0');
InitBoard(board2, ROWS, COLS, '*');
//打印二维数组
//DisplayBoard(board1, ROW, COL);
DisplayBoard(board2, ROW, COL);
//布置雷
Arrange(board1, ROW, COL);
//DisplayBoard(board1, ROW, COL);
//排查雷
//重复排查,直到玩家失败或排除结束
int x = 0;
int y = 0;
int count = ROW * COL - NUM;
int ret = 0;
do {
printf("请输入你想排查雷的坐标(例如:1空格2):");
scanf("%d %d", &x, &y);
ret = FindMine(board1, board2, x, y);
if (0 == ret)
{
DisplayBoard(board1, ROW, COL);
break;
}
else
{
DisplayBoard(board2, ROW, COL);
count--;
}
} while (count);
if (count == 0)
{
printf("玩家胜利!!!\n");
printf("玩家胜利!!!\n");
printf("玩家胜利!!!\n");
}
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do{
//打印菜单
menu();
printf("请输入你的操作内容:");
scanf("%d", &input);
switch (input)
{
case 1:
//printf("开始游戏\n");
game();
break;
case 2:
printf("退出游戏\n");
break;
default:
printf("输入错误,请重新输入!\n");
break;
}
} while (input != 2);
return 0;
}