自制扫雷,优化版

本文介绍了作者从头构建扫雷游戏的过程,包括设置菜单、打印棋盘、初始化、随机布雷、计算相邻雷数、递归展开安全区域等功能。游戏设有胜利和失败的趣味彩蛋,并允许自定义棋盘大小,优化了用户体验。通过代码实现,展现了游戏逻辑和编程技巧。
摘要由CSDN通过智能技术生成

下面是我在学习扫雷后,自己整理思路写出的代码,并完成了拓展以及优化,还有对胜利条件,失败条件设立彩蛋,分为三个文件,两个源文件,一个头文件,我会在附属文件里定义函数,在头文件声明,而主函数所在的源文件短小精悍。

//这个是附属源文件
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu()
{
	printf("*************************\n");
	printf("*******1. 进入游戏*******\n");
	printf("*******0. 退出游戏*******\n");
	printf("*************************\n");
}
void print_board(char show[ROWS][COLS], int row, int col)
{
	printf("-----------------扫雷------------------\n");
	int i, j;
	for (j = 1; j <= col + 1; j++)
	{
		printf("--- ");

	}
	printf("\n");
	for (j = 0; j <= col; j++)
		printf(" %d】", j);
	printf("\n");
	for (j = 0; j <= col; j++)
		printf("--- ");
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		printf(" %d】", i);
		for (j = 1; j <= col; j++)
		{
			printf(" %c |", show[i][j]);

		}
		printf("\n");
		for (j = 1; j <= col + 1; j++)
		{
			printf("--- ");

		}
		printf("\n");
	}
}
void init_board(char  show[ROWS][COLS], int row, int col, char a)
{
	int i, j;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
			show[i][j] = a;
	}
}
void setmine(char mine[ROWS][COLS], int row, int col)
{
	int i;
	for (i = 0; i < NUM; i++)
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (mine[x][y] == '0')
			mine[x][y] = '1';
		else
			i--;
	}
}
int get_mine_num(char mine[ROWS][COLS], int row, int col)
{
	return (mine[row + 1][col + 1] + mine[row][col + 1] + mine[row + 1][col]
		+ mine[row - 1][col + 1] + mine[row + 1][col - 1] + mine[row - 1][col - 1]
		+ mine[row][col - 1] + mine[row - 1][col] - '0' * 8);
}
void it_is_0(char mine[ROWS][COLS], char show[ROWS][COLS],int x,int y)
{
	int i , j;
	if (get_mine_num(mine, x, y) == 0)
	{
		show[x][y] = ' ';
		for (i = -1; i <= 1; i++)
		{
			if (x + i == 0 || x + i == ROW + 1)
				continue;
			for (j = -1; (j <= 1) && (y + i != 0) && (y + i != COL + 1); j++)
			{
				if (y + j == 0 || y + j != COL + 1)
					if (!(i == 0 && j == 0) && show[x + i][y + j] == '*')
				    {
					show[x + i][y + j] = get_mine_num(mine, x + i, y + j) + '0';
					
					it_is_0(mine, show, x+i, y+j);
				    }
			}
		}
	}
}
int howmany_mine(char show[ROWS][COLS], int row, int col)
{
	int n = 0, i, j;
	for (i = 1; i <= row; i++)
	{
		for (j = 1; j <= col; j++)
		{
			if (show[i][j] == '*')
				n++;
		}
	}
	return n;
}
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0, y = 0;
	while ((howmany_mine(show,ROW,COL))>NUM)
	{
		printf("\n请输入你要排查的位置:>");
		scanf("%d%d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (show[x][y] != '*')
			{
				printf("这个位置被排查过了!\n");
				Sleep(2500);
			}
			if (mine[x][y] == '1')
			{
				system("cls");
				printf("Oh!");
				Sleep(1000);
				system("cls");
				printf("NO!");
				Sleep(1000);
				system("cls");
				printf("脑子被雷炸没了!\n");
				print_board(show, ROW, COL);
				printf("这个是答案坐标,1就是雷的位置,0是安全点\n");
				print_board(mine, ROW, COL);
				break;
			}
			else
			{
				show[x][y] = get_mine_num(mine, x, y) + '0';				
				it_is_0(mine, show, x, y);
				system("cls");
				print_board(show, ROW, COL);
			}	
		}
		else
		{
			printf("输入错误,请重新输入\n");
			print_board(mine, ROW, COL);
		}
	}

	if ((howmany_mine(show, ROW, COL)) == NUM)
	{
		system("cls");
		char arr5[] = "ohhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh";
		char arr6[] = "                                            ";
		int left2 = 0;
		int right2 = strlen(arr5) - 1;//用sizeof会把\0算进去。
		for (; left2 <= right2; left2++)
		{
			arr6[left2] = arr5[left2];
			printf("%s\n", arr6);
			printf("%s\n", arr6);
			printf("%s\n", arr6);
			printf("%s\n", arr6);
			printf("%s\n", arr6);
			printf("%s\n", arr6);
			printf("%s\n", arr6);
			printf("%s\n", arr6);
			Sleep(25);
			system("cls");
		}
		char arr1[] = "gong xi ni cheng gong la !";
		char arr2[] = "                           ";
		int left = 0;
		int right = strlen(arr1) - 1;
		for (; left <= right; left++, right--)
		{
			arr2[left] = arr1[left];
			arr2[right] = arr1[right];
			printf("%s\n", arr2);
			Sleep(250);
			system("cls");
		}
		printf("gong xi ni cheng gong la !");
		Sleep(1000);
		system("cls");

		char arr3[] = "CONGRATULATION!";
		char arr4[] = "                ";
		int left1 = 0;
		int right1 = strlen(arr3) - 1;
		for (; left1 <= right1; left1++, right1--)
		{
			arr4[left1] = arr3[left1];
			arr4[right1] = arr3[right1];
			printf("%s\n", arr4);
			Sleep(250);
		}
		system("cls");
		printf("CONGRATULATION!");
		Sleep(1000);
		system("cls");
		printf("恭喜你!!!!!!!!!!!!!!!!!");
		system("cls");
		printf("恭喜你呀恭喜你\n");
		Sleep(500);
		printf("              恭喜你呀恭喜你~\n");
		Sleep(500);
		printf("恭喜你呀恭喜你\n");
		Sleep(500);
		printf("              恭喜你呀恭喜你~\n");
		Sleep(500);
		printf("恭喜你呀恭喜你\n");
		Sleep(500);
		printf("              恭喜你呀恭喜你~\n");
		Sleep(500);
		printf("恭喜你呀恭喜你\n");
		Sleep(500);
		printf("              恭喜你呀恭喜你~\n");
		Sleep(500);
		system("cls");
		print_board(show, ROW, COL);
		printf("恭喜你成功了!\n这个是布雷的坐标图,1因为雷点,0为安全点\n");
		print_board(mine, ROW, COL);
	}
}

