一、目的
实现一个扫雷游戏
二、过程
1、游戏框架
首先,游戏开始之前,显示游戏菜单Menu()
static void Menu()
{printf("#############################\n");printf("########欢迎来到扫雷游戏#######\n");printf("#############################\n");printf("## 1.play 2.exit ##\n");printf("#############################\n");printf("请输入你的选择");
}
让我知道你的选择
1.选择玩游戏,继续
2.选择退出,直接结束
3.选择错误,重新来一次
int main(){int quit = 0;do{int select=0;Menu();scanf("%d", &select);switch (select){case 1:Game();printf("当前游戏已经结束。。。再来一次?\n");break;case 2:printf("退出\n");quit = 1;break;default:printf("你的输入有误,请重新输入\n");break;}} while (!quit);//printf("hello mine clear\n");system("pause");return 0;
}
2、游戏过程
1.选择玩游戏之后,进入Game()
不能让玩家看到雷在哪,所以需要两个二维数组,一个负责显示给玩家看,一个负责记录游戏进度和雷的分布情况
ROW 和COL分别宏定义为12 12(实际只显示10*10),宏定义雷的数量是20个
从以下几个步骤进行游戏
1.负责显示的扫雷区和负责记录的扫雷区的二维数组的初始化InitBoard()
2.初始化结束后,利用Setmine()在负责记录的数组中放雷
3.一个循环,包括
3.1显示扫雷区ShowBoard()
3.2开始扫雷,输入对应坐标(先要判断几种情况)
3.2.1玩家输入的坐标不正确,结束本次循环
3.2.2坐标正确,但已经被扫描过,结束本次循环
3.2.3坐标正确,也没有被扫描过,继续
3.2.3.1扫到没雷,返回这个坐标周围八个格子雷的个数 GetNum()
3.2.3.2扫到有雷,游戏结束,挑战失败
4.最后,无论输赢,都应该让玩家看到雷的分布情况
代码如下:
void Game()
{printf("欢迎你来到挑战\n");char board[ROW][COL];char mine[ROW][COL];InitBoard(board, ROW, COL,'*'); //'*'InitBoard(mine, ROW, COL,'0'); //'0'SetMine(mine, ROW, COL);int count = (ROW - 2)*(COL - 2)-NUM;//没有雷的格子数do{int x = 0;int y = 0;ShowBoard(board, ROW, COL);printf("请输入你要扫描的位置\n");scanf("%d %d", &x, &y);if (x < 1 || x>10 || y < 1 || y>10){printf("输入位置错误,请重新输入\n");continue;}if (board[x][y] != '*'){printf("输入位置已经被扫描过了,请重新输入\n");continue;}if (board[x][y] == '0'){count--;char num = GetNum(mine, x, y);board[x][y] = num;}else{printf("你输入的位置(%d %d)有雷\n", x, y);break;}}while (count>0);if (count > 0){printf("扫雷结束,你被炸死了\n");}else{printf("扫雷结束,你成功了\n");}}
2.每个函数的实现
2.1、InitBoard()
void InitBoard(char board[][COL], int row, int col,char elem)
{for (int i = 0; i < row; i++){for (int j = 0; j < col; j++){board[i][j] = elem;}}
}
- 两个数组都需要初始化
- 将用于显示的数组全部初始化为‘*’
- 用于记录的数组全部初始化为‘0’
2.2、SetMine()
void SetMine(char mine[][COL], int row, int col)
{int n = NUM;while (n){int x = rand() % (row - 2) + 1;int y = rand() % (col - 2) + 1;if (mine[x][y] == '1'){continue;}mine[x][y] = '1';n--;}
}
- 分别对row-2和col-2取余,就不会发生坐标错误的问题
- 考虑到电脑的随机值有一定的可能性会相同,因此判断以下插入的位置是否已经被插入雷的,如果是,跳出此次循环,如果否,则执行插入
- n的大小是雷的总个数,没执行一次插入后,n--;
2.3、ShowBoard()
void ShowBoard(char board[][COL], int row, int col)
{printf(" ");for (int i = 1; i <= col - 2; i++){printf(" %-2d|", i);}printf("\n");printf("--------------------------------------------\n");for (int i = 1; i <= row - 2; i++){printf("%2d |", i);for (int j = 1; j <= col-2; j++){printf(" %-2c|", board[i][j]);}printf("\n");printf("--------------------------------------------\n");}
}
- 这里主要是格式输出问题,注意一点,可以让小黑框里输出的更好看
2.4、GetNum()
char GetNum(char mine[][COL], 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]-7*'0';}
- 这里补充,为什么有雷用字符1表示,没雷用字符0表示
- 1.如果扫的地方没雷,则是要在显示出这个位置周围的八个格子里有几个雷的
- 2.用枚举法将这八个格子里的字符相加,之后减去8*‘0’
- 3.得到的是一个整数,即‘1’的个数,但是我们想要的是字符型的数字
- 4.因此,减去7*‘0’,得到的是字符型的雷的个数,即’0‘+(个数)
3、游戏代码
mine.h
#ifndef _MINE_H_
#define _MINE_H_#include <stdio.h>
#include <windows.h>
#pragma warning(disable:4996)
#define ROW 12
#define COL 12
#define NUM 20
#include <stdlib.h>
#include <time.h>void Game();
void InitBoard(char board[][COL], int row, int col,char elem);
void SetMine(char mine[][COL],int row,int col);
void ShowBoard(char board[][COL], int row, int col);
char GetNum(char mine[][COL], int x, int y);#endif
mine.cpp
#include "mine.h"//初始化
void InitBoard(char board[][COL], int row, int col,char elem)
{for (int i = 0; i < row; i++){for (int j = 0; j < col; j++){board[i][j] = elem;}}
}
///
//设置雷
void SetMine(char mine[][COL], int row, int col)
{int n = NUM;while (n){int x = rand() % (row - 2) + 1;int y = rand() % (col - 2) + 1;if (mine[x][y] == '1'){continue;}mine[x][y] = '1';n--;}
}
/
//显示面板
void ShowBoard(char board[][COL], int row, int col)
{printf(" ");for (int i = 1; i <= col - 2; i++){printf(" %-2d|", i);}printf("\n");printf("--------------------------------------------\n");for (int i = 1; i <= row - 2; i++){printf("%2d |", i);for (int j = 1; j <= col-2; j++){printf(" %-2c|", board[i][j]);}printf("\n");printf("--------------------------------------------\n");}
}
/
//周围雷的个数
char GetNum(char mine[][COL], 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]-7*'0';}//游戏入口
void Game()
{srand((unsigned long)time(NULL));printf("欢迎你来到挑战\n");char board[ROW][COL];char mine[ROW][COL];InitBoard(board, ROW, COL,'*'); //'*'InitBoard(mine, ROW, COL,'0'); //'0'SetMine(mine, ROW, COL);int count = (ROW - 2)*(COL - 2)-NUM;//没有雷的格子数do{system("cls");int x = 0;int y = 0;ShowBoard(board, ROW, COL);printf("请输入你要扫描的位置\n");scanf("%d %d", &x, &y);if (x < 1 || x>10 || y < 1 || y>10){printf("输入位置错误,请重新输入\n");Sleep(2000);continue;}if (board[x][y] != '*'){printf("输入位置已经被扫描过了,请重新输入\n");Sleep(2000);continue;}if (mine[x][y] == '0'){count--;char num = GetNum(mine, x, y);board[x][y] = num;}else{printf("你输入的位置(%d %d)有雷\n", x, y);break;}}while (count>0);if (count > 0){printf("扫雷结束,你被炸死了\n");}else{printf("扫雷结束,你成功了\n");}ShowBoard(mine, ROW, COL);
}
main.cpp
#include "mine.h"static void Menu()
{printf("#############################\n");printf("########欢迎来到扫雷游戏#######\n");printf("#############################\n");printf("## 1.play 2.exit ##\n");printf("#############################\n");printf("请输入你的选择");
}int main(){int quit = 0;do{int select=0;Menu();scanf("%d", &select);switch (select){case 1:Game();printf("当前游戏已经结束。。。再来一次?\n");break;case 2:printf("退出\n");quit = 1;break;default:printf("你的输入有误,请重新输入\n");break;}} while (!quit);//printf("hello mine clear\n");system("pause");return 0;
}
三、结果