Greed: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎{{header|REXX}}: added the REXX computer programming language.)
m (→‎{{header|REXX}}: added wording to the REXX section header.)
Line 348: Line 348:


=={{header|REXX}}==
=={{header|REXX}}==
No attempt was made to validate the input the input arguments (parameters) for this REXX program.


<lang rexx>/*REXX program lets a user play the game of GREED from the console (terminal). */
<lang rexx>/*REXX program lets a user play the game of GREED from the console (terminal). */
parse arg sw sd @ b ?r . /*obtain optional argumenst from the CL*/
parse arg sw sd @ b ?r . /*obtain optional argumenst from the CL*/

Revision as of 01:10, 8 February 2018

Greed is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

This task is about making a clone of the game "GREED" by Matthew Day.

This game is played on a grid of 79 column by 22 rows of random numbers from 1 to 9. The player location is signified by the '@' symbol.

The object of Greed is to erase as much of the screen as possible by moving around (all 8 directions are allowed) in this grid. When you move in a direction, you erase N number of grid squares in that direction, N being the first number in that direction. Your score reflects the total number of squares eaten.

You may not make a move that places you off the grid or over a previously eaten square.

The game is over if there is no more valid moves.

Video on YouTube


C++

Windows console version.

<lang cpp>

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

const int WID = 79, HEI = 22; const float NCOUNT = ( float )( WID * HEI );

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 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 greed { public:

   greed() { console = winConsole::getInstamnce(); }
   ~greed() { console->kill(); }
   void play() {
       char g; do {
           console->showCursor( false ); createBoard();
           do { displayBoard(); getInput(); } while( existsMoves() );
           displayBoard(); console->setCursor( coord( 0, 24 ) ); console->setColor( 0x07 );
           console->setCursor( coord( 19,  8 ) ); std::cout << "+----------------------------------------+";
           console->setCursor( coord( 19,  9 ) ); std::cout << "|               GAME OVER                |";
           console->setCursor( coord( 19, 10 ) ); std::cout << "|            PLAY AGAIN(Y/N)?            |";
           console->setCursor( coord( 19, 11 ) ); std::cout << "+----------------------------------------+";
           console->setCursor( coord( 48, 10 ) ); console->showCursor( true ); console->flush(); std::cin >> g;
       } while( g == 'Y' || g == 'y' );
   }

private:

   void createBoard() {
       for( int y = 0; y < HEI; y++ ) {
           for( int x = 0; x < WID; x++ ) {
               brd[x + WID * y] = rand() % 9 + 1;
           }
       }
       cursor.set( rand() % WID, rand() % HEI );
       brd[cursor.X + WID * cursor.Y] = 0; score = 0;
       printScore();
   }
   void displayBoard() {
       console->setCursor( coord() ); int i;

for( int y = 0; y < HEI; y++ ) {

           for( int x = 0; x < WID; x++ ) {
               i = brd[x + WID * y]; console->setColor( 6 + i );
               if( !i ) std::cout << " "; else std::cout << i;
           }
           std::cout << "\n";
       }
       console->setColor( 15 ); console->setCursor( cursor ); std::cout << "@";
   }
   void getInput() { 
       while( 1 ) {
           if( ( GetAsyncKeyState( 'Q' ) & 0x8000 ) && cursor.X > 0 && cursor.Y > 0 ) { execute( -1, -1 ); break; }
           if( ( GetAsyncKeyState( 'W' ) & 0x8000 ) &&  cursor.Y > 0 ) { execute( 0, -1 ); break; }
           if( ( GetAsyncKeyState( 'E' ) & 0x8000 ) && cursor.X < WID - 1 && cursor.Y > 0 ) { execute( 1, -1 ); break; }
           if( ( GetAsyncKeyState( 'A' ) & 0x8000 ) && cursor.X > 0 ) { execute( -1, 0 ); break; }
           if( ( GetAsyncKeyState( 'D' ) & 0x8000 ) && cursor.X < WID - 1 ) { execute( 1, 0 ); break; }
           if( ( GetAsyncKeyState( 'Y' ) & 0x8000 ) && cursor.X > 0 && cursor.Y < HEI - 1 ) { execute( -1, 1 ); break; }
           if( ( GetAsyncKeyState( 'X' ) & 0x8000 ) && cursor.Y < HEI - 1 ) { execute( 0, 1 ); break; }
           if( ( GetAsyncKeyState( 'C' ) & 0x8000 ) && cursor.X < WID - 1 && cursor.Y < HEI - 1 ) { execute( 1, 1 ); break; }
       }
       console->flush(); printScore();
   }
   void printScore() {
       console->setCursor( coord( 0, 24 ) ); console->setColor( 0x2a );
       std::cout << "      SCORE: " << score << " : " << score * 100.f / NCOUNT << "%      ";
   }
   void execute( int x, int y ) {
       int i = brd[cursor.X + x + WID * ( cursor.Y + y )];
       if( countSteps( i, x, y ) ) {
           score += i;
           while( i ) {
               --i; cursor.X += x; cursor.Y += y;
               brd[cursor.X + WID * cursor.Y] = 0;
           }
       }
   }
   bool countSteps( int i, int x, int y ) {
       coord t( cursor.X, cursor.Y );
       while( i ) {
           --i; t.X += x; t.Y += y;
           if( t.X < 0 || t.Y < 0 || t.X >= WID || t.Y >= HEI || !brd[t.X + WID * t.Y] ) return false;
       }
       return true;
   }
   bool existsMoves() {
       int i;
       for( int y = -1; y < 2; y++ ) {
           for( int x = -1; x < 2; x++ ) {
               if( !x && !y ) continue;
               i = brd[cursor.X + x + WID * ( cursor.Y + y )];
               if( i > 0 && countSteps( i, x, y ) ) return true;
           }
       }
       return false;
   }
   winConsole* console;
   int brd[WID * HEI];
   float score; coord cursor;

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

   srand( ( unsigned )time( 0 ) );
   SetConsoleTitle( "Greed" );
   greed g; g.play(); return 0;

} </lang>

