C++實現推箱子功能附加回撤示例
跟著B站老師 做的,鏈接[C/C++]180行代碼,推箱子就是這麼簡單~抄詳細,學不會我還不信瞭,關卡切換和回退都實現瞭哦_嗶哩嗶哩_bilibili
編碼環境:VS2019
利用 鏈棧實現的回撤功能。
LinkStack.h
#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文件
#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+++ 推箱子內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!