C++实现推箱子功能附加回撤示例

时间:2021-12-27 18:21:10

跟着B站老师 做的,链接[C/C++]180行代码,推箱子就是这么简单~抄详细,学不会我还不信了,关卡切换和回退都实现了哦_哔哩哔哩_bilibili

编码环境:VS2019 

利用 链栈实现的回撤功能。

LinkStack.h

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#pragma once
/***链栈的实现***/
#ifdef _cplusplus
extern "C"
{
#endif
 
#include <fstream>
#include <iostream>
#include<stdbool.h>
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("ok\n");
    //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
/*
int main()
{
    LinkStack s;
    int choose, flag = 0;
    SElemType j, t;
    cout << "1.初始化\n";
    cout << "2.入栈\n";
    cout << "3.读栈顶元素\n";
    cout << "4.出栈\n";
    cout << "0.退出\n\n";
    choose = -1;
    while (choose != 0)
    {
        cout << "请选择:";
        cin >> choose;
        switch (choose)
        {
        case 1: //算法q1 链栈的初始化
            if (InitStack(s))
            {
                flag = 1;
                cout << "成功对栈进行初始化\n\n";
            }
            else
                cout << "初始化栈失败\n\n";
            break;
        case 2:
        { //算法2 链栈的入栈
            fstream file;
            file.open("/Users/xiaokaixin/Documents/Code/cpp_code/txt_file/SqStack.txt");
            if (!file)
            {
                cout << "错误!未找到文件!\n\n"
                     << endl;
                exit(ERROR);
            }
            if (flag)
            {
                flag = 1;
                cout << "进栈元素依次为:\n";
                while (!file.eof())
                {
                    file >> j;
                    if (file.fail())
                        break;
                    else
                    {
                        Push(s, j);
                        cout << j << "  ";
                    }
                }
                cout << endl
                     << endl;
            }
            else
                cout << "栈未建立,请重新选择\n\n";
            file.close();
        }
        break;
        case 3: //算法3 取链栈的栈顶元素
            if (flag != -1 && flag != 0)
                cout << "栈顶元素为:\n"
                     << GetTop(s) << endl
                     << endl;
            else
                cout << "栈中无元素,请重新选择\n"
                     << endl;
            break;
        case 4: //算法4 链栈的出栈
            if (flag)
            {
                cout << "依次弹出的栈顶元素为:\n";
                while (Pop(s, t))
                    cout << t << "  ";
                cout << endl
                     << endl;
            }
            else
                cout << "栈未建立,请重新选择\n\n";
            break;
        }
    }
    return 0;
}
*/

cpp文件

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
#include<cstdlib>
#include<iostream>
#include<time.h>
#include<time.h>
#include<math.h>
#include<conio.h>
#include <WINDOWS.H>
#include<graphics.h>  //包含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;
}

附文件结构 

C++实现推箱子功能附加回撤示例

C++实现推箱子功能附加回撤示例

到此这篇关于C+++实现推箱子功能附加回撤示例的文章就介绍到这了,更多相关C+++ 推箱子内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/intmain_S/article/details/121016555