#include <graphics.h>
#include <iostream>
#include <Windows.h>
#include <string>
#include <conio.h>
using namespace std;
#define LINE 9 //行数
#define COLUMN 12 //列数
#define RATIO 61 //图片大小
#define START_X 64 //行偏移量
#define START_Y 60 //列偏移量
#define SCREEN_WIDTH 860 //屏幕的宽
#define SCREEN_HEIGHT 668 //屏幕的高
#define isValid(pos) pos.x>=0 && pos.x<LINE && pos.y>=0 && pos.y < COLUMN
//控制键 上下左右控制方向 按‘q’退出
#define KEY_UP 'W'
#define KEY_DOWN 'S'
#define KEY_LEFT 'A'
#define KEY_RIGHT 'D'
#define KEY_QUIT 'Q'
/*游戏地图*/
//墙: 0,地板: 1,箱子目的地: 2, 小人: 3, 箱子: 4, 箱子命中目标: 5
int map[LINE][COLUMN] = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
{ 0, 1, 4, 1, 0, 2, 1, 0, 2, 1, 0, 0 },
{ 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0 },
{ 0, 1, 0, 2, 0, 1, 1, 4, 1, 1, 1, 0 },
{ 0, 1, 1, 1, 0, 3, 1, 1, 1, 4, 1, 0 },
{ 0, 1, 2, 1, 1, 4, 1, 1, 1, 1, 1, 0 },
{ 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
};
struct _POS {
int x; //小人所在二维数组的行
int y; //小人所在二维数组的列
};
enum _PROPS { //枚举常量 道具
WALL,//墙
FLOOR,//地板
BOX_DES,//箱子目的地
MAN,//人
BOX,//箱子
HIT,//箱子命中目标
ALL
};
enum _DIRECTION { //游戏方向控制
UP,
DOWN,
LEFT,
RIGHT
};
IMAGE images[ALL];
struct _POS man;
struct _POS box_des1;//临时的箱子目的地存放点
struct _POS box_des2;
void changeMap(struct _POS *man, enum _PROPS prop) {
map[man->x][man->y] = prop;
putimage(START_X + man->y * RATIO, START_Y + man->x * RATIO, &images[prop]);
}
/**********************************************
*实现游戏四个方向(上、下、左、右)的控制
* 输入:
* direct - 人前进方向
* 输出: 无
**********************************************/
void gameControl(enum _DIRECTION direct) {
struct _POS next_pos = man;
struct _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;
}
if (isValid(next_pos) && map[next_pos.x][next_pos.y] == FLOOR) {//人的前方是地板
if (map[man.x][man.y] == map[box_des1.x][box_des1.y] || map[man.x][man.y] == map[box_des2.x][box_des2.y]) { //如果人所在的位置是箱子目的地
changeMap(&next_pos, MAN);
changeMap(&man, BOX_DES);
man = next_pos;
}
else {
changeMap(&next_pos, MAN); //小人前进一格
changeMap(&man, FLOOR);
man = next_pos;
}
}
else if (map[next_pos.x][next_pos.y] == BOX_DES) {//如果人的前方是箱子目的地
box_des1.x = next_pos.x;
box_des1.y = next_pos.y;
changeMap(&next_pos, MAN);
changeMap(&man, FLOOR);
man = next_pos;
}
else if (map[next_pos.x][next_pos.y] == HIT) {//如果人的前方是HIT
changeMap(&next_next_pos, BOX);
changeMap(&next_pos, MAN); //小人前进一格
changeMap(&man, FLOOR);
man = next_pos;
box_des2.x = next_pos.x;
box_des2.y = next_pos.y;
}
else if (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;
}
}
}
/**********************************************
* *游戏结束场景,在玩家通关后显示
*输入:
* 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("恭喜您~ \n 您终于成为了一个合格的搬箱子老司机!"),
&rec, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
void isGameFailed(IMAGE* bg) {
putimage(0, 0, bg);
settextcolor(WHITE);
RECT rec = { 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT };
settextstyle(20, 0, _T("宋体"));
drawtext(_T("GameOver!你这个小垃圾哈哈哈哈!"),
&rec, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
/**********************************************
*判断游戏是否结束,如果不存在任何一个箱子目的地,就代表游戏结束
*输入: 无
*返回值:
* 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;
}
int main() {
IMAGE bg_img; //背景图片
int num = 0;//统计步数
initgraph(SCREEN_WIDTH, SCREEN_HEIGHT);
loadimage(&bg_img,_T("blackground.bmp"), SCREEN_WIDTH, SCREEN_HEIGHT,true);
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] == 3) {
man.x = i;
man.y = j;
}
putimage(START_X + j * RATIO, START_Y + i * RATIO,
&images[map[i][j]]);
}
}
//游戏开始环节
bool isQuit = false;
ExMessage msg;
do {
//if (_kbhit()) {//如果玩家点击键盘 //win11用不了此操作
// char ch = _getch();
// switch (ch)
// {
// case KEY_UP:
// gameControl(UP);
// case KEY_DOWN:
// gameControl(DOWN);
// case KEY_LEFT:
// gameControl(LEFT);
// case KEY_RIGHT:
// gameControl(RIGHT);
// case KEY_QUIT:
// isQuit = true;
// if (isGameOver()) {
// gameOverScene(&bg_img);
// isQuit = true;
// }
// }
// Sleep(100);
//}
//WM_LBUTTONDOWN 鼠标左键按下
//WM_KEYDOWN 键盘按键按下
if (peekmessage(&msg) && msg.message == WM_KEYDOWN)
{
char ch = msg.vkcode;
num++;
switch (ch)
{
case KEY_UP:
gameControl(UP);
break;
case KEY_DOWN:
gameControl(DOWN);
break;
case KEY_LEFT:
gameControl(LEFT);
break;
case KEY_RIGHT:
gameControl(RIGHT);
break;
case KEY_QUIT:
if (isGameOver()) {
gameOverScene(&bg_img);
isQuit = true;
}
break;
}
Sleep(100);
if (num > 80) {
isGameFailed(&bg_img);
isQuit = true;
}
if (isGameOver()) {
gameOverScene(&bg_img);
isQuit = true;
}
}
} while (!isQuit);
system("pause");
return 0;
}