扫雷--C语言实现

  在学习过二维数组 简单的递归调用 ,之后很容易写一个扫雷小游戏。


主函数:

主函数所写的是玩家玩游戏的大致步骤。  

所其中包括游戏菜单,游戏选项 ,游戏 ,输赢结果的判断及显示 ,while或do...while循环实现游戏循环

#include "gmine.h"

void menu()
{
	printf("************  扫雷  ************\n");
	printf("********>   1.  play   <********\n");
	printf("********>   0.  exit   <********\n");
	printf("********************************\n");
}

void game()
{
	srand((unsigned)time(NULL));
	printf("设置雷的个数: ");
	int num;
	scanf("%d", &num);
	char panel[ROW][COL];                //有记录雷的界面
	char panel2[ROW][COL];               //对玩家显示界面
	int row = 0, col = 0, flag = 0;
	InitBoard(num, panel, panel2);     //初始化panel,panel2
	FillNum(panel);                //填充雷周围的数字
	//ShowBoard(panel); 
	ShowBoard(panel2);                 
	int i = 0;
	int step = 0;
	for (i = 0; i < num; i++)
	{
		printf("请输入坐标并标记是否是雷(1代表是,0代表不是):");
		scanf("%d%d%d", &row, &col, &flag);
		int mine = Find(panel, panel2, row - 1, col - 1, flag);
		//如果踩到雷
		if (mine == 2)
		{
			//第一次就踩雷,将雷挪走
			if (step == 0)
			{
				mine = MoveMine(panel, panel2,row - 1,col - 1 );
			}
			else
			    break;
		}
		//如果找到雷
		else if (mine)
		{
			ShowBoard(panel2);
			continue;
		}
		step = 1;
		i--;
		ShowBoard(panel2);                  //显示盘
	}
	if (i < num)
	{
		printf(" 遗憾 > < 游戏结束. \n");
	}
	else
	{
		printf("!!恭喜,玩家胜利 !!\n");
	}
 
}

int main() 
{
	int input = 0;
	
		menu();
		printf("请输入:> ");
		scanf("%d", &input);
	do 
	{	switch (input)
		{
		case 1: game(); break;
		case 0: exit(0); break;
		default: printf("输入错误,请输入0 or 1\n"); break;
		}
	printf("再来一局??(1: 继续  0: 退出 ) ");
	int again = 0;
	scanf("%d", &again);
	if (again == 1)
	{
		input = 1;
	}
	else if (again == 0)
	{
		input = 0;
	}
	else
	{
	
	printf("输入错误\n");
	}
	} while (input);
	return 0;
}


扫雷的具体实现:

写这一模块时应该注重梳理,应该一步步写,如:绘制界面 --> 显示界面 --> 初始化盘 --> 检测雷周围的数字 --> 打印数字(0或其他)--> 标记雷 --> 扩展功能

#include "gmine.h"


//输出横向坐标
void PrintX() {
	int row = 0;
	printf("  ");
	for (row = 0; row < ROW; row++) 
	{
		printf("%4d", row + 1);
	}
	printf("\n");
}

//输出横向框
void PrintH() {
	int col = 0;
	printf("   +");
	for (col = 0; col < COL *2; col++) 
	{
		if (!((col + 1) % 2)){
			printf("+");
		}
		else {
			printf("---");
		}
	}
	printf("\n");
}


//显示盘
void ShowBoard(char panel[ROW][COL])
{
	int row = 0, col = 0;
	PrintX();
	PrintH();
	for (row = 0; row < ROW; row++) 
	{
		printf("%2d ", row + 1); //输出竖向坐标
		printf("| ");
		for (col = 0; col < COL; col++)
		{
			printf("%c ", panel[row][col]);
			printf("| ");
		}
		printf("%d\n", row +1); //输出竖向坐标
		PrintH();   //横向框
	}
	PrintX();
}

//初始化盘
void InitBoard(int num, char panel[ROW][COL], char panel2[ROW][COL])
{
	int i = 0;
	int row = 0;
	int col = 0;
	for (row = 0; row < ROW; row++) 
	{
		for (col = 0; col < COL; col++) 
		{
			panel[row][col] = ' ';
			panel2[row][col] = ' ';
		}
	}
	for (i = 0; i < num; i++) 
	{
		row = rand() % ROW;
		col = rand() % COL;
		if (panel[row][col] == '*') 
		{
			i--;
		}
		else 
		{
			panel[row][col] = '*';
		}
	}
}

//根据布置好的雷计算雷周围的数字
void FillNum(char panel[][COL]) 
{ 
	//填充数字
	int row = 0, col = 0;
	for (row = 0; row < ROW; row++) 
	{
		for (col = 0; col < COL; col++) 
		{
			int count = 0;
			//如果是雷,则不需要计算该位置周围的雷数
			if (panel[row][col] == '*')
				continue;
			if ((row - 1) >= 0 && (col - 1) >= 0)
			{
				//检测左上角是否在盘内
				if (panel[row - 1][col - 1] == '*') 
					count++;                           //检测到雷,则count加1
			}

			if ((row + 1) < ROW && (col - 1) >= 0)
			{
				//左下角
				if (panel[row + 1][col - 1] == '*')
					count++;
			}

			if ((row - 1) >= 0 && (col + 1) < COL)
			{
				//右上角
				if (panel[row - 1][col + 1] == '*')
					count++;
			}

			if ((row + 1) < ROW && (col + 1) < COL)
			{
				//右下角
				if (panel[row + 1][col + 1] == '*')
					count++;
			}

			if ((row - 1) >= 0) 
			{
				//正上方
				if (panel[row - 1][col] == '*') 
					count++;
			}

			if ((row + 1) < ROW)
			{
				//正下方
				if (panel[row + 1][col] == '*')
					count++;
			}

			if ((col - 1) >= 0)
			{
				//左边
				if (panel[row][col - 1] == '*')
					count++;
			}

			if ((col + 1) < COL)
			{
				//右边
				if (panel[row][col + 1] == '*')
					count++;
			}

			panel[row][col] = '0' + count;                     //将计算出的周围的雷数整型转换成字符型
		}
	}
}


