ステージの縦と横の長さに当たるwidthとheightをまとめたいのですが、方法がわかりません。
テンプレートを使ったクラスで2つ、Stateの方でも1つの計3つ、同じ変数が出来てしまっており、これらをまとめようと思ったのですが、自力でやろうとするとどうしてもテンプレートクラスを崩すやり方しか思いつきませんでした。テンプレートをStateクラスの下位クラスとするなど(?)して変数のスコープを伸ばすやり方はありませんか。回答をお願いします。
※下記コードの元は、SEGAのプログラミング本にある"荷物くん"というコードです。
#include <fstream>
#include <iostream>
using namespace std;
template<class T> class Array2D{
T* p;
int width,height;//Size
public:
Array2D() :p(0){}
~Array2D(){ delete[]p; }
void PinNewArray(int x, int y){ if (p){ delete[]p; } width = x; height = y; p = new T[x*y]; }
T& operator()(int x, int y){ return p[y*width + x]; }
const T& operator()(int x, int y)const{ return p[y*width + x]; }
};
class State{
enum Object{ Wall, Space, Load, Other };
int width;
int height;
int px,py;//Player Position
int goal, load;
Array2D<Object>stage;
Array2D<bool>goalflags;
void MeasuringSize(const char* stageData, int size){
width = height = 0;//Initialize
int x = 0, y = 0;
for (int i = 0; i < size; ++i){
switch (stageData[i]){
case'#':
case'.':
case' ':
case'O':
case'o':
case'P':
case'p':++x; break;
case'\n'://yを加算してから最大値更新
++y;
width = (width > x) ? width : x;
height = (height > y) ? height : y;
x = 0;
break;
}
}
}
bool CheckDivision(int x, int y){ return (x < 0 || y < 0 || x >= width || y >= height) ? false : true; }
void MovePlayer(int x, int y){ px = x; py = y; }
public:
State(const char* stageData, int size){
goal = load = 0;
MeasuringSize(stageData, size);
stage.PinNewArray(width, height);
goalflags.PinNewArray(width, height);
//Array Initialize
for (int y = 0; y < height; ++y){
for (int x = 0; x < width; ++x){
stage(x, y) = Wall; goalflags(x, y) = false;
}
}
//stageDataからstage配列に書き込み
int x = 0;
int y = 0;
for (int i = 0; i < size; ++i){
Object t;
switch (stageData[i]){
case'#':t = Wall; break;
case'.':goalflags(x, y) = true; ++goal;
case' ':t = Space; break;
case'O':goalflags(x, y) = true; ++goal;
case'o':t = Load; ++load; break;
case'P':goalflags(x, y) = true; ++goal;
case'p':t = Space; MovePlayer(x, y); break;
case'\n':x = 0; ++y;
default:t = Other; break;
}
if (t != Other){ stage(x, y) = t; ++x; }
}
}
void Update(char input){
//入力を変化量に変換
int dx = 0;
int dy = 0;
switch (input){
case'w':dy = -1; break;
case's':dy = 1; break;
case'a':dx = -1; break;
case'd':dx = 1; break;
}
//プレイヤーの移動(移動方向先2マスを調べる)
int tx = px + dx;
int ty = py + dy;
int tx2 = tx + dx;
int ty2 = ty + dy;
if (CheckDivision(tx, ty)){
if (stage(tx, ty) == Space) { MovePlayer(tx, ty); }
else if (CheckDivision(tx2, ty2) && stage(tx, ty) == Load && stage(tx2, ty2) == Space){ MovePlayer(tx, ty); stage(tx, ty) = Space; stage(tx2, ty2) = Load; }
}
}
void Draw() const{
for (int y = 0; y < height; ++y){
for (int x = 0; x < width; ++x){
switch (stage(x, y)){
case Wall: cout << '#'; break;
case Space: if (x == px && y == py){ cout << (goalflags(x, y)? 'P' : 'p'); }
else{ cout << (goalflags(x, y)? '.' : ' '); } break;
case Load: cout << (goalflags(x, y)? 'O' : 'o'); break;
}
}
cout << endl;
}
}
bool CheckClear() const{
int clear = (goal < load) ? goal : load;//クリアに必要なゴールに到達した荷物の数
for(int y = 0; y < height; ++y){
for (int x = 0; x < width; ++x){
if (goalflags(x, y) && stage(x, y) == Load){ if (--clear <= 0)return true; }
}
}
return false;
}
};