C语言实现推箱子游戏!(超简单详细)代码思路+源码分享

Posted 一起学编程

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言实现推箱子游戏!(超简单详细)代码思路+源码分享相关的知识,希望对你有一定的参考价值。

经典的推箱子是一个很古老的游戏了,相信大家都不陌生。其目的是在训练我们的逻辑思考能力。在一个狭小的仓库中,要求把木箱放到指定的位置,稍不小心就会出现箱子无法移动或者通道被堵住的情况,所以需要巧妙的利用有限的空间和通道,合理安排移动的次序和位置,才能顺利的完成任务。

我们将编写推箱子游戏,玩家键盘控制游戏角色将所有黄色箱子推到白色方块处,效果如图所示:

操作方法:方向键↑↓←→控制移动推箱子,将箱子推到对应位置。

首先学习字符串与字符数组的概念,并应用字符数组初始化关卡数据;然后利用键盘控制游戏角色移动,实现地图元素更新和游戏胜利的判断;接着利用三维字符数组,实现多关卡的游戏;最后学习基于文件的关卡数据读取,利用枚举类型改进游戏代码。

源码:

#include <graphics.h>  
#include <conio.h>
#include <stdio.h>
#define B_SIZE 60 // 方块大小
#define B_NUM 8 // 方块个数,一共8*8个方块

struct Player // 结构体,用于记录玩家位置

	int i;
	int j;
;
Player player; // 玩家全局变量

enum Element // 定义枚举类型,小方块所有的可能的种类

	wall,target,box,empty,achieved,role
;

// 用于存储地图数据,用枚举类型实现
Element level[B_NUM][B_NUM] = 
wall,wall,wall,wall,wall,wall,wall,wall,
wall,wall,wall,target,box,empty,empty,wall,
wall,empty,empty,empty,empty,empty,empty,wall,
wall,empty,empty,empty,empty,empty,empty,wall,
wall,empty,empty,empty,empty,empty,empty,wall,
wall,role,empty,box,target,wall,wall,wall,
wall,empty,empty,empty,empty,wall,wall,wall,
wall,wall,wall,wall,wall,wall,wall,wall;

int targetNum,achievedNum; // 目标位置个数、完成目标个数

void startup()  // 初始化函数

	initgraph(B_NUM*B_SIZE,B_NUM*B_SIZE); // 新开一个画面
	setbkcolor(RGB(150,150,150)); // 灰色背景
	BeginBatchDraw(); // 开始批量绘图
	int i,j;
	targetNum = 0; // 目标个数,初始为0
	// 对二维数组遍历
	for (i=0;i<B_NUM;i++)
		for (j=0;j<B_NUM;j++)
		
			if (level[i][j]==role) // 找到地图中player位置
			
				player.i = i; // 设定player位置
				player.j = j; // 
				level[i][j]=empty; // 把地图元素变成空白empty
			
			else if (level[i][j]==target || level[i][j]==achieved ) // 如果元素是target或achieved
				targetNum++; // 目标个数+1
		


void show() // 绘制函数

	int i,j;
	cleardevice(); // 以背景颜色清空屏幕
	// 遍历关卡二维数组数据
	for (i=0;i<B_NUM;i++)
	
		for (j=0;j<B_NUM;j++)
		
			if (level[i][j]==empty) // empty 元素是空白区域
			
				setfillcolor(RGB(150,150,150)); // 绘制灰色地面
				setlinecolor(RGB(150,150,150));
				fillrectangle(j*B_SIZE,i*B_SIZE,(j+1)*B_SIZE,(i+1)*B_SIZE);
			
			else if (level[i][j]==wall)  // wall 元素是墙
			
				setfillcolor(RGB(155,0,0));
				setlinecolor(RGB(150,150,150)); // 绘制淡红色、灰色线的方框
				fillrectangle(j*B_SIZE,i*B_SIZE,(j+1)*B_SIZE,(i+1)*B_SIZE);
			
			else if (level[i][j]==box) // box 元素是可移动的箱子
			
				setfillcolor(RGB(255,255,0)); // 绘制一个黄色的方块
				setlinecolor(RGB(150,150,150));
				fillrectangle(j*B_SIZE,i*B_SIZE,(j+1)*B_SIZE,(i+1)*B_SIZE);
			
			else if (level[i][j]==target) // target 元素是目标
			
				setfillcolor(RGB(250,250,250)); // 绘制一个白色的小方块
				fillrectangle((j+0.3)*B_SIZE,(i+0.3)*B_SIZE,
					(j+0.7)*B_SIZE,(i+0.7)*B_SIZE);
			
			else if (level[i][j]==achieved) // achieved 元素是已完成目标
			
				setlinecolor(RGB(150,150,150));
				setfillcolor(RGB(255,255,0)); // 绘制一个黄色的方块
				fillrectangle(j*B_SIZE,i*B_SIZE,(j+1)*B_SIZE,(i+1)*B_SIZE);
				setfillcolor(RGB(250,250,250)); // 绘制一个白色的小方块
				fillrectangle((j+0.3)*B_SIZE,(i+0.3)*B_SIZE,
					(j+0.7)*B_SIZE,(i+0.7)*B_SIZE);
					
		
	
	// 以下绘制玩家,绘制一个人脸图案
	i = player.i; 
	j = player.j;
	setfillcolor(RGB(255,0,0));
	fillcircle((j+0.5)*B_SIZE,(i+0.5)*B_SIZE,0.4*B_SIZE);//一个红色圆脸
	setfillcolor(RGB(80,80,80));
	setlinecolor(RGB(80,80,80));
	fillcircle((j+0.3)*B_SIZE,(i+0.45)*B_SIZE,0.08*B_SIZE);//两个黑色眼睛
	fillcircle((j+0.7)*B_SIZE,(i+0.45)*B_SIZE,0.08*B_SIZE); 
	setlinestyle(PS_SOLID,3);
	line((j+0.35)*B_SIZE,(i+0.7)*B_SIZE,(j+0.65)*B_SIZE,(i+0.7)*B_SIZE);//深灰色嘴巴
	setlinestyle(PS_SOLID,1);

	if (achievedNum==targetNum) // 如完成目标个数==目标个数
	
		setbkmode(TRANSPARENT); // 透明显示文字
		settextcolor(RGB(0,255,255)); // 设置字体颜色
		settextstyle(80, 0, _T("宋体")); // 设置字体大小、样式
		outtextxy(80,200,_T("游戏胜利")); // 显示游戏胜利文字
	
	FlushBatchDraw(); // 开始批量绘制


