通过C语言实现扫雷

通过C语言实现扫雷

1.整体思路

(1)存储雷的信息:

  一个myboard存放雷的信息一个playboard存放坐标雷的个数,其中myboard中有雷为字符‘1’,没有雷为字符‘0’,playboard中则用字符表示周围的雷的个数,如果有雷则是‘*’,且通过宏定义的方法,定义ROW和COL,其中两个二维数组的大小应为borad[ROW+2][COL+2],因为在处理雷的信息的时候,需要判断某个坐标周围一圈的雷的个数,这个时候对周围的边界值得判断,如果将原先雷的表格中扩大一圈,并将扩大的一圈中的所有格数置为‘0’即没有雷,解决这个问题。

(2)设置雷的信息

  通过编写三个函数,initboard用来将数组中所有的值初始化为某一个值;takemine函数用来存放雷到数组里面并且将雷只存放在board[ROW][COL]中(其中mine也是一个宏定义,好让我们能轻松改变雷的个数);displayboard函数用来打印存储雷的数组,并且打出来要为游戏表格形式。

(3)对存放雷数组的处理

  通过编写两个函数来实现用户输入坐标之后就能使playboard中该坐标处显示周围的雷的值。首先编写一个minenumber函数,该函数能返回输入的坐标处周围的雷的个数。再设置一个open函数,通过open函数实现在点击某坐标时如果minenumber=0,即该坐标周围没有雷的时候实现展开,注意此处要使用递归,此时还要定义一个flag数组用来存放每个坐标是否被展开过,从而避免被重复递归而导致程序崩溃,

(4)用户进行游戏

  主函数中通过do while循环的方式让用户选择是否进入游戏,并且保证在用户完成一次游戏之后再次出现直到用户选择退出游戏。进入游戏函数中,先设置一个count=表格格数-雷的个数,在设置一个remain=count-以及排除掉的不是雷的格数,当没有不是雷的格数的时候,游戏结束,即可以通过while(remain)控制循环。while循环中如果判断用户输入的坐标为雷,则退出循环并且提示你被炸死了并把内部的雷的棋盘打印出来给用户看,如果判断用户输入的坐标不是雷,则进入open函数,open函数中会先将你输入的值得雷的个数显示,如果为0的话则会继续展开,然后再通过takecount函数计算已经批排除掉的雷的个数用来判断是否游戏结束。最后在循环到最后,用户将所有非雷坐标排查出来时,remain=0,循环终止,提示玩家游戏胜利,

2.代码实现

(1)头文件game.h

#define _CRT_SECURE_NO_WARNINGS
#define ROW 9  //行数
#define COL 9  //列数
#define ROWS 11  //因为排查地雷时要排查一圈的地雷,故直接将棋盘扩大一圈,并把外围的存放雷的棋盘全部置0,避免了对边界的复杂讨论
#define COLS 11 
#define MINE 10 //地雷数


#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<math.h>

void menu(); //菜单打印
void game(); //游戏开始
void initboard(char board[ROWS][COLS],char a); //初始化棋盘
void displayboard(char board[ROWS][COLS]); //打印棋盘
void takemine(char board[ROWS][COLS]);  //布置雷
void open(char myboard[ROWS][COLS], char playboard[ROWS][COLS],char flag[ROWS][COLS],int x,int j); //展开棋盘
int minenumber(char board[ROWS][COLS],int x,int j); //用户点击过后展开并且显示雷的个数
int takecount(char board[ROWS][COLS]);//记录排雷的个数

(2)game.c文件

#include"game.h"

void menu() {
	printf("****************************\n");
	printf("********1.开始游戏**********\n");
	printf("********0.退出游戏**********\n");
	printf("****************************\n");
}



void initboard(char board[ROWS][COLS], char a) {
	for (int i = 0; i < ROWS; i++) {
		for (int j = 0; j < COLS; j++) {
			board[i][j] = a;
		}
	}
}

void displayboard(char board[ROWS][COLS]) {
	printf("  ");
	for (int i = 1; i <= 9; i++) {
		printf("%d ",i);
	}
	printf("\n");
	for (int i = 1; i <= 9; i++) {
		printf("%d ", i);
		for (int j = 1; j <= 9; j++) {
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
	printf("\n");
}

void takemine(char board[ROWS][COLS]) {
	int x = 0;
	int y = 0;
	int mine = MINE;
	while (mine) {
		x = rand() % 9 + 1;
		y = rand() % 9 + 1;
		if (board[x][y] != '1') {
			board[x][y] = '1';
			mine--;
		}
	}
}

int minenumber(char board[ROWS][COLS],int i,int j){
	return(board[i - 1][j - 1] + board[i - 1][j] + board[i - 1][j + 1] + board[i][j - 1] + board[i][j] + board[i][j + 1] + 
	board[i + 1][j - 1] + board[i + 1][j] + board[i + 1][j + 1] - 9 * '0');
	}

void open(char myboard[ROWS][COLS], char playboard[ROWS][COLS],char flag[ROWS][COLS],int i,int j) {
	playboard[i][j] = '0'+minenumber(myboard, i, j);
	if (playboard[i][j] == '0'&&flag[i][j]=='0') {
		flag[i][j] = '1';
		for (int a = i - 1; a <= i + 1; a++) {
			for (int b = j - 1; b <= j + 1; b++) {
				open(myboard, playboard, flag, a, b);
			}
		}
	}
}

int takecount(char playboard[ROWS][COLS]) {
	int count = 0;
	for (int i = 1; i <= ROW; i++) {
		for (int j = 1; j <= COL; j++) {
			if (playboard[i][j] != '*') {
				count += 1;
			}
		}
	}
	return count;
}


void game() {
	char flag[ROWS][COLS] = { 0 };
	int count = 81-MINE;
	int remain = 1;//剩下的没有被排除过的没雷的格数
	int x = 0;
	int y = 0;
	char myboard[ROWS][COLS] = { 0 };   //存放雷的棋盘
	char playboard[ROWS][COLS] = { 0};   //玩家看到的棋盘
	int flagplayboard[ROWS][COLS] = { 0 }; //标记是否被展开过,避免展开时重复递归
	printf("*****游戏开始*****\n");
	initboard(flag, '0');
	initboard(myboard, '0');
	initboard(playboard, '*');
	takemine(myboard);
	displayboard(myboard);
	displayboard(playboard);     
	while (remain) {
		printf("请输入坐标\n");
		scanf("%d%d",&x,&y);
		if (x > 0 && x <= ROW && y > 0 && y <= COL) {
			if (myboard[x][y] == '1') {
				printf("你被炸死了\n");
				displayboard(playboard);
				displayboard(myboard);
				break;
			}
			else if (myboard[x][y] == '0') {
				open(myboard, playboard,flag,x,y);
				displayboard(playboard);
				remain = count - takecount(playboard);
			}
		}
	}
	if (remain == 0) {
		printf("恭喜你胜利666\n");
	}
}

(3)主函数

#include"game.h"


int main() {
	int input = 0;
	srand((unsigned int)time(NULL));
	do {
		menu();
		scanf("%d", &input);
		switch (input) {
		case 1:
			game();
			break;
		case 0:
			printf("*****游戏结束*****\n");
			break;
		default: printf("选择错误请重新输入");
		}
	} while (input);
}

感谢各位的聆听

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值