第一章 第一个游戏--“推箱子”
自己也把代码实现一遍。
游戏程序,就是获取输入,将输入反映到游戏世界,显示结果这三项 的无限循环。这个过程称为游戏循环或者主循环。
while(ture){getInput();updateGame();draw();
}
推箱子代码:
#include <iostream>
using namespace std;//#墙 _空白区 .终点 o砖块 p人
const char gStageData[] = "\
########\n\
# .. p #\n\
# oo #\n\
# #\n\
########";
const int gStageWidth = 8;
const int gStageHeight = 5;enum Object {OBJ_SPACE,//空间OBJ_WALL, //墙壁OBJ_GOAL, //目的地OBJ_BLOCK,//箱子OBJ_BLOCK_ON_GOAL, //箱子在目的地OBJ_MAN, //玩家OBJ_MAN_ON_GOAL, //玩家在目的地。为了表示状态OBJ_UNKNOWN, //未知字符串,也用于换行时的判断
};//函数声明
void initialize(Object* state, int w, int h, const char* stageData);
void draw(const Object* state, int w, int h);
void update(Object* state, char input, int w, int h);
bool checkClear(const Object* state, int w, int h);int main() {Object* state = new Object[gStageWidth * gStageHeight]; //分配状态数组空间initialize(state, gStageWidth, gStageHeight, gStageData); //舞台初始化//主循环while (true) {system("cls");//清屏操作//首先绘制draw(state, gStageWidth, gStageHeight);//通关检测if (checkClear(state, gStageWidth, gStageHeight)) {break; //通关检测}//提示如何操作cout << "a:left d:right w:up s:down. command?" << endl; //操作说明char input;cin >> input;//更新update(state, input, gStageWidth, gStageHeight);}//通关祝贺信息cout << "Congratulation's! you won." << endl;//析构delete[] state;state = 0;return 0;
}
//---------------------下面是函数定义--------------
void initialize(Object* state, int width, int height, const char* stageData) {const char* d = stageData;//读取位置int x = 0, y = 0;while (*d != NULL) {Object t;switch (*d){case '#': t = OBJ_WALL; break;case ' ': t = OBJ_SPACE; break;case 'o': t = OBJ_BLOCK; break;case 'O': t = OBJ_BLOCK_ON_GOAL; break;case '.': t = OBJ_GOAL; break;case 'p': t = OBJ_MAN; break;case 'P': t = OBJ_MAN_ON_GOAL; break;case '\n': x = 0; ++y; t = OBJ_UNKNOWN; break; //换行处理default: t = OBJ_UNKNOWN; break;}++d;if (t != OBJ_UNKNOWN) {state[y * width + x] = t;++x;} }
}
void draw(const Object* state, int width, int height) {const char font[] = { ' ', '#', '.', 'o', 'O', 'p', 'P' }; //需要与Object 对应。for (int y = 0; y < height; ++y) {for (int x = 0; x < width; ++x) {Object temp = state[y * width + x];cout << font[temp];//使用枚举类型作为下标,因为枚举本质上是int}cout << endl;}
}
//判断是否通关
bool checkClear(const Object* state, int width, int height) {int len = width * height;for (int i = 0; i < len; ++i) {if (state[i] == OBJ_BLOCK)return false;}return true;
}
//玩家输入移动指令后,更新操作。
void update(Object* state, char input, int width, int height) {int dx = 0, dy = 0;switch (input){case 'a': dx = -1; break;case 'd': dx = 1; break;case 'w': dy = -1; break;case 's': dy = 1; break;default: break;}int x = 0, y = 0,len = width * height;//查询小人的坐标for (int i = 0; i < len; ++i) {if (state[i] == OBJ_MAN || state[i] == OBJ_MAN_ON_GOAL) {x = i % width;y = i / width;break;}}//移动后的坐标int tx = dx + x;int ty = dy + y;if (tx < 0 || ty < 0 || tx >= width || ty >= height) {return;}int player = x + y * width; //玩家位置int tp = ty * width + tx; //目标位置 TargetPosition//A.该方向上是空白或者终点。小人则移动if (state[tp] == OBJ_SPACE || state[tp] == OBJ_GOAL) {//如果该位置是终点,则将该位置值变为“终点上站着人”state[tp] = (state[tp] == OBJ_GOAL) ? OBJ_MAN_ON_GOAL : OBJ_MAN;//如果该位置已经是“终点上站着人”,则变为“终点”state[player] = (state[player] == OBJ_GOAL) ? OBJ_GOAL : OBJ_SPACE;}//B.如果该方向上是箱子。并且该方向的下下个格子是空白或者终点,则允许移动else if (state[tp] == OBJ_BLOCK || state[tp] == OBJ_BLOCK_ON_GOAL) {int tx2 = tx + dx;int ty2 = ty + dy; if (tx2 < 0 || ty2 < 0 || tx2 >= width || ty2 >= height) {return;}int tp2 = tx2 + ty2 * width;//这是箱子的移动目的地if (state[tp2] == OBJ_SPACE || state[tp2] == OBJ_GOAL) {state[tp2] = (state[tp2] == OBJ_GOAL) ? OBJ_BLOCK_ON_GOAL : OBJ_BLOCK;state[tp] = (state[tp] == OBJ_BLOCK_ON_GOAL) ? OBJ_MAN_ON_GOAL : OBJ_MAN;state[player] = (state[player] == OBJ_MAN_ON_GOAL) ? OBJ_GOAL : OBJ_SPACE;}}
}
运行效果如下: p(小写的)为玩家位置, ' . ' 为箱子的目的地,o(小写)为箱子。
下一篇,写一下学到的知识点。虽然只有150行代码,学的东西还是很多的。之前学的C++只是简单地找到语法,这是简单地应用,还是学到很多的,有收获。