せっかくなのでC++ぽく書いてみる。なおCOMファイルは生成できない。
>msdos tcc -ms nimotsu2.cpp >msdos nimotsu.exe ######## # .. p # # oo # # # ######## a:left s:right w:up z:down. command?
nimotsu2.cpp
#include <iostream.h> typedef int bool; #define true 1 #define false 0 #define max(a,b) (((a)>(b))?(a):(b)) #define matrix(x,y) (x + y * mWidth) //#壁 _空間 .ゴール oブロック p人 const char gStageData[] = "\ ########\n\ # .. p #\n\ # oo #\n\ # #\n\ ########\n"; enum Object{ OBJ_SPACE, OBJ_WALL, OBJ_GOAL, OBJ_BLOCK, OBJ_BLOCK_ON_GOAL, OBJ_MAN, OBJ_MAN_ON_GOAL, OBJ_UNKNOWN, }; //状態クラス class State{ public: State( const char* stageData, int size ); void update( char input ); void draw(); bool hasCleared(); private: void setSize( const char* stageData, int size ); //マス描画関数 static void drawCell( int x, int y, unsigned color ); int mWidth; int mHeight; int* mObjects; int* mGoalFlags; }; //グローバル変数 State* gState = 0; int main(){ gState = new State(gStageData, sizeof(gStageData)); gState->draw(); //メインループ while (true) { //メインループ //入力取得 cout << "a:left s:right w:up z:down. command?" << endl; //操作説明 char input; cin >> input; //更新 gState->update( input ); //描画 gState->draw(); //クリアチェック if ( gState->hasCleared() ){ //祝いのメッセージ cout << "Congratulation! you win." << endl; delete gState; gState = 0; return 0; } } } //---------------------以下関数定義------------------------------------------ State::State(const char* stageData, int size ){ int x = 0; int y = 0; //サイズ測定 setSize( stageData, size ); //配列確保 mObjects = new int[ mWidth * mHeight ]; //状態配列確保 mGoalFlags = new int[ mWidth * mHeight ]; //状態配列確保 //初期値で埋めとく for ( y = 0; y < mHeight; ++y ){ for ( x = 0; x < mWidth; ++x ){ mObjects[matrix(x , y)] = OBJ_WALL; //あまった部分は壁 mGoalFlags[matrix(x , y)] = false; //ゴールじゃない } } const char* d = stageData; //読み込みポインタ x = 0; y = 0; for (int i = 0; i < size; ++i ){ Object t; bool goalFlag = false; switch ( *d ){ case '#': t = OBJ_WALL; break; case ' ': t = OBJ_SPACE; break; case 'o': t = OBJ_BLOCK; break; case 'O': t = OBJ_BLOCK; goalFlag = true; break; case '.': t = OBJ_SPACE; goalFlag = true; break; case 'p': t = OBJ_MAN; break; case 'P': t = OBJ_MAN; goalFlag = true; break; case '\n': x = 0; ++y; t = OBJ_UNKNOWN; break; //改行処理 default: t = OBJ_UNKNOWN; break; } ++d; if ( t != OBJ_UNKNOWN ){ //知らない文字なら無視するのでこのif文がある mObjects[matrix(x , y)] = t; //書き込み mGoalFlags[matrix(x , y)] = goalFlag; //ゴール情報 ++x; } } } void State::setSize( const char* stageData, int size ){ mWidth = mHeight = 0; //初期化 //現在位置 int x = 0; int y = 0; for ( int i = 0; i < size; ++i ){ switch ( stageData[ i ] ){ case '#': case ' ': case 'o': case 'O': case '.': case 'p': case 'P': ++x; break; case '\n': ++y; //最大値更新 mWidth = max( mWidth, x ); mHeight = max( mHeight, y ); x = 0; break; } } } void State::draw() { for ( int y = 0; y < mHeight; ++y ){ for ( int x = 0; x < mWidth; ++x ){ Object o = mObjects[matrix(x , y)]; bool goalFlag = mGoalFlags[matrix(x , y)]; unsigned color = 0; if ( goalFlag ){ switch ( o ){ case OBJ_SPACE: cout << '.'; color = 0x0000ff; break; case OBJ_WALL: cout << '#'; color = 0xffffff; break; case OBJ_BLOCK: cout << 'O'; color = 0xff00ff; break; case OBJ_MAN: cout << 'P'; color = 0x00ffff; break; } }else{ switch ( o ){ case OBJ_SPACE: cout << ' '; color = 0x000000; break; case OBJ_WALL: cout << '#'; color = 0xffffff; break; case OBJ_BLOCK: cout << 'o'; color = 0xff0000; break; case OBJ_MAN: cout << 'p'; color = 0x00ff00; break; } } drawCell( x, y, color ); } cout << endl; } } void State::drawCell( int x, int y, unsigned color ){ /// unsigned* vram = Framework::instance().videoMemory(); /// unsigned windowWidth = Framework::instance().width(); /// for ( int i = 0; i < 16; ++i ){ /// for ( int j = 0; j < 16; ++j ){ /// vram[ (y*16+i) * windowWidth + (x*16+j) ] = color; /// } /// } return; } void State::update( char input ){ //移動差分に変換 int dx = 0; int dy = 0; switch ( input ){ case 'a': dx = -1; break; //左 case 's': dx = 1; break; //右 case 'w': dy = -1; break; //上。Yは下がプラス case 'z': dy = 1; break; //下。 } //短い変数名をつける。 int w = mWidth; int h = mHeight; //人座標を検索 int x, y; x = y = -1; bool found = false; for ( y = 0; y < mHeight; ++y ){ for ( x = 0; x < mWidth; ++x ){ if ( mObjects[matrix(x , y)] == OBJ_MAN ){ found = true; break; } } if ( found ){ break; } } //移動 //移動後座標 int tx = x + dx; int ty = y + dy; //座標の最大最小チェック。外れていれば不許可 if ( tx < 0 || ty < 0 || tx >= w || ty >= h ){ return; } //A.その方向が空白またはゴール。人が移動。 if ( mObjects[ tx + ty * mWidth] == OBJ_SPACE ){ mObjects[matrix(tx,ty)] = OBJ_MAN; mObjects[matrix(x , y)] = OBJ_SPACE; //B.その方向が箱。その方向の次のマスが空白またはゴールであれば移動。 }else if ( mObjects[matrix(tx,ty)] == OBJ_BLOCK ){ //2マス先が範囲内かチェック int tx2 = tx + dx; int ty2 = ty + dy; if ( tx2 < 0 || ty2 < 0 || tx2 >= w || ty2 >= h ){ //押せない return; } if ( mObjects[matrix(tx2,ty2)] == OBJ_SPACE ){ //順次入れ替え mObjects[matrix(tx2,ty2)] = OBJ_BLOCK; mObjects[matrix(tx ,ty )] = OBJ_MAN; mObjects[matrix( x , y )] = OBJ_SPACE; } } } //ブロックのところのgoalFlagが一つでもfalseなら //まだクリアしてない bool State::hasCleared() { for ( int y = 0; y < mHeight; ++y ){ for ( int x = 0; x < mWidth; ++x ){ if ( mObjects[matrix(x , y)] == OBJ_BLOCK ){ if ( mGoalFlags[matrix(x , y)] == false ){ return false; } } } } return true; }