Greed: Difference between revisions
m →{{header|REXX}}: added wording in the REXX section header about an OS dependency. |
m →{{header|REXX}}: shortened the output sections. |
||
Line 463: | Line 463: | ||
──────── |
──────── |
||
──────── enter a move ──or── enter QUIT to quit. (score is: 6) |
──────── enter a move ──or── enter QUIT to quit. (score is: 6) |
||
quit ◄■■■■■■■■■■■■■ user input |
|||
</pre> |
|||
{{out|output|text=: the 3<sup>rd</sup> screen shown.}} |
|||
<pre> |
|||
↓ |
|||
1636166561333644938615925878672969839136949348125385742112849651343354296271245 |
|||
4935939188413836477495369151362748736256329449564639583731265554747438655579797 |
|||
2761827294343258918258167935625127433626644177165772453435474591949917695547965 |
|||
53367846463736826763986884759899724514997762521649898992391917 3912697265898925 |
|||
4952948995581413589577455233495962736898536553933712711747529 1 371573895413265 |
|||
532864374567248546851664532617648257116237712895866925224443 799 14145324756787 |
|||
96826484164758284343761542591115968181128196265187547153859 92117 4235211148126 |
|||
4771918124154627513339665771138169237888886368882335865655 2689465 352121961215 |
|||
794644718989445262471866768299551827168758297323537929749 815519895 87457566428 |
|||
93479698326176241138667327228421215218547458884581988529132658754459 6923272597 |
|||
──────── |
──────── quitting. |
||
<pre> |
</pre> |
Revision as of 01:37, 8 February 2018
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.
C++
Windows console version.
![](http://static.miraheze.org/rosettacodewiki/thumb/3/3d/NewGreedCpp.png/200px-NewGreedCpp.png)
<lang cpp>
- include <windows.h>
- include <iostream>
- 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
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
This REXX version's only dependency is that the DOS command cls is used to clear the terminal screen.
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 (by Matthew Day) from the console. */ 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 ◄■■■■■■■■■■■■■ user input
- 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) quit ◄■■■■■■■■■■■■■ user input ──────── quitting.