C语言:扫雷游戏进阶版讲解

 1.游戏模式的增加(简单--中等--困难) 

 2.扫雷功能的扩展(展开一片功能的实现) 

 3.标记地雷和删除标记的功能的实现

 4.部分代码根据需求进行重做

在前文的基础上,我们将扫雷游戏进一步完善与升级,将它的游戏功能趋于完整。

1.游戏模式的增加(简单--中等--困难)

 我们首先把game.h中的define定义的常量变成整形常量。在VS中是不支持这种变长数组的使用,建议使用其他编译器来执行。

 在text.c中,我们加入了这样一个函数,它的功能是模式的选择。

 选择1:就是简单模式。 选择2:就是中等模式。选择3:就是困难模式。如果输入其他数据,就会让你重新选择。选择完毕,我们就进入这个模式的游戏。

2.扫雷功能的扩展(展开一片功能的实现)

 

 在game.c我们创建了Around_Bomb_count函数,它的功能是在没有选到有雷的坐标的情况下,读取选中坐标附件雷的个数,如果附件坐标的九宫格内没有雷就会继续展开,直到展开的某个坐标的九宫格内有雷为止。

这个函数我们用到了函数的递归调用,首先判断这个坐标是否越界(第一次进入这个函数时肯定不会越界因为在输入时已经判断了),其次,判断坐标是否被排查过。接着,返回这个坐标附近雷的个数。最后,如果返回的是0字符,也就是附件没有雷,就会进行坐标的展开,让附件的坐标进行函数递归,重新进入这个函数。判断它和它周围的坐标是否满足这个函数从而进行展开或者返回。

3.标记地雷和删除标记的功能的实现

 在game.c中的FindMine函数中我们丰富了标记地雷和删除标记的功能

按1就进行排查地雷,输入坐标后退出循环,进入下面的排雷环节

按2就进行标记地雷,输入坐标后继续这个内部循环,如果输入错误坐标会提示你重新输入

按3就行删除标记,  输入坐标后删除这个标记,返还从前的标记,如果输入错误会提示你重新输入

按其他错误数据,会继续循环,如果打破内循环,还有外循环while(1)回到原点继续让你选择

4.部分代码根据需求进行重做

我们修改了判断游戏是否胜利的条件,即增加了一个胜利函数VICTORY

 如果最后剩余的字符*或者#的坐标之和的总数等于总的地雷数,那么就判断这位玩家游戏胜利了

并在FindMine函数中加入了相关条件

具体代码如下:

text.c 

#include "game.h"
void menu()
{
 printf("***********************\n");
 printf("***** 1. play *****\n");
 printf("***** 0. exit *****\n");
 printf("***********************\n");
}
void game()
{
 char mine[ROWS][COLS];//存放布置好的雷
 char show[ROWS][COLS];//存放排查出的雷的信息
 //初始化棋盘
 //1. mine数组最开始是全'0'
 //2. show数组最开始是全'*'
 InitBoard(mine, ROWS, COLS, '0');
 InitBoard(show, ROWS, COLS, '*');
 //打印棋盘
 //DisplayBoard(mine, ROW, COL);
 DisplayBoard(show, ROW, COL);
 //1. 布置雷
 SetMine(mine, ROW, COL);
 //DisplayBoard(mine, ROW, COL);
 //2. 排查雷
 FindMine(mine, show, ROW, COL);
}
void moshi()
{ 

while(1)
{	
int input2; 
 printf("***********************\n");
 printf("***** 1.简单 *****\n");
 printf("***** 2.中等 *****\n");
 printf("***** 3.困难 *****\n");
 printf("***********************\n");
 printf("请选择:>");	
 scanf("%d", &input2);	
 switch(input2)
 {
   case(1):ROW=9;COL=9;ROWS=ROW+2;COLS=COL+2;EASY_COUNT=10;break;
   case(2):ROW=16;COL=16;ROWS=ROW+2;COLS=COL+2;EASY_COUNT=40;break;
   case(3):ROW=16;COL=30;ROWS=ROW+2;COLS=COL+2;EASY_COUNT=99;break;
   default:
   printf("选择错误,重新选择\n");break;
 }
 if(input2==1||input2==2||input2==3)
	break;
 }		
} 
int main()
{
 int input = 0; 
 srand((unsigned int)time(NULL));
 do
 {
 menu();
 printf("请选择:>");
 scanf("%d", &input);
 switch (input)
 {
 case 1: 
 moshi();
 game();  
 break;
 case 0:
 printf("退出游戏\n");
 break;
 default:
 printf("选择错误,重新选择\n");
 break;
 }
 } while (input);
 return 0;
}

game.c

