1.先制作一个菜单,要求循环可玩。第一次进入就需要选择,所以用do while语句(进入游戏的函数先放着)
void menu()
{
printf("**************************\n");
printf("**********1.play**********\n");
printf("**********0.exit**********\n");
printf("**************************\n");
}
int main()
{
int input = 0;
do
{
menu();
printf("请输入数字:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
break;
default:
printf("请输入正确的值!!!\n");
break;
}
} while (input);
return 0;
}
2.写出游戏函数里的内容
先定下来有多少行和列以及地雷个数,#define定义固定
需要注意的是:1.我们要创造两个空间,一个是藏地雷的数组,另一个是战场具体情况的数组 2.
#define ROW 9
#define COL 9
#define ROWS (ROW+2)
#define COLS (COL+2)
#define MINE 10
2.1得到两个数组,一个是雷区,一个是战场
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
2.2给两个数组赋值,给一个函数,实现出雷区(0);战场(*)【因为雷区跟战场是全赋值,所以就把他们需要赋值成的数也传入函数内部方便设计】
get_board(mine, ROWS, COLS, '0');
get_board(show, ROWS, COLS, '*');
void get_board(char board[ROWS][COLS], int row, int col, char p)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < row; j++)
{
board[i][j] = p;
}
}
}
2.3打印雷区和战场方便下一步调试,所以做一个打印的函数:需要从1开始到设定的行列结束,并且为了方便别人看,我们还需要写出对应坐标(前面用//注释是为了方便看)
//print_board(mine, ROW, COL);
//print_board(show, ROW, COL);
void print_board(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf("-------------------\n");
for (i = 0; j <= row; j++)
{
printf("%d ", j);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d ", i);
for (j = 1; j <= row; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
printf("-------------------\n");
}
2.4随机生成炸弹,需要用到rand()函数对9取模,得到0~8,然后加一范围向上一位,并且写给打印函数,以观察是不是生成正确
get_mine(mine, ROW, COL);
//print_board(mine, ROW, COL);
void get_mine(char board[ROWS][COLS], int row, int col)
{
int count = 1;
while (count <= MINE)
{
int i = rand() % ROW + 1;
int j = rand() % COL + 1;
if (board[i][j] == '0')
{
board[i][j] = '1';
}
else
continue;
count++;
}
}
需要在main函数里加入srand函数
srand((unsigned int)time(NULL));
2.5.做个循环,判断游戏进行状况(需要做到一个标记,一个选择地址,判断输赢)
2.5.1外面一层循环做标记,区域判断和输赢判断先不写
void choice()
{
printf("**********1.排 雷**********\n");
printf("**********2.标记雷**********\n");
}
while (1)
{
int ret = 0;
print_board(show, ROW, COL);
choice();
int cho = 1;
scanf("%d", &cho);
while (cho == 1)
{
//
//选择区域判断有没有炸弹的模块
//
}
while (cho == 2)
{
//标记雷函数guess_mine()
guess_mine(show, ROW, COL);
print_board(show, ROW, COL);
choice();
cho = 0;
scanf("%d", &cho);
}
if (/*输赢的条件*/)
{
break;
}
}
void guess_mine(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf("请输入坐标\n");
scanf("%d %d", &i, &j);
if (board[i][j] == '*')
{
board[i][j] = '#';
}
else if (board[i][j] == '#')
{
board[i][j] = '*';
}
}
2.5.2区域判断和跳出区域判断的循环
while (cho == 1)
{
print_board(show, ROW, COL);
int i = 0; int j = 0;
printf("请输入坐标\n");
scanf("%d %d", &i, &j);
//坐标在范围内的
if (i >= 1 && i <= 9 && j >= 1 && j <= 9)
{
//1.不是地雷且没探索过的
if (mine[i][j] == '0' && show[i][j] == '*')
{
//1)下面是点开的格子周围地雷分布
get_blank(mine, show, i, j);
//2.做给函数判断是否赢了
num = if_win(show, ROW, COL);
if (num == MINE)
{
printf("你赢了\n");
print_board(show, ROW, COL);
ret = 1;
break;
}
}
//1.2.不是地雷但是重复探索的
else if (mine[i][j] == '0' && show[i][j] != '*')
{
printf("这个坐标你已经探索过了,请重新输入其他未探索目标!\n");
}
//1.3.踩到地雷的
else
{
printf("你踩到地雷了...\n");
printf("以下是地雷的分布图\n");
print_board(mine, ROW, COL);
ret = 1;
break;
}
}
//2.在范围外的
else
{
printf("请输入正确的坐标!\n");
}
print_board(show, ROW, COL);
choice();
cho = 0;
scanf("%d", &cho);
}
以下是开辟空格,以及如果选择的区域没有雷,向四周扩散的函数
void get_blank(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
//1.最重要的一步就是获取格子周围的地雷数目
show[x][y] = mine[x - 1][y - 1] + mine[x - 1][y] + mine[x - 1][y + 1] + mine[x][y - 1] +
mine[x][y + 1] + mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] - 8 * '0' + '0';
//2.扩散空白部分
if ((show[x][y] == '0') && (x - 1 >= 1) && (mine[x - 1][y] != 1) && show[x - 1][y] == '*')
{
get_blank(mine, show, x - 1, y);
}
if ((show[x][y] == '0') && (x + 1 <= ROW) && (mine[x + 1][y] != 1) && show[x + 1][y] == '*')
{
get_blank(mine, show, x + 1, y);
}
if ((show[x][y] == '0') && (y - 1 >= 1) && (mine[x][y - 1] != 1) && show[x][y - 1] == '*')
{
get_blank(mine, show, x, y - 1);
}
if ((show[x][y] == '0') && (y + 1 <= COL) && (mine[x - 1][y] != 1) && show[x][y + 1] == '*')
{
get_blank(mine, show, x, y + 1);
}
}
再是判断输赢的函数,赢的条件就是剩下的*跟雷的个数一致
int if_win(char show[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
int count = 0;
for (i = 1; i <= row; i++)
{
for (j = 1; j <= col; j++)
{
if (show[i][j] == '*')
{
count++;
}
}
}
return count;
}
最后整体的实现是这样的
while (1)
{
int ret = 0;
print_board(show, ROW, COL);
choice();
int cho = 1;
scanf("%d", &cho);
while (cho == 1)
{
print_board(show, ROW, COL);
int i = 0; int j = 0;
printf("请输入坐标\n");
scanf("%d %d", &i, &j);
//5.1.坐标在范围内的
if (i >= 1 && i <= 9 && j >= 1 && j <= 9)
{
//5.1.1.不是地雷且没探索过的
if (mine[i][j] == '0' && show[i][j] == '*')
{
//1)下面是点开的格子周围地雷分布
get_blank(mine, show, i, j);
//2).做给函数判断是否赢了
num = if_win(show, ROW, COL);
if (num == MINE)
{
printf("你赢了\n");
print_board(show, ROW, COL);
ret = 1;
break;
}
}
//5.1.2.不是地雷但是重复探索的
else if (mine[i][j] == '0' && show[i][j] != '*')
{
printf("这个坐标你已经探索过了,请重新输入其他未探索目标!\n");
}
//5.1.3.踩到地雷的
else
{
printf("你踩到地雷了...\n");
printf("以下是地雷的分布图\n");
print_board(mine, ROW, COL);
ret = 1;
break;
}
}
//5.2.在范围外的
else
{
printf("请输入正确的坐标!\n");
}
print_board(show, ROW, COL);
choice();
cho = 0;
scanf("%d", &cho);
}
while (cho == 2)
{
//标记雷函数guess_mine()
guess_mine(show, ROW, COL);
print_board(show, ROW, COL);
choice();
cho = 0;
scanf("%d", &cho);
}
if (ret == 1)
{
break;
}
}
最后是我写的代码,其实还有挺多漏洞跟赘余的,不过我有好多想法有点难实现,以后再试试
test.c文件
#define _CRT_SECURE_NO_WARNINGS
#include"game.h"
void menu()
{
printf("**************************\n");
printf("**********1.play**********\n");
printf("**********0.exit**********\n");
printf("**************************\n");
}
//6.标记雷
void choice()
{
printf("**********1.排 雷**********\n");
printf("**********2.标记雷**********\n");
}
void game()
{
//1.得到两个数组,一个是雷区,一个是战场
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
//2.给两个数组赋值,雷区(0);战场(*)
get_board(mine, ROWS, COLS, '0');
get_board(show, ROWS, COLS, '*');
//3.打印雷区和战场方便下一步调试
//print_board(mine, ROW, COL);
//print_board(show, ROW, COL);
//4.随机生成炸弹;
get_mine(mine, ROW, COL);
//print_board(mine, ROW, COL);
//5.做个循环,判断游戏进行状况
int num = ROW * COL;
while (1)
{
int ret = 0;
print_board(show, ROW, COL);
choice();
int cho = 1;
scanf("%d", &cho);
while (cho == 1)
{
print_board(show, ROW, COL);
int i = 0; int j = 0;
printf("请输入坐标\n");
scanf("%d %d", &i, &j);
//5.1.坐标在范围内的
if (i >= 1 && i <= 9 && j >= 1 && j <= 9)
{
//5.1.1.不是地雷且没探索过的
if (mine[i][j] == '0' && show[i][j] == '*')
{
//1)下面是点开的格子周围地雷分布
get_blank(mine, show, i, j);
//2).做给函数判断是否赢了
num = if_win(show, ROW, COL);
if (num == MINE)
{
printf("你赢了\n");
print_board(show, ROW, COL);
ret = 1;
break;
}
}
//5.1.2.不是地雷但是重复探索的
else if (mine[i][j] == '0' && show[i][j] != '*')
{
printf("这个坐标你已经探索过了,请重新输入其他未探索目标!\n");
}
//5.1.3.踩到地雷的
else
{
printf("你踩到地雷了...\n");
printf("以下是地雷的分布图\n");
print_board(mine, ROW, COL);
ret = 1;
break;
}
}
//5.2.在范围外的
else
{
printf("请输入正确的坐标!\n");
}
print_board(show, ROW, COL);
choice();
cho = 0;
scanf("%d", &cho);
}
while (cho == 2)
{
//标记雷函数guess_mine()
guess_mine(show, ROW, COL);
print_board(show, ROW, COL);
choice();
cho = 0;
scanf("%d", &cho);
}
if (ret == 1)
{
break;
}
}
}
int main()
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
menu();
printf("请输入数字:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
break;
default:
printf("请输入正确的值!!!\n");
break;
}
} while (input);
return 0;
}
game.c文件
#define _CRT_SECURE_NO_WARNINGS
#include"game.h"
void get_board(char board[ROWS][COLS], int row, int col, char p)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < row; j++)
{
board[i][j] = p;
}
}
}
void print_board(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf("-------------------\n");
for (i = 0; j <= row; j++)
{
printf("%d ", j);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d ", i);
for (j = 1; j <= row; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
printf("-------------------\n");
}
void get_mine(char board[ROWS][COLS], int row, int col)
{
int count = 1;
while (count <= MINE)
{
int i = rand() % ROW + 1;
int j = rand() % COL + 1;
if (board[i][j] == '0')
{
board[i][j] = '1';
}
else
continue;
count++;
}
}
void get_blank(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
//1.最重要的一步就是获取格子周围的地雷数目
show[x][y] = mine[x - 1][y - 1] + mine[x - 1][y] + mine[x - 1][y + 1] + mine[x][y - 1] +
mine[x][y + 1] + mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] - 8 * '0' + '0';
//2.扩散空白部分
if ((show[x][y] == '0') && (x - 1 >= 1) && (mine[x - 1][y] != 1) && show[x - 1][y] == '*')
{
get_blank(mine, show, x - 1, y);
}
if ((show[x][y] == '0') && (x + 1 <= ROW) && (mine[x + 1][y] != 1) && show[x + 1][y] == '*')
{
get_blank(mine, show, x + 1, y);
}
if ((show[x][y] == '0') && (y - 1 >= 1) && (mine[x][y - 1] != 1) && show[x][y - 1] == '*')
{
get_blank(mine, show, x, y - 1);
}
if ((show[x][y] == '0') && (y + 1 <= COL) && (mine[x - 1][y] != 1) && show[x][y + 1] == '*')
{
get_blank(mine, show, x, y + 1);
}
}
int if_win(char show[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
int count = 0;
for (i = 1; i <= row; i++)
{
for (j = 1; j <= col; j++)
{
if (show[i][j] == '*')
{
count++;
}
}
}
return count;
}
void guess_mine(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf("请输入坐标\n");
scanf("%d %d", &i, &j);
if (board[i][j] == '*')
{
board[i][j] = '#';
}
else if (board[i][j] == '#')
{
board[i][j] = '*';
}
}
game.h文件
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 9
#define COL 9
#define ROWS (ROW+2)
#define COLS (COL+2)
#define MINE 10
void get_board(char board[ROWS][COLS], int row, int col, char p);
void print_board(char board[ROWS][COLS], int row, int col);
void get_mine(char board[ROWS][COLS], int row, int col);
void get_blank(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y);
int if_win(char show[ROWS][COLS], int row, int col);
void guess_mine(char board[ROWS][COLS], int row, int col);