C/C++ _补充 - 推箱子游戏

43 篇文章 1 订阅

补充项目 - 推箱子游戏

第 1 节 项目需求

实现一款推箱子游戏,效果如下图所示,具体规则: 1. 箱子只能推动而不能拉动; 2.如果箱子前一格是地板或箱子目的地,则可以推动一个箱子往前走一格,如果箱子已经在 箱子目的地则不能再推动; 3.推箱子的小人不能从箱子目的地上直接穿过; 4.注意不要把箱子推到死角上,不然就无法再推动它了; 5.所有箱子都成功推到箱子目的地,游戏结束,过关成功!
在这里插入图片描述
美工资源:

链接:https://pan.baidu.com/s/1MZv8pDBXdNDbXxuAAPSM-A **提取码:**2syq

图形库: www.easyx.cn

第 2 节 项目实现

2.1 模块划分
(作用:1.化繁为简 2.适合团队协作 3.高质量代码)
在这里插入图片描述
2.1.1 地图初始化
搭台唱戏
戏台坐标系(650 x 650):
在这里插入图片描述
地图表示:
在这里插入图片描述
使用二维数组

1、游戏道具显示(墙、箱子、箱子目的地、小人、地板)
2、便于程序在游戏过程中进行逻辑判断和控制小人向前一步的动作控制
3、判断游戏结果

道具表示:
墙: 0,地板: 1,箱子目的地: 2, 小人: 3, 箱子: 4, 箱子命中目标: 5
在这里插入图片描述
编码实现:
box_man.cpp

#include "box_man.h"
#include <iostream>
#include <stdlib.h>
#include <string>
#include <conio.h>
#include <graphics.h>

#include "box_man.h"

using namespace std;

IMAGE images[ALL];

struct _POS man; /* 小人在二维数组的位置 */

int map[LINE][COLUMN] =
{
	{WALL,	WALL,	WALL,    WALL,    WALL,  WALL,    WALL,  WALL,  WALL,    WALL,  WALL,  WALL},
	{WALL,	FLOOR,	WALL,    FLOOR,   FLOOR, FLOOR,   FLOOR, FLOOR, FLOOR,   FLOOR, WALL,  WALL},
	{WALL,	FLOOR,	BOX,     FLOOR,   WALL,  BOX_DES, FLOOR, WALL,  BOX_DES, FLOOR, WALL,  WALL},
	{WALL,	FLOOR,	WALL,    FLOOR,   WALL,  FLOOR,   FLOOR, WALL,  FLOOR,   FLOOR, FLOOR, WALL},
	{WALL,	FLOOR,	WALL,    BOX_DES, WALL,  FLOOR,   FLOOR, BOX,   FLOOR,   FLOOR, FLOOR, WALL},
	{WALL,	FLOOR,	FLOOR,   FLOOR,   WALL,  MAN,     FLOOR, FLOOR, FLOOR,   BOX,   FLOOR, WALL},
	{WALL,	FLOOR,	BOX_DES, FLOOR,   FLOOR, BOX,     FLOOR, FLOOR, FLOOR,   FLOOR, FLOOR, WALL},
	{WALL,	FLOOR,	WALL,    WALL,    FLOOR, WALL,    FLOOR, FLOOR, WALL,    WALL,  FLOOR, WALL},
	{WALL,	WALL,	WALL,    WALL,    WALL,  WALL,    WALL,  WALL,  WALL,    WALL,  WALL,  WALL},
};

/*****************************************************
* 判断游戏是否结束, 如果不存在任何一个箱子目的地, 就代表游戏结束
* 输入: 无
* 返回值: 
*		true - 游戏结束 false - 游戏继续
*****************************************************/
bool isGameOver()
{
	for (int i = 0; i < LINE; i++)
	{
		for (int j = 0; j < COLUMN; j++)
		{
			if (map[i][j] == BOX_DES)
			{
				return false;
			}
		}
	}

	return true;
}

