简单方法实现扫雷游戏
要求:
1:第一下输入坐标,不炸死。
2:坐标周围没有雷,可以实现展开。
思想:
(一)用一个测试函数test()完成用户的整个游戏体验,放在主函数中。
(二)test()函数中应该完成的内容:菜单选择和游戏部分。
菜单选择即menu()函数;
游戏部分即game()函数;
因为是游戏,所以以用户体验为先,先让用户玩一把。在这应该使用do…while()语句。
!!!
(三)game()函数的具体实现:
同三子棋游戏,给game函数单独创建一个源文件。
扫雷游戏的思想:
首先需要一个雷盘存放雷;
1,雷盘有行和列,因此应该定义一个二维数组。ROW为行,COL为列。
在扫雷的过程中,如果选择一个坐标,则会计算周围坐标的雷数。如果输入坐标为(0,0),则该坐标周围并非都是坐标,无法计算,因此在设计雷盘时应该大一圈。定义为mine[ROWS][COLS],定义ROWS=ROW+2,COLS=COL+2。
雷盘数组——mine[ROWS][COLS]
2,当输入一个坐标时,会计算周围坐标的雷数,如果把计算后的雷数直接放在雷盘中,则下一个坐标计算时就会出错,因此应该定义一个新的数组用来存放雷的信息information[ROWS][COLS]。该数组应该和雷盘数组一样大。
存放雷信息的数组——information[ROWS][COLS]
3,两个数组中都存放字符。
4,给两个数组赋初值。——InItFirst()
5,布雷——SetMine()
6,展示雷盘数组,展示信息数组——Display()
7,排查雷——FimdMine()
排查雷的过程中:
需要一个函数实现计算该坐标周围雷数——MineCount()
输入一个坐标,坐标周围没有雷,实现坐标展开 ——OpenMine()
如果输入的第一个坐标为雷,不能让用户被炸死,转移雷的位置
——FirstMine()
具体代码如下:
1:将所有的重定义,函数声明,引用的头文件放在创建的头文件中
#ifndef __GAME__H__
#define __GAME__H__
#define ROW 9
#define COL 9
#define ROWS ROW + 2
#define COLS COL + 2
#define COUNT 10
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void InItFirst(char arr[ROWS][COLS], int rows, int cols,char set);
void SetMine(char mine[ROWS][COLS], int row, int col);
void Display(char arr[ROWS][COLS], int row, int col);
void FimdMine(char mine[ROWS][COLS],char information[ROWS][COLS], int row, int col);
int MineCount(char mine[ROWS][COLS], int x, int y);
void FirstMine(char mine[ROWS][COLS], int i, int j);
void OpenMine(char mine[ROWS][COLS], char information[ROWS][COLS], int x, int y);
#endif __GAME__H__
2,主函数部分代码如下
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
//打印菜单
void menu()
{
printf("*********************\n");
printf("****** 1. play ******\n");
printf("****** 0. exit ******\n");
printf("*********************\n");
}
//游戏部分
void game()
{
srand((unsigned)time(NULL));
//需要两个二维数组。一个数组存放雷和非雷。另外一个存放排查之后雷的信息
// 数组中存放字符,不能存放数字
char mine[ROWS][COLS] = { 0 };
char information[ROWS][COLS] = { 0 };
//给两个数组分别赋初值
InItFirst(mine, ROWS, COLS,'0');
InItFirst(information, ROWS, COLS,'*');
//布雷
SetMine(mine,ROW,COL);
//打印雷盘
Display(mine, ROW, COL);
Display(information, ROW, COL);
//排查雷
FimdMine(mine, information, ROW, COL);
}
//测试函数
void test()
{
int input = 0;
do
{
menu();
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏!!!");
break;
default:
break;
}
} while (input);
}
int main()
{
test();
system("pause");
return 0;
}
3,游戏部分代码如下
//扫雷游戏
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
//赋初值
void InItFirst(char arr[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++)
{
arr[i][j] = set;
}
}
}
//布雷
void SetMine(char mine[ROWS][COLS], int row, int col)
{
int count = COUNT;
while (count > 0)
{
int i = rand() % row + 1;
int j = rand() % col + 1;
if (i >= 1 && i <= row && j >=1 && j <= col)
{
if ('0' == mine[i][j])
{
mine[i][j] = '1';
count--;
}
}
}
}
//展示布局,可展示雷盘,也可展示信息盘,根据情况而定
void Display(char arr[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
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 ", arr[i][j]);
}
printf("\n");
}
}
//保证第一下不被炸死,如果输入的第一个坐标是雷,则交换雷的位置,将一个非雷与雷交换
void FirstMine(char mine[ROWS][COLS], int i, int j)
{
int x = rand() % ROW + 1;
int y = rand() % COL + 1;
mine[i][j] = '0';
while (1)
{
if (x >= 1 && x <= ROW && y >= 1 && y <= COL)
{
if ('0' == mine[x][y])
{
mine[x][y] = '1';
break;
}
}
}
}
//计算该坐标周围雷的个数
int MineCount(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';
}
//若输入坐标周围雷数为0,则展开周围一周,直至雷数为0
void OpenMine(char mine[ROWS][COLS],char information[ROWS][COLS], int x, int y)
{
int i = 0;
int j = 0;
if (x >= 1 && x <= ROW && y >= 1 && y <= COL)
{
if (MineCount(mine,x,y) == 0)
{
information[x][y] = '0';
for (i = x - 1; i <= x + 1; i++)
{
for (j = y - 1; j <= y + 1; j++)
{
if (information[i][j] == '*')
{
OpenMine(mine, information, i, j);
}
}
}
}
else
{
information[x][y] = MineCount(mine, x, y)+'0';
}
}
}
//排查雷
void FimdMine(char mine[ROWS][COLS], char information[ROWS][COLS], int row, int col)
{
int ret = 0;
int allcount = 0;
//如何判断游戏成功
while (1)
{
int win = 0;
int i = 0;
int j = 0;
//int count = 0;
allcount++;
printf("请输入坐标:>");
scanf("%d%d", &i, &j);
//判断坐标是否有效
if (i >= 1 && i <= row && j >= 1 && j <= col)
{
//判断该坐标是否为雷
if ('1' == mine[i][j])
{
if (allcount == 1)
{
//如果输入的第一个坐标为雷,则交换一个非雷到该位置
FirstMine(mine, i, j);
continue;;
}
else
{
printf("你被炸死了!!!游戏结束!\n");
Display(mine, row, col);
break;
}
}
else
{
OpenMine(mine, information, i, j);
for (i = 1; i <= row; i++)
{
for (j = 1; j <= col; j++)
{
if (information[i][j] != '*')
{
win++;
}
}
}
Display(information, ROW, COL);
}
}
else
{
printf("输入的坐标无效!请重新输入!!!\n");
}
if (win == row*col - COUNT)
{
printf("恭喜你!游戏成功!!!\n");
break;
}
}
}