//点到0,显示多个数字
void ShowNum(char panel[][COL], int row, int col, char panel2[][COL])
{
	panel2[row][col] = panel[row][col];        //显示数字

	//检测相邻点是否超出棋盘 若相邻点为0且没有雷则以该点为中心继续显示

	//正上方
	if ((row - 1) >= 0) 
	{
		if (panel[row - 1][col] == '0' && panel2[row - 1][col] == ' ')
			ShowNum(panel, row - 1, col, panel2);
		else 
			panel2[row - 1][col] = panel[row - 1][col];
	}

	//正下方
	if ((row + 1) < ROW)
	{
		if (panel[row + 1][col] == '0' && panel2[row + 1][col] == ' ')
			ShowNum(panel, row + 1, col, panel2);
		else 
			panel2[row + 1][col] = panel[row + 1][col];
	}

	//左边
	if ((col - 1) >= 0)
	{
		if (panel[row][col - 1] == '0' && panel2[row][col - 1] == ' ')
			ShowNum(panel, row, col - 1, panel2);
		else 
			panel2[row][col - 1] = panel[row][col - 1];
	}

	//右边
	if ((col + 1) < COL)
	{
		if (panel[row][col + 1] == '0' && panel2[row][col + 1])
			ShowNum(panel, row, col + 1, panel2);
		else panel2[row][col + 1] = panel[row][col + 1];
	}

	//左上角
	if ((row - 1) >= 0 && (col - 1) >= 0)
	{
		if (panel[row - 1][col - 1] == '0' && panel2[row - 1][col - 1] == ' ')
			ShowNum(panel, row - 1, col - 1, panel2);
		else
			panel2[row - 1][col - 1] = panel[row - 1][col - 1];
	}
	
	//左下角
	if ((row + 1) < ROW && (col - 1) >= 0)
	{	
		if (panel[row + 1][col - 1] == '0' && panel2[row + 1][col - 1] == ' ')
			ShowNum(panel, row + 1, col - 1, panel2);
		else panel2[row + 1][col - 1] = panel[row + 1][col - 1];

	}

	//右上角
	if ((row - 1) >= 0 && (col + 1) < COL)
	{
		if (panel[row - 1][col + 1] == '0' && panel2[row - 1][col + 1] == ' ')
			ShowNum(panel, row - 1, col + 1, panel2);
		else panel2[row - 1][col + 1] = panel[row - 1][col + 1];
	}	

	//右下角
	if ((row + 1) < ROW && (col + 1) < ROW) 
	{
		if (panel[row + 1][col + 1] == '0' && panel2[row + 1][col + 1] == ' ')
			ShowNum(panel, row + 1, col + 1, panel2);
		else
			panel2[row + 1][col + 1] = panel[row + 1][col + 1];
	}
}


//找雷
int Find(char panel[][COL],  char panel2[][COL],int row, int col, int flag) 
{
	if (flag == 1) 
	{ 
		//标记可能是雷的位置 
		//是雷返回 1 不是返回 0
		panel2[row][col] = 'F';       //如果是雷标记‘F' 
		if (panel[row][col] == '*') 
		{
			return 1;
		}
		else 
		{
			return 0;
		}
	}
	else
	{
		//猜测不是雷
		if (panel[row][col] == '*') 
		{ 
			//点到雷,游戏失败
			return 2;
		}
		else if (panel[row][col] == '0') 
		{ 
			//点击到0,显示多个数字
			ShowNum(panel, row, col, panel2);
			return 0;
		}
		else 
		{
			panel2[row][col] = panel[row][col];      //显示数字
			return 0;
		}
	}
}

//防止第一次踩雷
int MoveMine(char panel[][COL], char panel2[][COL], int row, int col)
{

	int row2 = 0;
	int col2 = 0;
	//找到没有雷的位置与输入位置交换
	for (row2 = 0; row2 < ROW; row++)
	{
		for (col2 = 0; col2 < COL; col++)
		{
			int tmp = 0;
			if (panel[row2][col2] == '*')
				continue;
			else
			{
				//将雷移走
				tmp = panel[row][col];
				panel[row][col] = panel[row2][col2];
				panel[row2][col2] = tmp;
				//更新
				FillNum(panel);
				//ShowBoard(panel);
                panel2[row][col] = panel[row][col];     
				return panel2[row][col];
			}
		}

	}

}


头文件:

#ifndef _GAME_H_
#define _GAME_H_
 
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define ROW 10
#define COL 10

void ShowaBoard (char panel[ROW][COL]);
void InitBoard (int num, char panel[ROW][COL], char panel2[ROW][COL]);
void FillNumber(char panel[][COL]);
void ShowNum(char panel[][COL], int row, int col, char panel2[][COL]);
int Find(char panel[][COL], char panel2[][COL], int row, int col, int flag);
int MoveMine(char panel[][COL], char panel2[][COL],int row,int col);

#endif //_GAME_H_

由于多次修改过,可能代码有很多地方很乱,而且应该有许多地方写的比较挫,然后功能比较简单,之后希望能有好的建议。

  

猜你喜欢

转载自blog.csdn.net/timecur/article/details/80475933