Robots: Difference between revisions
Content added Content deleted
(→{{header|Java}}: link to Java entry) |
m (→{{header|Kotlin}}: link to Kotlin entry) |
||
Line 214: | Line 214: | ||
=={{header|Kotlin}}== |
=={{header|Kotlin}}== |
||
{{trans|Java}} |
|||
<lang scala>// version 1.1.51 |
|||
See [[Robots/Kotlin]]. |
|||
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> |