/***************************************************
* 功能: 游戏结束场景, 在玩家通过后显示
* 输入:
*	  bg - 背景图片变量的指针
* 返回值: 无
***************************************************/
void gameOverScene(IMAGE* bg)
{
	putimage(0, 0, bg);
	settextcolor(WHITE);
	RECT rec = { 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT };
	settextstyle(20, 0, _T("宋体"));
	drawtext(_T("恭喜你, 通关了!!!"), &rec, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}


/*************************************************
* 功能: 改变游戏地图视图中一格对应的道具并重新显示
* 输入:
*	   pos - 道具在地图数组的行列下标 
*	   prop - 道具的类型
* 返回值: 无
*************************************************/
void changeMap(POS* pos, PROPS prop)
{
	map[pos->x][pos->y] = prop;
	putimage(START_X + pos->y * RATIO, START_Y + pos->x * RATIO, &images[prop]);
}


/**********************************************
* 功能: 实现游戏四个方向 (上, 下, 左, 右) 的控制
* 输入:
*     direct - 人前进的方向
* 输出: 无
**********************************************/
void gameControl(DIRECTION direct)
{
	POS next_pos = man; /* man 类型(结构体) 与 next_pos 相同 */
	POS next_next_pos = man;
	switch (direct)
	{
	case UP:
		next_pos.x--;
		next_next_pos.x -= 2;
		break;
	case DOWN:
		next_pos.x++;
		next_next_pos.x += 2;
		break;
	case LEFT:
		next_pos.y--;
		next_next_pos.y -= 2;
		break;
	case RIGHT:
		next_pos.y++;
		next_next_pos.y += 2;
		break;
	}

	/* 宏展开 next_pos.x >= 0 && next_pos.x < LINE && next_pos.y >= 0 && next_pos.y < COLUMN */
	if (isValid(next_pos) && map[next_pos.x][next_pos.y] == FLOOR) /* 人的前方是地板 */
	{
		changeMap(&next_pos, MAN);
		changeMap(&man, FLOOR);
		man = next_pos;
	}
	else if (isValid(next_next_pos) && map[next_pos.x][next_pos.y] == BOX)
	{
		if (map[next_next_pos.x][next_next_pos.y] == FLOOR)
		{
			changeMap(&next_next_pos, BOX);
			changeMap(&next_pos, MAN); /* 小人前进一格 */
			changeMap(&man, FLOOR);
			man = next_pos;
		}
		else if (map[next_next_pos.x][next_next_pos.y] == BOX_DES)
		{
			changeMap(&next_next_pos, HIT);
			changeMap(&next_pos, MAN);
			changeMap(&man, FLOOR);
			man = next_pos;
		}
	}
}


int main(void)
{
	IMAGE bg_img;

	/* 搭台 */
	initgraph(SCREEN_WIDTH, SCREEN_HEIGHT);
	loadimage(&bg_img, _T("blackground.bmp"), SCREEN_WIDTH, SCREEN_HEIGHT);
	putimage(0, 0, &bg_img);

	/* 加载道具 */
	loadimage(&images[WALL], _T("wall_right.bmp"), RATIO, RATIO, true);
	loadimage(&images[FLOOR], _T("floor.bmp"), RATIO, RATIO, true);
	loadimage(&images[BOX_DES], _T("des.bmp"), RATIO, RATIO, true);
	loadimage(&images[MAN], _T("man.bmp"), RATIO, RATIO, true);
	loadimage(&images[BOX], _T("box.bmp"), RATIO, RATIO, true);
	loadimage(&images[HIT], _T("box.bmp"), RATIO, RATIO, true);

	for (int i = 0; i < LINE; i++)
	{
		for (int j = 0; j < COLUMN; j++)
		{
			if (map[i][j] == MAN)
			{
				man.x = i;
				man.y = j;
			}

			putimage(START_X + j * RATIO, START_Y + i * RATIO, &images[map[i][j]]);
		}
	}

	/* 游戏环节 */
	bool quit = false;

	do
	{
		if (_kbhit())
		{
			char ch = _getch();

			if (ch == KEY_UP)
			{
				gameControl(UP);
			}
			else if (ch == KEY_DOWN)
			{
				gameControl(DOWN);
			}
			else if (ch == KEY_LEFT)
			{
				gameControl(LEFT);
			}
			else if (ch == KEY_RIGHT)
			{
				gameControl(RIGHT);
			}
			else if (ch == KEY_QUIT)
			{
				quit = true;
			}
			if (isGameOver())
			{
				gameOverScene(&bg_img);
				quit = true;
			}
		}

		Sleep(100);
	} while (quit == false);

	::system("pause");

	closegraph();
	return 0;
}

box_man.h

#pragma once

#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 650

#define RATIO 50

/* 控制键 上 下 左 右 控制方向 */
#define KEY_UP    'w'
#define KEY_LEFT  'a'
#define KEY_RIGHT 'd'
#define KEY_DOWN  's'
#define KEY_QUIT  'q'

#define LINE 9
#define COLUMN 12

#define START_X 100
#define START_Y 100

enum _PROPS  /* 道具 */
{
	WALL,    /* 墙 */
	FLOOR,   /* 地板 */
	BOX_DES, /* 箱子的目地 */
	MAN,     /* 小人 */
	BOX,     /* 箱子 */
	HIT,     /* 箱子命中目标 */
	ALL 
};

/* 游戏控制方向 */
enum _DIRECTION
{
	UP,
	DOWN,
	LEFT,
	RIGHT
};

struct _POS /* 位置 */
{
	int x;  /* 小人所在二维数组的行 */
	int y;  /* 小人所在二维数据在列 */
};


typedef enum _PROPS PROPS;         /* 道具 */
typedef enum _DIRECTION DIRECTION; /* 控制方向 */
typedef struct _POS POS;           /* 道具的位置 */

#define isValid(pos) pos.x>=0 && pos.x<LINE && pos.y>=0 && pos.y < COLUMN

结语:

时间: 2020-07-15

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值