#include "game.h"
void InitBoard(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 DisplayBoard(char board[ROWS][COLS], int row, int col)
{
 int i = 0;
 printf("--------扫雷游戏-------\n");
 for (i = 0; i <= col; i++)
 {	
    printf("%d  ", i);
 }
 printf("\n");
 for (i = 1; i <= row; i++)
 {
 	if(i>=10)
 	printf("%d ", i);
    else	
    printf("%d  ", i);
 int j = 0;
 for (j = 1; j <= col; j++)
 {
 	if(j>=10)
 printf("%c   ", board[i][j]);
    else
 printf("%c  ", board[i][j]);   
 }
 printf("\n");
 }
}
void SetMine(char board[ROWS][COLS], int row, int col)
{
 //布置10个雷 
 //生成随机的坐标,布置雷 
 int count = EASY_COUNT;
 while (count)
 {
 int x = rand() % row + 1;
 int y = rand() % col + 1;
 if (board[x][y] == '0')
 {
 board[x][y] = '1';
 count--;
 }
 }
}
int GetMineCount(char mine[ROWS][COLS], int x, int y)
{
 return (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] +
        mine[x - 1][y + 1] - 8 * '0');
}
void Around_Bomb_count(char mine[ROWS][COLS], char show[ROWS][COLS],int x,int y)
{
	if (x == 0 || y == 0 || x == ROWS - 1 || y == COLS - 1)//判断坐标是否越界
	{
		return;
	}
	if (show[x][y] != '*'&&show[x][y]!='#')//判断坐标是否被排查过
	{
		return;
	}
	int count = GetMineCount(mine, x, y);
	show[x][y] = count + '0';//该位置不是雷,就统计这个坐标周围有几个雷,如果周围都没有雷就展开一片直到周围有雷
	
	if(show[x][y]!='0')
		return;
	
	else if (show[x][y]=='0')
	{		
		Around_Bomb_count(mine, show, x - 1, y);
		Around_Bomb_count(mine, show, x - 1, y - 1);
		Around_Bomb_count(mine, show, x, y - 1);
		Around_Bomb_count(mine, show, x + 1, y - 1);
		Around_Bomb_count(mine, show, x + 1, y);
		Around_Bomb_count(mine, show, x + 1, y + 1);
		Around_Bomb_count(mine, show, x, y + 1);
		Around_Bomb_count(mine, show, x - 1, y + 1);
	}
}
int VICTORY(char show[ROWS][COLS],int row,int col)
{
int i,j; int count=0;
for(i=1;i<=row;i++)
{
	for(j=1;j<=col;j++)
	{
		if(show[i][j]=='*'||show[i][j]=='#') 
		  count++;	
		
	}
}	
	return count;	
}

void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
 int x = 0;    
 int y = 0;
 int input3; 
 while (1)
 { 
do
{
 printf("*****排查地雷请按1*****\n");	
 printf("*****标记地雷请按2*****\n");
 printf("*****删除标记请按3*****\n");	
 scanf("%d", &input3);	
 switch(input3)
 {
 case(1):printf("请输入要排查的坐标:>");
         scanf("%d %d", &x, &y);
		 break;	
 		
 case(2):printf("请输入要标记的坐标>");
         scanf("%d %d", &x, &y);
     if(show[x][y]=='*')
         show[x][y]='#';
     else
         printf("坐标标记有误,请重新选择\n");
     DisplayBoard(show, ROW, COL);
     break;	
 
 case(3):printf("请输入要删除的坐标>");    
         scanf("%d %d", &x, &y);
     if(show[x][y]=='#')
         show[x][y]='*';
     else
         printf("坐标标记有误,请重新选择\n");   
      DisplayBoard(show, ROW, COL);
	  break;   
 default:printf("输入有误重新输入\n");break; 
 }
 }while(input3-1);
 if (x >= 1 && x <= row && y >= 1 && y <= col)
 {
 if(show[x][y]!='*'&&show[x][y]!='#') 
 printf("重复排查,重新输入\n");	
 else if (mine[x][y] == '1')
 {
 printf("很遗憾,你被炸死了\n");
 DisplayBoard(mine, ROW, COL); 
 break;
 }
 else
 {  
 Around_Bomb_count(mine,show,x,y); 
 DisplayBoard(show, ROW, COL);
 }
 }
 else
 {
 printf("坐标非法,重新输入\n");
 }
 VICTORY(show,ROW,COL);
 if(VICTORY(show,ROW,COL)==EASY_COUNT)
	{
	   printf("恭喜你,排雷成功\n");
       DisplayBoard(mine, ROW, COL);
       break;
	}
 
 }
 		
}

game.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <Windows.h>

int EASY_COUNT;
int ROW;
int COL;
int ROWS;
int COLS; 
//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);
//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col);
//布置雷
void SetMine(char board[ROWS][COLS], int row, int col);
//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

                                                           感谢您的阅读!

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你好,赵志伟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值