前言
关于扫雷小游戏,整体代码还是比较简单的,比较适合刚学完c语言二维数组来练习,还可以巩固前面学习的基础知识。
游戏截图
一、代码实现
利用do while循环来实现,当玩家输入0 ,switch判断,0为假break跳到最后while里,再进行判断,为假就直接结束程序。为1时就进game函数,进行游戏。
- 主函数
void menu()
{
printf("#####################\n");
printf("###### 1. play ######\n");
printf("###### 0. exit ######\n");
printf("#####################\n");
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
//printf("扫雷游戏\n");
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("请正确输入\n");
break;
}
} while (input);
return 0;
}
- game函数
这里的game函数,创建了两个数组,用于布置雷和排查雷。布置雷的棋盘可以隐藏,不让玩家看见,就把需要下棋的部分给他看就好。
- 创建mine和show数组
void game()
{
//mine数组用于存放布置雷的信息
char mine[ROWS][COLS] = { 0 };
//show数组用于存放排查雷的信息
char show[ROWS][COLS] = { 0 };
}
- 定义枚举常量
用于二维数组的行和列,ROWS和COLS加2是因为,扫雷需要判定周围8个格子的数量,在边缘的就少一部分,所以这边准备用11 * 11 的格子来进行判断,但是我们只显示9 * 9的格子。这样就很好的解决了边缘空格没有数据判断了,也方便了许多。
#define ROW 9
#define COL 9
#define ROWS ROW + 2
#define COLS COL + 2
- InitBoard函数-初始化棋盘
- InitBoard函数调用部分
把创建的数组传过去,进行初始化。传数组、数组的行和列,还有想要初始化的字符,这里布置雷的传的是0,排查雷传的是*。可以改成你想要的字符。
void game()
{
//mine数组用于存放布置雷的信息
char mine[ROWS][COLS] = { 0 };
//show数组用于存放排查雷的信息
char show[ROWS][COLS] = { 0 };
//初始化棋盘
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
}
- InitBoard函数构造
通过for 循环不断把二维数组初始化传过来的字符串。
//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
- InitBoard函数声明
//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);
- DisplayBoard函数-打印棋盘
- DisplayBoard函数调用部分
把排查雷的数组传过去。这里的行和列是9 * 9因为打印的棋盘是这么大。
void game()
{
//mine数组用于存放布置雷的信息
char mine[ROWS][COLS] = { 0 };
//show数组用于存放排查雷的信息
char show[ROWS][COLS] = { 0 };
//初始化棋盘
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
//打印棋盘
DisplayBoard(show, ROW, COL);
}
- DisplayBoard函数构造
第一个for循环打印0-9的数字用于显示坐标。第二个先打印行的数字坐标,然后进第三个循环打印棋盘。
//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf("****** 扫雷游戏 ******\n");
for (j = 0; j <= col; j++)
{
printf("%d ", j);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
- DisplayBoard函数声明
//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col);
- SetMine函数-布置雷
- SetMine函数调用
传mine数组,9 * 9 的行和列。
void game()
{
//mine数组用于存放布置雷的信息
char mine[ROWS][COLS] = { 0 };
//show数组用于存放排查雷的信息
char show[ROWS][COLS] = { 0 };
//初始化棋盘
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
//打印棋盘
DisplayBoard(show, ROW, COL);
//布置雷
SetMine(mine, ROW, COL);
//这里调用DisplayBoard函数可以查看雷的位置,但是传过去的得是mine,因为只有这个是存放雷的
//DisplayBoard(mine, ROW, COL);
}
- SetMine函数构造
EASY_COUNT是创建的枚举常量,用于需要布置雷的数量。
rand是随机生成一个数字,% row + 1 是为了限定数字的大小。需要在主函数里调用一下srand((unsigned int)time(NULL));
if判断每次生成的随机坐标是否是字符0,是就改成1,作为雷,在count--一下。直到为0,跳出循环。
//布置雷
void SetMine(char mine[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
- SetMine函数声明和EASY_COUNT枚举常量
#define EASY_COUNT 10雷的数量
#define EASY_COUNT 10
//布置雷
void SetMine(char mine[ROWS][COLS], int row, int col);
- FindMine函数和GetMineCount函数
- FindMine函数调用
把布置雷和排查雷的数组传过去,
void game()
{
//mine数组用于存放布置雷的信息
char mine[ROWS][COLS] = { 0 };
//show数组用于存放排查雷的信息
char show[ROWS][COLS] = { 0 };
//初始化棋盘
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
//打印棋盘
DisplayBoard(show, ROW, COL);
//布置雷
SetMine(mine, ROW, COL);
//这里调用DisplayBoard函数可以查看雷的位置,但是传过去得是mine,因为只有这个是存放雷的
//DisplayBoard(mine, ROW, COL);
//排查雷
FindMine(mine, show, ROW, COL);
}
- FindMine函数和GetMineCount函数构造
解释就写在代码里吧,比较容易看清哪里是哪里
int GetMineCount(char mine[ROWS][COLS], int x, int y)
{
//周围坐标相加- 8 * '0',统计周围雷的数量
return (mine[x - 1][y] +
mine[x - 1][y - 1] +
mine[x][y - 1] +
mine[x + 1][y - 1] +
mine[x + 1][y] +
mine[x + 1][y + 1] +
mine[x][y + 1] +
mine[x - 1][y + 1] - 8 * '0');
}
//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int win = 0;
//当win小于row * col(9 * 9) - 雷的数量时,证明所有没有雷的地方都排完了,就结束循环。
while (win < row * col - EASY_COUNT)
{
printf("请输入要排查的坐标:>");
scanf("%d %d", &x, &y);
//判断输入的坐标是否在棋盘内
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
//判断输入的坐标是否等于1,等于就就结束游戏,打印有雷的棋盘给他看。
if (mine[x][y] == '1')
{
printf("不好意思,你没了\n");
DisplayBoard(mine, ROW, COL);
break;
}
//不等于1就进入GetMineCount函数判断坐标周围有几个雷。
else
{
int count = GetMineCount(mine, x, y);
show[x][y] = count + '0';
DisplayBoard(show, ROW, COL);
win++;
}
}
//输入错误的结果
else
{
printf("请正确输入坐标\n");
}
}
//当所有没有雷的坐标排查完了之后,打印棋盘。
if (win == row * col - EASY_COUNT)
{
printf("恭喜你,没被炸死\n");
DisplayBoard(mine, ROW, COL);
}
}
- FindMine函数声明
//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
二、整体代码
- 主函数部分
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
void menu()
{
printf("#####################\n");
printf("###### 1. play ######\n");
printf("###### 0. exit ######\n");
printf("#####################\n");
}
void game()
{
//mine数组用于存放布置雷的信息
char mine[ROWS][COLS] = { 0 };
//show数组用于存放排查雷的信息
char show[ROWS][COLS] = { 0 };
//初始化棋盘
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
//打印棋盘
DisplayBoard(show, ROW, COL);
//布置雷
SetMine(mine, ROW, COL);
//这里调用DisplayBoard函数可以查看雷的位置,但是传过去的得是mine,因为只有这个是存放雷的
//DisplayBoard(mine, ROW, COL);
//排查雷
FindMine(mine, show, ROW, COL);
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
//printf("扫雷游戏\n");
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("请正确输入\n");
break;
}
} while (input);
return 0;
}
- 函数实现部分
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf("****** 扫雷游戏 ******\n");
for (j = 0; j <= col; j++)
{
printf("%d ", j);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
//布置雷
void SetMine(char mine[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
int GetMineCount(char mine[ROWS][COLS], int x, int y)
{
return (mine[x - 1][y] +
mine[x - 1][y - 1] +
mine[x][y - 1] +
mine[x + 1][y - 1] +
mine[x + 1][y] +
mine[x + 1][y + 1] +
mine[x][y + 1] +
mine[x - 1][y + 1] - 8 * '0');
}
//排查雷
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 - EASY_COUNT)
{
printf("请输入要排查的坐标:>");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mine[x][y] == '1')
{
printf("不好意思,你没了\n");
DisplayBoard(mine, ROW, COL);
break;
}
else
{
int count = GetMineCount(mine, x, y);
show[x][y] = count + '0';
DisplayBoard(show, ROW, COL);
win++;
}
}
else
{
printf("请正确输入坐标\n");
}
}
if (win == row * col - EASY_COUNT)
{
printf("恭喜你,没被炸死\n");
DisplayBoard(mine, ROW, COL);
}
}
- 函数声明部分
#pragma once
#define ROW 9
#define COL 9
#define ROWS ROW + 2
#define COLS COL + 2
#define EASY_COUNT 10
//头文件
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//函数声明
//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);
//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col);
//布置雷
void SetMine(char mine[ROWS][COLS], int row, int col);
//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
总结
大部分地方代码还是比较简单,多看几遍代码就容易看明白了。
谢谢观看。