首页 > 其他分享 >用C语言完成扫雷游戏

用C语言完成扫雷游戏

时间:2024-09-11 23:24:04浏览次数:9  
标签:ROWS 游戏 int COLS C语言 扫雷 board printf mine

引言        

《扫雷》是一款大众类的益智小游戏,于1992年发行。游戏目标是在最短的时间内根据点击格子出现的数字找出所有非雷格子,同时避免踩雷,踩到一个雷即全盘皆输。

        

        相信大家一定对《扫雷》这个游戏不陌生,我们只要知道游戏运行的逻辑,就可以把扫雷游戏用C语言写出来

        和上一期写的三子棋小游戏一样,我们这里用game.h game.c文件实现游戏 用fox.c文件放游戏运行逻辑

一、 目录

        运用while循环和switch选择语句做出游戏运行逻辑,并打印菜单

#define  _CRT_SECURE_NO_WARNINGS 1;
#include"game.h"

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

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

int main()
{
	test();
	return 0;
}

 

二、 初始化雷区

        假设我们要设置9*9的雷区,里面布置十个雷,那我们就需要初始化两个雷区(9*9的字符型数组),一个用来显示附近雷的数量,另外一个就是雷场,为了后面避免越界检查,我们把雷区设为11*11的数组,只显示1 ~ 9就行了

     

        

#define  _CRT_SECURE_NO_WARNINGS 1;
#define  _CRT_SECURE_NO_WARNINGS 1;
#include"game.h"

//初始化棋盘
void init_board(char board[ROWS][COLS], int row, int col, char set)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < col; j++)
			board[i][j] = set;
	}
}

这个是雷的数组(0代表安全,1代表雷,雷还没埋呢,后面代码会埋地雷)

这个是显示给玩家看到的数组

三、 打印雷区

        各位发挥自己的聪明才智,巧妙运用循环,打出更好看的游戏界面

//打印棋盘
void print_board(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	printf("-------------扫雷------------\n");
	printf("  ");
	for (j = 1; j <= col; j++)
	{
		printf("%2d ", j);
	}
	printf("\n  -");
	for (j = 0; j <= 3 * col - 2; j++)
	{
		printf("-");
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		printf("%d |", i);
		for (j = 1; j <= col; j++)
		{
			printf("%c", board[i][j]);
			if (j < col)
				printf("  ");
		}
		printf("|%2d", i);
		printf("\n");
	}
	printf("  ");
	for (j = 0; j <= 3 * col - 2; j++)
	{
		printf("-");
	}
	printf("\n");
	printf("-------------扫雷------------\n");
}

四、布置雷区

        运用rand()函数随机生成坐标x y,埋十个

//布置雷区
void set_mine(char mine[ROWS][COLS], int row, int col)
{
	int count = EASY_COUNT;
	while (count)
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			count--;
		}
	}

}

        此时的雷区:

五、 排查地雷

        排查地雷是这个游戏最难的部分,我们需要一步一步把玩家选的这个格子周围都排查一下有没有地雷,只要有一颗雷就+1,这样周围有x个雷就能显示x

        5.1 运用递归增加游戏可玩性

        假设9*9的雷区,有10个地雷,那么玩家就要点击71次才能把简单的排雷搞定,那这也太不人性化了!因此我们运用递归函数,当周围没有地雷的时候,程序自动扩展周围的探索范围,直到周围有地雷为止

int better_count_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
	int count = 0;
	if (1 <= x && x <= ROW && 1 <= y && y <= COL && show[x][y] == '*')
	{
		int ret;
		ret = (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');
		if (0 == ret)
		{
			show[x][y] = ' ';
			count++;
			better_count_mine(mine, show, x - 1, y);
			better_count_mine(mine, show, x - 1, y - 1);
			better_count_mine(mine, show, x, y - 1);
			better_count_mine(mine, show, x + 1, y + 1);
			better_count_mine(mine, show, x + 1, y);
			better_count_mine(mine, show, x + 1, y + 1);
			better_count_mine(mine, show, x, y + 1);
			better_count_mine(mine, show, x - 1, y + 1);
		}
		else
		{
			show[x][y] = ret + '0';
			count++;
		}

	}
	return count;
}

        5.2 判断输赢 

        我的方法是当显示的数组只有10个(雷的个数)且玩家还没有被炸飞的时候,就排雷成功



