跟着B站老师 做的,链接[C/C++]180行代码,推箱子就是这么简单~抄详细,学不会我还不信了,关卡切换和回退都实现了哦_哔哩哔哩_bilibili
编码环境:VS2019
利用 链栈实现的回撤功能。
linkStack.h
#pragma once
#ifdef _cplusplus
extern "C"
{
#endif
#include
#include
#include
using namespace std;
#define OK 1
#define ERROR 0
#define OVERFLOW -2
//typedef int Data;
struct Point
{
int r;
int c;
int data;
};
typedef struct _State
{
Point pos[3];
}Data,State;
typedef struct StackNode
{
Data data;
struct StackNode* next;
} StackNode, * linkStack;
//算法1 链栈的初始化(无头节点)
void InitStack(linkStack& S)
{ // 构造一个空栈 S,栈顶指针置空
S = NULL;
// return OK;
}
//算法2 链栈的入栈
void Push(linkStack& S, Data e)
{ //在栈顶插入元素e
linkStack p;
p = new StackNode; //生成新结点
p->data = e; //将新结点数据域置为e
p->next = S; //将新结点插入栈顶(类似与前插法,只不过没有头节点)
S = p; //修改栈顶指针为p
printf("okn");
//return OK;
}
//算法3链栈的出栈
void Pop(linkStack& S)
{ //删除S的栈顶元素,用e返回其值
linkStack p;
if (S == NULL)
return ; //栈空
// e = S->data; //将栈顶元素赋给e
p = S; //用p临时保存栈顶元素空间,以备释放
S = S->next; //修改栈顶指针
delete p; //释放原栈顶元素的空间
// return OK;
}
//算法4 取链栈的栈顶元素
Data GetTop(linkStack S)
{ //返回S的栈顶元素,不修改栈顶指针
if (S != NULL) //栈非空
return S->data; //返回栈顶元素的值,栈顶指针不变
}
bool empty(linkStack& S) {
if (S == NULL)
return true;
else return false;
}
//
//void empty(linkStack& S) {
//
//}
#ifdef _cplusplus
}
#endif
cpp文件
#include#include #include #include #include #include #include #include //包含IMAGE数组 #include"linkStack.h" using namespace std; #define SIZE 10 #define TOTAL_LEVEL 3 linkStack ls; //?? enum MINE { SPACE, WALL, DEST, BOX, PLAYER, }; //linkStack* ls; int x; int y; int level; IMAGE all_image[6]; //空地0 墙1 目的地2 箱子3 玩家4 //PLAYER+DEST 5 BOX+DEST:6 //a75 d77 72w 80s int map[TOTAL_LEVEL][SIZE][SIZE] = { { {0,0,0,0,0,0,0,0,0,0}, {0,0,0,1,1,1,0,0,0,0}, {0,0,0,1,2,1,0,0,0,0}, {0,0,0,1,3,1,1,1,1,0}, {0,1,1,1,0,0,3,2,1,0}, {0,1,2,3,4,0,1,1,1,0}, {0,1,1,1,1,3,1,0,0,0}, {0,0,0,0,1,2,1,0,0,0}, {0,0,0,0,1,1,1,0,0,0}, {0,0,0,0,0,0,0,0,0,0} }, { {0,0,0,0,0,0,0,0,0,0}, {0,0,1,1,1,1,1,1,0,0}, {0,0,1,0,2,0,0,1,0,0}, {0,0,1,0,0,3,0,1,0,0}, {0,0,1,0,0,0,0,1,0,0}, {0,0,1,0,0,4,0,1,0,0}, {0,0,1,1,1,1,1,1,0,0}, {0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0} }, { {0,0,0,0,0,0,0,0,0,0}, {0,1,1,1,0,0,0,0,0,0}, {0,1,2,1,0,0,0,0,0,0}, {0,1,3,1,0,0,0,0,0,0}, {0,1,4,1,0,0,0,0,0,0}, {0,1,1,1,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0} } }; void loadIMG() { for (int i = 0; i < 6; i++) { char file[20] = ""; sprintf(file, "./image/%d.bmp", i); loadimage(all_image + i, file, 64, 64);//IMAGE *pDstImg(// 保存图像的 IMAGE 对象指针), //e.g.loadimage(all_image + i,"0.bmp",64,64); //LPCTSTR pImgFile,图片文件名 //int nWidth = 0, int nHeight = 0, bool bResize = false); //putimage(i*64,0,all_image + i); //坐标原点为左上角。注意x,y坐标 } } void upMove() { if (map[level][x - 1][y] == SPACE || map[level][x - 1][y] == DEST) { map[level][x - 1][y] += PLAYER; map[level][x][y] -= PLAYER; } else if (map[level][x - 1][y] == BOX || map[level][x - 1][y] == BOX + DEST) { if (map[level][x - 2][y] == SPACE || map[level][x - 2][y] == DEST) { map[level][x - 2][y] += BOX; map[level][x - 1][y] = map[level][x - 1][y] + PLAYER - BOX; map[level][x][y] -= PLAYER; } } } void downMove() { if (map[level][x + 1][y] == SPACE || map[level][x + 1][y] == DEST) { map[level][x + 1][y] += PLAYER; map[level][x][y] -= PLAYER; } else if (map[level][x + 1][y] == BOX || map[level][x + 1][y] == BOX + DEST) { if (map[level][x + 2][y] == SPACE || map[level][x + 2][y] == DEST) { map[level][x + 2][y] += BOX; map[level][x + 1][y] = map[level][x + 1][y] + PLAYER - BOX; map[level][x][y] -= PLAYER; } } } void leftMove() { if (map[level][x][y - 1] == SPACE || map[level][x][y - 1] == DEST) { map[level][x][y - 1] += PLAYER; map[level][x][y] -= PLAYER; } else if (map[level][x][y - 1] == BOX || map[level][x][y - 1] == BOX + DEST) { if (map[level][x][y - 2] == SPACE || map[level][x][y - 2] == DEST) { map[level][x][y - 2] += BOX; map[level][x][y - 1] = map[level][x][y - 1] + PLAYER - BOX; map[level][x][y] -= PLAYER; } } } void rightMove() { if (map[level][x][y + 1] == SPACE || map[level][x][y + 1] == DEST) { map[level][x][y + 1] += PLAYER; map[level][x][y] -= PLAYER; } else if (map[level][x][y + 1] == BOX || map[level][x][y + 1] == BOX + DEST) { if (map[level][x][y + 2] == SPACE || map[level][x][y + 2] == DEST) { map[level][x][y + 2] += BOX; map[level][x][y + 1] = map[level][x][y + 1] + PLAYER - BOX; map[level][x][y] -= PLAYER; } } } void gameDraw() { for (int i = 0; i < SIZE; i++) { for (int j = 0; j < SIZE; j++) { switch (map[level][i][j]) { case SPACE: putimage(j * 64, i * 64, all_image); break; case WALL: putimage(j * 64, i * 64, all_image + 1); break; case DEST: putimage(j * 64, i * 64, all_image + 2); break; case BOX: putimage(j * 64, i * 64, all_image + 3); break; case PLAYER: x = i; y = j; putimage(j * 64, i * 64, all_image + 4); break; case PLAYER + DEST: putimage(j * 64, i * 64, all_image + 4); x = i; y = j; break; case BOX + DEST: putimage(j * 64, i * 64, all_image + 5); break; default: break; } } cout << endl; } } //对应的ASC码值 //W w:119,87 Dd:100,68 Ww:119,87 Ss:115,83 空格:32 void saveState(int x, int y, int dir) {//player的坐标,以及keyevent //State t; State t; memset(&t, 0, sizeof(State)); switch (dir) { case 119://w case 87: for (int i = 0; i < 3; i++) { t.pos[i].r = x - i; //依次记录 player 、player的下一格、以及player的下下一格 的行列坐标以及data t.pos[i].c = y; t.pos[i].data = map[level][t.pos[i].r][t.pos[i].c]; } Push(ls, t); break; case 115://s case 83: for (int i = 0; i < 3; i++) { t.pos[i].r = x + i; //依次记录 player 、player的下一格、以及player的下下一格 的行列坐标以及data t.pos[i].c = y; t.pos[i].data = map[level][t.pos[i].r][t.pos[i].c]; } Push(ls, t); Data p = GetTop(ls); break; case 97://a case 65: for (int i = 0; i < 3; i++) { t.pos[i].r = x; //依次记录 player 、player的下一格、以及player的下下一格 的行列坐标以及data t.pos[i].c = y - i; t.pos[i].data = map[level][t.pos[i].r][t.pos[i].c]; } Push(ls, t); break; case 100://d case 68: for (int i = 0; i < 3; i++) { t.pos[i].r = x; //依次记录 player 、player的下一格、以及player的下下一格 的行列坐标以及data t.pos[i].c = y + i; t.pos[i].data = map[level][t.pos[i].r][t.pos[i].c]; } Push(ls, t); break; default: break; } } void rollBack() { if (empty(ls)) { return; } State t = GetTop(ls); for (int i = 0; i < 3; i++) { map[level][t.pos[i].r][t.pos[i].c] = t.pos[i].data; } Pop(ls); } void keyEvent() { char event = _getch(); if (event != 32 && event != -32) { saveState(x, y, event); } switch (event) { case 'W': case 'w': upMove(); break; case 's': case 'S': downMove(); break; case 'A': case 'a': leftMove(); break; case 'd': case 'D': rightMove(); break; case 32: rollBack(); break; default: break; } } bool judge_pass() { for (int i = 0; i < SIZE; i++) { for (int j = 0; j < SIZE; j++) { if (map[level][i][j] == BOX) { return false; } } } return true; } int main() { InitStack(ls); initgraph(SIZE * 64, SIZE * 64, TRUE); loadIMG(); //system("mode con lines=20 cols=25"); level = 0; while (level < TOTAL_LEVEL) { //system("cls"); gameDraw(); keyEvent(); if (judge_pass()) { if (level == TOTAL_LEVEL - 1) { //system("cls"); gameDraw(); } level++; while (!empty(ls)) { Pop(ls); } } } MessageBox(NULL, TEXT("CONGRATULATIONS!"), TEXT("GAME OVER"), MB_OK); // getchar(); return 0; }
附文件结构



