直接上代码
#include <iostream>
#include <fstream>
#include <algorithm>
using namespace std;
void readFile(char** buffer, int* size, const char* filename)
{
ifstream in(filename);
if (!in)
{
*buffer = NULL;
*size = 0;
}
else
{
in.seekg(0, ifstream::end);
*size = static_cast<int>(in.tellg());
in.seekg(0, ifstream::beg);
*buffer = new char[*size];
in.read(*buffer, *size);
}
}
template<class T> class Array2D
{
public:
Array2D() : m_pArray(NULL) {}
~Array2D()
{
if (m_pArray)
{
delete[] m_pArray;
m_pArray = NULL;
}
}
public:
void setSize(int sizex, int sizey)
{
m_nSizeX = sizex;
m_nSizeY = sizey;
m_pArray = new T[sizex * sizey];
}
T& operator()(int indexX,int indexY)
{
return m_pArray[indexY * m_nSizeX + indexX];
}
const T& operator()(int indexX, int indexY) const
{
return m_pArray[indexY * m_nSizeX + indexX];
}
private:
T* m_pArray;
int m_nSizeX;
int m_nSizeY;
};
class State
{
public:
State(const char* stageData, int size);
void update(char input);
void draw() const;
bool hasCleared() const;
private:
void setSize(const char* stageData, int size);
private:
enum Object
{
OBJ_SPACE,
OBJ_WALL,
OBJ_BLOCK,
OBJ_MAN,
OBJ_UNKNOWN,
};
int m_nWidth;
int m_nHeight;
Array2D<Object> m_Objects;
Array2D<bool> m_GoalFlags;
};
State::State(const char* stageData, int size)
{
setSize(stageData, size);
m_Objects.setSize(m_nWidth, m_nHeight);
m_GoalFlags.setSize(m_nWidth, m_nHeight);
for (int y = 0; y < m_nHeight; ++y)
{
for (int x = 0; x < m_nWidth; ++x)
{
m_Objects(x, y) = OBJ_WALL;
m_GoalFlags(x, y) = false;
}
}
int xPos = 0, yPos = 0;
for (int i = 0; i < size; ++ i)
{
Object t;
bool goalFalg = false;
switch (stageData[i])
{
case '#': t = OBJ_WALL; break;
case ' ': t = OBJ_SPACE; break;
case 'o': t = OBJ_BLOCK; break;
case 'O': t = OBJ_BLOCK; goalFalg = true; break;
case '.': t = OBJ_SPACE; goalFalg = true; break;
case 'p': t = OBJ_MAN; break;
case 'P': t = OBJ_MAN; goalFalg = true; break;
case '\n': xPos = 0; ++yPos; t = OBJ_UNKNOWN; break;
default: t = OBJ_UNKNOWN; break;
}
if (t != OBJ_UNKNOWN)
{
m_Objects(xPos, yPos) = t;
m_GoalFlags(xPos, yPos) = goalFalg;
++xPos;
}
}
}
void State::setSize(const char* stageData, int size)
{
m_nWidth = m_nHeight = 0;
int xPos = 0, yPos = 0;
for (int i = 0; i < size; i++)
{
switch (stageData[i])
{
case '#':
case ' ':
case 'o':
case 'O':
case 'p':
case 'P':
{
++xPos;
break;
}
case '\n':
{
++yPos;
m_nWidth = max(m_nWidth, xPos);
m_nHeight = max(m_nHeight, yPos);
xPos = 0;
break;
}
}
}
}
void State::draw() const
{
for ( int y = 0; y < m_nHeight; ++y)
{
for (int x = 0; x < m_nWidth; ++x)
{
Object o = m_Objects(x, y);
bool goalFlag = m_GoalFlags(x, y);
if (goalFlag)
{
switch (o)
{
case OBJ_SPACE: cout << '.'; break;
case OBJ_WALL: cout << '#'; break;
case OBJ_BLOCK: cout << 'O'; break;
case OBJ_MAN: cout << 'P'; break;
}
}
else
{
switch (o)
{
case OBJ_SPACE: cout << ' '; break;
case OBJ_WALL: cout << '#'; break;
case OBJ_BLOCK: cout << 'o'; break;
case OBJ_MAN: cout << 'p'; break;
}
}
}
cout << endl;
}
}
void State::update(char input)
{
int dx = 0, dy = 0;
switch (input)
{
case 'a': dx = -1; break;
case 's': dx = 1; break;
case 'w': dy = -1; break;
case 'z': dy = 1; break;
}
int width = m_nWidth;
int height = m_nHeight;
Array2D<Object>& o = m_Objects;
int x = 0, y = 0;
bool found = false;
for (y = 0; y < height; ++y)
{
for (x = 0; x < width; ++x)
{
if (o(x,y) == OBJ_MAN)
{
found = true;
break;
}
}
if (found)
break;
}
int xMov = x + dx;
int yMov = y + dy;
if (xMov < 0 || yMov < 0 || xMov > width || yMov > height)
return ;
if (o(xMov, yMov) == OBJ_SPACE)
{
o(xMov, yMov) = OBJ_MAN;
o(x, y) = OBJ_SPACE;
}
else if (o(xMov, yMov) == OBJ_BLOCK)
{
int xMovNext = xMov + dx;
int yMovNext = yMov + dy;
if (xMovNext < 0 || yMovNext < 0 || xMovNext > width || yMovNext > height)
return ;
if (o(xMovNext, yMovNext) == OBJ_SPACE)
{
o(xMovNext, yMovNext) = OBJ_BLOCK;
o(xMov, yMov) = OBJ_MAN;
o(x, y) = OBJ_SPACE;
}
}
}
bool State::hasCleared() const
{
for (int y = 0; y < m_nHeight; ++y)
for (int x = 0; x < m_nWidth; ++x)
if (m_Objects(x, y) == OBJ_BLOCK && m_GoalFlags(x, y) == false)
return false;
return true;
}
int main(int argc, char** argv)
{
const char* filename = "stageData.txt";
if (argc >= 2)
{
filename = argv[1];
}
char* stageData;
int fileSize;
readFile(&stageData, &fileSize, filename);
if (!stageData)
{
cout << "stage file could not be read." << endl;
return 1;
}
State* state = new State(stageData, fileSize);
while (true)
{
state->draw();
if (state->hasCleared())
break;
cout << "a:left s:right w:up z:down. command?" <<endl;
char input;
cin >> input;
state->update(input);
}
cout << "Congratulation's! you won." << endl;
delete[] stageData;
stageData = 0;
system("pause");
return 0;
}
|