Tiny Application Java

import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
/**
 *
 * @author Aniruddha Dutta Chowdhury
 * @googleProfile http://www.google.com/profiles/a.d.chowdhury
 * @blog http://adchowdhury.blogspot.com/
 * 
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@   @@@@@@@@@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@@  @@@@@  @@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@   @@@@@@@@@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@@  @@@@@  @@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@  @  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@@  @@@@@  @@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@  @  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@@  @@@@@  @@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@   @   @@@@@@@@@  @@    @@@@@@@  @@@@@  @   @@@@@  @@@@@@  @@@@@@@@    @@  @@@@@@@@    @@  @@@@@  @@    @@@@@@@@@@     @@@@@@
@@@@@@  @@@  @@@@@@@@@  @      @@@@@@  @@@@@      @@@@@  @@@@@@  @@@@@@@         @@@@@@@         @@@@@  @      @@@@@@@        @@@@@
@@@@@@  @@@  @@@@@@@@@    @@@   @@@@@  @@@@@   @@@@@@@@  @@@@@@  @@@@@@   @@@    @@@@@@   @@@    @@@@@    @@@   @@@@@   @@@@   @@@@
@@@@@  @@@@@  @@@@@@@@   @@@@@  @@@@@  @@@@@  @@@@@@@@@  @@@@@@  @@@@@@  @@@@@   @@@@@@  @@@@@   @@@@@   @@@@@  @@@@@  @@@@@@  @@@@
@@@@@  @@@@@  @@@@@@@@  @@@@@@  @@@@@  @@@@@  @@@@@@@@@  @@@@@@  @@@@@  @@@@@@@  @@@@@  @@@@@@@  @@@@@  @@@@@@  @@@@@@@@@@@@@  @@@@
@@@@@  @@@@@  @@@@@@@@  @@@@@@  @@@@@  @@@@@  @@@@@@@@@  @@@@@@  @@@@@  @@@@@@@  @@@@@  @@@@@@@  @@@@@  @@@@@@  @@@@@@@@@@     @@@@
@@@@           @@@@@@@  @@@@@@  @@@@@  @@@@@  @@@@@@@@@  @@@@@@  @@@@@  @@@@@@@  @@@@@  @@@@@@@  @@@@@  @@@@@@  @@@@@@@        @@@@
@@@@           @@@@@@@  @@@@@@  @@@@@  @@@@@  @@@@@@@@@  @@@@@@  @@@@@  @@@@@@@  @@@@@  @@@@@@@  @@@@@  @@@@@@  @@@@@@    @@@  @@@@
@@@   @@@@@@@   @@@@@@  @@@@@@  @@@@@  @@@@@  @@@@@@@@@  @@@@@@  @@@@@  @@@@@@@  @@@@@  @@@@@@@  @@@@@  @@@@@@  @@@@@  @@@@@@  @@@@
@@@  @@@@@@@@@  @@@@@@  @@@@@@  @@@@@  @@@@@  @@@@@@@@@  @@@@@   @@@@@@  @@@@@   @@@@@@  @@@@@   @@@@@  @@@@@@  @@@@@  @@@@@@  @@@@
@@@  @@@@@@@@@  @@@@@@  @@@@@@  @@@@@  @@@@@  @@@@@@@@@   @@@    @@@@@@   @@@    @@@@@@   @@@    @@@@@  @@@@@@  @@@@@   @@@    @@@@
@@  @@@@@@@@@@@  @@@@@  @@@@@@  @@@@@  @@@@@  @@@@@@@@@@      @  @@@@@@@      @  @@@@@@@      @  @@@@@  @@@@@@  @@@@@@         @@@@
@@  @@@@@@@@@@@  @@@@@  @@@@@@  @@@@@  @@@@@  @@@@@@@@@@@    @@  @@@@@@@@    @@  @@@@@@@@    @@  @@@@@  @@@@@@  @@@@@@@    @@@  @@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
*
*/
public class MineSweeper extends JPanel implements AWTEventListener, ActionListener {
  public static enum State {
    Clicked, Marked, Initial, WrongMarked
  }
  public static enum GameState {
    NotStarted, Playing, Finished
  }
  private static final int  MAX_BOMB_COUNT  = 10;
  private int          ROWS      = 9, COLUMNS = 9, TOTAL = ROWS * COLUMNS;
  private JPanel        pnlMain      = new JPanel(new GridLayout(ROWS, COLUMNS));
  private JLabel        lblBombCount  = new JLabel(MAX_BOMB_COUNT + "");
  private JLabel        lblTimer    = new JLabel("0");
  private boolean        isColorCheatOn  = false;
  private JButton        btnReset    = new JButton("Reset");
  private void startThread() {
    Thread th = new Thread(new Runnable() {
      public void run() {
        while (state == GameState.Playing) {
          lblTimer.setText((Long.parseLong(lblTimer.getText()) + 1) + "");
          lblTimer.updateUI();
          try {
            Thread.sleep(1000);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
    });
    th.start();
  }
  private GameState  state  = GameState.NotStarted;
  public MineSweeper() {
    setLayout(new BorderLayout());
    add(pnlMain, BorderLayout.CENTER);
    createButtons();
    addControlPanel();
    Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.KEY_EVENT_MASK);
  }
  private void showAbout() {
    JOptionPane.showMessageDialog(this, "Author : Aniruddha Dutta Chowdhury 
Version : 1.0", "About", JOptionPane.INFORMATION_MESSAGE);
  }
  private void restartGame() {
    state = GameState.NotStarted;
    lblTimer.setText("0");
    pnlMain.removeAll();
    createButtons();
    pnlMain.updateUI();
    lblBombCount.setText("" + MAX_BOMB_COUNT);
    lblBombCount.updateUI();
  }
  private void addControlPanel() {
    JPanel pnlTimer = new JPanel(new FlowLayout(FlowLayout.RIGHT));
    pnlTimer.add(lblTimer);
    JPanel pnl = new JPanel(new FlowLayout(FlowLayout.CENTER));
    btnReset.setToolTipText("Press F2 to reset the current game");
    pnl.add(lblBombCount);
    pnl.add(btnReset);
    JPanel pnlN = new JPanel(new GridLayout(1, 3));
    pnlN.add(lblBombCount);
    pnlN.add(pnl);
    pnlN.add(pnlTimer);
    add(pnlN, BorderLayout.NORTH);
    btnReset.addActionListener(this);
  }
  private void createButtons() {
    List lstBombsLocation = new ArrayList();
    for (int row = 0; row < ROWS; row++) {
      for (int col = 0; col < COLUMNS; col++) {
        JButton btn = getButton(lstBombsLocation, TOTAL, new Point(row, col) {
          @Override
          public String toString() {
            return (int) getX() + ", " + (int) getY();
          }
          @Override
          public boolean equals(Object obj) {
            return ((Point) obj).getX() == getX() && ((Point) obj).getY() == getY();
          }
        });
        pnlMain.add(btn);
      }
    }
    while (lstBombsLocation.size() < MAX_BOMB_COUNT) {
      updateBomds(lstBombsLocation, pnlMain.getComponents());
    }
    for (Component c : pnlMain.getComponents()) {
      updateBombCount((GameButton) c, pnlMain.getComponents());
    }
    // System.out.println("Total Bomb Count: " + lstBombsLocation.size());
  }
  private void updateBomds(List lstBombsLocation, Component[] components) {
    // int currentPosition = new Double(((location.x) * COLUMNS ) +
    // location.getY()).intValue();
    Random r = new Random();
    for (Component c : components) {
      Point location = ((GameButton) c).getPosition();
      int currentPosition = new Double(((location.x) * COLUMNS) + location.getY()).intValue();
      int bombLocation = r.nextInt(TOTAL);
      if (bombLocation == currentPosition) {
        ((GameButton) c).setBomb(true);
        lstBombsLocation.add(((GameButton) c).getPosition());
        return;
      }
    }
  }
  private GameButton getButton(List lstBombsLocation, int totalLocations, Point location) {
    GameButton btn = new GameButton(location);
    btn.setMargin(new Insets(0, 0, 0, 0));
    btn.setFocusable(false);
    if (lstBombsLocation.size() < MAX_BOMB_COUNT) {
      if (isBomb()) {
        btn.setBomb(true);
        lstBombsLocation.add(location);
      }
    }
    btn.addMouseListener(new MouseAdapter() {
      @Override
      public void mouseClicked(MouseEvent mouseEvent) {
        if (state != GameState.Playing) {
          state = GameState.Playing;
          startThread();
        }
        if (((GameButton) mouseEvent.getSource()).isEnabled() == false) {
          return;
        }
        if (mouseEvent.getButton() == MouseEvent.BUTTON1) {
          if (((GameButton) mouseEvent.getSource()).getState() == State.Marked) {
            ((GameButton) mouseEvent.getSource()).setState(State.Initial);
            lblBombCount.setText((Long.parseLong(lblBombCount.getText()) + 1) + "");
            ((GameButton) mouseEvent.getSource()).updateUI();
            return;
          }
          ((GameButton) mouseEvent.getSource()).setState(State.Clicked);
          if (((GameButton) mouseEvent.getSource()).isBomb()) {
            blastBombs();
            return;
          } else {
            if (((GameButton) mouseEvent.getSource()).getBombCount() == 0) {
              updateSurroundingZeros(((GameButton) mouseEvent.getSource()).getPosition());
            }
          }
          if (!checkGameState()) {
            ((GameButton) mouseEvent.getSource()).setEnabled(false);
          }
        } else if (mouseEvent.getButton() == MouseEvent.BUTTON3) {
          if (((GameButton) mouseEvent.getSource()).getState() == State.Marked) {
            ((GameButton) mouseEvent.getSource()).setState(State.Initial);
            lblBombCount.setText((Long.parseLong(lblBombCount.getText()) + 1) + "");
          } else {
            ((GameButton) mouseEvent.getSource()).setState(State.Marked);
            lblBombCount.setText((Long.parseLong(lblBombCount.getText()) - 1) + "");
          }
        }
        ((GameButton) mouseEvent.getSource()).updateUI();
      }
    });
    return btn;
  }
  private boolean checkGameState() {
    boolean isWin = false;
    for (Component c : pnlMain.getComponents()) {
      GameButton b = (GameButton) c;
      if (b.getState() != State.Clicked) {
        if (b.isBomb()) {
          isWin = true;
        } else {
          return false;
        }
      }
    }
    if (isWin) {
      state = GameState.Finished;
      for (Component c : pnlMain.getComponents()) {
        GameButton b = (GameButton) c;
        if (b.isBomb()) {
          b.setState(State.Marked);
        }
        b.setEnabled(false);
      }
      JOptionPane.showMessageDialog(this, "You win the game :D", "Congrats", JOptionPane.INFORMATION_MESSAGE, null);
    }
    return isWin;
  }
  private void updateSurroundingZeros(Point currentPoint) {
    Point[] points = getSurroundings(currentPoint);
    for (Point p : points) {
      GameButton b = getButtonAt(pnlMain.getComponents(), p);
      if (b != null && b.getBombCount() == 0 && b.getState() != State.Clicked && b.getState() != State.Marked && b.isBomb() == false) {
        b.setState(State.Clicked);
        updateSurroundingZeros(b.getPosition());
        b.updateUI();
      }
      if (b != null && b.getBombCount() > 0 && b.getState() != State.Clicked && b.getState() != State.Marked && b.isBomb() == false) {
        b.setEnabled(false);
        b.setState(State.Clicked);
        b.updateUI();
      }
    }
  }
  private void blastBombs() {
    int blastCount = 0;
    for (Component c : pnlMain.getComponents()) {
      ((GameButton) c).setEnabled(false);
      ((GameButton) c).transferFocus();
      if (((GameButton) c).isBomb() && ((GameButton) c).getState() != State.Marked) {
        ((GameButton) c).setState(State.Clicked);
        ((GameButton) c).updateUI();
        blastCount++;
      }
      if (((GameButton) c).isBomb() == false && ((GameButton) c).getState() == State.Marked) {
        ((GameButton) c).setState(State.WrongMarked);
      }
    }
    lblBombCount.setText("" + blastCount);
    lblBombCount.updateUI();
    state = GameState.Finished;
    JOptionPane.showMessageDialog(this, "You loose the game :(", "Game Over", JOptionPane.ERROR_MESSAGE, null);
    for (Component c : pnlMain.getComponents()) {
      GameButton b = (GameButton) c;
      b.setEnabled(false);
    }
  }
  private boolean isBomb() {
    Random r = new Random();
    return r.nextInt(ROWS) == 1;
  }
  public static void main(String... args) {
    JFrame fr = new JFrame("MineSweeper");
    fr.setLayout(new BorderLayout());
    fr.add(new MineSweeper());
    fr.setResizable(false);
    fr.setSize(250, 350);
    fr.setLocationRelativeTo(null);
    fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    fr.setVisible(true);
  }
  class GameButton extends JButton {
    private boolean  isBomb    = false;
    private Point  position  = null;
    private int    bombCount  = 0;
    private State  state    = State.Initial;
    public void setState(State state) {
      this.state = state;
      if (getBombCount() == 0 && !isBomb) {
        setEnabled(false);
      }
    }
    public State getState() {
      return state;
    }
    public int getBombCount() {
      return bombCount;
    }
    public void setBombCount(int bombCount) {
      this.bombCount = bombCount;
    }
    public GameButton(Point position) {
      setPosition(position);
      setText(position.toString());
    }
    public Point getPosition() {
      return position;
    }
    public void setPosition(Point position) {
      this.position = position;
    }
    public boolean isBomb() {
      return isBomb;
    }
    public void setBomb(boolean isBomb) {
      this.isBomb = isBomb;
    }
    @Override
    public String getText() {
      if (state == State.Initial) {
        return "";
      }
      if (state == State.Marked) {
        return "\u00B6";
      }
      if (state == State.Clicked) {
        if (isBomb) {
          return "*";
        } else {
          if (getBombCount() > 0)
            return getBombCount() + "";
          else
            return "";
        }
      }
      if (state == State.WrongMarked) {
        return "X";
      }
      return super.getText();
    }
    @Override
    public Color getBackground() {
      if (isColorCheatOn && isBomb) {
        return Color.MAGENTA;
      }
      if (state == State.Clicked) {
        if (isBomb) {
          return Color.RED;
        }
        if (getBombCount() > 0) {
          return Color.GREEN;
        }
      }
      if (isEnabled()) {
        return Color.YELLOW.brighter();
      } else {
        return super.getBackground();
      }
    }
  }
  private Point[] getSurroundings(Point cPoint) {
    int cX = (int) cPoint.getX();
    int cY = (int) cPoint.getY();
    Point[] points = { new Point(cX - 1, cY - 1), new Point(cX - 1, cY), new Point(cX - 1, cY + 1), new Point(cX, cY - 1), new Point(cX, cY + 1), new Point(cX + 1, cY - 1), new Point(cX + 1, cY), new Point(cX + 1, cY + 1) };
    return points;
  }
  private void updateBombCount(GameButton btn, Component[] components) {
    Point[] points = getSurroundings(btn.getPosition());
    for (Point p : points) {
      GameButton b = getButtonAt(components, p);
      if (b != null && b.isBomb()) {
        btn.setBombCount(btn.getBombCount() + 1);
      }
    }
    btn.setText(btn.getBombCount() + "");
  }
  private GameButton getButtonAt(Component[] components, Point position) {
    for (Component btn : components) {
      if ((((GameButton) btn).getPosition().equals(position))) {
        return (GameButton) btn;
      }
    }
    return null;
  }
  public void eventDispatched(AWTEvent event) {
    if (KeyEvent.class.isInstance(event) && ((KeyEvent) (event)).getID() == KeyEvent.KEY_RELEASED) {
      if (((KeyEvent) (event)).getKeyCode() == KeyEvent.VK_F1) {
        showAbout();
      }
      if (((KeyEvent) (event)).getKeyCode() == KeyEvent.VK_F2) {
        restartGame();
      }
      if (((KeyEvent) (event)).getKeyCode() == KeyEvent.VK_F3) {
        isColorCheatOn = !isColorCheatOn;
        if (state == GameState.Playing) {
          pnlMain.updateUI();
        }
      }
      if (((KeyEvent) (event)).getKeyCode() == KeyEvent.VK_F12) {
        for (Component c : pnlMain.getComponents()) {
          GameButton b = (GameButton) c;
          if (b.isBomb() == false) {
            b.setState(State.Clicked);
          } else {
            b.setState(State.Marked);
          }
          b.setEnabled(false);
        }
        checkGameState();
      }
    }
  }
  public void actionPerformed(ActionEvent actionEvent) {
    if (actionEvent.getSource() == btnReset) {
      restartGame();
    }
  }
}