CSDN小伙伴们,大家好啊,这次我们来实现一个小游戏——扫雷
扫雷规则大概是点击未开的方块,若是雷,游戏失败,若不是雷,将该位置换为一个数字,该数字表示该位置一圈的8个位置的雷的个数
接下来,让我们一起实现它吧!
一、主体
1、框架
//test.c
int main()
{
return 0;
}
2、主页
①选择主体
游戏首先画面是选择画面,开始游戏后结束游戏返回该界面,退出游戏直接停止程序
//test.c
int main()
{
int input = 0;
do
{
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
printf("扫雷\n");
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误\n");
break;
}
} while (input);
return 0;
}
②主页主体
主页画面,我们简单设计一下
void menu()
{
printf("******************************\n");
printf("********* 1 . play *********\n");
printf("********* 0 . quit *********\n");
printf("******************************\n");
}
效果大致是这样
之后我们就可以开始思考编写游戏规则代码啦,为了总体代码的效率和可读性,我们采用多自定义函数来实现。
test.c为主,game.c为辅
二、客体
1、声明数组
首先我们思考,扫雷是 某*某 大的方格,这样我们可以用二维数组来实现,而且我们要用两个,一个用来布置雷,一个用来显示
以制作9*9为例
//game.h
#define POW 11
#define COL 11
//test.c
void game()
{
int arr1[POW][COL] = { 0 };
int arr2[POW][COL] = { 0 };
}
为什么我们用11而不是9呢?
在我们打开一个非雷的方格时,需要显示其中一圈的雷的个数,如果用9,在顶点的位置需要判断3个位置,边上需要判断5个位置,而其他地方需要判断8个位置,数量不统一,容易越界访问,这样会加大代码的难度,而我们在9*9的方格外再加一层的话,有效9*9的区域就都可以判断8个位置了,得到了统一,也不易越界。
2、初始化数组
我们将展示的数字为arr1(用“*”表示未打开),布置雷为arr2(0表示非雷,1表示雷)
//game.c
void arr_init(int arr[POW][COL], int pow, int col, char set)
{
int i = 0;
int j = 0;
for (i = 0; i < pow; i++)
{
for (j = 0; j < col; j++)
{
arr[i][j] = set;
}
}
}
//test.c
void game()
{
int arr1[POW][COL] = { 0 };
int arr2[POW][COL] = { 0 };
arr_init(arr1, POW, COL, '*');
arr_init(arr2, POW, COL, '0');
}
3、布置雷
布置雷要有随机性,所以我们使用rand函数和srand来实现,用时间戳来给srand提供变化值
//game.c
void lay_mine(int arr2[POW][COL], int pow, int col)
{
int z = 10;
while (z)
{
int x = rand() % pow + 1;
int y = rand() % col + 1;
if (arr2[x][y] == '0')
{
arr2[x][y] = '1';
z--;
}
}
}
//pow=POW-2
//col=COL-2
//test.c
int main()
{
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");
break;
}
}
} while (input);
return 0;
}
4、打印雷盘
//game.c
void chess(int arr[POW][COL], int pow, int col)
{
int i = 0;
int j = 0;
printf("*************扫雷*************\n");
for (i = 0; i <= 9; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= 9; i++)
{
printf("%d ", i);
for (j = 1; j <=9; j++)
{
printf("%c ", arr[i][j]);
}
printf("\n");
}
}
效果大概就是这样
我们也可以打印一下arr2来看看雷的布置情况
5、排雷
大概思路是,输入坐标,坐标范围正确,若该位置是雷,游戏结束,并打印arr2
若输入坐标不是雷,将该位置的“*”改为数字,该数字代表旁边有几个雷,并打印arr1
坐标错误重新输入坐标
(x-1,y-1) | (x-1,y) | (x-1,y+1) |
(x,y-1) | 打开的位置(x,y) | (x,y+1) |
(x+1,y-1) | (x+1,y) | (x+1,y+1) |
非雷是用字符‘0’表示的,雷是用字符‘1’表示的
所以(x,y)所显示的数字应该是旁边8个数的ASCII码相加再减8个字符‘0’的ASCII码
//game.c
void check(int arr2[POW][COL], int arr1[POW][COL], int pow, int col)
{
int x = 0;
int y = 0;
int z = 0;
while (z <= 71)
{
printf("请输入坐标:>");
scanf("%d%d", &x, &y);
if (x >= 1 && x <= pow && y >= 1 && y <= col)
{
if (arr2[x][y] == '1')
{
printf("很遗憾,你踩雷了\n");
chess(arr2, POW, COL);
break;
}
else
{
int s = judge(arr2, x, y);
arr1[x][y] = s + '0';
chess(arr1, POW, COL);
z++;
}
}
else printf("请输入正确坐标\n");
}
if (z == 71) printf("恭喜你,排雷成功\n");
}
int judge(int arr2[POW][COL], int x, int y)
{
return ((arr2[x - 1][y - 1] +
arr2[x - 1][y] + arr2[x - 1][y + 1] +
arr2[x][y - 1] + arr2[x][y + 1] +
arr2[x + 1][y - 1] + arr2[x + 1][y] + arr2[x + 1][y + 1]) - 8 * 48);
}
三、主体和客体连接
//game.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define POW 11
#define COL 11
//数组初始化
void arr_init(int arr1[POW][COL], int pow, int col, char set);
//打印棋盘
void chess(int arr[POW][COL], int pow, int col);
//布置雷
void lay_mine(int arr2[POW][COL], int pow, int col);
//排查雷
void check(int arr2[POW][COL], int arr1[POW][COL], int pow, int col);
四、总代码
最后所以代码为下
//game.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define POW 11
#define COL 11
//数组初始化
void arr_init(int arr1[POW][COL], int pow, int col, char set);
//打印棋盘
void chess(int arr[POW][COL], int pow, int col);
//布置雷
void lay_mine(int arr2[POW][COL], int pow, int col);
//排查雷
void check(int arr2[POW][COL], int arr1[POW][COL], int pow, int col);
//game.c
#include"game.h"
//数组初始化
void arr_init(int arr[POW][COL], int pow, int col, char set)
{
int i = 0;
int j = 0;
for (i = 0; i < pow; i++)
{
for (j = 0; j < col; j++)
{
arr[i][j] = set;
}
}
}
//布置雷
void lay_mine(int arr2[POW][COL], int pow, int col)
{
int z = 10;
while (z)
{
int x = rand() % pow + 1;
int y = rand() % col + 1;
if (arr2[x][y] == '0')
{
arr2[x][y] = '1';
z--;
}
}
}
void chess(int arr[POW][COL], int pow, int col)
{
int i = 0;
int j = 0;
printf("*************扫雷*************\n");
for (i = 0; i <= 9; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= 9; i++)
{
printf("%d ", i);
for (j = 1; j <= 9; j++)
{
printf("%c ", arr[i][j]);
}
printf("\n");
}
}
//排查雷
void check(int arr2[POW][COL], int arr1[POW][COL], int pow, int col)
{
int x = 0;
int y = 0;
int z = 0;
while (z <= 71)
{
printf("请输入坐标:>");
scanf("%d%d", &x, &y);
if (x >= 1 && x <= pow && y >= 1 && y <= col)
{
if (arr2[x][y] == '1')
{
printf("很遗憾,你踩雷了\n");
chess(arr2, POW, COL);
break;
}
else
{
int s = judge(arr2, x, y);
arr1[x][y] = s + '0';
chess(arr1, POW, COL);
z++;
}
}
else printf("请输入正确坐标\n");
}
if (z == 71) printf("恭喜你,排雷成功\n");
}
int judge(int arr2[POW][COL], int x, int y)
{
return ((arr2[x - 1][y - 1] +
arr2[x - 1][y] + arr2[x - 1][y + 1] +
arr2[x][y - 1] + arr2[x][y + 1] +
arr2[x + 1][y - 1] + arr2[x + 1][y] + arr2[x + 1][y + 1]) - 8 * 48);
}
//test.c
#include"game.h"
void menu()
{
printf("******************************\n");
printf("********* 1 . play *********\n");
printf("********* 0 . quit *********\n");
printf("******************************\n");
}
void game()
{
int arr1[POW][COL] = { 0 };
int arr2[POW][COL] = { 0 };
arr_init(arr1, POW, COL, '*');
arr_init(arr2, POW, COL, '0');
lay_mine(arr2, POW-2, COL-2);
chess(arr1, POW-2, COL-2);
check(arr2, arr1, POW-2, COL-2);
}
int main()
{
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");
break;
}
}
} while (input);
return 0;
}
以上就是基本扫雷的全部内容,主要运用的是循环,分支语句,函数调用,ASCII运用等,感谢观看~