入力はgetchar(),出力はprintf().
画面はこんな.
一見,何が何だかわからんけど… ↓
心の目で見れば,こんな感じに捉えることができるハズ.
//向きに関する定数
const int DX[] = { 0, 1, 0, -1 };
const int DY[] = {-1, 0, 1, 0 };
const char DName[] = { 'N', 'E', 'S', 'W' };
//迷路データ
const int MAZE_W = 8;
const int MAZE_H = 6;
const char Maze[MAZE_H][MAZE_W+1] =
{ //'#' is Wall
"....#...",
".####.#.",
"........",
".#....##",
".##.#.#G",
"....#..."
};
//迷路データの位置(x,y)の内容を取得する.
//(x,y)が領域外の場合は,壁を表す'#'が返される.
char Attr( int x, int y )
{ return ( ( x<0 || x>=MAZE_W || y<0 || y>=MAZE_H ) ? '#' : Maze[y][x] ); }
//Show()で使う作業用構造体.矩形範囲を表す.
struct Rect
{
int Left, Top, Right, Bottom;
Rect( int Left=0, int Top=0, int Right=-1, int Bottom=-1 )
: Left(Left), Top(Top), Right(Right), Bottom(Bottom) {}
bool IsValid() const { return (Left<=Right && Top<=Bottom ); }
};
//Show()から使う作業関数.Buff[][]の指定範囲をCで埋める
void DrawRect( char Buff[12][12+1], const Rect &R, char C )
{
for( int y=R.Top; y<=R.Bottom; ++y )
{
for( int x=R.Left; x<=R.Right; ++x )
{ Buff[y][x] = C; }
}
}
//現在の視界の絵を表示
void Show( int PX,int PY, int iDir )
{
const int kr[8] = { -1, 0, 1, -1, 0, 1, -1,1 };
const int kf[8] = { 2, 2, 2, 1, 1, 1, 0,0 };
const Rect FillRect[8][2] = {
{ Rect(0,4,3,7), Rect() }, { Rect(4,4,7,7), Rect() }, { Rect(8,4,11,7), Rect() },
{ Rect(0,2,2,9), Rect(3,3,3,8) }, { Rect(2,2,9,9), Rect() }, { Rect(9,2,11,9), Rect(8,3,8,8) },
{ Rect(0,0,0,11), Rect(1,1,1,10) }, { Rect(11,0,11,11), Rect(10,1,10,10) }
};
//Buff[][]に表示内容を作る
char Buff[12][12+1] = { 0 };
{
DrawRect( Buff, Rect(0,0, 11,11), ' ' );
//壁の描画
const int fx = DX[ iDir ];
const int fy = DY[ iDir ];
const int rx = -fy;
const int ry = fx;
for( int i=0; i<8; ++i )
{
int x = PX + fx*kf[i] + rx*kr[i];
int y = PY + fy*kf[i] + ry*kr[i];
if( Attr(x,y) == '#' )
{
for( int iRect=0; iRect<2; ++iRect )
{
if( FillRect[i][iRect].IsValid() )
{ DrawRect( Buff, FillRect[i][iRect], '#' ); }
}
}
}
//ゴールの描画
if( Attr( PX,PY )=='G' ){ Buff[11][5] = 'G'; }
else if( Attr( PX+fx, PY+fy )=='G' ){ Buff[9][5] = 'G'; }
}
//Buff[][]の内容を表示
printf("+------------+\n" );
for( int y=0; y<12; ++y ){ printf( "|%s|\n", Buff[y] ); }
printf("+------------+\n" );
}
//操作方法表示
void ShowHelp()
{
printf( "===Cmd List===============\n" );
printf( "{f,F,8} : Walk Forward\n" );
printf( "{l,L,4} : Turn Left\n" );
printf( "{r,R,6} : Turn Right\n" );
printf( "{q,Q} : Quit This Game\n" );
printf( "{h,H,?} : Show This Help\n" );
printf( "==========================\n" );
}
//入力処理
char InputCmd()
{
printf( "Cmd? : " );
char Input;
while( true )
{
Input = getchar();
if( Input!='\r' && Input!='\n' )break; //※前回のEnterの影響をどうにかする用
}
return Input;
}
//main
int main()
{
printf( "== The Maze Game ==\n" );
printf( "(input '?' Cmd to show help)\n" );
//データ初期化
// (PX,PY):現在位置, iDir:現在の向き(0~3)
int PX = 3;
int PY = 0;
int iDir = 3;
//Game Loop
bool bLoop = true;
while( bLoop )
{
//現在の視界を表示
printf( "\n" );
Show( PX,PY, iDir );
//ゴール判定
if( Attr( PX,PY )=='G' )
{
printf( "\n *** GOAL! *** \n" );
printf( "(Input Any Cmd to Quit)\n" );
InputCmd();
break;
}
//入力受付とゲーム進行
printf( "Pos(%d,%d) Dir(%c)\n", PX,PY,DName[iDir] );
switch( InputCmd() )
{
case 'f': //Forward
case 'F':
case '8':
{
int FX = PX + DX[iDir];
int FY = PY + DY[iDir];
if( Attr(FX,FY) != '#' ){ PX = FX; PY = FY; }
}
break;
case 'l': //Turn Left
case 'L':
case '4':
if( --iDir < 0 ){ iDir = 3; }
break;
case 'r': //Turn Right
case 'R':
case '6':
if( ++iDir > 3 ){ iDir = 0; }
break;
case 'q': //Quit
case 'Q':
bLoop = false;
break;
case 'h': //Show Help
case 'H':
case '?':
ShowHelp();
break;
default:
printf( "Invalid Cmd\n" );
break;
}
}
return 0;
}