Greed: Difference between revisions

From Rosetta Code
Content added Content deleted
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

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.