Kotlin

Translation of: C++
Works with: Windows 10

Note that this version uses the Z key (rather than the Y key) to move diagonally downwards to the left. <lang scala>// Kotlin Native v0.5

import kotlinx.cinterop.* import platform.posix.* import platform.windows.*

const val WID = 79 const val HEI = 22 const val NCOUNT = (WID * HEI).toFloat()

class WinConsole {

   val conOut: HANDLE
   val conIn: HANDLE
   private constructor() {
       conOut = GetStdHandle(STD_OUTPUT_HANDLE)!!
       conIn  = GetStdHandle(STD_INPUT_HANDLE)!!
       showCursor(FALSE)
   }
   fun showCursor(s: WINBOOL) {
       memScoped {
           val ci = alloc<CONSOLE_CURSOR_INFO>().apply { dwSize = 1; bVisible = s }
           SetConsoleCursorInfo(conOut, ci.ptr)
       }
   }
   fun setColor(clr: WORD) = SetConsoleTextAttribute(conOut, clr)
   fun setCursor(p: COORD) = SetConsoleCursorPosition(conOut, p.readValue())
   fun flush() =  FlushConsoleInputBuffer(conIn)
   fun kill() {
       inst = null
   }
   companion object {
       val instance: WinConsole 
           get() {
               if (inst == null) inst = WinConsole()
               return inst!!
           }
       private var inst: WinConsole? = null
   }

}

class Greed {