int is_win(char show[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	int count = 0;
	for (i = 1; i <= row; i++)
	{
		for (j = 1; j <= col; j++)
		{
			if (show[i][j] == '*')
				count++;
		}
	}
	return count;
}

void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int ret = 0;
	int count = row * col - EASY_COUNT;
	while (1)
	{
		printf("请输入要排查的雷的坐标:");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (show[x][y] != '*')
			{
				printf("该位置已被排查,请重输\n");
				continue;
			}
			if (mine[x][y] == '1')
			{
				printf("芜湖~ 你被炸飞咯!\n");
				print_board(mine, ROW, COL);
				break;
			}
			else
			{
				better_count_mine(mine, show, x, y);
				print_board(show, ROW, COL);
			}
		}
		else
		{
			printf("非法输入,请重新输入\n");
		}
		ret = is_win(show, ROW, COL);
		if (ret == EASY_COUNT)
		{

			printf("恭喜你,排完了!\n");
			print_board(mine, ROW, COL);
			break;
		}
	}

}

六、 游戏全代码

        6.1 game.h

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

#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define EASY_COUNT 10

//初始化棋盘
void init_board(char board[ROWS][COLS], int row, int col, char set);

//打印棋盘
void print_board(char board[ROWS][COLS], int row, int col);

//布置雷
void set_mine(char mine[ROWS][COLS], int row, int col);

//排查雷
void find_mine(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col);

        6.2 game.c

#define  _CRT_SECURE_NO_WARNINGS 1;
#define  _CRT_SECURE_NO_WARNINGS 1;
#include"game.h"

//初始化棋盘
void init_board(char board[ROWS][COLS], int row, int col, char set)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < col; j++)
			board[i][j] = set;
	}
}


//打印棋盘
void print_board(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	printf("-------------扫雷------------\n");
	printf("  ");
	for (j = 1; j <= col; j++)
	{
		printf("%2d ", j);
	}
	printf("\n  -");
	for (j = 0; j <= 3 * col - 2; j++)
	{
		printf("-");
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		printf("%d |", i);
		for (j = 1; j <= col; j++)
		{
			printf("%c", board[i][j]);
			if (j < col)
				printf("  ");
		}
		printf("|%2d", i);
		printf("\n");
	}
	printf("  ");
	for (j = 0; j <= 3 * col - 2; j++)
	{
		printf("-");
	}
	printf("\n");
	printf("-------------扫雷------------\n");
}

//布置雷区
void set_mine(char mine[ROWS][COLS], int row, int col)
{
	int count = EASY_COUNT;
	while (count)
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			count--;
		}
	}

}

int better_count_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
	int count = 0;
	if (1 <= x && x <= ROW && 1 <= y && y <= COL && show[x][y] == '*')
	{
		int ret;
		ret = (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');
		if (0 == ret)
		{
			show[x][y] = ' ';
			count++;
			better_count_mine(mine, show, x - 1, y);
			better_count_mine(mine, show, x - 1, y - 1);
			better_count_mine(mine, show, x, y - 1);
			better_count_mine(mine, show, x + 1, y + 1);
			better_count_mine(mine, show, x + 1, y);
			better_count_mine(mine, show, x + 1, y + 1);
			better_count_mine(mine, show, x, y + 1);
			better_count_mine(mine, show, x - 1, y + 1);
		}
		else
		{
			show[x][y] = ret + '0';
			count++;
		}

	}
	return count;
}


int is_win(char show[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	int count = 0;
	for (i = 1; i <= row; i++)
	{
		for (j = 1; j <= col; j++)
		{
			if (show[i][j] == '*')
				count++;
		}
	}
	return count;
}

void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int ret = 0;
	int count = row * col - EASY_COUNT;
	while (1)
	{
		printf("请输入要排查的雷的坐标:");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (show[x][y] != '*')
			{
				printf("该位置已被排查,请重输\n");
				continue;
			}
			if (mine[x][y] == '1')
			{
				printf("芜湖~ 你被炸飞咯!\n");
				print_board(mine, ROW, COL);
				break;
			}
			else
			{
				better_count_mine(mine, show, x, y);
				print_board(show, ROW, COL);
			}
		}
		else
		{
			printf("非法输入,请重新输入\n");
		}
		ret = is_win(show, ROW, COL);
		if (ret == EASY_COUNT)
		{

			printf("恭喜你,排完了!\n");
			print_board(mine, ROW, COL);
			break;
		}
	}

}

        6.3 fox.c

#define  _CRT_SECURE_NO_WARNINGS 1;
#include"game.h"

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

