相信大家都有玩过扫雷游戏吧,今天我们来用C语言程序来实现这样一个小游戏!
目录
一、游戏规则
在给定的棋盘中,随机生成雷,玩家随机点击一个格子,格子中显示数字,该数字就是周围雷的个数的总数。玩家需要通过此方法排查出雷,直到所有雷排查完毕或者踩雷,游戏结束!
在这个程序中,我们暂定棋盘为9×9宫格,随机生成10个雷(后期如果想改变可以直接改)。
布置雷时,我们可以用‘ 0 ’来表示这个位置没有雷,用‘ 1 ’来表示这个位置是有雷的(用“1”来表示雷是为了更好的统计雷的个数)
二、基本思路
1.棋盘的设置:此游戏应该有两个棋盘:一个是玩家可见的,一个是玩家不可见的。雷应该放在不可见的棋盘上。
2.棋盘的初始化:可见的棋盘用“ * ”初始化打印,而不可见的棋盘用“ 0 ”初始化。
3.雷的布置:随机生成一个数,将该位置给成“ 1 ”。
4.统计雷的个数:计算周围元素并相加
5.进行排雷:直到碰到雷或者排完雷为止,游戏结束!
三、代码实现
1.菜单目录和玩家进入游戏提示
main函数中,因为游戏不只可以玩一次,玩家可以控制玩多少次。这里我们设置 “ 1 ” 为进入游戏,而“ 0 ”为退出游戏。因此这里应该运用到do-while语句和switch-case语句。
void menu()//菜单实现
{
printf("***********************\n");
printf("***** 1.play ******\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();//输入“1”则进入游戏
break;
case 0:
printf("游戏结束!");//输入“0”则退出游戏
break;
default:
printf("输入有误!请重新输入.");//输入1 0之外的提示输入错误
break;
}
} while (input);
2. 编写游戏
这里我们用game()函数来封装。game()函数中应该包含:棋盘的初始化、雷的布置、排雷判断、打印棋盘。
void game()
{
char mine[ROWS][COLS] = { 0 };//定义二维数组隐藏棋盘
char show[ROWS][COLS] = { 0 };//定义二维数组隐藏棋盘
Initboard(mine, ROWS, COLS,'0');//初始化隐藏棋盘
Initboard(show, ROWS, COLS, '*');//初始化可视棋盘
Setmine(mine, ROW, COL);//布置雷
Displayboard(show, ROW, COL);//打印可视棋盘
Findmine(mine, show, ROW, COL);//排查雷,判断,最后出结果
}
3.初始化棋盘
定义char set可以不用创建两个函数来初始化两个棋盘,只需要传入 “ * ” ,“ 0 ”。
void Initboard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i;
int j;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
4.布置雷
定义两个随机数,并将其坐标变成 “ 1 ” 。
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--;
}
}
}
5.打印棋盘:
void Displayboard(char board[ROWS][COLS], int row, int col)
{
int i;
int j;
for (i = 0; i <= row; i++)//打印坐标,第一个坐标为空格
{
if (i == 0)
printf(" ");
else
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}

6.排查雷:
这一函数中包含雷个数的统计,判断玩家的坐标与雷是否相同,判断周围是否为0,若为0,自动变成空格(避免了9个格子都是0但要一个一个的排)。
void Findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int count = row * col - EASY_COUNT;
while (1)
{
printf("请输入一个坐标(排查雷):");
scanf("%d%d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mine[x][y] == '1')
{
printf("很遗憾你被炸死了!\n");
DisplayEnd(mine, show, ROW, COL);//打印最后的棋盘,包含雷和玩家选的坐标
break;
}
else
{
Judgemine(mine, show, x, y,&count);//判断周围是否为0
Displayboard(show, ROW, COL);
}
}
else
{
printf("坐标输入有误!请重新输入!");
}
if (count == 0)//雷排完了
{
printf("恭喜你!排雷成功!\n");
DisplayEnd(mine, show, ROW, COL);
break;
}
}
}
(1)统计雷的个数:
统计上下左右坐标的数字(由于当初布置雷的时候雷是字符“1”,所以结果需要减去8×字符“0”)。
int Total(char mine[ROWS][COLS], int x, int y)
{
return 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';
}
也可以用一个循环来完成。(因为布置雷的时候是字符类型,不能直接用int 来累加)
int Total(char mine[ROWS][COLS], int x, int y)
{
int sum = 0;
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
{
if (mine[x + i][y + j] == '1')
{
sum++;
}
}
}
return sum;
}
(2)判断周围是否为0
(这个是优化游戏的一个函数)
void Judgemine(char mine[ROWS][COLS],char show[ROWS][COLS],int x,int y,int *count)
{
int i;
int j;
if (x >= 1 && x <= 9 && y >= 1 && y <= 9 && mine[x][y] == '0' && show[x][y] == '*')
{
if (Total(mine, x, y))
{
show[x][y] = Total(mine, x, y) + '0';
(*count)--;
}
else
{
show[x][y] = ' ';
(*count)--;
for (i = -1; i <= 1; i++)
{
for (j = -1; j <= 1; j++)
{
Judgemine(mine, show, x + i, y + j, count);
}
}
}
}
}
(3)打印最后的棋盘:
游戏结束后,打印玩家坐标和雷的位置
void DisplayEnd(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols)
{
{
int i = 0;
int j = 0;
for (i = 0; i <= rows; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= rows; i++)
{
printf("%d ", i);
for (j = 1; j <= cols; j++)
{
if (mine[i][j] == '1')//如果是雷就打印出来
{
mine[i][j] = '@';
printf("%c ", mine[i][j]);//与打印棋盘唯一不同之处
}
else
{
printf("%c ", show[i][j]);
}
}
printf("\n");
}
printf("\n");
}
}
7.建立game.h
由于要用到众多函数,所以建立一个头文件game.h来定义函数
#pragma once
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <windows.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2 //判断边界值时需要用到额外的格子
#define COLS COL+2 //判断边界值时需要用到额外的格子
#define EASY_COUNT 10
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);
int Total(char mine[ROWS][COLS], int x, int y);
void DisplayEnd(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols);
void Judgemine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int* count);
四、源代码
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu()
{
printf("***********************\n");
printf("***** 1.play ******\n");
printf("***** 0.exit ******\n");
printf("***********************\n");
}
void game()
{
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
Initboard(mine, ROWS, COLS,'0');//初始化隐藏棋盘
Initboard(show, ROWS, COLS, '*');//初始化可视棋盘
Setmine(mine, ROW, COL);//布置雷
Displayboard(show, 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("游戏结束!");
break;
default:
printf("输入有误!请重新输入.");
break;
}
} while (input);
return 0;
}
game.h
#pragma once
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <windows.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2 //判断边界值时需要用到额外的格子
#define COLS COL+2 //判断边界值时需要用到额外的格子
#define EASY_COUNT 10
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);
int Total(char mine[ROWS][COLS], int x, int y);
void DisplayEnd(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols);
void Judgemine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int* count);
game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
//初始化棋盘
void Initboard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i;
int j;
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;
int j;
for (i = 0; i <= row; i++)
{
if (i == 0)
printf(" ");
else
printf("%d ", i);
}
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 Total(char mine[ROWS][COLS], int x, int y)
//{
// return 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';
//}
int Total(char mine[ROWS][COLS], int x, int y)
{
int sum = 0;
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
{
if (mine[x + i][y + j] == '1')
{
sum++;
}
}
}
return sum;
}
//排查雷
void Findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int count = row * col - EASY_COUNT;
while (1)
{
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);
DisplayEnd(mine, show, ROW, COL);
break;
}
else
{
//int total = Total(mine, x, y);
//show[x][y] = total + '0';
//count--;
Judgemine(mine, show, x, y,&count);
Displayboard(show, ROW, COL);
}
}
else
{
printf("坐标输入有误!请重新输入!");
}
if (count == 0)
{
printf("恭喜你!排雷成功!\n");
DisplayEnd(mine, show, ROW, COL);
break;
}
}
}
//判断周围是否为0
void Judgemine(char mine[ROWS][COLS],char show[ROWS][COLS],int x,int y,int *count)
{
int i;
int j;
if (x >= 1 && x <= 9 && y >= 1 && y <= 9 && mine[x][y] == '0' && show[x][y] == '*')
{
//mine[x][y] = '2';
if (Total(mine, x, y))
{
show[x][y] = Total(mine, x, y) + '0';
(*count)--;
}
else
{
show[x][y] = ' ';
(*count)--;
for (i = -1; i <= 1; i++)
{
for (j = -1; j <= 1; j++)
{
Judgemine(mine, show, x + i, y + j, count);
}
}
}
}
}
//打印结局
void DisplayEnd(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols)
{
{
int i = 0;
int j = 0;
for (i = 0; i <= rows; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= rows; i++)
{
printf("%d ", i);
for (j = 1; j <= cols; j++)
{
if (mine[i][j] == '1')//如果是雷就打印出来
{
mine[i][j] = '@';
printf("%c ", mine[i][j]);//与打印棋盘唯一不同之处
}
else
{
printf("%c ", show[i][j]);
}
}
printf("\n");
}
printf("\n");
}
}
运行结果:


442





