Robots/C++

From Rosetta Code
Revision as of 23:08, 30 October 2017 by rosettacode>Fwend (Moved C++ entry to separate page)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Code

Windows Console implementation - No safe teleport is implemeted, just the random one.

<lang cpp>

  1. include <windows.h>
  2. include <iostream>
  3. include <ctime>

const int WID = 62, HEI = 42, INC = 10;

class coord : public COORD { public:

   coord( short x = 0, short y = 0 ) { set( x, y ); }
   void set( short x, short y ) { X = x; Y = y; }

}; class winConsole { public:

   static winConsole* getInstamnce() { 
       if( 0 == inst ) { 
           inst = new winConsole(); 
       } 
       return inst; 
   }
   void showCursor( bool s ) { 
       CONSOLE_CURSOR_INFO ci = { 1, s }; 
       SetConsoleCursorInfo( conOut, &ci ); 
   }
   void setColor( WORD clr ) { SetConsoleTextAttribute( conOut, clr ); }
   void setCursor( coord p ) { SetConsoleCursorPosition( conOut, p ); }
   void setSize( int w, int h ) {
       coord crd( w + 1, h + 1 ); 
       SetConsoleScreenBufferSize( conOut, crd );
       SMALL_RECT rc = { 0, 0, WID, HEI }; 
       SetConsoleWindowInfo( conOut, TRUE, &rc );
   }
   void flush() { FlushConsoleInputBuffer( conIn ); }
   void kill() { delete inst; }

private:

   winConsole() { conOut = GetStdHandle( STD_OUTPUT_HANDLE ); 
                  conIn  = GetStdHandle( STD_INPUT_HANDLE ); showCursor( false ); }
   static winConsole* inst;
   HANDLE conOut, conIn;

}; class robots { public:

   robots() { 
       console = winConsole::getInstamnce();
       console->setSize( WID, HEI );
   }
   ~robots() { console->kill(); }
   void play() {
       char g; do {
           console->showCursor( false ); 
           robotsCount = 10; score = 0; alive = true; 
           clearBoard(); cursor.set( rand() % ( WID - 2 ) + 1, rand() % ( HEI - 2 ) + 1 );
           brd[cursor.X + WID * cursor.Y] = '@'; createBoard();
           do{ 
               displayBoard(); getInput(); 
               if( !aliveRobots ) { 
                   robotsCount += INC; clearBoard(); 
                   brd[cursor.X + WID * cursor.Y] = '@'; createBoard(); 
               }
           } while( alive );
           displayBoard(); console->setCursor( coord( 0, 24 ) ); console->setColor( 0x07 );
           console->setCursor( coord( 10,  8 ) ); 
           std::cout << "+----------------------------------------+";
           console->setCursor( coord( 10,  9 ) ); 
           std::cout << "|               GAME OVER                |";
           console->setCursor( coord( 10, 10 ) ); 
           std::cout << "|            PLAY AGAIN(Y/N)?            |";
           console->setCursor( coord( 10, 11 ) ); 
           std::cout << "+----------------------------------------+";
           console->setCursor( coord( 39, 10 ) ); console->showCursor( true ); 
           console->flush(); std::cin >> g;
       } while( g == 'Y' || g == 'y' );
   }

private:

   void clearBoard() {
       for( int y = 0; y < HEI; y++ ) {
           for( int x = 0; x < WID; x++ ) {
               brd[x + WID * y] = 32;
               if( x == 0 || x == WID - 1 || y == 0 || y == HEI - 1 ) 
                   brd[x + WID * y] = '#';
           }
       }
   }
   void createBoard() {
       aliveRobots = robotsCount;
       int a, b; for( int x = 0; x < robotsCount; x++ ) {
           do {
               a = rand() % WID; b = rand() % HEI;
           } while( brd[a + WID * b] != 32 );
           brd[a + WID * b] = '+';
       }
       printScore();
   }
   void displayBoard() {
       char t; console->setCursor( coord() );
       for( int y = 0; y < HEI; y++ ) {
           for( int x = 0; x < WID; x++ ) {
               t = brd[x + WID * y];
               switch( t ) {
                   case ' ': console->setColor( 0x00 ); break;
                   case '#': console->setColor( 0x09 ); break;
                   case '+': console->setColor( 0x0e ); break;
                   case 'Å': case '*': console->setColor( 0x0c ); break;
                   case '@': console->setColor( 0x0a );
               }
               std::cout << t; 
           }
           std::cout << "\n";
       }
   }
   void getInput() { 
       while( 1 ) {
           if( ( GetAsyncKeyState( 'Q' ) & 0x8000 ) && cursor.X > 1 && cursor.Y > 1 ) 
               { execute( -1, -1 ); break; }
           if( ( GetAsyncKeyState( 'W' ) & 0x8000 ) && cursor.Y > 1 ) 
               { execute( 0, -1 ); break; }
           if( ( GetAsyncKeyState( 'E' ) & 0x8000 ) && cursor.X < WID - 2 && cursor.Y > 1 ) 
               { execute( 1, -1 ); break; }
           if( ( GetAsyncKeyState( 'A' ) & 0x8000 ) && cursor.X > 1 ) 
               { execute( -1, 0 ); break; }
           if( ( GetAsyncKeyState( 'D' ) & 0x8000 ) && cursor.X < WID - 2 ) 
               { execute( 1, 0 ); break; }
           if( ( GetAsyncKeyState( 'Y' ) & 0x8000 ) && cursor.X > 1 && cursor.Y < HEI - 2 ) 
               { execute( -1, 1 ); break; }
           if( ( GetAsyncKeyState( 'X' ) & 0x8000 ) && cursor.Y < HEI - 2 ) 
               { execute( 0, 1 ); break; }
           if( ( GetAsyncKeyState( 'C' ) & 0x8000 ) && cursor.X < WID - 2 && cursor.Y < HEI - 2 ) 
               { execute( 1, 1 ); break; }
           if( ( GetAsyncKeyState( 'T' ) & 0x8000 ) ) 
               { teleport(); moveRobots(); break; }
           if( ( GetAsyncKeyState( 'Z' ) & 0x8000 ) ) 
               { waitForEnd(); break; }
       }
       console->flush(); printScore();
   }
   void teleport() {
       brd[cursor.X + WID * cursor.Y] = 32;
       cursor.X = rand() % ( WID - 2 ) + 1;
       cursor.Y = rand() % ( HEI - 2 ) + 1;
       int x = cursor.X + WID * cursor.Y;
       if( brd[x] == '*' || brd[x] == '+' || brd[x] == '~' ) {
           alive = false; brd[x] = 'Å';
       } else  brd[x] = '@'; 
   }
   void printScore() {
       console->setCursor( coord( 0, HEI ) ); console->setColor( 0x2a );
       std::cout << "      SCORE: " << score << "      ";
   }
   void execute( int x, int y ) {
       brd[cursor.X + WID * cursor.Y] = 32; cursor.X += x; cursor.Y += y;
       brd[cursor.X + WID * cursor.Y] = '@'; moveRobots();
   }
   void waitForEnd() {
       while( aliveRobots && alive ) {
           moveRobots(); displayBoard(); Sleep( 500 );
       }
   }
   void moveRobots() {
       int tx, ty;
       for( int y = 0; y < HEI; y++ ) {
           for( int x = 0; x < WID; x++ ) {
               if( brd[x + WID * y] != '+' ) continue;
               tx = x; ty = y;
               if( tx < cursor.X ) tx++; else if( tx > cursor.X ) tx--;
               if( ty < cursor.Y ) ty++; else if( ty > cursor.Y ) ty--;
               if( tx != x || ty != y ) {
                   brd[x + WID * y] = 32;
                   if( brd[tx + WID * ty] == 32 ) brd[tx + WID * ty] = '~';
                   else checkCollision( tx, ty );
               }
           }
       }
       for( int x = 0; x < WID * HEI; x++ ) {
           if( brd[x] == '~') brd[x] = '+';
       }
   }
   void checkCollision( int x, int y ) {
       if( cursor.X == x && cursor.Y == y ) { 
           alive = false; brd[x + y * WID] = 'Å'; return; 
       }
       x = x + y * WID; 
       if( brd[x] == '*' || brd[x] == '+' || brd[x] == '~' ) {
           if( brd[x] != '*' ) { aliveRobots--; score++; }
           brd[x] = '*'; aliveRobots--; score++;
       }
   }
   winConsole* console; char brd[WID * HEI]; 
   int robotsCount, score, aliveRobots;
   coord cursor; bool alive;

}; winConsole* winConsole::inst = 0; int main( int argc, char* argv[] ) {

   srand( ( unsigned )time( 0 ) );
   SetConsoleTitle( "Robots" );
   robots g; g.play(); return 0;

} </lang>