Robots/Kotlin

Revision as of 13:59, 30 October 2017 by rosettacode>Fwend (Moved Kotlin entry to separate page)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Code

Translation of: Java

<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>