Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

Java Minesweeper JFrame Flicker

  1. Aug 12, 2017 #1
    Hello, I am currently working on a version of Minesweeper that uses Java.
    Currently the code seems to work relatively well and the game runs properly, however there is an issue.
    I currently have the set to update the board on every mouse click and release, as these are currently the only actions that can trigger a change in the board. I have not implemented a timer yet. The board updates correctly but it flickers, flashing white for a moment and then quickly drawing the objects on the board like the tiles.
    I believe that this is due to me using a loop in the paint method to individually draw each tile based on its given characteristics. I do not know if this is simply too much for the system to handle when trying to drawing instantaneously or if there is some other underlying issue.
    I have searched the web and I think that implementing double buffering or what not might solve the issue but I am not exactly sure how to do that.
    Here is the code, any advice is much appreciated.

    Code (Java):

    //================================//

    import javax.swing.JFrame;
    import javax.swing.SwingUtilities;

    import java.awt.Font;
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseListener;
    import java.util.Scanner;

    /********
     * Minesweeper
     * @author Kaura
     ********/

    public class Minesweeper {
     
        /****
        * Tile
        ****/

        public static class Tile {
         
            private boolean bomb = false;
            private boolean marked = false;
            private boolean covered = true;
            private int number = 0;
         
            public boolean checkBomb() {return bomb;}
            public boolean checkMarked() {return marked;}
            public boolean checkCovered() {return covered;}
            public int getNumber() {return number;}
            public void setBomb() {bomb = true;}
            public void mark() {marked = !marked;}
            public void uncover() {covered = false;}
            public void setNumber(int number) {this.number = number;}
         
        }
     
        /****
        * Board
        ****/

        public static class Board {
         
            private int width;
            private int height;
            private int difficulty;
            private int bombs;
            private int covered;
            private int marked;
            private int deadX;
            private int deadY;
            private long time;
            private boolean running;
            private boolean winner;
            private Tile[][] tiles;
         
            public Board(int width, int height, int bombs) {
             
                this.width = width;
                this.height = height;
                this.bombs = bombs;
                this.covered = width*height;
                this.marked = 0;
                this.deadX = -1;
                this.deadY = -1;
                this.time = System.currentTimeMillis();
                this.running = true;
                this.winner = false;
             
                //Create Tiles//
                tiles = new Tile[width][height];
                for(int k = 0; k < width; k++) {
                    for(int f = 0; f < height; f++) {
                        tiles[k][f] = new Tile();
                    }
                }
             
                //Set Bombs//
                for(int k = 0; k < bombs; k++) {
                    int x = (int)Math.floor(Math.random()*width);
                    int y = (int)Math.floor(Math.random()*height);
                    if(!tiles[x][y].checkBomb()) {
                        tiles[x][y].setBomb();
                    } else {
                        k--;
                    }
                }
             
                //Set Numbers//
                for(int k = 0; k < width; k++) {
                    for(int f = 0; f < height; f++) {
                        int total = 0;
                        if(k > 0 && f > 0 && tiles[k-1][f-1].checkBomb()) total++;
                        if(f > 0 && tiles[k][f-1].checkBomb()) total++;
                        if(k < width-1 && f > 0 && tiles[k+1][f-1].checkBomb()) total++;
                        if(k > 0 && tiles[k-1][f].checkBomb()) total++;
                        if(k < width-1 && tiles[k+1][f].checkBomb()) total++;
                        if(k > 0 && f < height-1 && tiles[k-1][f+1].checkBomb()) total++;
                        if(f < height-1 && tiles[k][f+1].checkBomb()) total++;
                        if(k < width-1 && f < height-1 && tiles[k+1][f+1].checkBomb()) total++;
                        tiles[k][f].setNumber(total);
                    }
                }
            }
         
            //Uncover a Tile//
            public void uncoverTile(int x, int y) {
                covered--;
                tiles[x][y].uncover();
                if(tiles[x][y].checkMarked()) markTile(x, y);
                if(tiles[x][y].checkBomb()) {
                    deadX = x;
                    deadY = y;
                    gameover();
                    return;
                } else if(tiles[x][y].getNumber() == 0) {
                    for(int k = (x==0?0:-1); k <= (x<width-1?1:0); k++) {
                        for(int f = (y==0?0:-1); f <= (y<height-1?1:0); f++) {
                            if(tiles[k+x][f+y].checkCovered()) {
                                uncoverTile((k+x), (f+y));
                            }
                        }
                    }      
                } if(covered <= bombs) {
                    winner = true;
                    gameover();
                }
            }
         
            //Mark Tile//
            public void markTile(int x, int y) {
                if(!tiles[x][y].checkCovered()) return;
                tiles[x][y].mark();
                marked += (tiles[x][y].checkMarked())?1:-1;
            }
         
            //Uncover Bombs//
            public void reveal() {
                for(int k = 0; k < this.width; k++) {
                    for(int f = 0; f < this.height; f++) {
                        if(tiles[k][f].checkBomb()) tiles[k][f].uncover();
                    }
                }
            }
         
            //Game Over//
            public void gameover() {
                running = false;
                if(!winner) reveal();
                System.out.print("Game Over: ");
                System.out.println((winner)?"You Win":"You Lose");
            }
         
            //Timer//
            public int getTime() {
                return (int)(System.currentTimeMillis()-time)/1000;
            }
         
            //Access//
            public int getWidth() {return this.width;}
            public int getHeight() {return this.height;}
            public int getBombs() {return this.bombs;}
            public int getCovered() {return this.covered;}
            public int getMarked() {return this.marked;}
            public int getDeadX() {return this.deadX;}
            public int getDeadY() {return this.deadY;}
            public boolean checkRunning() {return this.running;}
            public Tile getTile(int x, int y) {return this.tiles[x][y];}
         
        }
     
        /****
        * Screen
        ****/

        public static class Screen extends JFrame implements MouseListener {
         
            private static final long serialVersionUID = 1L;
         
            private final int WIDTH = 960;
            private final int HEIGHT = 960;
            private final int TILE = 40;
         
            private final Font font = new Font("Terminal", Font.BOLD, 30);
         
            private final Color BG = Color.decode("#black");
            private final Color FG = Color.decode("#f0f0f0");
            private final Color GD = Color.decode("#c0c0c0");
            private final Color HL1 = Color.decode("#f8f8f8");
            private final Color HL2 = Color.decode("#c0c0c0");
            private final Color F1 = Color.decode("#000000");
            private final Color F2 = Color.decode("#ff0000");
            private final Color BM = Color.decode("#000000");
            private final Color EX = Color.decode("#ff0000");
         
            private final Color[] color = {
                Color.decode("#f0f0f0"),
                Color.decode("#0100fe"),
                Color.decode("#017f01"),
                Color.decode("#fe0000"),
                Color.decode("#010080"),
                Color.decode("#0100fe"),
                Color.decode("#810102"),
                Color.decode("#008081"),
                Color.decode("#000000"),
                Color.decode("#808080"),
            };
         
            private int boardX, boardY;
            private int boardWidth, boardHeight;
         
            private Board board;
         
            //Constructor//
            public Screen() {
                addMouseListener(this);
                setTitle("Minesweeper");
                setSize(WIDTH, HEIGHT);
                setResizable(false);
                setVisible(true);
                setDefaultCloseOperation(EXIT_ON_CLOSE);
                newgame();
            }
         
            //New Game//
            private void newgame() {
                board = new Board(20, 15, 25);
                boardX = WIDTH/2-board.getWidth()*TILE/2;
                boardY = HEIGHT/2-board.getHeight()*TILE/2;
                boardWidth = board.getWidth()*TILE;
                boardHeight = board.getHeight()*TILE;
            }
         
            //Painter//
            public void paint(Graphics canvas) {
                canvas.clearRect(0, 0, WIDTH, HEIGHT);
             
                canvas.setColor(BG);
                canvas.fillRect(0, 0, WIDTH, HEIGHT);
             
                canvas.setColor(HL2);
                canvas.fillPolygon(
                    new int[] {boardX-6, boardX+boardWidth+6, boardX-6},
                    new int[] {boardY-6, boardY-6, boardY+boardHeight+6}, 3
                );
             
                canvas.setColor(HL1);
                canvas.fillPolygon(
                    new int[] {boardX+boardWidth+6, boardX-6, boardX+boardWidth+6},
                    new int[] {boardY+boardHeight+6, boardY+boardHeight+6, boardY-6}, 3
                );
             
                canvas.setColor(FG);
                canvas.fillRect(boardX, boardY, boardWidth, boardHeight);
             
                canvas.setColor(GD);
                for(int k = 0; k < board.getWidth(); k++) {
                    canvas.drawLine(boardX+k*TILE, boardY, boardX+k*TILE, boardY+boardHeight);
                } for(int k = 0; k < board.getHeight(); k++) {
                    canvas.drawLine(boardX, boardY+k*TILE, boardX+boardWidth, boardY+k*TILE);
                }
             
                //Fill Board//
                for(int k = 0; k < board.getWidth(); k++) {
                    for(int f = 0; f < board.getHeight(); f++) {
                     
                        //Base//
                        if(board.getTile(k, f).checkBomb()) {
                            if(k == board.getDeadX() && f == board.getDeadY()) {
                                canvas.setColor(EX);
                                canvas.fillRect(boardX+k*TILE, boardY+f*TILE, TILE, TILE);
                            }
                            canvas.setColor(BM);
                            canvas.fillOval(boardX+k*TILE+TILE/2-9, boardY+f*TILE+TILE/2-9, 20, 20);
                            canvas.setColor(FG);
                            canvas.fillOval(boardX+k*TILE+TILE/2-5, boardY+f*TILE+TILE/2-5, 6, 6);
                        } else {
                            canvas.setFont(font);
                            canvas.setColor(color[board.getTile(k, f).getNumber()]);
                            canvas.drawString(board.getTile(k, f).getNumber()+"", boardX+k*TILE+TILE/2-7, boardY+f*TILE+TILE/2+12);
                        }
                     
                        //Covered
                        if(board.getTile(k, f).checkCovered()) {
                            canvas.setColor(HL1);
                            canvas.fillPolygon(
                                new int[] {boardX+k*TILE, boardX+k*TILE+TILE, boardX+k*TILE},
                                new int[] {boardY+f*TILE, boardY+f*TILE, boardY+f*TILE+TILE}, 3
                            );
                            canvas.setColor(HL2);
                            canvas.fillPolygon(
                                new int[] {boardX+k*TILE, boardX+k*TILE+TILE, boardX+k*TILE+TILE},
                                new int[] {boardY+f*TILE+TILE, boardY+f*TILE+TILE, boardY+f*TILE}, 3
                            );
                            canvas.setColor(BG);
                            canvas.fillRect(boardX+k*TILE+5, boardY+f*TILE+5, 30, 30);
                        }
                     
                        //Marked//
                        if(board.getTile(k, f).checkMarked()) {
                            canvas.setColor(F1);
                            canvas.fillPolygon(
                                new int[] {
                                    boardX+k*TILE+10, boardX+k*TILE+10,
                                    boardX+k*TILE+19, boardX+k*TILE+19,
                                    boardX+k*TILE+21, boardX+k*TILE+21,
                                    boardX+k*TILE+30, boardX+k*TILE+30
                                },
                                new int[] {
                                    boardY+f*TILE+32, boardY+f*TILE+26,
                                    boardY+f*TILE+24, boardY+f*TILE+8,
                                    boardY+f*TILE+8, boardY+f*TILE+24,
                                    boardY+f*TILE+26, boardY+f*TILE+32
                                }, 8
                            );
                            canvas.setColor(F2);
                            canvas.fillPolygon(
                                new int[] {boardX+k*TILE+21, boardX+k*TILE+10, boardX+k*TILE+10, boardX+k*TILE+21},
                                new int[] {boardY+f*TILE+6, boardY+f*TILE+12, boardY+f*TILE+14, boardY+f*TILE+20}, 4
                            );
                        }
                    }
                }

            }
         
            //Mouse Events//
            private int pressX, pressY, releaseX, releaseY;
            public void mouseClicked(MouseEvent e) {return;}
            public void mouseEntered(MouseEvent e) {return;}
            public void mouseExited(MouseEvent e) {return;}
         
            public void mousePressed(MouseEvent e) {
                if(board.checkRunning()) {
                  pressX = e.getX();
                    pressY = e.getY();
                    int tileX = (pressX-boardX)/TILE;
                    int tileY = (pressY-boardY)/TILE;
                } repaint();
            }
         
            public void mouseReleased(MouseEvent e) {
                if(board.checkRunning()) {
                    releaseX = e.getX();
                    releaseY = e.getY();
                    int tileX = (releaseX-boardX)/TILE;
                    int tileY = (releaseY-boardY)/TILE;
                    if(tileX != (pressX-boardX)/TILE || tileY != (pressY-boardY)/TILE) return;
                    if((tileX<0||tileX>board.getWidth())||(tileY<0||tileY>board.getHeight())) return;
     
                    //System.out.println(tileX+", "+tileY);
                    Tile tile = board.getTile(tileX, tileY);
                 
                    if(SwingUtilities.isLeftMouseButton(e)) {
                        if(!tile.checkMarked()) {
                            if(tile.checkCovered()) {
                                board.uncoverTile(tileX, tileY);
                            }
                        }
                    } else if(SwingUtilities.isRightMouseButton(e)) {
                        board.markTile(tileX, tileY);
                    }
                } repaint();
            }
         
        }

        /****
        * Main Method
        ****/

        public static void main(String[] args) {
         
            Screen game = new Screen();
         
        }

    }

    //================================//
     
     
    Last edited by a moderator: Aug 12, 2017
  2. jcsd
  3. Aug 12, 2017 #2

    jedishrfu

    Staff: Mentor

Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook

Have something to add?
Draft saved Draft deleted



Similar Discussions: Minesweeper JFrame Flicker
Loading...