本文实例为大家分享了C语言实现扫雷小游戏的具体代码,供大家参考,具体内容如下
实现的拓展功能如下:
1.设置游戏难度等级
2.保证玩家在第一把踩雷后不被炸死
3.若排雷的地方无雷,自动扩展到有雷的周围,并给出雷数
4.标记(相当于扫雷游戏中的插旗子)
5.取消标记
分析:
1.用二维字符数组mine[ROWS][COLS]来存储雷,现在我们用字符1来表示有雷,字符0表示无雷。用二维字符数组show[ROWS][COLS]将所有的元素初始化为*,并打印作为展现给玩家的。同时用show数组来表示对应的mine数组中周围雷即字符0的个数。
对于边缘的格子无法计算雷的个数,因此需再增加2行2列,防止数组越界。
2.游戏难度等级的设置即就是雷的个数和棋盘大小不同,即就是Putmine中传的COUNT(雷数)不同,棋盘大小不同也就是在初始化、埋雷、扫雷、打印棋盘等函数中传的行、列数不同,由于是控制台程序,没有将一般模式和困难模式的棋盘打印的过大(因为会丑,也容易眼花),正常情况下扫雷的中级模式是40个雷,16*16格,高级模式是99个雷,16*30格.
3.为了保证玩家体验,保证玩家在第一把踩雷后不被炸死,此时只需要判断玩家第一次排查的坐标是否等于雷的坐标,如果是,将雷悄悄移走(重新生成随机数)
4.若排雷的地方无雷,自动扩展到有雷的周围,并给出雷数,此时需要用到递归,直至递归到周围有雷停止,并计算雷数,显示在棋盘上。
5.标记与取消标记这个是很容易实现的,将标记位置改为P(也可以为其他),取消标记改回*即可。
实现效果:
详细代码如下:
test.c
/*
date:2018/12/27
author:Better Me1
program:Mine Clearance
compiler:Visual Studio 2013
拓展功能:
1.设置游戏难度等级
2.保证玩家在第一把踩雷后不被炸死
3.若排雷的地方无雷,自动扩展到有雷的周围,并给出雷数
4.标记(相当于扫雷游戏中的插旗子)
5.取消标记
*/
/*测试部分*/
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
#include <stdio.h>
#include <stdlib.h>
void menu(){
printf("************ 扫雷小游戏 ************\n");
printf("****** 1.进入游戏 2.退出游戏 ******\n");
printf("**************************************\n");
}
void menu2(){
printf("******** 请选择要挑战的模式 ********\n");
printf("******** 1.简单模式(10个雷)********\n");
printf("******** 2.一般模式(15个雷)********\n");
printf("******** 3.困难模式(20个雷)********\n");
}
void game(int COUNT ){
if (COUNT == 10){
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };//显示雷,给玩家看
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');//初始化棋盘
Putmine(mine, ROW-6, COL-6, COUNT);//埋雷
//DisplayBoard(mine, ROW - 6, COL - 6);
DisplayBoard(show, ROW-6, COL-6);//打印棋盘
Findmine(mine, show, ROW-6, COL-6, COUNT);//扫雷
}
else if (COUNT == 15){
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };//显示雷,给玩家看
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');//初始化棋盘
Putmine(mine, ROW - 2, COL - 2, COUNT);//埋雷
//DisplayBoard(mine, ROW - 2, COL - 2);
DisplayBoard(show, ROW - 2, COL - 2);//打印棋盘
Findmine(mine, show, ROW - 2, COL - 2, COUNT);//扫雷
}
else{
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };//显示雷,给玩家看
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');//初始化棋盘
Putmine(mine, ROW, COL, COUNT);//埋雷
//DisplayBoard(mine, ROW, COL);
DisplayBoard(show, ROW, COL);//打印棋盘
Findmine(mine, show, ROW , COL, COUNT);//扫雷
}
}
void test(){
srand((unsigned int)time(0));//随机种子
int input = 0;
int input2 = 0;
int COUNT = 0;
do{
menu();
printf("请选择:>");
scanf("%d", &input);
system("cls");
switch (input){
case 1:
while (1){
menu2();
printf("请选择:>");
scanf("%d", &input2);
switch (input2){
case 1:
COUNT = EASY_COUNT;
break;
case 2:
COUNT = USUAL_COUNT;
break;
case 3:
COUNT = HARD_COUNT;
break;
default:
printf("输入有误,请重新选择!\n");
break;
}
if (input2 >= 1 && input2 <= 3){
break;
}
}
system("cls");
game(COUNT);
break;
case 2:
printf("退出游戏!\n");
break;
default:
printf("输入有误,请重新选择!\n");
break;
}
} while ((input - 2));
}
void main(){
test();
system("pause");
}
game.h
#ifndef _GAME_H_
#define _GAME_H
#define EASY_COUNT 10 //简单级,10个雷
#define USUAL_COUNT 15 //普通级,15个雷
#define HARD_COUNT 20 //单级,20个雷
#define ROW 15//行
#define COL 15 //列
#define ROWS ROW+2
#define COLS COL+2
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);//初始化棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col);//打印棋盘
void Putmine(char board[ROWS][COLS], int row, int col, int count);//埋雷
void Findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col,int count);//扫雷
#endif
game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set){
memset(board, set, rows*cols*sizeof(board[0][0]));
}
void DisplayBoard(char board[ROWS][COLS], int row, int col){
int i, j = 0;
if (row == ROW - 6){
printf("------------------------------\n");
}
if (row == ROW - 2){
printf("-----------------------------------------\n");
}
if (row == ROW){
printf("----------------------------------------------\n");
}
for (i = 0; i <= row; i++){
for (j = 0; j <= col; j++){
if (i == 0 || j == 0){
if (j == 0){
if (i < 10){
printf("%d ", i);
}
else{
printf("%d ", i);
}
}
else{
if (j < 10){
printf("%d ", j);
}
else{
printf("%d ", j);
}
}
}
else{
printf("%c ", board[i][j]);
}
}
printf("\n");
}
if (row == ROW - 6){
printf("------------------------------\n");
}
if (row == ROW - 2){
printf("-----------------------------------------\n");
}
if (row == ROW){
printf("----------------------------------------------\n");
}
}
void Putmine(char board[ROWS][COLS], int row, int col, int count){
int c = 0;//埋好的雷的个数
int i = 0;
int j = 0;
do{
i = rand() % row + 1;
j = rand() % col + 1;
if (board[i][j] =='0'){//保证雷的个数为 count个
board[i][j] = '1';
c++;
}
} while (count-c);
}
/*统计雷的个数*/
int MineCount(char mine[ROWS][COLS], int i, int j){
return (mine[i - 1][j] +
mine[i - 1][j + 1] +
mine[i][j + 1] +
mine[i + 1][j + 1] +
mine[i + 1][j] +
mine[i + 1][j - 1] +
mine[i][j - 1] +
mine[i - 1][j - 1]) - 8 * '0';
}
void ExpansionMine(char mine[ROWS][COLS], char show[ROWS][COLS], int i, int j, int row, int col){
if (MineCount(mine, i, j) == 0){
show[i][j] = ' ';
//再次遍历周围的雷
if (i - 1 > 0 && show[i - 1][j] == '*'){
// printf("1\n");
ExpansionMine(mine, show, i - 1, j, row, col);//递归
}
if (i - 1 > 0 && j + 1 <= col && show[i - 1][j + 1] == '*'){
ExpansionMine(mine, show, i - 1, j + 1, row, col);
}
if (j + 1 <= col && show[i][j + 1] == '*'){
ExpansionMine(mine, show, i, j + 1, row, col);
}
if (i + 1 <= row && j + 1 <= col && show[i + 1][j + 1] == '*'){
ExpansionMine(mine, show, i + 1, j + 1, row, col);
}
if (i + 1 <= row && show[i + 1][j] == '*'){
ExpansionMine(mine, show, i + 1, j, row, col);
}
if (i + 1 <= row && j - 1 >0 && show[i + 1][j - 1] == '*'){
ExpansionMine(mine, show, i + 1, j - 1, row, col);
}
if (j - 1 > 0 && show[i][j - 1] == '*'){
ExpansionMine(mine, show, i, j - 1, row, col);
}
if (i - 1 > 0 && j - 1 > 0 && show[i - 1][j + 1] == '*'){
ExpansionMine(mine, show, i - 1, j + 1, row, col);
}
}
else{//周边有雷
show[i][j] = MineCount(mine, i, j) + '0';
}
}
void menu3(){
printf("******** 1.标记 2.排查 ********\n");
printf("请选择:>");
}
void Findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int count){
int i, j;//行列坐标
int playcount = 0;//玩家排雷的次数
int remine = 0;//已标记的或没有排查的坐标;
while (remine!=count){
//printf("%d", remine);
int input = 0;
printf("***** 1.标记 2.取消标记 3.排查 *****\n");
printf("请选择:>");
scanf("%d", &input);
if (input == 1){
printf("请输入要标记的坐标(如:a b):>");
scanf("%d %d", &i, &j);
if (i >= 1 && i <= row && j >= 1 && j <= col){
if (show[i][j] == '*'){
show[i][j] = 'P';
system("cls");
DisplayBoard(show, row, col);
}
else if (show[i][j] == 'P'){
printf("此坐标已被标记过,请重新输入!\n");
}
else{
printf("此坐标已被排查过,请重新输入!\n");
}
}
else{
printf("坐标输入有误,请重新输入!\n");
}
}
else if (input == 2){
printf("请输入要取消标记的坐标(如:a b):>");
scanf("%d %d", &i, &j);
if (i >= 1 && i <= row && j >= 1 && j <= col){
if (show[i][j] == 'P'){
show[i][j] = '*';
system("cls");
DisplayBoard(show, row, col);
}
else if (show[i][j] == '*'){
printf("此坐标还没有被标记过,请重新输入!\n");
}
else{
printf("此坐标已被排查过,请重新输入!\n");
}
}
else{
printf("坐标输入有误,请重新输入!\n");
}
}
else if (input == 3){
//printf("%d", remine);
printf("请输入要排查的坐标(如:a b):>");
scanf("%d%d", &i, &j);
if (i >= 1 && i <= row && j >= 1 && j <= col){
if (show[i][j] == '*'){
if (mine[i][j] == '1'){
if (playcount == 0){//此时说明玩家首次排雷且踩到雷了
mine[i][j] = '0';
Putmine(mine, row, col, 1);//重新放雷,保证玩家在第一把不踩雷
playcount = 1;
ExpansionMine(mine, show, i, j, row, col);//扩展周边的雷
DisplayBoard(show, row, col);
}
else{
printf("很遗憾,你被炸死了!\n");
printf("雷阵布局如下:\n");
DisplayBoard(mine, row, col);
break;
}
}
else{
ExpansionMine(mine, show, i, j, row, col);//扩展周边的雷
system("cls");
//DisplayBoard(mine, row, col);
DisplayBoard(show, row, col);
playcount = 1;
}
}
else if (show[i][j] == 'P'){
printf("此坐标已被标记过,请重新输入!\n");
}
else{
printf("此坐标已被排查过,请重新输入!\n");
}
}
else{
printf("坐标输入有误,请重新输入!\n");
}
}
else{
printf("输入有误,请重新输入!\n");
}
remine = 0;//重新统计;
for (int m = 1; m <= row; m++){
for (int n = 1; n <= col; n++){
if ((show[m][n] == '*' )||( show[m][n] == 'P')){
remine++;
}
}
}
}
//printf("%d", remine);
if (remine == count){
printf("恭喜您,排雷成功!\n");
printf("雷阵布局如下:\n");
DisplayBoard(mine, row, col);
}
}