扫雷游戏介绍:程序在棋盘内随机生成十个雷,玩家通过输入坐标进行排雷,当输入的坐标下有雷时,游戏结束,并在五秒后关机;如果输入的坐标下不是雷,则显示在该坐标下的九宫格范围内雷的个数。把雷排查完后,游戏胜利。
扫雷游戏实现
文件的创建
首先,我们创建两个.c源文件,一个用于函数的声明和实现(game.c),一个用于调用函数(test.c)。还有一个.h头文件:game.h
分两个文件来写,会使得代码美观,有序,易理解。
棋盘的分析
创建一个9*9的棋盘,在这个范围内存放雷和排查雷。字符‘1’表示雷,字符‘0’表示非雷。
当扫到非雷时,显示该坐标下的九宫格范围内的雷的个数。
比如我们输入坐标(3,6)检测到九宫格内雷的个数为:1,那么我们将在(3,6)处显示:1。
但是存在一个问题:当我们输入的坐标是在如上图的(9,7)时,该如何处理呢?我们创建的99的棋盘不就越界了吗?
此时为了防止出现越界的情况,我们创建的棋盘的大小应该是1111的,这正好与边界坐标可以构成一个九宫格。但是显示出来的范围是棋盘9*9的部分,多出来的部分只是为了防止数组越界,不需要显示出来。
准备工作
以下代码都放在创建的头文件game.h下
通过宏定义,来控制数组的大小,棋盘的范围,雷的个数,这方便我们以后对程序数据的修改。
宏定义棋盘的行数:
//这是显示给玩家的棋盘
#define ROW 9
#defien COl 9
//这是棋盘实际的行数
#define ROWS ROW+2
#define COLS COL+2
宏定义雷的个数:
#define MINE_COUNT 10
需要用到的头文件:
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#include<Windows.h>
扫雷开始界面
在test.c的文件下,创建一个函数test(),用于开始选择界面。
定义一个choice变量,用于记录玩家输入的值,并通过switch实现分流。将switch放在while循环下,玩家输入1,开始游戏,输入0,退出游戏。当玩家输入的不是0或者1时,则提示“请重新输入”,然后让用户重新选择。
在test()函数下调用菜单函数menu(),提示用户输入。
将menu()函数创建在game.c的源文件下
棋盘的初始化
当然,想要实现扫雷,我们得先有两个棋盘,一个用于存放雷和一个用于向玩家展示。
定义两个char类型的数组,一个用于存放雷(mine),一个用于向玩家展示(show)。
我们再在game.c文件下创建一个inItchess()函数,用于函数的初始化。
在test.c文件下调用,并把数组和行,列数以及初始化的字符传入。
geme.c文件下:
test.c文件下:
向这个函数里传入创建好的两个数组、数组的行、列个数以及字符。
show数组:向玩家展示的棋盘是加密的,看不到雷的,所以用‘*’表示。
mine数组:我们规定字符‘1’表示雷,字符‘0’表示非雷;开始先全部赋值‘0’。
//放在test.c文件下
inItchess(show,ROWS,COLS,'*');
inItchess(mine,ROWS,COLS,'0');
//放在game.c文件下
void inItchess(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;
}
}
}
初始化是把棋盘全部都初始化,不只是初始化棋盘9*9的部分
打印棋盘
在玩家输入“1"开始游戏后,我们需要向玩家展示出棋盘。
打印棋盘:
//放在test.c文件下
Display(show,ROW,COL);
//放在game.c的文件下
void Display(char board[ROWS][COLS],int row,int col)
{
int i = 0;
for (i = 0; i <= 9; i++)//这里显示的是棋盘横坐标
{
printf("%d ",i);
}
printf("\n");
for (i=1;i<=row;i++)
{
printf("%d ",i);//这里显示棋盘纵坐标。
int j = 0;
for (j=1;j<=col;j++)
{
printf("%c ",board[i][j]);
}
printf("\n");
}
printf("-------------------扫雷-------------------\n");
}
运行效果图:
布置雷
扫雷当然不能没有雷啦,但是雷该如何布置呢?如果每次雷的位置都是固定的,那玩起来多没意思。
这里我们就可以用随机数进行布雷。
通过时间戳,改变随机数的种子。
//放在test()函数内
srand((unsigned int)time(NULL));
定义一个函数SetMine()进行布雷:
SetMine(mine,ROW,COL);
//放在game.c文件下
void SetMine(char board[ROWS][COLS],int row,int col)
{
int x = 0;
int y = 0;
int count = MINE_COUNT;
while(count!=0)
{
x = rand()%ROW+1;
y = rand()%COL+1;
if (board[x][y] != '1')
{
board[x][y] = '1';
count--;
}
}
}
因为玩家游玩的范围是在棋盘9*9的范围内,就是坐标(1,1)到坐标(9,9),所以布置雷只需要在这个范围内布置就可以了。
排雷
布置完雷后,我们应该如何排雷呢?
先说下扫雷游戏的胜利条件:当把所以不是雷的坐标全部排完,则游戏胜利。
所以我需要定义一个变量win,用来记录排雷的次数。
一下是代码实现:
//在test.c文件下
DelMine(mine,show,ROW,COL);
//在game.c文件下
void DelMine(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col)
{
int x = 0;
int y = 0;
int win = 0;//记录排雷的次数
printf("请输入坐标:");
while (win<row*col-MINE_COUNT) //当排雷的次数小于总坐标数减去雷数时,进入循环
{
scanf("%d %d", &x, &y);
if (x >= 1 && x <= 9 && y >= 1 && y <= 9)
{
if (mine[x][y] == '1')
{
break;
}
else
{
int count = Get_Mine(mine,x,y);
show[x][y] = count - '0';
Display(show,row,col);
win++;
}
}
else
{
printf("请重新输入坐标");
}
}
if (win == row * col - MINE_COUNT)
{
printf("恭喜你赢了");
}
else
{
system("cls");
printf("输了");
Display(mine,row,col);
printf("五秒后关机");
system("shutdown -s -t 5");
int a = 5;
while (a)//关机倒计时
{
printf("%d\n",a);
a--;
Sleep(1000);
system("cls");
}
}
}
扫雷游戏代码实现
以下是在test.c文件下
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void game()
{
char show[ROWS][COLS] = {0};
char mine[ROWS][COLS] = {0};
//初始化数组
inItchess(show,ROWS,COLS,'*');
inItchess(mine,ROWS,COLS,'0');
//打印棋盘
Display(show,ROW,COL);
//布雷
SetMine(mine,ROW,COL);
//Display(mine, ROW, COL);
//排雷
DelMine(mine,show,ROW,COL);
}
void test()
{
srand((unsigned int)time(NULL));
menu();
int choice = 0;
scanf("%d",&choice);
while (1)
{
switch (choice)
{
case 1:game();
break;
case 0:printf("退出游戏");
break;
default:
break;
}
break;
}
}
int main()
{
test();
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 MINE_COUNT 80
以下是在game.c文件下
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu()
{
printf("********************************\n");
printf("***********1.开始游戏***********\n");
printf("***********0.退出游戏***********\n");
printf("********************************\n");
}
void inItchess(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;
}
}
}
void Display(char board[ROWS][COLS],int row,int col)
{
int i = 0;
for (i = 0; i <= 9; i++)
{
printf("%d ",i);
}
printf("\n");
for (i=1;i<=row;i++)
{
printf("%d ",i);
int j = 0;
for (j=1;j<=col;j++)
{
printf("%c ",board[i][j]);
}
printf("\n");
}
printf("-------------------扫雷-------------------\n");
}
void SetMine(char board[ROWS][COLS],int row,int col)
{
int x = 0;
int y = 0;
int count = MINE_COUNT;
while(count!=0)
{
x = rand()%ROW+1;
y = rand()%COL+1;
if (board[x][y] != '1')
{
board[x][y] = '1';
count--;
}
}
}
int Get_Mine(char mine[ROWS][COLS],int x,int y)
{
int count = 0;
int i = 0;
for (i=-1;i<=1;i++)
{
int j = 0;
for (j=-1;j<=1;j++)
{
count += mine[x+i][y+j] + '0';
}
}
return count;
}
void DelMine(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col)
{
int x = 0;
int y = 0;
int win = 0;
printf("请输入坐标:");
while (win<row*col-MINE_COUNT)
{
scanf("%d %d", &x, &y);
if (x >= 1 && x <= 9 && y >= 1 && y <= 9)
{
if (mine[x][y] == '1')
{
break;
}
else
{
int count = Get_Mine(mine,x,y);
show[x][y] = count - '0';
Display(show,row,col);
win++;
}
}
else
{
printf("请重新输入坐标");
}
}
if (win == row * col - MINE_COUNT)
{
printf("恭喜你赢了");
}
else
{
system("cls");
printf("输了");
Display(mine,row,col);
printf("五秒后关机");
system("shutdown -s -t 5");
int a = 5;
while (a)
{
printf("%d\n",a);
a--;
Sleep(1000);
system("cls");
}
}
}