C++實(shí)現(xiàn)推箱子功能附加回撤示例
跟著B(niǎo)站老師 做的,鏈接[C/C++]180行代碼,推箱子就是這么簡(jiǎn)單~抄詳細(xì),學(xué)不會(huì)我還不信了,關(guān)卡切換和回退都實(shí)現(xiàn)了哦_嗶哩嗶哩_bilibili
編碼環(huán)境:VS2019
利用 鏈棧實(shí)現(xiàn)的回撤功能。
LinkStack.h
#pragma once
/***鏈棧的實(shí)現(xiàn)***/
#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 鏈棧的初始化(無(wú)頭節(jié)點(diǎn))
void InitStack(LinkStack& S)
{ // 構(gòu)造一個(gè)空棧 S,棧頂指針置空
S = NULL;
// return OK;
}
//算法2 鏈棧的入棧
void Push(LinkStack& S, Data e)
{ //在棧頂插入元素e
LinkStack p;
p = new StackNode; //生成新結(jié)點(diǎn)
p->data = e; //將新結(jié)點(diǎn)數(shù)據(jù)域置為e
p->next = S; //將新結(jié)點(diǎn)插入棧頂(類似與前插法,只不過(guò)沒(méi)有頭節(jié)點(diǎn))
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臨時(shí)保存棧頂元素空間,以備釋放
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 << "請(qǐng)選擇:";
cin >> choose;
switch (choose)
{
case 1: //算法q1 鏈棧的初始化
if (InitStack(s))
{
flag = 1;
cout << "成功對(duì)棧進(jìn)行初始化\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 << "錯(cuò)誤!未找到文件!\n\n"
<< endl;
exit(ERROR);
}
if (flag)
{
flag = 1;
cout << "進(jìn)棧元素依次為:\n";
while (!file.eof())
{
file >> j;
if (file.fail())
break;
else
{
Push(s, j);
cout << j << " ";
}
}
cout << endl
<< endl;
}
else
cout << "棧未建立,請(qǐng)重新選擇\n\n";
file.close();
}
break;
case 3: //算法3 取鏈棧的棧頂元素
if (flag != -1 && flag != 0)
cout << "棧頂元素為:\n"
<< GetTop(s) << endl
<< endl;
else
cout << "棧中無(wú)元素,請(qǐng)重新選擇\n"
<< endl;
break;
case 4: //算法4 鏈棧的出棧
if (flag)
{
cout << "依次彈出的棧頂元素為:\n";
while (Pop(s, t))
cout << t << " ";
cout << endl
<< endl;
}
else
cout << "棧未建立,請(qǐng)重新選擇\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數(shù)組
#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 對(duì)象指針),
//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); //坐標(biāo)原點(diǎn)為左上角。注意x,y坐標(biāo)
}
}
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;
}
}
//對(duì)應(yīng)的ASC碼值
//W w:119,87 Dd:100,68 Ww:119,87 Ss:115,83 空格:32
void saveState(int x, int y, int dir) {//player的坐標(biāo),以及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的下下一格 的行列坐標(biāo)以及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的下下一格 的行列坐標(biāo)以及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的下下一格 的行列坐標(biāo)以及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的下下一格 的行列坐標(biāo)以及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;
}
附文件結(jié)構(gòu)


到此這篇關(guān)于C+++實(shí)現(xiàn)推箱子功能附加回撤示例的文章就介紹到這了,更多相關(guān)C+++ 推箱子內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++ OpenCV學(xué)習(xí)之圖像金字塔與圖像融合詳解
圖像金字塔分為兩種:高斯金字塔和拉普拉斯金字塔。圖像金字塔在保持細(xì)節(jié)的條件下進(jìn)行圖像融合等多尺度編輯操作非常有用。本文將利用圖像金字塔實(shí)現(xiàn)圖像融合,需要的可以參考一下2022-03-03
C++入門(mén)指南之貪吃蛇游戲的實(shí)現(xiàn)
這篇文章主要給大家介紹了關(guān)于C++入門(mén)指南之貪吃蛇游戲?qū)崿F(xiàn)的相關(guān)資料,文章通過(guò)示例代碼介紹的非常詳細(xì),可以讓大家能短時(shí)間內(nèi)寫(xiě)出一個(gè)貪吃蛇,需要的朋友可以參考下2021-10-10
二分法求多項(xiàng)式在-10 10間值的實(shí)現(xiàn)代碼
以下實(shí)例是介紹了二分法求多項(xiàng)式在-10 10間值的實(shí)現(xiàn)代碼。需要的朋友參考下2013-05-05
劍指offer之C語(yǔ)言不修改數(shù)組找出重復(fù)的數(shù)字
今天小編就為大家分享一篇關(guān)于劍指offer之C語(yǔ)言不修改數(shù)組找出重復(fù)的數(shù)字,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-02-02
一文詳解C語(yǔ)言中文件相關(guān)函數(shù)的使用
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言中文件相關(guān)函數(shù)的使用,可以實(shí)現(xiàn)文件的讀寫(xiě)、打開(kāi)和關(guān)閉。文中通過(guò)示例進(jìn)行了詳細(xì)介紹,需要的可以參考一下2022-07-07
基于C語(yǔ)言實(shí)現(xiàn)shell指令的詳解
本篇文章是對(duì)C語(yǔ)言實(shí)現(xiàn)shell指令的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05