   private val console: WinConsole
   private val brd = IntArray(WID * HEI)
   private var score = 0
   private lateinit var cursor: COORD
   init {
       console = WinConsole.instance
       SetConsoleTitleW("Greed")
   }
   fun destroy() {
       nativeHeap.free(cursor)
       console.kill()
   }
   fun play() {
       memScoped {
           val coord1 = alloc<COORD>().apply { X = 0;  Y = 24 }
           val coord2 = alloc<COORD>().apply { X = 19; Y = 8  }
           val coord3 = alloc<COORD>().apply { X = 19; Y = 9  }
           val coord4 = alloc<COORD>().apply { X = 19; Y = 10  }
           val coord5 = alloc<COORD>().apply { X = 19; Y = 11  }
           val coord6 = alloc<COORD>().apply { X = 48; Y = 10  }
           do {
               console.showCursor(FALSE)
               createBoard()
               do {
                   displayBoard()
                   getInput()
               }
               while (existsMoves())
               displayBoard()
               with (console) {
                   setCursor(coord1)
                   setColor(0x07)
                   setCursor(coord2);  print("+----------------------------------------+")
                   setCursor(coord3);  print("|               GAME OVER                |")
                   setCursor(coord4);  print("|            PLAY AGAIN(Y/N)?            |")
                   setCursor(coord5);  print("+----------------------------------------+")
                   setCursor(coord6)
                   showCursor(TRUE)
                   flush()
               }
               val g = readLine()!!.toUpperCase()
           }
           while (g.length >= 1 && g[0] == 'Y')
       }
       destroy()
   }
   private fun createBoard() {
       for (y in 0 until HEI) {
           for (x in 0 until WID) {
               brd[x + WID * y] = rand() % 9 + 1
           }
       }
       cursor = nativeHeap.alloc<COORD>().apply {
           X = (rand() % WID).toShort(); Y = (rand() % HEI).toShort()
       }
       brd[cursor.X + WID * cursor.Y] = 0
       score = 0
       printScore()
   }
   private fun displayBoard() {
       memScoped {
           val coord = alloc<COORD>().apply { X = 0; Y = 0 }
           console.setCursor(coord)
       }
       for (y in 0 until HEI) {
           for (x in 0 until WID) {
               val i = brd[x + WID * y]
               console.setColor((6 + i).toShort())
               print(if (i == 0) " " else "$i")
           }
           println()
       }
       console.setColor(15)
       console.setCursor(cursor)
       print("@")
   }
   private fun checkKey(k: Char) = (GetAsyncKeyState(k.toInt()).toInt() and 0x8000) != 0
   private fun getInput() {
       while (true) {
           if (checkKey('Q') && cursor.X > 0 && cursor.Y > 0) { execute(-1, -1); break }
           if (checkKey('W') && cursor.Y > 0) { execute(0, -1); break }
           if (checkKey('E') && cursor.X < WID - 1 && cursor.Y > 0) { execute(1, -1); break }
           if (checkKey('A') && cursor.X > 0) { execute(-1, 0); break }
           if (checkKey('D') && cursor.X < WID - 1) { execute(1, 0); break }
           if (checkKey('Z') && cursor.X > 0 && cursor.Y < HEI - 1) { execute(-1, 1); break }
           if (checkKey('X') && cursor.Y < HEI - 1) { execute(0, 1); break }
           if (checkKey('C') && cursor.X < WID - 1 && cursor.Y < HEI - 1) { execute(1, 1); break }
       }
       console.flush()
       printScore()
   }
   private fun printScore() {
       memScoped {
           val coord = alloc<COORD>().apply { X = 0; Y = 24 }
           console.setCursor(coord)
       }
       console.setColor(0x2a)
       print("      SCORE: $score :  ${score * 100.0f / NCOUNT}%      ")
   }
   private fun execute(x: Int, y: Int) {
       var i = brd[cursor.X + x + WID * ( cursor.Y + y )]
       if (countSteps(i, x, y)) {
           score += i
           while (i-- != 0) {
               cursor.X = (cursor.X + x).toShort()
               cursor.Y = (cursor.Y + y).toShort()
               brd[cursor.X + WID * cursor.Y] = 0
           }
       }
   }
   private fun countSteps(i: Int, x: Int, y: Int): Boolean {
       var ii = i
       memScoped {
           val t = alloc<COORD>().apply { X = cursor.X; Y = cursor.Y }
           while (ii-- != 0) {
               t.X = (t.X + x).toShort()
               t.Y = (t.Y + y).toShort()
               if (t.X < 0 || t.Y < 0 || t.X >= WID || t.Y >= HEI || brd[t.X + WID * t.Y] == 0 ) return false
           }
       }
       return true
   }
   private fun existsMoves(): Boolean {
       for (y in -1..1) {
           for (x in -1..1) {
               if (x == 0 && y == 0) continue
               val i = brd[cursor.X + x + WID * ( cursor.Y + y )]
               if (i > 0 && countSteps(i, x, y)) return true
           }
       }
       return false
   }

}

