How to Fix Flickering JFrame in Java Minesweeper?

  • Java
  • Thread starter Kaura
  • Start date
  • Tags
    java
In summary: Tile(); } } } /******** * Main ****/ public static void main(String[] args) { Board board = new Board(800, 600, 10); JFrame frame = new JFrame(); // Create the JFrame frame.setDefaultCloseOperation(
  • #1
Kaura
122
22
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.

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:
Technology news on Phys.org

Related to How to Fix Flickering JFrame in Java Minesweeper?

1. Why does Minesweeper JFrame Flicker occur?

The flickering in Minesweeper JFrame can occur due to several reasons, such as a slow graphics card, low memory, or outdated drivers. It can also be caused by conflicting programs running in the background or a glitch in the game's code.

2. How can I fix Minesweeper JFrame Flicker?

To fix the flickering issue in Minesweeper JFrame, you can try updating your graphics card drivers, closing any unnecessary programs, or allocating more memory to the game. You can also try playing the game in a different browser or reinstalling the game if the issue persists.

3. Can hardware affect Minesweeper JFrame Flicker?

Yes, hardware can affect Minesweeper JFrame Flicker. If you have a slow graphics card or low memory, it can cause the game to flicker. Upgrading your hardware or playing the game on a computer with better specs can help reduce the flickering.

4. Does the screen resolution affect Minesweeper JFrame Flicker?

Yes, the screen resolution can affect Minesweeper JFrame Flicker. If your screen resolution is too low, it can cause the game to flicker. It is recommended to play the game in a higher resolution for a smoother gameplay experience.

5. Is there a way to prevent Minesweeper JFrame Flicker?

While there is no guaranteed way to prevent Minesweeper JFrame Flicker, there are some steps you can take to minimize it. These include updating your drivers, closing unnecessary programs, and playing the game in a higher resolution. You can also try playing the game on a different device with better specs to reduce the flickering.

Similar threads

  • Programming and Computer Science
Replies
2
Views
2K
  • Programming and Computer Science
Replies
6
Views
2K
  • Programming and Computer Science
Replies
5
Views
1K
  • Programming and Computer Science
Replies
3
Views
3K
  • Programming and Computer Science
Replies
1
Views
1K
  • Programming and Computer Science
Replies
13
Views
4K
  • Engineering and Comp Sci Homework Help
Replies
5
Views
2K
  • Programming and Computer Science
Replies
2
Views
2K
  • Programming and Computer Science
Replies
2
Views
1K
  • Programming and Computer Science
Replies
3
Views
2K
Back
Top