扫雷游戏
游戏模式:
- 起初所有方格都用 ’ @ ’ 覆盖
- 输入要选择的方格:例如
( r , c , 0 ) =>第r行第c列不是雷,所有该处显示其周围雷的个数;
( r , c , # ) =>第r行第c列是地雷;
( r , c , @ ) =>第r行第c列不是地雷,但是玩家标识成了地雷,
此时用’ @ ’ 覆盖该方格 - 游戏区域需要显示的数据:
(1):初始化全为 ’ @ ’
(2):显示地雷用 ’ # ’
(3):不是地雷就显示数字:0–8
(4):标识错误就用 ’ @ ’ 覆盖
初始化游戏网格
地雷放置区域为 15X15
但是为了方便计算边界值和4个角,将区域初始化为 17X17
游戏区域从(1,1)下标到(15,15)
向网格中随机填充地雷
随机因子函数确保每一次产生的地雷位置不定
srand();
time():可以获取当前系统的时间(是一个整型数据),因为时间是不同的所以随机
srand(time(nullptr));//随机因子函数,当括号内的数值每次调用都不一样,rand()函数每次产生的随机值都不一样
方式一:
- time_t x ;
time_t te = time ( & x ) ;//计算出当前的日历时间赋值给 x ;并把得到的数据给 te ;
方式二:
- time_t te = time ( nullptr ) ;//赋值为空,只需要返回日历时间
time_t te = time(nullptr);
struct tm tx;
localtime_s(&tx, &te);
#define ROWSIZE 15
#define COLSIZE 15
#define MINESIZE 64 //地雷个数
typedef unsigned char Grid[ROWSIZE + 2][COLSIZE + 2];//初始化网格
// typedef:把合法的数组声明变成类型声明
// Grid ar是一个指向数组的指针=unsigned char(*ar)[COLSIZE+2];
void Print_Ar(Grid ar, int row, int col)
{
//int size = sizeof(ar);size=4 Grid ar=unsigned char(*ar)[COLSIZE+2];
assert(ar != nullptr);
for (int i = 0;i < row+2;++i)
{
for (int j = 0;j < col+2;++j)
{
printf("%3d", ar[i][j]);
}
printf("\n");
}
printf("\n");
}
void Init_Ar(Grid ar, int row, int col)
{
assert(ar != nullptr);
for (int i = 1;i <= row;++i)//初始化游戏区域,全部用 @ 覆盖
{
for (int j = 1;j <= col;++j)
{
ar[i][j] |= INIT_VIEW;
}
}
int num = 0;
//rand()函数每次产生的随机值都一样,所以是伪随机,要使每次产生地雷的位置都不一样
srand(time(nullptr));//随机因子函数,当括号内的数值每次调用都不一样,rand()函数每次产生的随机值都不一样
while (num < MINENUM)//初始化地雷的个数
{
int r = rand() % ROWSIZE + 1;// 1--15
int c = rand() % COLSIZE + 1;// 1--15
if (!(ar[r][c] & MAKE_MINE))//如果第5个比特位是1,代表该处有地雷
{
ar[r][c] |= MAKE_MINE;
++num;
}
}
}
原因:
因为 ar 是一个无符号值,给出的 -1 二进制全1,所以按照无符号打印出来就是255
将地雷显示成 ‘#’
void Print_Ar(Grid ar, int row, int col)
{
assert(ar != nullptr);
for (int i = 0;i < row+2;++i)
{
for (int j = 0;j < col+2;++j)
{
if (ar[i][j] == 255)
{
printf("%3c", '#');
}
else
{
printf("%3d", ar[i][j]);
}
}
printf("\n");
}
printf("\n");
}
void Init_Ar(Grid ar, int row, int col)
{
assert(ar != nullptr);
int i = 0;
while (i < MINESIZE)
{
int r = rand() % ROWSIZE + 1;// 1--15
int c = rand() % COLSIZE + 1;// 1--15
if (ar[r][c] != -1)
{
ar[r][c] = 255;
++i;
}
}
}
计算每一个不是地雷的方格周围8个方格的地雷数
void SetDig_Ar(Grid ar, int row, int col)//设置数字
{
assert(ar != nullptr);
for (int r = 1;r < row;++r)//扫每一行
{
for (int c = 1;c < col;++c)
{
if (ar[r][c] == 0)//该处不是地雷,需要填充数字
{
int sum = 0;
for (int i = r - 1;i < r + 2;++i)
{
for (int j = c - 1;j < c + 2;++j)
{
if (ar[i][j] == 255)
{
sum += 1;
}
}
}
ar[r][c] = sum;
}
}
}
}
将一个字节按每一个比特位进行标识
(1)最高比特位为1:代表该位置是地雷
void Print_Ar(Grid ar, int row, int col)
{
//int size = sizeof(ar);size=4 Grid ar=unsigned char(*ar)[COLSIZE+2];
assert(ar != nullptr);
for (int i = 0;i < row+2;++i)
{
for (int j = 0;j < col+2;++j)
{
if ((ar[i][j]&0x80 )== MAKEMINE)
{
printf("%3c", '#');
}
else
{
printf("%3d", ar[i][j]);
}
}
printf("\n");
}
printf("\n");
}
void Init_Ar(Grid ar, int row, int col)
{
assert(ar != nullptr);
int i = 0;
while (i < MINESIZE)
{
int r = rand() % ROWSIZE + 1;// 1--15
int c = rand() % COLSIZE + 1;// 1--15
if (ar[r][c] != -1)
{
ar[r][c] = MAKEMINE;
++i;
}
}
}
void SetDig_Ar(Grid ar, int row, int col)//设置数字
{
assert(ar != nullptr);
for (int r = 1;r < row;++r)//扫每一行
{
for (int c = 1;c < col;++c)
{
if (ar[r][c] == 0)//该处不是地雷,需要填充数字
{
int sum = 0;
for (int i = r - 1;i < r + 2;++i)
{
for (int j = c - 1;j < c + 2;++j)
{
if ((ar[i][j]&0x80 )== MAKEMINE)
{
sum += 1;
}
}
}
ar[r][c] = sum;
}
}
}
}
(2)游戏改进:8个Bit位进行标识
游戏模式:
- 起初所有方格都用 ’ @ ’ 覆盖
- 输入要选择的方格:例如
( r , c , 0 ) =>第r行第c列不是雷,所有该处显示其周围雷的个数;
( r , c , # ) =>第r行第c列是地雷;
( r , c , @ ) =>第r行第c列不是地雷,但是玩家标识成了地雷,
此时用’ @ ’ 覆盖该方格 - 游戏区域需要显示的数据:
(1):初始化全为 ’ @ ’
(2):显示地雷用 ’ # ’
(3):不是地雷就显示数字:0–8
(4):标识错误就用 ’ @ ’ 覆盖
将每一个方格想象成一个 unsigned char 类型: