C语言实现——推箱子(文章后面附件全代码)

本文作者分享了其作为初学者独立完成游戏开发的经历,从初始化定义地图,到主函数的控制逻辑,详细介绍了如何使用C语言实现虫子的移动判断,包括加载图片、地图绘制和键盘输入响应。通过实例展示了寻路判断的复杂性和多线程控制的重要性。
摘要由CSDN通过智能技术生成

这是我发布的第一篇文章,对我来说是非常有意义的,这也是对我一个初学者能独立自主的完成一件事情的肯定。因为这个游戏是我根据自己的想法独立实现的,加上水平有限,可能存在不足之处,希望大家能谅解。

闲话不多说,就开始入正题吧。

目录

1.初始化定义

2.主函数

3.加载函数

 4.画地图

 4.控制判断

完整代码:


1.初始化定义

开始我们先要初始化定义,定义地图,我们定义一个二维数组,用来保存游戏的初始信息,这里的大小,大家可以根据自己设计的地图可以改变,数组里面的数据与紧接着定义的几个变量相关,注释我已经写得很清楚,下面定义的几个必须都是全局变量。

2.主函数

主函数中调用“加载函数”放在循环函数外面,加载一次就行

3.加载函数

加载虫子时,我设置了循环,为了简单,(你也可以把每个图片的地址以键入的形式加载)因为虫子有上下左右第四个运动方向,对应四张素材照片,大家学了C语言,对printf非常熟悉,那图片中的sprintf又是什么鬼呢,通俗的来说printf是输出让人看的,而sprintf是让电脑(控制台)看的,我们之前定义的字符数组people_name就是暂时保存图片的地址,最终地址是放在people图片数组中的我们再导入图片地址的是时候,一定要注意我们存放素材地址的位置,如果你把图片存放在和.cpp同一级,就直接输入图片名.后缀。这里素材文件和.c或者.cpp在同一级(c++中可以运行),图片最好和程序源文件放在一起,这样导入的是相对路径,易程序于打包。加载图片时,就可以设置宽和高。

 4.画地图

因为我定义数组行和列都为8,建立循环,其中嵌入switch(),访问数组中的数据,判断然后打印相应的图片,打印虫子后就要记录虫子开始的数组坐标位置,我们要时刻知道虫子的坐标位置,这里虫子的位置是关键。case3和case7都打印箱子,但是代表的含义不一样,在最开始我定义变量后面的注释时就说明了。

 4.控制判断

1.这只列出当你按出“上”键情况的判断,其他三个方向与其非常相似,只不过是数组坐标的变化的不同,说道数组坐标,我就要强调以下,数组坐标的行和列,和win窗口的x,y坐标不同,win窗口左上角为xy(0,0)位置,向右移动是x的增加,向下移动是y的增加,而数组的行和列我想大家都熟悉,因为我在初始化虫子的坐标时,是将x=i,y=j;所以大家不要被win窗口的x,y误导了,这里的x,y就是表示行和列,之所以说就是我当时犯过这个错误,按win窗口的x,y写,导致按“上”键,他给我向左移动,当时就是忽略这个问题,错误找不到,为了调试好走捷径把函数相互调换了,解决了问题但是逻辑上说不动,(我说这个,这可能是我们经常犯的错误,短的代码就不说,长一点的找问题能把人找疯,因为这错误电脑检测不出,不怕犯大错误就怕犯小错误,就怕忽略,所以说我们写代码的就必须严谨,提前把所有情况尽可能的考虑完全,这样就能为我们省下不少功夫)

2.这个控制函数,是受外部影响的,这里我们是键入的指令,不输入就不执行,我说这个有些人可能不太理解,因为这个游戏我们不控制是静止的,放在运动的场景,如果我们没有多线程的概念,你写出来的游戏,按逻辑来说你不控住,他也是运动的,(你的指令,只不过是控制他的方向和有些动作)结果他不动,就是以为你写得语句阻碍了人物的正常动作,这是人物初始化就有的,举个例子,我们人出生就是会呼吸,(废话)你不能干一件事阻碍你的呼吸,多线程就可以实现互不干扰的问题,(由于了解有限这只不过是一种方法),这个—kbhit()就能解决这个问题,你不键入指令它是不会执行以下语句的,不会干扰其他程序的正常执行。

—getch()和scanf的区别是scanf需要按回车键才能执行命令

现在就到了游戏的的核心,我称之为寻路判断,我们要把所有情况的考虑完,不然就会出现bug,

我就遇到过,不是虫把墙吃了,就是把箱子要覆盖的东西吃了,要么就是遇到(箱子+东西)推不动。开始了

