MagisterRain

Minesweeper

Jul 19th, 2018
131
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 8.42 KB | None | 0 0
  1. /*
  2.  * Warning!
  3.  * This game has 3 bugs!
  4.  * 1. Lagging.
  5.  * Maybe it takes some lags because I use to many loops? Idk...
  6.  * I read javadocs, but dont understand why it does lags.
  7.  * 2. Game can't mark cell where player does lose
  8.  * 3. If u notice, end-game screen graphics take some effect
  9.  * like gradient. This is bug, not mine idea...
  10.  */
  11. package jsx;
  12.  
  13. import java.awt.Color;
  14. import java.awt.Dimension;
  15. import java.awt.Font;
  16. import java.awt.FontMetrics;
  17. import java.awt.Graphics;
  18. import java.awt.Graphics2D;
  19. import java.awt.RenderingHints;
  20. import java.awt.event.KeyAdapter;
  21. import java.awt.event.KeyEvent;
  22. import java.awt.event.MouseAdapter;
  23. import java.awt.event.MouseEvent;
  24. import java.util.ArrayList;
  25. import java.util.List;
  26. import java.util.Random;
  27.  
  28. import javax.swing.JFrame;
  29. import javax.swing.JPanel;
  30. import javax.swing.WindowConstants;
  31.  
  32. public class Minesweeper extends JPanel {
  33.  
  34.     final static int MINES = 12;
  35.  
  36.     List<Tile> field;
  37.     Random random;
  38.     boolean inGame, isWin;
  39.     int winCondition;
  40.  
  41.     enum Flag {
  42.         NONE, OPEN, MARKED, CRUSHED, ERROR, VERIFIED;
  43.     }
  44.  
  45.     public Minesweeper() {
  46.         random = new Random();
  47.  
  48.         setPreferredSize(new Dimension(346, 368));
  49.         setFocusable(true);
  50.         addKeyListener(new KeyAdapter() {
  51.             @Override
  52.             public void keyPressed(KeyEvent e) {
  53.                 if (e.getKeyCode() == KeyEvent.VK_ESCAPE)
  54.                     init();
  55.             }
  56.         });
  57.         addMouseListener(new MouseAdapter() {
  58.             @Override
  59.             public void mouseClicked(MouseEvent e) {
  60.                 if (inGame) {
  61.                     if (e.getButton() == MouseEvent.BUTTON1) {
  62.                         Tile tile = getTile(e.getX(), e.getY());
  63.                         if (tile == null)
  64.                             return;
  65.  
  66.                         clickLeft(tile);
  67.                     } else if (e.getButton() == MouseEvent.BUTTON3) {
  68.                         Tile tile = getTile(e.getX(), e.getY());
  69.                         if (tile == null)
  70.                             return;
  71.  
  72.                         clickRight(tile);
  73.                     }
  74.                 } else {
  75.                     init();
  76.                 }
  77.             }
  78.         });
  79.         init();
  80.     }
  81.  
  82.     void init() {
  83.         inGame = true;
  84.         isWin = false;
  85.         winCondition = 0;
  86.         generate();
  87.         calculate();
  88.         repaint();
  89.     }
  90.  
  91.     void calculate() {
  92.         for (Tile t0 : field) {
  93.             if (!t0.isMined()) {
  94.                 List<Tile> temp = getNearby(t0);
  95.                 for (Tile t1 : temp) {
  96.                     if (t1.isMined()) {
  97.                         t0.setValue(t0.getValue() + 1);
  98.                     }
  99.                 }
  100.             }
  101.         }
  102.         for (Tile t0 : field) {
  103.             if (t0.getValue() > 0) {
  104.                 winCondition++;
  105.             }
  106.         }
  107.     }
  108.  
  109.     void generate() {
  110.         field = new ArrayList<Tile>();
  111.         for (int x = 0; x < 9; x++) {
  112.             for (int y = 0; y < 9; y++) {
  113.                 field.add(new Tile(x, y));
  114.             }
  115.         }
  116.         for (int i = 0; i < MINES + 1; i++) {
  117.             Tile t = field.get(random.nextInt(field.size()));
  118.             if (t.isMined()) {
  119.                 i--;
  120.             } else {
  121.                 t.setMined();
  122.  
  123.             }
  124.         }
  125.     }
  126.  
  127.     void checkWin() {
  128.         int counter = 0;
  129.         for (int i = 0; i < field.size(); i++) {
  130.             Tile t0 = field.get(i);
  131.             if (t0.isFlag(Flag.OPEN) && t0.getValue() > 0) {
  132.                 counter++;
  133.             }
  134.         }
  135.         if (counter == winCondition) {
  136.             inGame = false;
  137.             isWin = true;
  138.         }
  139.     }
  140.  
  141.     List<Tile> getNearby(Tile t) {
  142.         List<Tile> out = new ArrayList<Tile>();
  143.         for (Tile tile : field) {
  144.             if (t.isNear(tile)) {
  145.                 out.add(tile);
  146.             }
  147.         }
  148.         return out;
  149.     }
  150.  
  151.     int getInt(int coord) {
  152.         if (coord < 16 || coord > 320) {
  153.             return -1;
  154.         }
  155.         int i = 16;
  156.         for (int c = 0; c < 9; c++) {
  157.             i += 34;
  158.             if (coord < i) {
  159.                 return c;
  160.             }
  161.         }
  162.         return -1;
  163.     }
  164.  
  165.     Tile getTile(int x, int y) {
  166.         x = getInt(x);
  167.         y = getInt(y);
  168.         if (x != -1 && y != -1) {
  169.             for (Tile t0 : field) {
  170.                 if (t0.getX() == x && t0.getY() == y) {
  171.                     return t0;
  172.                 }
  173.             }
  174.         }
  175.         return null;
  176.     }
  177.  
  178.     void clickRight(Tile tile) {
  179.         if (tile.isFlag(Flag.NONE)) {
  180.             tile.setFlag(Flag.MARKED);
  181.         } else if (tile.isFlag(Flag.MARKED)) {
  182.             tile.setFlag(Flag.NONE);
  183.         }
  184.         repaint();
  185.     }
  186.  
  187.     void clickLeft(Tile tile) {
  188.         if (!tile.isFlag(Flag.NONE))
  189.             return;
  190.  
  191.         if (tile.isMined()) {
  192.             inGame = false;
  193.             tile.setFlag(Flag.CRUSHED);
  194.         } else {
  195.             tile.setFlag(Flag.OPEN);
  196.             checkWin();
  197.         }
  198.         repaint();
  199.     }
  200.  
  201.     @Override
  202.     public void paint(Graphics g) {
  203.         super.paint(g);
  204.         g.setColor(new Color(255, 223, 94));
  205.         g.fillRect(0, 0, 346, 368);
  206.  
  207.         for (Tile t : field) {
  208.             if (!inGame) {
  209.                 if (isWin) {
  210.                     if (t.isMined()) {
  211.                         t.setFlag(Flag.VERIFIED);
  212.                     } else if (t.isFlag(Flag.NONE)) {
  213.                         t.setFlag(Flag.OPEN);
  214.                     }
  215.                 } else {
  216.                     if (t.isMined() && t.isFlag(Flag.MARKED)) {
  217.                         t.setFlag(Flag.VERIFIED);
  218.                     } else if (t.isMined() && t.isFlag(Flag.NONE)) {
  219.                         t.setFlag(Flag.CRUSHED);
  220.                     } else if (!t.isMined() && t.isFlag(Flag.MARKED)) {
  221.                         t.setFlag(Flag.ERROR);
  222.                     } else {
  223.                         t.setFlag(Flag.OPEN);
  224.                     }
  225.                 }
  226.             }
  227.             drawTile(g, t);
  228.         }
  229.     }
  230.  
  231.     void drawTileText(Graphics2D g, int oX, int oY, String text, Color color) {
  232.         g.setColor(color);
  233.         Font font = new Font("Arial", Font.BOLD, 18);
  234.         g.setFont(font);
  235.         FontMetrics fm = getFontMetrics(font);
  236.         int w = fm.stringWidth(text);
  237.         int h = -(int) fm.getLineMetrics(text, g).getBaselineOffsets()[2];
  238.  
  239.         g.drawString(text, oX + (32 - w) / 2, oY + 32 - (32 - h) / 2 - 2);
  240.     }
  241.  
  242.     void drawTile(Graphics gr, Tile tile) {
  243.         Graphics2D g = ((Graphics2D) gr);
  244.         g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  245.         g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE);
  246.         int oX = 18 + tile.getX() * 34;
  247.         int oY = 18 + tile.getY() * 34;
  248.  
  249.         if (inGame) {
  250.             g.setColor(tile.getTileColor());
  251.             g.fillRect(oX, oY, 32, 32);
  252.  
  253.             if (tile.isFlag(Flag.OPEN)) {
  254.                 if (tile.getValue() > 0)
  255.                     drawTileText(g, oX, oY, String.valueOf(tile.getValue()), tile.getTextColor());
  256.             } else if (tile.isFlag(Flag.MARKED)) {
  257.                 drawTileText(g, oX, oY, "?", tile.getTextColor());
  258.             }
  259.         } else {
  260.             g.setColor(tile.getTileColor());
  261.             g.fillRect(oX, oY, 32, 32);
  262.  
  263.             if (tile.isFlag(Flag.OPEN)) {
  264.                 g.setColor(tile.getTileColor());
  265.                 g.fillRect(oX, oY, 32, 32);
  266.                 if (tile.getValue() > 0)
  267.                     drawTileText(g, oX, oY, String.valueOf(tile.getValue()), tile.getTextColor());
  268.             } else {
  269.                 g.setColor(tile.getTileColor());
  270.                 g.fillRect(oX, oY, 32, 32);
  271.             }
  272.             g.setColor(new Color(255, 255, 255, 2));
  273.             g.fillRect(0, 0, getWidth(), getHeight());
  274.             g.setColor(new Color(44, 44, 44));
  275.             g.setFont(new Font("Arial", Font.BOLD, 80));
  276.             if (isWin) {
  277.                 g.drawString("Win!", 88, 188);
  278.             } else {
  279.                 g.drawString("Lose!", 64, 188);
  280.             }
  281.         }
  282.     }
  283.  
  284.     static class Tile {
  285.  
  286.         private boolean mined;
  287.         private int value, x, y;
  288.         private Flag flag;
  289.  
  290.         public Tile(int x, int y) {
  291.             this.mined = false;
  292.             this.value = 0;
  293.             this.x = x;
  294.             this.y = y;
  295.             this.flag = Flag.NONE;
  296.         }
  297.  
  298.         public boolean isNear(Tile t) {
  299.             return Math.abs(x - t.getX()) < 2 && Math.abs(y - t.getY()) < 2;
  300.         }
  301.  
  302.         public int getX() {
  303.             return x;
  304.         }
  305.  
  306.         public int getY() {
  307.             return y;
  308.         }
  309.  
  310.         public boolean isMined() {
  311.             return mined;
  312.         }
  313.  
  314.         public void setMined() {
  315.             this.mined = true;
  316.         }
  317.  
  318.         public int getValue() {
  319.             return value;
  320.         }
  321.  
  322.         public void setValue(int i) {
  323.             this.value = i;
  324.         }
  325.  
  326.         public boolean isFlag(Flag f) {
  327.             return flag == f;
  328.         }
  329.  
  330.         public Flag getFlag() {
  331.             return flag;
  332.         }
  333.  
  334.         public void setFlag(Flag f) {
  335.             this.flag = f;
  336.         }
  337.  
  338.         public Color getTextColor() {
  339.             if (flag == Flag.MARKED) {
  340.                 return new Color(255, 255, 255);
  341.             }
  342.             switch (value) {
  343.             case 1:
  344.                 return new Color(0, 45, 183);
  345.             case 2:
  346.                 return new Color(22, 122, 0);
  347.             case 3:
  348.                 return new Color(183, 0, 0);
  349.             case 4:
  350.                 return new Color(0, 10, 163);
  351.             case 5:
  352.                 return new Color(183, 0, 0);
  353.             case 6:
  354.                 return new Color(140, 184, 255);
  355.             case 7:
  356.                 return new Color(183, 0, 0);
  357.             case 8:
  358.                 return new Color(147, 0, 160);
  359.             }
  360.             return null;
  361.         }
  362.  
  363.         public Color getTileColor() {
  364.             switch (flag) {
  365.             case CRUSHED:
  366.                 return new Color(186, 37, 0);
  367.             case ERROR:
  368.                 return new Color(255, 251, 30);
  369.             case MARKED:
  370.                 return new Color(43, 102, 196);
  371.             case NONE:
  372.                 return new Color(43, 102, 196);
  373.             case OPEN:
  374.                 return new Color(221, 234, 255);
  375.             case VERIFIED:
  376.                 return new Color(22, 188, 0);
  377.             }
  378.             return null;
  379.         }
  380.  
  381.     }
  382.  
  383.     public static void main(String[] args) {
  384.         JFrame game = new JFrame();
  385.         game.setTitle("Minesweeper");
  386.         game.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
  387.  
  388.         game.setSize(346, 368);
  389.         game.setResizable(false);
  390.  
  391.         game.add(new Minesweeper());
  392.  
  393.         game.setLocationRelativeTo(null);
  394.         game.setVisible(true);
  395.     }
  396.  
  397. }
Advertisement
Add Comment
Please, Sign In to add comment