目录
一,前言
前言:面对扫雷从何下手?面对一个完整的程序,我们第一步就是细化出过程并且画出来。
扫雷的过程我分为了四步: 一,创建棋盘
二,布置雷
三,开始排雷
四,状态判断
二,逻辑图
我们根据以上四步,画出逻辑图:
然后细化逻辑图:
进一步细化可以写出要完成这个步骤需要什么,或者这个步骤包含什么,或者这个步骤里面有什么易错点,又或是这个步骤需要完成有何技巧
1. (步骤)创建棋盘:
创造容器定义数组即可,初始化就是遍历数组赋初始值即可
打印是打印棋盘,但是 :棋盘每格子的信息包括:1.是否是雷,2.周边雷的信息;
我们打印的时候,死了需要打印出所有雷,但是不包含雷的信息;没有死需要打印雷的信息,不能打印出雷;显然,这个是一个数组难以完成的,所以,我们创造容器的时候,可以创造两个容器,一个放是否是雷,一个放周边雷的信息;
(由此可以看出,细分的时候,每个步骤之间的联系可以引出更多的思考和细节)
2.(步骤)布置雷:
一个数组内,用什么表示雷呢?由于后面会用到雷的数量,如果一个雷用数字1表示,之后排雷点的范围内的雷的数量直接就是该范围内数字的和;所以,雷用数字1表示更好;
(这就是步骤有何技巧)
3.(步骤)排雷:
涉及数组,并且涉及对数组位置的变化的时候,一定考虑越界问题!!!(易错点)
这时,可以再多加一圈数组的大小,数组中间设置为游戏区域(技巧)
4.(步骤)状态判断
状态分为:1.结束 2.继续
结束有两种情况:1.被雷炸死 2.非雷区域全部探索完
三,代码实现
根据逻辑图,我们先用代码先写出整体步骤来
写完之后再一个一个实现代码逻辑
具体代码逻辑:
初始化棋盘:
//初始化棋盘
void IntiBoard(char board[ROW][COL], int row, int col, char tag)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
board[i][j] = tag;
}
}
return 0;
}
打印棋盘:
//打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col)
{
printf("\n棋盘如下:\n");
//打印棋盘有两个部分 1.提示行列数 2.棋盘内容
int i = 0;
int j = 0;
//第一行内容:0 1 2 3 4 5 6 7 8 9.....
for (i = 0; i <= GAMECOL; 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");
}
return;
}
布置雷:
//布置雷
void GetMine(char board[ROW][COL])
{
int minecounts = MINECOUNT;
while(minecounts != 0)
{
//未布置雷的地方才可以放
int x = rand() % GAMEROW + 1;
int y = rand() % GAMECOL + 1;
if(board[x][y] == '0')
{
board[x][y] = '1';
minecounts--;
}
}
return;
}
扫雷:
//得到雷的数量
int GetMineCounts(char board[ROW][COL], int row, int col)
{
//逻辑就是该点周围的内容之和-‘0’*8
return
(
board[row - 1][col + 1] +
board[row - 1][col] +
board[row - 1][col - 1] +
board[row][col + 1] +
board[row][col - 1] +
board[row + 1][col - 1] +
board[row + 1][col] +
board[row + 1][col - 1]
-(8*'0')
);
}
game函数内逻辑拼装:(重点)
void game()
{
//1.创建棋盘
//
//a.定义棋盘
char mine[ROW][COL] = { '0' };
char infor[ROW][COL] = { '0' };
//b.初始化棋盘
IntiBoard(mine, ROW, COL, '0');//雷为1非雷为0,初始化全0
IntiBoard(infor,ROW,COL,'*');//为探索为*,探索为周围雷的数量,初始化全*
//c.打印棋盘
DisplayBoard(infor,GAMEROW,GAMECOL);
//2.布置雷
GetMine(mine);
int x = 0;
int y = 0;
//3.扫雷
//4.结束条件是排除所有不是雷的地方(gamerow*gamecol-MINECOUNT),flag等于这个数字的时候获胜
int flag = 0;
while (flag < (GAMEROW*GAMECOL-MINECOUNT))
{
//a.输入目标行列
printf("请输入你扫的行列数:>");
scanf("%d %d", &x, &y);
//x,y必须是合法的
//一:在范围内
if (x >= 1 && x < GAMEROW && y >= 1 && y < GAMECOL && infor[x][y] == '*')
{
//b.检查雷
if (mine[x][y] == '1')
{
//是雷,炸死
printf("被炸死,游戏结束\n");
//被炸死的时候显示所有雷
DisplayBoard(mine, GAMEROW, GAMECOL);
return;
}
else
{
//不是雷的话,infor该位置显示周围地雷的数量
int minecounts = GetMineCounts(mine, x, y);
infor[x][y] = (minecounts + '0');
//然后显示
DisplayBoard(infor, GAMEROW, GAMECOL);
flag++;
}
}
else
{
printf("输入错误,请重新输入\n");
}
}
//flag等于这个数字的时候获胜
if (flag == (GAMEROW * GAMECOL - MINECOUNT))
{
printf("恭喜你,获得游戏胜利\n");
}
return;
}
主函数:
#include"all.h"
int main()
{
srand((unsigned int)time(NULL));
int choice = 0;
do
{
menu();
printf("请输入你的选择:>");
scanf("%d", &choice);
//根据选择进行游戏还是退出游戏
switch (choice)
{
case 1:
game();
break;
case 0:
printf("退出游戏成功\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
//choice为0代表退出游戏
} while (choice != 0);
return 0;
}
void menu()
{
printf("************************\n");
printf("**** 1.开始游戏 ******\n");
printf("**** 0.退出游戏 ******\n");
printf("************************\n");
return;
}
头文件:
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
//*** 宏定义 ***
#define ROW 11
#define COL 11
#define GAMEROW (ROW-2)
#define GAMECOL (COL-2)
#define MINECOUNT 80
//*** 函数定义 ***
void menu();
void game();
void IntiBoard(int board[ROW][COL], int row, int col, char tag);//初始化棋盘
void DisplayBoard(int board[ROW][COL], int row, int col);//打印棋盘
void GetMine(char board[ROW][COL]);//布置雷
int GetMineCounts(char board[ROW][COL], int row, int col);//得到周围雷的数量
四,心得总结
对于长代码程序,先画逻辑图是非常非常重要的,然后再细分逻辑图,根据逻辑图逐步逐步完善代码逻辑;
觉得不错的兄弟点个赞呗b( ̄▽ ̄)d