刚开始有个大前提,因为是一运动的虫子或者人(看你加什么素材)为中心的,我们先判断,        人所在的坐标位置是人还是(人+障碍)(这个不考虑清楚有可能你经过障碍物后他就没了,不       信,代码见分晓)

只分析一点,和下面的代码对照着看。代码也有注释

1.现在位置只是人,

   1.1判断要移动的位置为空地:当前位置打印空地,要移动的位置打印人,x--控制人物移动

        (如果大前提下是人+障碍物,当前位置打印障碍物,要移动的位置打印人)

   1.2要移动的位置为箱子:

           1.2.1如果要移动到的位置的下一位置为空地---现在位置打印空地,要移动            的位置打                     印人,下一个位置打印箱子(人视角上就能显现推箱子的动作)

             1.2.2  如果要移动到的位置的下一个位置为障碍---现在位置打印空地,移动 的位置打印                            人,下一个为只打印(箱子+障碍)(视觉上只是箱子其实就 是打印箱,为的是                             区别以后的判断)

     。。。。。。。。。。。。。。。。。。

     这些都判断完成,后dir=0;(方向)朝上,break;结束Switch();

               觉得大家都能看懂就不做过多解释

int n;
	if (_kbhit()){
		n = _getch();
		switch (n){
		case 72:
			if (map[x][y] != 9){//现在位置不是为人+障碍
				if (map[x - 1][y] == 1){  //为空地
					map[x][y] = 1;
					map[x - 1][y] = 5;
					x--;
				}
				else if (map[x - 1][y] == 3){//移动方向为箱子
					if (map[x - 2][y] == 1){  //移动方向的下下一个为空地
						map[x][y] = 1;
						map[x - 1][y] = 5;
						map[x - 2][y] = 3;
						x--;
					}
					else if (map[x - 2][y] == 4){//移动方向的下下一个为障碍
						map[x][y] = 1;
						map[x - 1][y] = 5;
						map[x - 2][y] = 7;
						x--;
					}

				}
				else if (map[x - 1][y] == 4){//移动的方向为障碍
					map[x][y] = 1;
					map[x - 1][y] = 9;
					x--;
				}
				else if (map[x - 1][y] == 7){//移动方向为箱子+障碍
					if (map[x - 2][y] != 3 && map[x - 2][y] != 7 && map[x - 2][y] != 2){
						if (map[x - 2][y] == 4){//下下位置为障碍
							map[x][y] = 1;
							map[x - 1][y] = 9;
							map[x - 2][y] = 7;
							x--;
						}
						else{  //则为空地
							map[x][y] = 1;
							map[x - 1][y] = 9;
							map[x - 2][y] = 3;
							x--;
						}
					}


				}
			}           //现在位置是为人+障碍
			else{
				if (map[x - 1][y] == 1){  //为空地
					map[x][y] = 4;
					map[x - 1][y] = 5;
					x--;
				}
				else if (map[x - 1][y] == 3){//移动方向为箱子
					if (map[x - 2][y] == 1){  //移动方向的下下一个为空地
						map[x][y] = 4;
						map[x - 1][y] = 5;
						map[x - 2][y] = 3;
						x--;
					}
					else if(map[x - 2][y] == 4){//移动方向的下下一个为障碍
						map[x][y] = 4;
						map[x - 1][y] = 5;
						map[x - 2][y] = 7;
						x--;
					}
					

				}
				else if (map[x - 1][y] == 4){//移动的方向为障碍
					map[x][y] = 4;
					map[x - 1][y] = 9;
					x--;
				}
				else if (map[x-1][y ] == 7){//移动方向为箱子+障碍
					
						if (map[x - 2][y] == 4){//下下位置为障碍
							map[x][y] = 4;
							map[x - 1][y] = 9;
							map[x - 2][y] = 7;
							x--;
						}
						else if(map[x-2][y]==1 ){            //下下位置为空地
							map[x][y] = 4;
							map[x - 1][y] = 9;
							map[x - 2][y] = 3;
							x--;
						}
						else;
					}
         }
			dir = 0;
			break;

完整代码:

#include<stdio.h>
#include<graphics.h>
#include<conio.h>

#define window_width 400
#define window_height 400
#define tu_width 50
#define tu_height 50
void init_map();
void init_jz();
void cont();
int decide();

int map[window_width / tu_width][window_height / tu_height] = {
	2, 2, 2, 2, 2, 2, 2, 2,
	2, 1, 1, 2, 1, 1, 1, 2,
	2, 1, 3, 4, 4, 3, 1, 2,
	2, 5, 3, 4, 7, 1, 2, 2,
	2, 1, 3, 4, 4, 3, 1, 2,
	2, 1, 1, 2, 1, 1, 1, 2,
	2, 1, 1, 1, 1, 1, 2, 2,
	2, 2, 2, 2, 2, 2, 2, 2
};
IMAGE wall, people[4], box, area, barrier;//空地=1 墙=2 箱子=3 障碍=4 人=5  人+障碍=9  箱子+障碍=7
char people_name[MAX_PATH];  //定义字符数组  为了保存素材图片的地址
int dir = 0; //初始化定义虫子的方向 默认为向上
int x, y;//记录虫子的坐标位置
int main(){
	initgraph(window_width, window_height); //创建一个窗口,参数宽,高
	init_jz();//加载

	while (1){
		init_map();//画图
		cont();//控制


	}
	closegraph();//关闭
	return 0;
}
//加载
void init_jz(){
	for (int i = 0; i < 4; i++){
		sprintf(people_name, "素材\\people\\people%d.png", i + 1);
		loadimage(&people[i], people_name, tu_width, tu_height, true);
	}
	loadimage(&wall, "素材\\wall.png", tu_width, tu_height, true);
	loadimage(&box, "素材\\box.png", tu_width, tu_height, true);
	loadimage(&area, "素材\\area.png", tu_width, tu_height, true);
	loadimage(&barrier, "素材\\barrier.png", tu_width, tu_height, true);
}
//画地图
void init_map(){
	for (int i = 0; i < 8; i++)
	for (int j = 0; j < 8; j++)
	{

		switch (map[i][j]){
		case 1:putimage(j*tu_width, i*tu_height, &area);
			break;
		case 2:putimage(j*tu_width, i*tu_height, &wall);
			break;
		case 3:putimage(j*tu_width, i*tu_height, &box);
			break;
		case 4:putimage(j*tu_width, i*tu_height, &barrier);
			break;
		case 5:
			putimage(j*tu_width, i*tu_height, &people[dir]);
			x = i; y = j;
			break;
		case 7:putimage(j*tu_width, i*tu_height, &box);
			break;
		case 9:putimage(j*tu_width, i*tu_height, &people[dir]);
			break;

		}
	}
}

void cont(){
	int n;
	if (_kbhit()){
		n = _getch();
		switch (n){
		case 72:
			if (map[x][y] != 9){//现在位置不是为人+障碍
				if (map[x - 1][y] == 1){  //为空地
					map[x][y] = 1;
					map[x - 1][y] = 5;
					x--;
				}
				else if (map[x - 1][y] == 3){//移动方向为箱子
					if (map[x - 2][y] == 1){  //移动方向的下下一个为空地
						map[x][y] = 1;
						map[x - 1][y] = 5;
						map[x - 2][y] = 3;
						x--;
					}
					else if (map[x - 2][y] == 4){//移动方向的下下一个为障碍
						map[x][y] = 1;
						map[x - 1][y] = 5;
						map[x - 2][y] = 7;
						x--;
					}

				}
				else if (map[x - 1][y] == 4){//移动的方向为障碍
					map[x][y] = 1;
					map[x - 1][y] = 9;
					x--;
				}
				else if (map[x - 1][y] == 7){//移动方向为箱子+障碍
					if (map[x - 2][y] != 3 && map[x - 2][y] != 7 && map[x - 2][y] != 2){
						if (map[x - 2][y] == 4){//下下位置为障碍
							map[x][y] = 1;
							map[x - 1][y] = 9;
							map[x - 2][y] = 7;
							x--;
						}
						else{  //则为空地
							map[x][y] = 1;
							map[x - 1][y] = 9;
							map[x - 2][y] = 3;
							x--;
						}
					}


				}
			}           //现在位置是为人+障碍
			else{
				if (map[x - 1][y] == 1){  //为空地
					map[x][y] = 4;
					map[x - 1][y] = 5;
					x--;
				}
				else if (map[x - 1][y] == 3){//移动方向为箱子
					if (map[x - 2][y] == 1){  //移动方向的下下一个为空地
						map[x][y] = 4;
						map[x - 1][y] = 5;
						map[x - 2][y] = 3;
						x--;
					}
					else if(map[x - 2][y] == 4){//移动方向的下下一个为障碍
						map[x][y] = 4;
						map[x - 1][y] = 5;
						map[x - 2][y] = 7;
						x--;
					}
					

				}
				else if (map[x - 1][y] == 4){//移动的方向为障碍
					map[x][y] = 4;
					map[x - 1][y] = 9;
					x--;
				}
				else if (map[x-1][y ] == 7){//移动方向为箱子+障碍
					
						if (map[x - 2][y] == 4){//下下位置为障碍
							map[x][y] = 4;
							map[x - 1][y] = 9;
							map[x - 2][y] = 7;
							x--;
						}
						else if(map[x-2][y]==1 ){            //下下位置为空地
							map[x][y] = 4;
							map[x - 1][y] = 9;
							map[x - 2][y] = 3;
							x--;
						}
						else;
					}
         }
			dir = 0;
			break;
		case 80: if (map[x][y] != 9){//现在位置不是为人+障碍
					 if (map[x + 1][y] == 1){  //为空地
						 map[x][y] = 1;
						 map[x + 1][y] = 5;
						 x++;
					 }
					 else if (map[x + 1][y] == 3){//移动方向为箱子
						 if (map[x + 2][y] == 1){  //移动方向的下下一个为空地
							 map[x][y] = 1;
							 map[x + 1][y] = 5;
							 map[x + 2][y] = 3;
							 x++;
						 }
						 else if (map[x + 2][y] == 4){//移动方向的下下一个为障碍
							 map[x][y] = 1;
							 map[x + 1][y] = 5;
							 map[x + 2][y] = 7;
							 x++;
						 }

					 }
					 else if (map[x + 1][y] == 4){//移动的方向为障碍
						 map[x][y] = 1;
						 map[x + 1][y] = 9;
						 x++;
					 }
					 else if (map[x + 1][y] == 7){//移动方向为箱子+障碍
						 
							 if (map[x + 2][y] == 4){//下下位置为障碍
								 map[x][y] = 1;
								 map[x + 1][y] = 9;
								 map[x + 2][y] = 7;
								 x++;
							 }
							 else if(map[x+2][y]==1){  //为空地
								 map[x][y] = 1;
								 map[x + 1][y] = 9;
								 map[x + 2][y] = 3;
								 x++;
							 }
							 else;
						 }
                     }       
				                     //现在位置是为人+障碍
				 else{
					 if (map[x + 1][y] == 1){  //为空地
						 map[x][y] = 4;
						 map[x + 1][y] = 5;
						 x++;
					 }
					 else if (map[x + 1][y] == 3){//移动方向为箱子
						 if (map[x + 2][y] == 1){  //移动方向的下下一个为空地
							 map[x][y] = 4;
							 map[x + 1][y] = 5;
							 map[x + 2][y] = 3;
							 x++;
						 }
						 else if (map[x + 2][y] == 4){//移动方向的下下一个为障碍
							 map[x][y] = 4;
							 map[x + 1][y] = 5;
							 map[x + 2][y] = 7;
							 x++;
						 }

					 }
					 else if (map[x + 1][y] == 4){//移动的方向为障碍
						 map[x][y] = 4;
						 map[x + 1][y] = 9;
						 x++;
					 }
					 else if (map[x+1][y] == 7){//移动方向为箱子+障碍
						 if (map[x + 2][y] != 3 && map[x + 2][y] != 7 && map[x + 2][y] != 2){
							 if (map[x + 2][y] == 4){//下下位置为障碍
								 map[x][y] = 4;
								 map[x + 1][y] = 9;
								 map[x + 2][y] = 7;
								 x++;
							 }
							 else{            //则下下位置为空地
								 map[x][y] = 4;
								 map[x + 1][y] = 9;
								 map[x + 2][y] = 3;
								 x++;
							 }
						 }


					 }

				 }


				 dir = 1;

				 break;
		case 75:
			if (map[x][y] != 9){//现在位置不是为人+障碍
				if (map[x][y - 1] == 1){  //为空地
					map[x][y] = 1;
					map[x][y - 1] = 5;
					y--;
				}
				else if (map[x][y - 1] == 3){//移动方向为箱子
					if (map[x][y - 2] == 1){  //移动方向的下下一个为空地
						map[x][y] = 1;
						map[x][y - 1] = 5;
						map[x][y - 2] = 3;
						y--;
					}
					else if (map[x][y - 2] == 4){//移动方向的下下一个为障碍
						map[x][y] = 1;
						map[x][y - 1] = 5;
						map[x][y - 2] = 7;
						y--;
					}

				}
				else if (map[x][y - 1] == 4){//移动的方向为障碍
					map[x][y] = 1;
					map[x][y - 1] = 9;
					y--;
				}
				else if (map[x][y - 1] == 7){//移动方向为箱子+障碍
					if (map[x][y - 2] != 3 && map[x][y - 2] != 7 && map[x][y - 2] != 2){
						if (map[x][y - 2] == 4){//下下位置为障碍
							map[x][y] = 1;
							map[x][y - 1] = 9;
							map[x][y - 2] = 7;
							y--;
						}
						else{  //则为空地
							map[x][y] = 1;
							map[x][y - 1] = 9;
							map[x][y - 2] = 3;
							y--;
						}
					}


				}
			}           //现在位置是为人+障碍
			else{
				if (map[x][y - 1] == 1){  //为空地
					map[x][y] = 4;
					map[x][y - 1] = 5;
					y--;
				}
				else if (map[x][y - 1] == 3){//移动方向为箱子
					if (map[x][y - 2] == 1){  //移动方向的下下一个为空地
						map[x][y] = 4;
						map[x][y - 1] = 5;
						map[x][y - 2] = 3;
						y--;
					}
					else if (map[x][y - 2] == 4){//移动方向的下下一个为障碍
						map[x][y] = 4;
						map[x][y - 1] = 5;
						map[x][y - 2] = 7;
						y--;
					}

				}
				else if (map[x][y - 1] == 4){//移动的方向为障碍
					map[x][y] = 4;
					map[x][y - 1] = 9;
					y--;
				}
				else if (map[x][y - 1] == 7){//移动方向为箱子+障碍
					
						if (map[x][y - 2] == 4){//下下位置为障碍
							map[x][y] = 4;
							map[x][y - 1] = 9;
							map[x][y - 2] = 7;
							y--;
						}
						else if(map[x][y-2]==1){            //下下位置为空地
							map[x][y] = 4;
							map[x][y - 1] = 9;
							map[x][y - 2] = 3;
							y--;
						}
						else;
					}
				

			}

			dir = 2;
			break;
		case 77:
			if (map[x][y] != 9){//现在位置不是为人+障碍
				if (map[x][y + 1] == 1){  //为空地
					map[x][y] = 1;
					map[x][y + 1] = 5;
					y++;
				}
				else if (map[x][y + 1] == 3){//移动方向为箱子
					if (map[x][y + 2] == 1){  //移动方向的下下一个为空地
						map[x][y] = 1;
						map[x][y + 1] = 5;
						map[x][y + 2] = 3;
						y++;
					}
					else if (map[x][y + 2] == 4){//移动方向的下下一个为障碍
						map[x][y] = 1;
						map[x][y + 1] = 5;
						map[x][y + 2] = 7;
						y++;
					}

				}
				else if (map[x][y + 1] == 4){//移动的方向为障碍
					map[x][y] = 1;
					map[x][y + 1] = 9;
					y++;
				}
				else if (map[x][y + 1] == 7){//移动方向为箱子+障碍
					if (map[x][y + 2] != 3 && map[x][y + 2] != 7 && map[x][y + 2] != 2){
						if (map[x][y + 2] == 4){//下下位置为障碍
							map[x][y] = 1;
							map[x][y + 1] = 9;
							map[x][y + 2] = 7;
							y++;
						}
						else{  //则为空地
							map[x][y] = 1;
							map[x][y + 1] = 9;
							map[x][y + 2] = 3;
							y++;
						}
					}


				}
			}           //现在位置是为人+障碍
			else{
				if (map[x][y + 1] == 1){  //为空地
					map[x][y] = 4;
					map[x][y + 1] = 5;
					y++;
				}
				else if (map[x][y + 1] == 3){//移动方向为箱子
					if (map[x][y + 2] == 1){  //移动方向的下下一个为空地
						map[x][y] = 4;
						map[x][y + 1] = 5;
						map[x][y + 2] = 3;
						y++;
					}
					else if (map[x][y + 2] == 4){//移动方向的下下一个为障碍
						map[x][y] = 4;
						map[x][y + 1] = 5;
						map[x][y + 2] = 7;
						y++;
					}

				}
				else if (map[x][y + 1] == 4){//移动的方向为障碍
					map[x][y] = 4;
					map[x][y + 1] = 9;
					y++;
				}
				else if (map[x][y + 1] == 7){//移动方向为箱子+障碍
					
						if (map[x][y + 2] == 4){//下下位置为障碍
							map[x][y] = 4;
							map[x][y + 1] = 9;
							map[x][y + 2] = 7;
							y++;
						}
						else if(map[x][y+2]==1){            //则下下位置为空地
							map[x][y] = 4;
							map[x][y + 1] = 9;
							map[x][y + 2] = 3;
							y++;
						}
						else;
					}


				

			}
			dir = 3;
			break;
		}
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Attention__

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

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

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

打赏作者

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

抵扣说明:

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

余额充值