前言
自从大家学习c语言过后,想必大部分都会接触这类游戏代码。扫雷,五子棋,围棋等等。本文将通过C语言简单的实现一个简易的扫雷代码。
扫雷历史
1992年,微软公司的罗伯特·杜尔和卡特·约翰逊两位工程师在Windows 3.1系统上加载了该游戏,扫雷游戏才正式在全世界推广开来. 扫雷的游戏规则非常简单:方格内的数字代表其周围的八个方格中含有的地雷数.通过不断地点击新的方块来获得新的数字,从而逐步推断出地雷的位置,并点开所有不是雷的安全方块即可.
代码思路
如果我们要编写一个扫雷程序,我们首先就要赋予它外形。如图所见,它是一个9*9的网格,共81个位置。很容易就会想到而二维数组。所以编写一个二维数组成为它的外形; 所以我们初始的想法就是 char arr_size=[9][9];
其次是它的表现形式;
1.灰色的方块(代表未知) 2.数字(周围八个方格存在的雷数)
3.空白(周围八个方格没有雷)
4.雷
最后是它的规则: 方格内的数字代表其周围的八个方格中含有的地雷数.通过不断地点击新的方块来获得新的数字,从而逐步推断出地雷的位置。(根据规则可以得到,我们的代码需要格子检测周围的八个方格是否存在雷,其次若是边界的格子,周围没有八个格子,我们该如何让代码不报错的正常运行。)
根据规则可知,我们需要它能检测周围的八个位置是否有雷,但是周围如果没有格子的话,我们就得给它创造格子。所以我们的9 * 9格子将会改成11*11的格子。根据它的表现形式,可知。我们需要将它能显示的四种都表示出来,就需要再来一个11宫格。
代码第一步:初始化11宫格
game.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
//需要的头文件全丢在这里
#define ROW 9 //9宫格
#define COL 9
#define ROWS ROW+2 //11宫格
#define COLS COL+2
#define EASY_COUNT 10
//初始化11宫格
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);
//显示9宫格
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);
game.c
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;
}
}
}
当我们初始化11宫格之后,就要就将其展示出来。但我们需要的只是九宫格,而不是十一宫格。所以我们 下列for代码块就会和初始化的有所不同。
显示9宫格
void DisplayBoard(char board[ROWS][COLS], int row, int col);
game.c
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf("----------扫雷-------------\n");
for (i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)// 我们的i是<=row而不是<=rows
{
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
printf("----------扫雷-------------\n");
}
上面这些做完再写下面的一个代码调用就可以轻松的实现了打印九宫格
game.c
void game()
{
char sizein[ROWS][COLS] = { 0 };
char sizeon[ROWS][COLS] = { 0 };
InitBoard(sizein, ROWS, COLS, '0');
InitBoard(sizeon, ROWS, COLS, '*');
DisplayBoard(sizeon, ROW, COL);
DisplayBoard(sizein, ROW, COL); //这个是给我们内部人看(雷)的哦,记得把这一段给删掉。
}
舞台已经布置完毕,接下来就是布置角色(雷)了。想要将雷随机的分布在这上面,就少不了随机值的经典代码串 srand((unsigned int)time(NULL)),该代码出现在主函数中,没有看到的不必着急,请看到最后。
布置雷
game.c
void SetMine(char mine[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
while (count)
{
int x = rand()%row+1;//随机数模上row(9),余数0-8
int y = rand()%col+1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
当我们进行到这一步的时候,我们就初步完成了雷的布置。随后我们要面临的问题是找雷和检测周围雷的个数。
根据上图能得到当我们输入的坐标是(x,y)时,我们周围的八个坐标都可以得到。如何计算雷的数量呢 根据ascll码我们可知'0'ascll码=48;'1'ascll码=49;因此我们只需将周围的八个字符加起来减去8*'0' 就可以得到雷的个数,代码如下。
计算周围雷的数量
game.c
int GetMineCount(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 + 1][y + 1] +
mine[x + 1][y] +
mine[x + 1][y - 1] +
mine[x][y - 1] - 8 * '0';
}
随后我们需要做的有:
1.玩家输入坐标检测是否有雷;
2.有雷游戏结束;
3.无雷检测周围的雷数并继续;
4.所有的位置排查完玩家胜利。
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 - EASY_COUNT)
{
printf("请输入你要排查的坐标:");
scanf("%d %d", &x,& y);
if (x >= 1 && x <= row &&y >= 1 && y <= col)
{
if (show[x][y] != '*')
{
printf("该坐标已被排查,请重新输入:\n");
}
else if (mine[x][y] == '1')
{
printf("该坐标有雷,game over\n");
DisplayBoard(mine, ROW, COL);
break;
}
else
{//没有雷,排查周围八个坐标
int z = GetMineCount(mine, x, y);
show[x][y] = z + '0';
DisplayBoard(show, ROW, COL);
win++;
}
}
if (win == row * col - EASY_COUNT)
{
printf("恭喜你通关了\n");
}
}
}
以上就以game.c为主体进行的代码讲解。
完整代码
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 EASY_COUNT 10
//初始化11宫格
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);
//显示9宫格
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);
game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
#include<stdio.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 (i = 0; i <= col; i++)
{
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");
}
printf("----------扫雷-------------\n");
}
void SetMine(char mine[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
while (count)
{
int x = rand()%row+1;//随机数模上row(9),余数0-8
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 - 1] +
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] - 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 (show[x][y] != '*')
{
printf("该坐标已被排查,请重新输入:\n");
}
else if (mine[x][y] == '1')
{
printf("该坐标有雷,game over\n");
DisplayBoard(mine, ROW, COL);
break;
}
else
{//没有雷,排查周围八个坐标
int z = GetMineCount(mine, x, y);
show[x][y] = z + '0';
DisplayBoard(show, ROW, COL);
win++;
}
}
if (win == row * col - EASY_COUNT)
{
printf("恭喜你通关了\n");
}
}
}
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include"game.h"
void menu()
{
printf("*************************\n");
printf("********1.进入游戏*******\n");
printf("********2.退出游戏*******\n");
printf("*************************\n");
}
void game()
{
char mine[ROWS][COLS] = {0};
char show[ROWS][COLS] = {0};
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
DisplayBoard(show, ROW, COL);
//布置雷
SetMine(mine, ROW, COL);
//检测
FindMine(mine, show, ROW, COL);
}
int main()
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
menu();
printf("请输入\n:");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 2:
printf("即将退出\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
return 0;
}