思路:
- 0表示无,1表示雷
- 1表示雷还是雷的个数不清楚,所以用两个数组分别存放
- 为了防止越界,方便统计九宫格的雷数量,加俩行俩列,即9x9 —> 11x11
- 棋盘11x11,且为字符数组
代码实现:
- test.c 测试游戏的代码
- game.c 游戏的实现
- game.h 游戏函数的声明
步骤:
1.菜单
(1)菜单在test.c源文件内实现
#include "game.h"
void menu()//打印菜单
{
printf("************************\n");
printf("******* 1 : enter ******\n");
printf("******* 0 : exit ******\n");
printf("************************\n");
}
int main()
{
srand((unsigned int)time(NULL));//此为随机时间戳,后面会用到,此处不赘述
int input = 0;
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;
}
2.设置棋盘
(1)先设置两个二维数组,即设置棋盘
(2)设置11*11便于在排查雷时显示九宫格雷数
(3)因采用数字显冗杂,故采用宏定义,在game.h头文件中实现
#pragma once
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#include <stdio.h>
#include "game.h"
void game()
{
char mine[ROWS][COLS];//存放雷
char show[ROWS][COLS];//排查雷
}
3.初始化棋盘
(1)再用函数初始化棋盘,这里采用 0无雷,1有雷
(2)为更加简洁,这里将 0 和 * 各自放在引用值中,便于一函数多用,下图为test.c文件的代码
void game()
{
char mine[ROWS][COLS];//存放雷
char show[ROWS][COLS];//排查雷
Intiboard(mine, ROWS, COLS, '0');
Intiboard(show, ROWS, COLS, '*');
}
(3)因为使用的函数在源文件的game()函数内,所以要在game.h头文件中进行函数的声明
#pragma once
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
void Intiboard(char board[ROWS][COLS], int rows, int cols, char set);
void Intiboard(char board[ROWS][COLS], int rows, int cols, char set);
(4)下图为game.c文件内具体函数的实现
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void Intiboard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0;
for ( i = 0; i < rows; i++)
{
int j = 0;
for ( j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
4.打印棋盘
(1)同样头文件函数声明
#pragma once
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
void Intiboard(char board[ROWS][COLS], int rows, int cols, char set);
void Intiboard(char board[ROWS][COLS], int rows, int cols, char set);
void Displayboard(char board[ROWS][COLS], int row, int col);
void Displayboard(char board[ROWS][COLS], int row, int col);
(2)打印只需要9*9的格子,下图为test.c文件代码
void game()
{
char mine[ROWS][COLS];//存放雷
char show[ROWS][COLS];//排查雷
Intiboard(mine, ROWS, COLS, '0');
Intiboard(show, ROWS, COLS, '*');
//打印棋盘
//Displayboard(mine, ROW, COL);
Displayboard(show, ROW, COL);
}
(3)打印中间9*9,顾从1开始,9结束,下图为game.c文件内函数实现
Displayboard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
for ( i = 1; i <= row; i++)
{
int j = 0;
for ( j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
此代码打印出的棋盘如图
(4)为了美观,修改代码如图
void Displayboard(char board[ROWS][COLS], int row, int col)
{
printf("*********扫雷游戏*********\n");
int i = 0;
printf(" | ");
for ( i = 1; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
printf(" | ");
for (i = 1; i <= col; i++)
{
printf("--");
}
printf("\n");
for (i = 1; i <= row; i++)//打印中间9*9,顾从1开始,9结束
{
int j = 0;
printf("%d | ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
效果如图
5.设置雷
(1)头文件函数声明
#pragma once
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define Eazycount 10
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//因为使用的函数在源文件的game()函数内,所以要进行函数的声明
void Intiboard(char board[ROWS][COLS], int rows, int cols, char set);
void Intiboard(char board[ROWS][COLS], int rows, int cols, char set);
void Displayboard(char board[ROWS][COLS], int row, int col);
void Displayboard(char board[ROWS][COLS], int row, int col);
void Setmine(char board[ROWS][COLS], int row, int col);
(2)随机数设置雷,注意此处用到一开始提到的时间戳,其中相应头文件,在game.h中实现,下图为game.c中函数实现
void Setmine(char board[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int count = Eazycount;//此处同样采用宏定义更方便,还可便于动态测试程序是否可行
while (count)
{
x = rand() % 9 + 1;//随机数设置雷
y = rand() % 9 + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
count--;
}
}
}
(3)下图是源文件test.c的函数调用及时间戳的实现
void game()
{
//先设置两个二维数组,即设置棋盘
//设置11便于在排查雷时显示九宫格雷数
char mine[ROWS][COLS];//存放雷
char show[ROWS][COLS];//排查雷
//因采用数字显冗杂,故采用宏定义,在头文件中实现
//再用函数初始化棋盘,这里采用 0无雷,1有雷
Intiboard(mine, ROWS, COLS, '0');
Intiboard(show, ROWS, COLS, '*');
//为更加简洁,这里将 0 和 * 各自放在引用值中,便于一函数多用
//打印棋盘
//Displayboard(mine, ROW, COL);//打印只需要9*9的格子
Displayboard(show, ROW, COL);
//设置雷
Setmine(mine, ROW, COL);
//Displayboard(mine, ROW, COL);
}
int main()
{
srand((unsigned int)time(NULL));
return 0;
}
6.寻找雷
(1)game.h头文件中函数的声明
#pragma once
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define Eazycount 10
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//因为使用的函数在源文件的game()函数内,所以要进行函数的声明
void Intiboard(char board[ROWS][COLS], int rows, int cols, char set);
void Intiboard(char board[ROWS][COLS], int rows, int cols, char set);
void Displayboard(char board[ROWS][COLS], int row, int col);
void Displayboard(char board[ROWS][COLS], int row, int col);
void Setmine(char board[ROWS][COLS], int row, int col);
void Findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
(2)test.c源代码的函数调用
void game()
{
//先设置两个二维数组,即设置棋盘
//设置11便于在排查雷时显示九宫格雷数
char mine[ROWS][COLS];//存放雷
char show[ROWS][COLS];//排查雷
//因采用数字显冗杂,故采用宏定义,在头文件中实现
//再用函数初始化棋盘,这里采用 0无雷,1有雷
Intiboard(mine, ROWS, COLS, '0');
Intiboard(show, ROWS, COLS, '*');
//为更加简洁,这里将 0 和 * 各自放在引用值中,便于一函数多用
//打印棋盘
//Displayboard(mine, ROW, COL);//打印只需要9*9的格子
Displayboard(show, ROW, COL);
//设置雷
Setmine(mine, ROW, COL);
//Displayboard(mine, ROW, COL);
//排查雷
Findmine(mine, show, ROW, COL);
}
(3)当排查完所以雷,即知道所以非雷坐标后,结束,所以采用循环结构
(4)被排查点显示数等于周围8个数减去'0'ASCII码值的八倍
(5)注意在使棋盘显示出周围雷个数时,应该加上'0',因为数组只能显示字符类型,这里用ASCII码值转换
(6)下图为game.c中的代码实现
void Findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int win = 0;//设置胜利条件
while ( win < row * col - Eazycount)//当排查完所以雷,即知道所以非雷坐标后,循环结束
{
printf("请输入坐标:>");
scanf("%d %d", &x, &y);
if (x <= 9 && x >= 1 && y <= 9 && y >= 1)//坐标需要满足条件
{
if (mine[x][y] == '1')
{
printf("很遗憾,你被炸死了\n");
Displayboard(mine, ROW, COL);
break;
}
else
{
int num = Getmine(mine, x, y);
show[x][y] = num + '0';//因为要用字符类型,所以用ASCII码值转换
Displayboard(show, ROW, COL);
win++;//每排查出一个雷,则win+1
}
}
else
{
printf("非法输入,请重试:>");
}
if (win == row * col - Eazycount)
{
printf("恭喜你,你赢了,埋雷如图\n");
Displayboard(mine, ROW, COL);
}
}
}
int Getmine(char mine[ROWS][COLS], int x, int y)
{
return (mine[x - 1][y - 1] + mine[x][y - 1] + mine[x + 1][y - 1] + mine[x - 1][y] + mine[x + 1][y] +
mine[x - 1][y + 1] + mine[x][y + 1] + mine[x + 1][y + 1] - 8 * '0');
}
7.总代码实现
(1)game.h
#pragma once
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define Eazycount 10
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//因为使用的函数在源文件的game()函数内,所以要进行函数的声明
void Intiboard(char board[ROWS][COLS], int rows, int cols, char set);
void Intiboard(char board[ROWS][COLS], int rows, int cols, char set);
void Displayboard(char board[ROWS][COLS], int row, int col);
void Displayboard(char board[ROWS][COLS], int row, int col);
void Setmine(char board[ROWS][COLS], int row, int col);
void Findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
(2)test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"//因要包含game.h,则在game.h中引入需要的头文件更简洁
void menu()//打印菜单
{
printf("************************\n");
printf("******* 1 : enter ******\n");
printf("******* 0 : exit ******\n");
printf("************************\n");
}
void game()
{
//先设置两个二维数组,即设置棋盘
//设置11便于在排查雷时显示九宫格雷数
char mine[ROWS][COLS];//存放雷
char show[ROWS][COLS];//排查雷
//因采用数字显冗杂,故采用宏定义,在头文件中实现
//再用函数初始化棋盘,这里采用 0无雷,1有雷
Intiboard(mine, ROWS, COLS, '0');
Intiboard(show, ROWS, COLS, '*');
//为更加简洁,这里将 0 和 * 各自放在引用值中,便于一函数多用
//打印棋盘
//Displayboard(mine, ROW, COL);//打印只需要9*9的格子
Displayboard(show, ROW, COL);
//设置雷
Setmine(mine, ROW, COL);
//Displayboard(mine, ROW, COL);
//排查雷
Findmine(mine, show, ROW, COL);
}
int main()
{
srand((unsigned int)time(NULL));
int input = 0;
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;
}
(3)game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void Intiboard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0;
for ( i = 0; i < rows; i++)
{
int j = 0;
for ( j = 0; j < cols; j++)
{
board[i][j] = set;//因为数组用的字符类型,所以这里也要字符类型,0加''号
}
}
}
//Displayboard(char board[ROWS][COLS], int row, int col)
//{
// int i = 0;
// for ( i = 1; i <= row; i++)//打印中间9*9,顾从1开始,9结束
// {
// int j = 0;
// for ( j = 1; j <= col; j++)
// {
// printf("%c ", board[i][j]);
// }
// printf("\n");
// }
//}
//为了美观,进行修正
void Displayboard(char board[ROWS][COLS], int row, int col)
{
printf("*********扫雷游戏*********\n");
int i = 0;
printf(" | ");
for ( i = 1; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
printf(" | ");
for (i = 1; i <= col; i++)
{
printf("--");
}
printf("\n");
for (i = 1; i <= row; i++)//打印中间9*9,顾从1开始,9结束
{
int j = 0;
printf("%d | ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
void Setmine(char board[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int count = Eazycount;//此处同样采用宏定义更方便,还可便于动态测试程序是否可行
while (count)
{
x = rand() % 9 + 1;//随机数设置雷
y = rand() % 9 + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
count--;
}
}
}
void Findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int win = 0;//设置胜利条件
while ( win < row * col - Eazycount)//当排查完所以雷,即知道所以非雷坐标后,循环结束
{
printf("请输入坐标:>");
scanf("%d %d", &x, &y);
if (x <= 9 && x >= 1 && y <= 9 && y >= 1)//坐标需要满足条件
{
if (mine[x][y] == '1')
{
printf("很遗憾,你被炸死了\n");
Displayboard(mine, ROW, COL);
break;
}
else
{
int num = Getmine(mine, x, y);
show[x][y] = num + '0';//因为要用字符类型,所以用ASCII码值转换
Displayboard(show, ROW, COL);
win++;//每排查出一个雷,则win+1
}
}
else
{
printf("非法输入,请重试:>");
}
if (win == row * col - Eazycount)
{
printf("恭喜你,你赢了,埋雷如图\n");
Displayboard(mine, ROW, COL);
}
}
}
int Getmine(char mine[ROWS][COLS], int x, int y)
{
return (mine[x - 1][y - 1] + mine[x][y - 1] + mine[x + 1][y - 1] + mine[x - 1][y] + mine[x + 1][y] +
mine[x - 1][y + 1] + mine[x][y + 1] + mine[x + 1][y + 1] - 8 * '0');
}
8.运行测试
(1)为了便于测试运行,将雷数Eazycount设置为80,并打印出埋雷棋盘
结语
以上便是C语言扫雷代码实现全过程,感谢大家垂阅!