Robots: Difference between revisions
(→{{header|Java}}: Added line to disable keystrokes until game starts which otherwise causes an exception) |
(→{{header|Java}}: link to Java entry) |
||
Line 210: | Line 210: | ||
=={{header|Java}}== |
=={{header|Java}}== |
||
{{works with|Java|8}} |
|||
<lang java>import java.awt.*; |
|||
import static java.awt.BasicStroke.*; |
|||
import java.awt.event.*; |
|||
import static java.lang.Math.abs; |
|||
import static java.lang.String.format; |
|||
import java.util.Random; |
|||
import javax.swing.*; |
|||
See [[Robots/Java]]. |
|||
public class Robots extends JPanel { |
|||
enum Grid { |
|||
Player("@"), Robot("+"), Scrap("*"), Mark("~"); |
|||
Grid(String s) { |
|||
symbol = s; |
|||
} |
|||
final String symbol; |
|||
} |
|||
final static int[][] dirs = {{-1, 1}, {0, 1}, {1, 1}, {-1, 0}, {1, 0}, |
|||
{-1, -1}, {0, -1}, {1, -1}}; |
|||
final static Random rand = new Random(); |
|||
final int nRows; |
|||
final int nCols; |
|||
Grid[][] grid; |
|||
int playerRow, playerCol, score, hiScore, level; |
|||
boolean gameOver = true; |
|||
Stroke dash; |
|||
public Robots() { |
|||
setPreferredSize(new Dimension(800, 650)); |
|||
setBackground(Color.white); |
|||
setForeground(Color.lightGray); |
|||
setFont(new Font("SansSerif", Font.PLAIN, 18)); |
|||
setFocusable(true); |
|||
nRows = 38; |
|||
nCols = 50; |
|||
dash = new BasicStroke(2.0f, CAP_BUTT, JOIN_MITER, 10.0f, |
|||
new float[]{5.0f}, 0.0f); |
|||
addMouseListener(new MouseAdapter() { |
|||
@Override |
|||
public void mousePressed(MouseEvent e) { |
|||
if (gameOver) { |
|||
startNewGame(); |
|||
repaint(); |
|||
} |
|||
} |
|||
}); |
|||
addKeyListener(new KeyAdapter() { |
|||
@Override |
|||
public void keyPressed(KeyEvent e) { |
|||
if (gameOver) return; // disable keystrokes until game starts |
|||
int keyCode = e.getKeyCode(); |
|||
if (keyCode == KeyEvent.VK_NUMPAD5) { |
|||
teleport(); |
|||
} else { |
|||
int k = keyCode - KeyEvent.VK_NUMPAD1; |
|||
if (k >= 0 && k < 9) { |
|||
move(k > 4 ? --k : k); |
|||
} |
|||
} |
|||
repaint(); |
|||
} |
|||
}); |
|||
} |
|||
void startNewGame() { |
|||
level = 1; |
|||
if (score > hiScore) |
|||
hiScore = score; |
|||
score = 0; |
|||
initGrid(); |
|||
gameOver = false; |
|||
} |
|||
void initGrid() { |
|||
grid = new Grid[nRows][nCols]; |
|||
teleport(); |
|||
int numRobots = 7 * level; |
|||
for (int i = 0; i < numRobots;) { |
|||
int r = rand.nextInt(nRows); |
|||
int c = rand.nextInt(nCols); |
|||
if (grid[r][c] == null) { |
|||
grid[r][c] = Grid.Robot; |
|||
i++; |
|||
} |
|||
} |
|||
} |
|||
boolean movePlayer(int r, int c) { |
|||
if (grid[r][c] != null) { |
|||
gameOver = true; |
|||
} else { |
|||
grid[playerRow][playerCol] = null; |
|||
playerRow = r; |
|||
playerCol = c; |
|||
grid[r][c] = Grid.Player; |
|||
} |
|||
return !gameOver; |
|||
} |
|||
void move(int d) { |
|||
int c = playerCol + dirs[d][0]; |
|||
int r = playerRow + dirs[d][1]; |
|||
if (!withinBounds(r, c)) |
|||
return; |
|||
if (!movePlayer(r, c)) |
|||
return; |
|||
for (int rr = 0; rr < nRows; rr++) |
|||
for (int cc = 0; cc < nCols; cc++) { |
|||
if (grid[rr][cc] == Grid.Robot) { |
|||
// calc new r and c based on dx + cc and dy + rr |
|||
int nc = (c == cc ? 0 : (c - cc) / abs(c - cc)) + cc; |
|||
int nr = (r == rr ? 0 : (r - rr) / abs(r - rr)) + rr; |
|||
if (!withinBounds(nr, nc)) |
|||
continue; |
|||
grid[rr][cc] = null; |
|||
if (grid[nr][nc] == Grid.Player) { |
|||
gameOver = true; |
|||
return; /* EARLY RETURN */ |
|||
} else if (grid[nr][nc] != null) { |
|||
score++; |
|||
if (grid[nr][nc] != Grid.Scrap) |
|||
score++; |
|||
grid[nr][nc] = Grid.Scrap; |
|||
} else { |
|||
// avoid processing the same robot twice |
|||
grid[nr][nc] = Grid.Mark; |
|||
} |
|||
} |
|||
} |
|||
int robotsLeft = 0; |
|||
for (int rr = 0; rr < nRows; rr++) |
|||
for (int cc = 0; cc < nCols; cc++) { |
|||
if (grid[rr][cc] == Grid.Mark) |
|||
grid[rr][cc] = Grid.Robot; |
|||
if (grid[rr][cc] == Grid.Robot) |
|||
robotsLeft++; |
|||
} |
|||
if (robotsLeft == 0) { |
|||
level++; |
|||
initGrid(); |
|||
} |
|||
} |
|||
void teleport() { |
|||
movePlayer(rand.nextInt(nRows), rand.nextInt(nCols)); |
|||
} |
|||
void drawBorder(Graphics2D g) { |
|||
g.setStroke(dash); |
|||
g.setColor(getForeground()); |
|||
g.drawRect(22, 20, getWidth() - 41, getHeight() - 72); |
|||
} |
|||
void drawGrid(Graphics2D g) { |
|||
for (int r = 0; r < nRows; r++) |
|||
for (int c = 0; c < nCols; c++) { |
|||
if (grid[r][c] != null) |
|||
g.drawString(grid[r][c].symbol, 24 + c * 15, 36 + r * 15); |
|||
} |
|||
} |
|||
void drawStartScreen(Graphics2D g) { |
|||
g.setColor(Color.gray); |
|||
g.setFont(new Font("SansSerif", Font.BOLD, 48)); |
|||
g.drawString("robots", 315, 280); |
|||
g.setFont(getFont()); |
|||
g.drawString("(use numpad to move player)", 270, 350); |
|||
g.drawString("(teleport is numpad 5)", 300, 380); |
|||
g.drawString("(click to start)", 328, 410); |
|||
} |
|||
void drawScore(Graphics2D g) { |
|||
g.setColor(Color.gray); |
|||
g.setFont(getFont()); |
|||
String s = format("hiscore %s score %s", hiScore, score); |
|||
g.drawString(s, 30, getHeight() - 17); |
|||
} |
|||
boolean withinBounds(int r, int c) { |
|||
return c >= 0 && c < nCols && r >= 0 && r < nRows; |
|||
} |
|||
@Override |
|||
public void paintComponent(Graphics gg) { |
|||
super.paintComponent(gg); |
|||
Graphics2D g = (Graphics2D) gg; |
|||
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, |
|||
RenderingHints.VALUE_ANTIALIAS_ON); |
|||
drawBorder(g); |
|||
drawScore(g); |
|||
if (gameOver) { |
|||
drawStartScreen(g); |
|||
} else { |
|||
drawGrid(g); |
|||
} |
|||
} |
|||
public static void main(String[] args) { |
|||
SwingUtilities.invokeLater(() -> { |
|||
JFrame f = new JFrame(); |
|||
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); |
|||
f.setTitle("Robots"); |
|||
f.setResizable(false); |
|||
f.add(new Robots(), BorderLayout.CENTER); |
|||
f.pack(); |
|||
f.setLocationRelativeTo(null); |
|||
f.setVisible(true); |
|||
}); |
|||
} |
|||
}</lang> |
|||
=={{header|Kotlin}}== |
=={{header|Kotlin}}== |
Revision as of 08:10, 30 October 2017
This page uses content from Wikipedia. The original article was at Robots_(computer_game). The list of authors can be seen in the page history. As with Rosetta Code, the text of Wikipedia is available under the GNU FDL. (See links for details on variance) |
The task is to implement a clone of Ken Arnold's turn-based game Robots.
Simple game where its only objective is to escape from a number of robots, which have been programmed to kill the player.
C++
Windows Console implementation - No safe teleport is implemeted, just the random one.
<lang cpp>
- include <windows.h>
- include <iostream>
- 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>
Java
See Robots/Java.
Kotlin
<lang scala>// version 1.1.51
import java.util.Random import java.awt.* import java.awt.BasicStroke.* import java.awt.event.* import javax.swing.JFrame import javax.swing.JPanel import javax.swing.SwingUtilities
val rand = Random()
val dirs = listOf(
-1 to 1, 0 to 1, 1 to 1, -1 to 0, 1 to 0, -1 to -1, 0 to -1, 1 to -1
)
class Robots : JPanel() {
val nRows = 38 val nCols = 50 val dash = BasicStroke(2.0f, CAP_BUTT, JOIN_MITER, 10.0f, floatArrayOf(5.0f), 0.0f)
var playerRow = 0 var playerCol = 0 var score = 0 var hiScore = 0 var level = 0 var gameOver = true
enum class Grid(val symbol: String) { Player("@"), Robot("+"), Scrap("*"), Mark("~") }
lateinit var grid: Array<Array<Grid?>>
init { preferredSize = Dimension(800, 650) background = Color.white foreground = Color.lightGray font = Font("SansSerif", Font.PLAIN, 18) isFocusable = true
addMouseListener(object : MouseAdapter() { override fun mousePressed(e: MouseEvent) { if (gameOver) { startNewGame() repaint() } } })
addKeyListener(object : KeyAdapter() { override fun keyPressed(e: KeyEvent) { if (gameOver) return // disable keystrokes until game starts val keyCode = e.keyCode if (keyCode == KeyEvent.VK_NUMPAD5) { teleport() } else { var k = keyCode - KeyEvent.VK_NUMPAD1 if (k in 0..8) move(if (k > 4) --k else k) } repaint() } }) }
fun startNewGame() { level = 1 if (score > hiScore) hiScore = score score = 0 initGrid() gameOver = false }
fun initGrid() { grid = Array(nRows) { arrayOfNulls<Grid>(nCols) } teleport() val numRobots = 7 * level var i = 0 while (i < numRobots) { val r = rand.nextInt(nRows) val c = rand.nextInt(nCols) if (grid[r][c] == null) { grid[r][c] = Grid.Robot i++ } } }
fun movePlayer(r: Int, c: Int): Boolean { if (grid[r][c] != null) { gameOver = true } else { grid[playerRow][playerCol] = null playerRow = r playerCol = c grid[r][c] = Grid.Player } return !gameOver }
fun move(d: Int) { val c = playerCol + dirs[d].first val r = playerRow + dirs[d].second
if (!withinBounds(r, c)) return if (!movePlayer(r, c)) return
for (rr in 0 until nRows) { for (cc in 0 until nCols) { if (grid[rr][cc] == Grid.Robot) { // calc new r and c based on dx + cc and dy + rr val nc = (if (c == cc) 0 else (c - cc) / Math.abs(c - cc)) + cc val nr = (if (r == rr) 0 else (r - rr) / Math.abs(r - rr)) + rr if (!withinBounds(nr, nc)) continue grid[rr][cc] = null
if (grid[nr][nc] == Grid.Player) { gameOver = true return /* EARLY RETURN */ } else if (grid[nr][nc] != null) { score++ if (grid[nr][nc] != Grid.Scrap) score++ grid[nr][nc] = Grid.Scrap } else { // avoid processing the same robot twice grid[nr][nc] = Grid.Mark } } } }
var robotsLeft = 0 for (rr in 0 until nRows) { for (cc in 0 until nCols) { if (grid[rr][cc] == Grid.Mark) grid[rr][cc] = Grid.Robot if (grid[rr][cc] == Grid.Robot) robotsLeft++ } } if (robotsLeft == 0) { level++ initGrid() } }
fun teleport() { movePlayer(rand.nextInt(nRows), rand.nextInt(nCols)) }
fun drawBorder(g: Graphics2D) { g.stroke = dash g.color = foreground g.drawRect(22, 20, width - 41, height - 72) }
fun drawGrid(g: Graphics2D) { for (r in 0 until nRows) { for (c in 0 until nCols) { if (grid[r][c] != null) g.drawString(grid[r][c]!!.symbol, 24 + c * 15, 36 + r * 15) } } }
fun drawStartScreen(g: Graphics2D) { g.color = Color.gray g.font = Font("SansSerif", Font.BOLD, 48) g.drawString("robots", 315, 280)
g.font = this.font g.drawString("(use numpad to move player)", 270, 350) g.drawString("(teleport is numpad 5)", 300, 380) g.drawString("(click to start)", 328, 410) }
fun drawScore(g: Graphics2D) { g.color = Color.gray g.font = this.font val s = String.format("hiscore %s score %s", hiScore, score) g.drawString(s, 30, height - 17) }
fun withinBounds(r: Int, c: Int) = (c in 0 until nCols) && (r in 0 until nRows)
override fun paintComponent(gg: Graphics) { super.paintComponent(gg) val g = gg as Graphics2D g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON) drawBorder(g) drawScore(g) if (gameOver) drawStartScreen(g) else drawGrid(g) }
}
fun main(args: Array<String>) {
SwingUtilities.invokeLater { val f = JFrame() with (f) { defaultCloseOperation = JFrame.EXIT_ON_CLOSE title = "Robots" isResizable = false add(Robots(), BorderLayout.CENTER) pack() setLocationRelativeTo(null) isVisible = true } }
}</lang>