void game()
{
	printf("扫雷游戏\n");
	char mine[ROWS][COLS] = { 0 };//布置好的雷的信息
	char show[ROWS][COLS] = { 0 };//排查出的雷的信息
	//初始化棋盘
	init_board(mine, ROWS, COLS,'0');
	init_board(show, ROWS, COLS,'*');
	//打印棋盘
	//print_board(mine, ROW, COL);
	print_board(show, ROW, COL);
	//布置雷
	set_mine(mine, ROW, COL);
	print_board(mine, ROW, COL);
	//排查雷
	find_mine(mine, show, ROW, COL);
}

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

int main()
{
	test();
	return 0;
}

        这样你就得到了一个扫雷小游戏,快和你的舍友分享把~

        记得点个小赞~

标签:ROWS,游戏,int,COLS,C语言,扫雷,board,printf,mine
From: https://blog.csdn.net/m0_74779094/article/details/142152025

相关文章

  • 20240909_111725 c语言 关于进位制
    各种进制注意:在较老的版本如VisualStudio2010中,C语言不支持直接使用0b开头来表示二进制数。对于八进制数,如果写成intnum=12;这是十进制的12,如果要明确表示八进制的12,可以写成intnum=012;测一测注,包含了语法错误的情况......
  • 【Unity精品源码】Auto Chess: 自走棋策略游戏开发框架
    ......
  • 娱乐小平板(功能:相册、游戏、画图、刮刮乐)
    #include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<unistd.h>#include<stdio.h>#include<sys/mman.h>//mmap#include<linux/input.h>#include<string.h>#include<pthread.h>#in......
  • 内存延迟对Zen5游戏性能影响有多大!为何首发评测我们会用技嘉X670E AORUS XTREME主板
    一、前言:为什么我们会一直使用技嘉X670E主板做锐龙处理器首发评测很多同学一直好奇,为什么我们在各种锐龙平台的评测中都会优先使用技嘉X670主板?也有同学很疑惑,为什么海外媒体的游戏性能测试,锐龙79700X连i7-14700K都打不过,而在我们这里却与i9-14900K旗鼓相当?主要原因是Zen5架构......
  • C语言之Strict Aliasing(严格别名)
    C语言之StrictAliasing(严格别名)alias(别名)C语言的左值(lvalue)和右值(rvalue)的含义以赋值符号=为界,=左边的就是左值,=右边就是右值。比如:(1)intb=3;(2)inta=b;第(2)行代码,a为左值,b为右值。可以将L-value的L,理解成Location,表示定位、地址。将R-value......
  • 游戏程序猿35岁的时候,技术还不够好该怎么办
    35岁对于游戏程序员来说,确实是一个需要认真思考和规划的年龄。如果你觉得自己的技术还不够好,不要灰心,以下是一些具体的策略和建议,帮助你提升技术水平,找到职业发展的新方向。具体策略1.制定学习计划明确目标:确定你需要提升的具体技术领域,如图形渲染、物理引擎、AI算法等......
  • fps游戏刷怪系统代码逻辑架构设计
    FPS游戏的刷怪系统主要负责生成怪物并在合适的时机和位置将它们放入游戏世界。在设计刷怪系统时,我们需要考虑以下几个方面:刷怪点:在游戏地图上设置一些预定的刷怪点,这些点用于生成怪物。可以将刷怪点存储在一个容器中,供刷怪系统使用。刷怪波次:将怪物刷怪划分为多个波次,每......
  • 【C语言基础】指针
    1指针与地址,指针变量地址就是内存区中对每个字节的编号。如整型变量a、b、c,整型变量需要4个字节,分配的地址分别为1000、1004、1008。可以通过访问变量的地址来找到所需的变量,我们称变量的地址为变量的“指针”。上例中的1000、1004、1008分别为变量a、b、c的指针。指针变量......
  • 《浪人崛起》游戏启动时闪退提示“找不到KernelBase.dll”该怎么解决?浪人崛起游戏崩溃
    启动《浪人崛起》时,游戏闪退并提示“找不到KernelBase.dll”,这着实令人烦恼。别着急,这个问题是可以解决的。可能需要重新安装相关组件,或者检查系统文件完整性。具体该如何操作才能顺利解决呢?本篇将为大家带来《浪人崛起》游戏启动时闪退提示“找不到KernelBase.dll”该怎么解决......
  • 《守望先锋2》游戏启动时黑屏弹窗“找不到steam_api.dll”该怎么处理?守望先锋2游戏崩
    在启动《守望先锋2》时,出现黑屏弹窗,提示“找不到steam_api.dll”,这给玩家带来极大困扰。别慌张,这种状况是能够处理的。可能需要重新获取该文件,或者检查相关设置是否正确。具体要怎么操作呢?本篇将为大家带来《守望先锋2》游戏启动时黑屏弹窗“找不到steam_api.dll”该怎么处理的......