fun main(args: Array<String>) {

   srand(time(null).toInt())
   Greed().play()

}</lang>

Java

See Greed/Java.

REXX

No attempt was made to validate the input the input arguments (parameters) for this REXX program. <lang rexx>/*REXX program lets a user play the game of GREED from the console (terminal). */ parse arg sw sd @ b ?r . /*obtain optional argumenst from the CL*/ if sw== | sw=="," then sw=79 /*cols specified? Then use the default*/ if sd== | sd=="," then sd=22 /*rows " " " " " */ if @== | @=="," then @= '@' /*here " " " " " */ if b== | b=="," then b= ' ' /*blank " " " " " */ if datatype(?r, 'W') then call random ,,?r /*maybe use a seed for the RANDOM BIF*/ if length(@)==2 & datatype(@,'X') then @=x2c(@) /*maybe use @ char for current pos. */ if length(b)==2 & datatype(b,'X') then b=x2c(b) /* " " B char for background. */ call init

         do  until  # == sw*sd                  /*keep playing until the grid is blank.*/
         call show 1                            /*show the playing field (grid) to term*/
         call ask                               /*obtain user's move, validate, or quit*/
         if \move()  then leave                 /*perform the user's move as per @ loc.*/
         end   /*until*/                        /* [↑]  Also, if out─of─bounds, LEAVE. */
     if show(1)==sw*sd  then say ____ "You've won, the grid is blank,  your score is: " #
     if @.!r.!c==@.     then say ____ "Game over  (out─of─bounds),  your score is: "    #
     if @.!r.!c==b      then say ____ "Game over  (a blank location),  your score is: " #
     exit  2

exit 0 /*stick a fork in it, we're all done. */ /*──────────────────────────────────────────────────────────────────────────────────────*/ ask: do forever /*play 'til done, or no possible moves.*/

         say  ____  'moves:'  ____  '   Q= ◄↑   W= ↑    E= ►↑'
         say  ____  'moves:'  ____  '   A= ◄            D= ►'
         say  ____  'moves:'  ____  '   Z= ◄↓   X= ↓    C= ►↓'
         say  ____
         say  ____ 'enter a move     ──or──  enter   QUIT   to quit.  (score is: '   #")"
         parse pull  $ 2 1 quit . 1 o$;              upper $ quit;
         if abbrev('QUIT', quit, 2) | abbrev('QQUIT', quit, 2)  then leave
         if length( space(o$) )==1  &  pos($, 'QWEADZXC')\==0   then return
         say ____ '***error*** invalid move:'  space(o$);            say
         end   /*forever*/

halt: say; say ____ 'quitting.'; exit 1 /*──────────────────────────────────────────────────────────────────────────────────────*/ init: @.= 'Ω'; ____= copies('─', 8) /*out─of─bounds literal; fence for SAYs*/

     signal on halt                             /*handle pressing of  Ctrl-Break  key. */
         do   r=1  for sd
           do c=1  for sw;  @.r.c=random(1, 9)  /*assign grid area to random digs (1►9)*/
           end   /*c*/
         end     /*r*/
     !r=random(1, sd);  !c=random(1, sw);  @.!r.!c=@;   return    /*assign 1st position*/

/*──────────────────────────────────────────────────────────────────────────────────────*/ move: @.!r.!c=b /*blank out this "start" position. */

     @@=.                                       /*nullify the count of move positions. */
         do until @@==0;          select
                                  when $== 'Q'  then do;   !r=!r - 1;   !c=!c - 1;    end
                                  when $== 'W'  then       !r=!r - 1
                                  when $== 'E'  then do;   !r=!r - 1;   !c=!c + 1;    end
                                  when $== 'A'  then                    !c=!c - 1
                                  when $== 'D'  then                    !c=!c + 1
                                  when $== 'Z'  then do;   !r=!r + 1;   !c=!c - 1;    end
                                  when $== 'X'  then       !r=!r + 1
                                  when $== 'C'  then do;   !r=!r + 1;   !c=!c + 1;    end
                                  end   /*select*/
         ?=@.!r.!c;  if ?==@. | ?==b  then return 0   /*cease if out─of─bounds or blank*/
         if @@==.  then @@=?;   if datatype(@@, 'W')  then @@=@@ - 1    /*diminish cnt.*/
         @.!r.!c=b                              /*blank out a single grid position.    */
         end   /*until*/
     @.!r.!c=@;                   return 1      /*signify current grid position with @ */

