c++可视化推箱子小游戏(EasyX图形库)

游戏实现步骤:数组勾画地图–控制人物移动–人物移动推动箱子移动。

数组勾画地图:

int map[20][10][10];//设置10*10的地图,设置20关
int mubiao[20][5][2];//用一个三维数组记录目的地的坐标
int iftab=0;//在游戏中利用这个变量记录是否重置关卡
int guan;
int makeitback=0;//为人站在空位和目的地上进入目的地作不同的移动
IMAGE img[5];
IMAGE zhuyebj, guanqiabj;
void setmapdate()//地图数据放在txz_map_in.txt,先输入数据
{
	 freopen("D:\\cpp\\终极推箱子\\Debug\\txz_map_in.txt", "r", stdin);//打开文件
	 for (int i = 0; i < 20; i++)//20关
	 {
		  for (int j = 0; j < 10; j++)//纵向
	 	 {
			   for (int k = 0; k < 10; k++)//横向
			   {
				    cin >> map[i][j][k];//输入每个数据
				    if (map[i][j][k] == 6 && iftab==0)//其中6就是目的地,将目的地的坐标记录入mubiao数组
				    {
					     for (int L = 0; L < 5; L++)
					     {
					    	  if (mubiao[i][L][0] == 0 && mubiao[i][L][1] == 0)//找到数组中空的位置
					    	  {
						       mubiao[i][L][0] = k;
						       mubiao[i][L][1] = j;
					    	       break;
					           }
					     }
				    }
			   }
		  }
	 }
	 loadimage(img + 0, _T("D:\\cpp\\终极推箱子\\Debug\\image\\1.jpg"));//加载若干图片
	 loadimage(img + 1, _T("D:\\cpp\\终极推箱子\\Debug\\image\\3.jpg"));
	 loadimage(img + 2, _T("D:\\cpp\\终极推箱子\\Debug\\image\\5.jpg"));
	 loadimage(img + 3, _T("D:\\cpp\\终极推箱子\\Debug\\image\\6.jpg"));
	 loadimage(img + 4, _T("D:\\cpp\\终极推箱子\\Debug\\image\\背景.jpg"), 640, 640);
	 loadimage(&zhuyebj, _T("D:\\cpp\\终极推箱子\\Debug\\image\\主页背景.jpg"), 640, 640);
	 loadimage(&guanqiabj, _T("D:\\cpp\\终极推箱子\\Debug\\image\\关卡背景.png"), 640, 640);
	 fclose(stdin);//关闭文件
}

void mapcreate()//开始绘画地图
{
	 putimage(0, 0, &img[4]);//输出背景图片
	 for (int i = 0; i < 10; i++)
	 {
		  int x, y;
		  for (int j = 0; j < 10; j++)
		  {
		  	 x = 64 * j;//64是图片大小
		   	 y = 64 * i;
		  	 switch (map[guan][i][j])
	  		 {
				   case 1: {putimage(x, y, &img[0]);
				    break; } //墙
				   case 0: {
				    cout << "  ";  break; }//空位
				   case 5: {putimage(x + 16, y, &img[2]);
				    break; }//人
				   case 3: { putimage(x, y, &img[1]);
				    break; }//箱子
				   case 6: { putimage(x + 16, y + 16, &img[3]);
				    break; }//箱子目标位置
			  }
			 if (map[guan][i][j] == 5)//获取人物初始位置
			   {
				    nowmany = i;
				    nowmanx = j;
			   }
		  }
	 }
}

人物移动:

int makieback2=0;//为箱子站在空位和目的地上进入目的地作不同的移动
void manmove(char a, int& x, int& y)
{
	 int temp;
	 if (total_mubiao == 3)
	  makeitback = 0;
	 switch (a)
	 {
	 case 'w':
	 {
	  if (map[guan][y - 1][x] != 1)//当人移动前方不是墙时,直接交换位置
	  { 
	   	   if (map[guan][y - 2][x] != 1 && map[guan][y - 1][x] == 3)//当人移动前方是箱子且箱子前不是墙时,让箱子移动
		    {
			    nowboxx = x;
			    nowboxy = y - 1;
			    boxmove(a, nowboxx, nowboxy);//箱子移动
		    }
		   if (map[guan][y - 1][x] == 0 || map[guan][y - 1][x] == 6)当是空位或者是目的地的时
	   	   {
			    if (map[guan][y - 1][x] != 6 && makeitback == 0)//当是空位时,直接交换数组两个元素位置
			    {
				     temp = map[guan][y][x];
				     map[guan][y][x] = map[guan][y - 1][x];
				     map[guan][y - 1][x] = temp;
			     }  
			    else // 当是目的地时
			     {
			     	      if (makeitback == 0)//原本人站的地方不是目的地时
				      {
					       map[guan][y][x] = 0;
					       map[guan][y - 1][x] = 5;
					       makeitback = 1;
					       total_mubiao--;
			      	      }
				      else//原本人站的地方时目的地时
				       {
					         if (map[guan][y - 1][x] != 6)//作判断
					         	total_mubiao++;
					         map[guan][y][x] = 6;
					         map[guan][y - 1][x] = 5;
			  	       }
			     }
		    }
	  }
	 break;
	 }//其他方向移动

**箱子移动:**原理同人物移动

void boxmove(char a, int& x, int& y)
{
	 int temp;
	 if (!ifthesame(x, y)) //推的箱子不是在目的地上
	 {
	 	 makeitback2 = 0;
	 }
	 else//推的箱子在目的地上
	 {
	 	 makeitback2 = 1;
	 }
	 switch (a)
	 {
	 case 'w':
	 {
	  if (map[guan][y - 1][x] == 3)//箱子前时箱子时,直接返回
	  	 return;
	  if (map[guan][y - 1][x] != 6 && makeitback2==0 )//箱子前不是目的地时,直接交换数组两元素的位置
	  {
		   temp = map[guan][y][x];
		   map[guan][y][x] = map[guan][y - 1][x];
		   map[guan][y - 1][x] = temp;
		   total_mubiao2--;
	  }
	  else
	  {
		   if (makeitback2 == 0)//当箱子站在空位上时
		   {
			    map[guan][y][x] = 0;
			    map[guan][y - 1][x] = 3;
			    makeitback2 = 1;
			    total_mubiao2--;
		  }
		 else//当箱子站在目的地上时
		   {
			    map[guan][y][x] = 6;
			    map[guan][y - 1][x] = 3;
			    total_mubiao2 = 3;
			    makeitback2 = 0;
		   }
	  }
	  break;
	 }//其他方向同上
	```
	**获取人物的位置:**
	
	```
	int getmanx()//得到人物的x坐标
{
  for (int i = 0; i < 10; i++)
  {
     for (int j = 0; j < 10; j++)
     {
          if (map[guan][i][j] == 5)
          {
                nowmanx = j;
          }
     }
 }
 return nowmanx;
}

int getmany()
{
   for (int i = 0; i < 10; i++)
   {
         for (int j = 0; j < 10; j++)
         {
      		if (map[guan][i][j] == 5)
   		{
    			nowmany = i;
  		 }
 	 }
     }
 return nowmany;
}

bool ifthesame(int x, int y)//判断箱子是否站在目的地上
{
 	for (int i = 0; i < 5; i++)
	 {
  		 if (mubiao[guan][i][0] == x && mubiao[guan][i][1] == y)
 			  return 1;
	}
return 0;
}

判断胜利的函数:

void win()
{
 int countmb = 0, totalmb = 0;//countmb是人物完成了几个目的地,totalmb是总共有几个目的地
 if (guan < 10)//1-10关设置了2个目的地
 {
  	totalmb = 2;
 }
 else//11-20关设置3个目的地
 {
  	if (guan < 20)
   		totalmb = 3;
 }
  for (int i = 0; i < 5; i++)
 {
 	 if (map[guan][mubiao[guan][i][1]][mubiao[guan][i][0]] == 3)//当目的地的坐标上的时箱子时
  		 countmb++;
 }
 if (countmb == totalmb)//当人物完成了总的目的地时
 {
  	settextstyle(32, 0, 0);//设置字体的大小
  	outtextxy(150, 320, _T("通过此关,进入下一关请按Enter"));//输出文字
  	if (_getch() == 13)//当玩家按下enter。
  	{
   		guan++; jguan++;
 	 }
}
}

制作游戏界面:

主界面:
bool a;//退出鼠标循环事件
void mainsite()
{
	 guan = 0;//回到主界面重置关卡
	 cleardevice();//清屏
	 putimage(0, 0, &zhuyebj);//输出主页的背景图片
	 settextcolor(GREEN);//字体颜色
	 settextstyle(0, 0, 0);
	 outtextxy(230, 0, _T("欢迎来到[终极推箱子]"));
	 settextcolor(RED);
	 outtextxy(275, 100, _T("主菜单"));
	 settextcolor(YELLOW);
	 outtextxy(260, 200, _T("1.开始游戏"));
	 outtextxy(260, 240, _T("2.选择关卡"));
	 outtextxy(260, 280, _T("3.游戏帮助"));
	 system("pause");
	 a = 0;
	 mousecontrol();//设置鼠标事件
}

void mousecontrol()
{
	 MOUSEMSG m; 
	 while (1)
	 {
	  	m = GetMouseMsg();//获取鼠标的信息
	  	if (m.uMsg == WM_LBUTTONDOWN)//当鼠标按下左键
	 	 {
	 	 	  a = 1
	  		 if ((m.x >= 260 && m.x <= 340) && (m.y >= 200 && m.y <= 215))//判断鼠标左键的位置是否在“开始游戏”上
	 		  {
	    			guan = 0;
	    			gamesite();
	 		  }
		         if ((m.x >= 260 && m.x <= 340) && (m.y >= 240 && m.y <= 255))判断鼠标左键的位置是否在“选择关卡”上
			   {
		  		  guanchoose(); 
		   	    }
		   	if ((m.x >= 260 && m.x <= 340) && (m.y >= 280 && m.y <= 295))//判断鼠标左键的位置是否在“游戏帮助”上
	  		 {
	 			   gamehelp();
	   		}
	    }
	    if (a == 1)break//按下左键后结束循环
         }
}

关卡选择界面:
void guanchoose()//进入选择关卡界面
{
	 cleardevice();//清屏
	 putimage(0, 0, &guanqiabj);//输出界面图片
	 system("pause");
	 int inix = 10, iniy = 70, count = 0, x, y;//
	 bool ifback = 0;
	 MOUSEMSG m;
	 while (1)
	 {
	  	 m = GetMouseMsg();
	  	 if (m.uMsg == WM_LBUTTONDOWN)//按下左键时
		  {
	 		  for (int i = 0; i < 8; i++)//设置每个关卡点击有效的位置
			   {
	  			  for (int j = 0; j < 9; j++)
	  			  {
					     x = 70 * (j + 1) + inix;
					     y = 70 * (i + 1) + iniy;
					     if (m.x >= inix && m.x <= x && m.y >= iniy && m.y <= y)//当点击的位置在某个关卡的范围里
					     {
						      guan = 8 * i + j; ifback = 1; break;
					     }
				   }
				  if (ifback == 1)break;//若选择了关卡则退出循环
	   		   }
			   if (m.x >= 0 && m.x <= 140 && m.y >= 0 && m.y <= 70)//判断点击在“返回”上
			   {
			   	 mainsite(); ifback = 1; break;
			   }
		 }
		 if (ifback == 1)break;//退出循环
	 }
}

游戏界面:
bool iftab=0;
void gamesite()
{
 while (1)
 {
	  cleardevice();//清屏
	  mapcreate();//勾画地图
	  instruct = _getch();//等待按下按键
	  if (instruct == 27)//当按下esc时返回主界面
	  	 mainsite();
	  if (instruct == 9)//当按下tab时重置此关卡
		  {
			   iftab = 1;
			   setmapdate();
			   cleardevice();
			   mapcreate();
			   instruct = _getch();
		  }
	  nowmanx = getmanx();//实时获取人物的坐标
	  nowmany = getmany();
	  manmove(instruct, nowmanx, nowmany);//人物移动
	  cleardevice();//清屏
	  mapcreate();//输出地图,显示人物移动
	  win();//判断是否胜利
 }
}
	
	
游戏帮助界面:
void gamehelp()
{
	 cleardevice();
	 putimage(0, 0, &zhuyebj);
	 settextstyle(30, 0, 0);
	 outtextxy(250, 0, _T("游戏帮助"));
	 settextstyle(20, 0, 0);
	 settextcolor(GREEN);
	 outtextxy(90, 100, _T("1.向上移动:w"));
	 outtextxy(220, 100, _T("向下移动:s"));
	 outtextxy(340, 100, _T("向左移动:a"));
	 outtextxy(460, 100, _T("向右移动:d"));
	 outtextxy(90, 130, _T("2.按下ESC返回"));
	 outtextxy(90, 160, _T("3.游戏进行时按下TAB重置关卡"));
	 instruct = _getch();
	 if (instruct == 27)//按下esc返回
	 	 mainsite();
}			
	```

主函数:
int main()
{
	 setmapdate(); //设数据
	 system("title   终极推箱子");//设置标题
	 initgraph(640, 640);//初始化窗口
	 PlaySound(_T("D:\\cpp\\终极推箱子\\Debug\\背景音乐.wav"), NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);//循环播放背景音乐
	 while (1)//进入游戏
	 {
		  mainsite();
		  gamesite();
	 }
	 closegraph();//关闭窗口
	 system("pause");
	 return 0;
}

这是游戏效果图:在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

利用简单的easyx图形库做出来的,就只能做到这种效果了。

记录这个小游戏的收获:
一.EasyX图形库的使用: 要包括头文件<graphics.h>
图像:IMAGE img;
loadimage( img,//图片地址//,width,height)//保存图片;图片对象,图片名,宽度,长度;图片名用LPCTSTR类型
putimage(x,y,&img)//输出图片;绘制的x坐标,绘制的y坐标,图片名
getimage(&img,sx,sy,x,y)//从当前绘图设备获取图像;图片名,要获取图像左上角x坐标,y坐标,要获取图像区域的宽度

cleardevice()//清空屏幕,用当前前景色清空屏幕。
initgraph(w,h)//初始化屏幕;宽度,高度
closegraph()//关闭图形环境

文字:
outtextxy(x,y,str)//xy是头字母的坐标,str是 LPCTSTR类型
gettextcolor(COLORREF);//获取当前字体字体颜色
settextcolor(COLORREF);//设置字体颜色
settextstyle()//设置字体样式

鼠标:
MOUSEMSG m;
m=GetMouseMsg()//获取鼠标信息
MouseHit();//检测是否有鼠标信息
struct MOUSEMSG
{
UINT uMsg; // 当前鼠标消息
bool mkCtrl; // Ctrl 键是否按下
bool mkShift; // Shift 键是否按下
bool mkLButton; // 鼠标左键是否按下
bool mkMButton; // 鼠标中键是否按下
bool mkRButton; // 鼠标右键是否按下
int x; // 当前鼠标 x 坐标(物理坐标)
int y; // 当前鼠标 y 坐标(物理坐标)
int wheel; // 鼠标滚轮滚动值
};

含义

WM_MOUSEMOVE
鼠标移动消息。

WM_MOUSEWHEEL
鼠标滚轮拨动消息。

WM_LBUTTONDOWN
左键按下消息。

WM_LBUTTONUP
左键弹起消息。

WM_LBUTTONDBLCLK
左键双击消息。

WM_MBUTTONDOWN
中键按下消息。

WM_MBUTTONUP
中键弹起消息。

WM_MBUTTONDBLCLK
中键双击消息。

WM_RBUTTONDOWN
右键按下消息。

WM_RBUTTONUP
右键弹起消息。

WM_RBUTTONDBLCLK
右键双击消息。

有问题或者意见的可以加我QQ一起讨论。QQ:295390431
有想要体验这个游戏的也可以找我要!

二:打开文件
FILE *freopen(char *filename, char *type, FILE *stream);
type:"r"读文件,"w"写文件
stream:stdin读文件,stdout写文件
利用cin输入文件里的每个数据
fclose(stdin;
fclose(stdout);

三:播放音乐函数
PlaySound函数:
#include<windows.h>
#include <mmsystem.h>
#pragma comment(lib, “WINMM.LIB”)
BOOL PlaySound(LPCSTR pszSound, HMODULE hwnd,DWORD fdwSound);
pszSound是文件名的字符串,必须是wav类型的音乐

hwnd是应用程序的实例句柄,除非pszSound的指向一个资源标识符(即fdwSound被定义为SND_RESOURCE),否则必须设置为NULL。

一般循环播放:PlaySound(//名字//, NULL,SND_FILENAME | SND_ASYNC | SND_LOOP);

有问题或者意见的朋友可以加我QQ:295390431
有想体验这个游戏的也可以找我要!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值