⚠️ Warning: This is a draft ⚠️

This means it might contain formatting issues, incorrect code, conceptual problems, or other severe issues.

If you want to help to improve and eventually enable this page, please fork RosettaGit's repository and open a merge request on GitHub.

==Code== {{works with|Java|8}}

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.*;

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);
        });
    }
}