/*──────────────────────────────────────────────────────────────────────────────────────*/ show: arg tell; #=0; if tell then do; 'CLS'; say left(,max(0,!c-1))"↓"; end

         do   r=1  for sd;            _=        /* [↑]  DOS cmd  CLS  clears the screen*/
           do c=1  for sw; ?=@.r.c;   _=_ || ?  /*construct row of the grid for display*/
           if ?==b | ?==@  then #=# + 1         /*Position==b ─or─ @?  Then bump score.*/
           end   /*c*/
         if r==!r  then _=_ '◄'                 /*indicate   row  of current position. */
         if tell   then say _                   /*display   a row of grid to screen.   */
         end     /*r*/; say;      return #      /*SHOW also counts # of blanks (score).*/</lang>

A note on the OUTPUT sections:   each screen displayed is shown below as a separate OUTPUT section.

The following are the screen shots when inputs used   (size of the grid)   are:     22   10

output :     the 1st screen shown.
                                                         ↓
1636166561333644938615925878672969839136949348125385742112849651343354296271245
4935939188413836477495369151362748736256329449564639583731265554747438655579797
2761827294343258918258167935625127433626644177165772453435474591949917695547965
5336784646373682676398688475989972451499776252164989899239191733912697265898925
4952948995581413589577455233495962736898536553933712711747529619371573895413265
5328643745672485468516645326176482571162377128958669252244431799914145324756787
9682648416475828434376154259111596818112819626518754715385939211764235211148126
4771918124154627513339665771138169237888886368882335865655526894655352121961215
794644718989445262471866768299551827168758297323537929749@815519895387457566428 ◄
9347969832617624113866732722842121521854745888458198852913265875445986923272597

──────── moves: ────────    Q= ◄↑   W= ↑    E= ►↑
──────── moves: ────────    A= ◄            D= ►
──────── moves: ────────    Z= ◄↓   X= ↓    C= ►↓
────────
──────── enter a move     ──or──  enter   QUIT   to quit.  (score is:  1)
e
output :     the 2nd screen shown.
                                                              ↓
1636166561333644938615925878672969839136949348125385742112849651343354296271245
4935939188413836477495369151362748736256329449564639583731265554747438655579797
2761827294343258918258167935625127433626644177165772453435474591949917695547965
53367846463736826763986884759899724514997762521649898992391917@3912697265898925 ◄
4952948995581413589577455233495962736898536553933712711747529 19371573895413265
532864374567248546851664532617648257116237712895866925224443 799914145324756787
96826484164758284343761542591115968181128196265187547153859 9211764235211148126
4771918124154627513339665771138169237888886368882335865655 26894655352121961215
794644718989445262471866768299551827168758297323537929749 815519895387457566428
9347969832617624113866732722842121521854745888458198852913265875445986923272597

──────── moves: ────────    Q= ◄↑   W= ↑    E= ►↑
──────── moves: ────────    A= ◄            D= ►
──────── moves: ────────    Z= ◄↓   X= ↓    C= ►↓
────────
──────── enter a move     ──or──  enter   QUIT   to quit.  (score is:  6)
c
output :     the 3rd screen shown.
                                                                     ↓
1636166561333644938615925878672969839136949348125385742112849651343354296271245
4935939188413836477495369151362748736256329449564639583731265554747438655579797
2761827294343258918258167935625127433626644177165772453435474591949917695547965
53367846463736826763986884759899724514997762521649898992391917 3912697265898925
4952948995581413589577455233495962736898536553933712711747529 1 371573895413265
532864374567248546851664532617648257116237712895866925224443 799 14145324756787
96826484164758284343761542591115968181128196265187547153859 92117 4235211148126
4771918124154627513339665771138169237888886368882335865655 2689465 352121961215
794644718989445262471866768299551827168758297323537929749 815519895 87457566428
93479698326176241138667327228421215218547458884581988529132658754459 6923272597

──────── Game over  (out─of─bounds),  your score is:  12