void update()  // 每帧更新运行

	if(kbhit() && (achievedNum<targetNum) )  // 如果按键,并且游戏没有胜利
	
		char input = getch(); // 获取按键
		if (input=='a' || input=='s' || input=='d' || input=='w') // 如果是有效按键
		
			int goal_i = player.i; // 移动的目标位置
			int goal_j = player.j;
			int goalNext_i = goal_i; // 目标位置再向前的一个位置
			int goalNext_j = goal_j;
			// 根据用户的不同按键输入,获得目标位置、再向前的一个位置
			if (input=='a') // 向左
			
				goal_j = player.j -1 ; // 目标位置在玩家位置的左边
				goalNext_j = goal_j-1; // 目标的下一个位置,在其再左边
			
			else if (input=='d') // 向右
			
				goal_j = player.j +1 ; // 目标位置在玩家位置的右边 
				goalNext_j = goal_j+1; // 目标的下一个位置,在其再右边
			
			else if (input=='s') // 向下
			
				goal_i = player.i+1; // 目标位置在玩家位置的下边 
				goalNext_i = goal_i+1; // 目标的下一个位置,在其再下边 
			
			else if (input=='w') // 向上
			
				goal_i = player.i-1; // 目标位置在玩家位置的上边 
				goalNext_i = goal_i-1; // 目标的下一个位置,在其再上边 
			

			// 根据不同地图元素的情况,判断如何移动角色和更新地图元素	
			if (level[goal_i][goal_j]==empty || level[goal_i][goal_j]==target ) 
				// 如果目标位置是empty,或者target
				player.i = goal_i; // 玩家移动到目标位置
				player.j = goal_j;  			
			
			else if (level[goal_i][goal_j]==box && level[goalNext_i][goalNext_j]==empty ) 
				// 如果目标位置是box,再前面一个是empty
				player.i = goal_i; // 玩家移动到目标位置
				player.j = goal_j;	  
				level[goal_i][goal_j]=empty;  // 目标位置变成empty
				level[goalNext_i][goalNext_j]=box;	 // 再前面变成box
			
			else if (level[goal_i][goal_j]==box && level[goalNext_i][goalNext_j]==target) 
				// 如果目标位置是box,再前面一个是target
				player.i = goal_i; // 玩家移动到目标位置
				player.j = goal_j;	
				level[goal_i][goal_j] = empty;  // 目标位置变成empty 
				level[goalNext_i][goalNext_j] = achieved;	// 再前面变成achieved
			
			else if (level[goal_i][goal_j]==achieved && level[goalNext_i][goalNext_j]== empty) 
				// 如果目标位置是achieved,再前面一个是empty
				player.i = goal_i; // 玩家移动到目标位置
				player.j = goal_j;  	
				level[goal_i][goal_j] = target;  // 目标位置变成target 
				level[goalNext_i][goalNext_j] = box; // 再前面变成box 	
			
			else if (level[goal_i][goal_j]==achieved && level[goalNext_i][goalNext_j]== target) 
				// 如果目标位置是achieved,再前面一个是target
				player.i = goal_i; // 玩家移动到目标位置
				player.j = goal_j;
				level[goal_i][goal_j] = target;  // 目标位置变成target  
				level[goalNext_i][goalNext_j] = achieved; // 再前面变成achieved  	
			
			else // 其他情况都推不动
				return; // 不做任何处理,函数直接返回
		
		achievedNum = 0; // 完成目标个数,初始为0
		int i,j;
		for (i=0;i<B_NUM;i++) // 对二维数组遍历
			for (j=0;j<B_NUM;j++) // 
				if (level[i][j]==achieved) // 如果元素是achieved
					achievedNum++; // 完成目标个数+1
	


int main() // 主函数

	startup();  // 初始化	
	while (1)  // 游戏主循环
	
		show();		// 绘制
		update();   // 更新
	
	return 0;

主要讲解了字符串与字符数组、文件读写、枚举类型等语法知识,实现了推箱子游戏。读者可以尝试在本章代码基础上继续改进:

1、实现多关卡的选择界面;

2、实现某一步移动的撤销功能(类似于下棋游戏中的悔棋功能);

3、实现按'h'键后进行提示,播放正确步骤动画的功能;

4、实现一个图形编辑器,并将设计的关卡信息保存为txt文件。

作者:童晶

希望对大家有帮助!

此外,我也给大家分享我收集的其他资源,从最零基础开始的教程到C语言C++项目案例,帮助大家在学习C语言的道路上披荆斩棘!

整理分享(多年学习的源码、项目实战视频、项目笔记,基础入门教程)最重要的是你可以在群里面交流提问编程问题哦!

欢迎转行和学习编程的伙伴,利用更多的资料学习成长比自己琢磨更快哦!(↓↓↓↓↓↓)

以上是关于C语言实现推箱子游戏!(超简单详细)代码思路+源码分享的主要内容,如果未能解决你的问题,请参考以下文章

C语言零基础项目:推箱子游戏,详细思路+源码分享

C语言十字消除游戏(超简单详细),详细思路+源码分享

C语言作业:如何实现多关卡推箱子?详细思路分析(有源码)

C语言实现小游戏篇我接触的第一款电脑游戏,你可以永远相信 “ 扫雷 ” 。[ C语言实现 ] [ 超详细,超清楚 ] [ 有代码 ]

程序员带你回味童年,一起用C语言做一个“推箱子”玩!文末源码

程序员带你回味童年,一起用C语言做一个“推箱子”玩!文末源码