Greed: Difference between revisions
m (→{{headerJava}}: added link to Java entry) |
(Added Kotlin) |
||
Line 138: | Line 138: | ||
} |
} |
||
</lang> |
</lang> |
||
=={{header|Kotlin}}== |
|||
{{trans|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> |
|||
=={{header|Java}}== |
=={{header|Java}}== |
Revision as of 01:07, 7 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.
<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.