void game()
{
	char mine[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };

	init_board(mine, ROWS, COLS, '0');
	init_board(show, ROWS, COLS, '*');
	print_board(show, ROW, COL);
	

	setmine(mine, ROW, COL);
	find_mine(mine, show, ROW, COL);
}
void start()
{
	srand((unsigned int)time(NULL));
	int count = 2;
	int n = 0;
	do
	{
		menu();
		printf("请玩家选择:>");
		scanf("%d", &n);
		switch (n)
		{
		case 1:
		{
			system("cls");
			game();
			break;
		}
		case 0:
		{
			if (count == 1)
				printf("好吧,下次再玩!\n");
			if (count == 2)
				printf("你确定要退出游戏?\n");
			count--;
			break;
		}
		default:
			printf("\n请重新输入:>");
			break;
		}
	} while (count);
}
//这个是声明用的头文件
#pragma once

#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#include<Windows.h>
#include<string.h>

#define ROW 9  //行数
#define COL 9  //列数
#define ROWS (ROW+2)
#define COLS (COL+2)
#define NUM 10  //雷数

//启动函数
void start();
//菜单函数
void menu();
//打印函数
void print_board(char show[ROWS][COLS], int row, int col);
//初始化函数
void inti_board(char show[ROWS][COLS], int row, int col, char a);
//随机布雷函数
void setmine(char mine[ROWS][COLS], int row, int col);
//获得附近雷数函数
int get_mine_num(char mine[ROWS][COLS], int row, int col);
//排雷函数
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
//游戏函数
void game();
//遇0自动扩展递归函数
void it_is_0(char mine[ROWS][COLS], char show[ROWS][COLS], int* win, int x, int y);
//*的个数函数
int howmany_mine(char show[ROWS][COLS], int row, int col);




这个是主函数所在源文件
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
int main()
{
	start();
	return 0;
}

而对于游戏创作,应该定好功能,分好模块,设立函数(先直接写函数名,然后再去定义),再去想算法,(临时的想法有可能成立,敢于尝试!!!)

这个扫雷有个很巧妙的地方,就是设立了两个棋盘,一个是布置雷的,一个是展示的,但也很正常,因为布置雷的是“答案”,而我们展示肯定是不能给答案的。

还有一个就是表格扩大一圈,目的是为了测试边边的地点周围的雷的个数,而打印什么,还是自己说了算。

还有优化方面,我优化了表格可以自定义(数组定义时不能填变量,但是可以填宏),还有使用递归去使得判定雷的个数是0的时候自动扩张,但是这样判定胜利条件的方法就要改变。

而观感优化了表格的形式,我加了一些线条,还有坐标提示,eg 0】| 1】.......,使得填的时候更加舒适,以及结束时候失败以及胜利设立有趣的彩蛋。

总而言之就是先定好框架,有自己的思路,一步一步来,需要什么函数大胆设立下来,然后去定义去实现,想到一些算法就大胆去干!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

s:103

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

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

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

打赏作者

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

抵扣说明:

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

余额充值