In: Computer Science
Use Java GUI to write a chessboard
8 Queens Problem
Write a program that can place 8 queens in such a manner on an 8 x 8 chessboard that no queens attack each other by being in the same row, column or diagonal.
Board.java
public class Board {
private int numRows;
private int numCols;
private final int initChar = 0;
private int[][] board;
/**
* Initialises variables required for the class to operate
* @param numRows
* @param numCols
* @param c
*/
public Board(int numRows, int numCols) {
this.numRows = numRows;
this.numCols = numCols;
board = new int[numRows][numCols];
}
/**
* Prints the game board to console
*/
public void display() {
for (int i = 0; i < board.length; i++) {
System.out.print("\t");
for (int k = 0; k < board[0].length; k++) {
System.out.print(board[i][k] + " ");
}
System.out.print("\n");
}
}
/**
* Initialises the board using the rows and columns provided in the constructor
* @see Configuration getDefaultCharacter()
*/
public void initialise() {
for (int i = 0; i < board.length; i++) {
for (int k = 0; k < board[0].length; k++) {
board[i][k] = initChar;
}
}
}
/**
* Checks if the board is full of attacked squares (not the default character)
* @see Configuration getDefaultCharacter()
* @return boolean
*/
public boolean boardFull() {
for (int i = 0; i < board[0].length; i++) {
for (int k = 0; k < board.length; k++) {
if (board[i][k] == initChar)
return false;
}
}
return true;
}
/**
* Checks if the specified row and column are within the bounds of the board
* @param numRow
* @param numCol
* @return boolean
*/
public boolean isValidCoord(int numRow, int numCol) {
if ((numRow >= 0 && numRow < this.numRows) && (numCol >= 0 && numCol < this.numCols))
return true;
else {
return false;
}
}
/**
* Returns if there is a title on the specified square (row x column)
* @param numRow
* @param numCol
* @return char
*/
public int getSquare(int numRow, int numCol) {
if (isValidCoord(numRow, numCol))
return board[numRow][numCol];
else
return (Character) null;
}
/**
* Sets the specified character to numRow x numCol
* @param numRow
* @param numCol
* @param c
*/
public void setSquare(int numRow, int numCol) {
if (isValidCoord(numRow, numCol))
board[numRow][numCol] += 1;
}
/**
* Set the specified square back to the default character
* @param numRow Row number
* @param numCol Column number
*/
public void unsetSquare(int numRow, int numCol) {
if (isValidCoord(numRow, numCol))
{
if (board[numRow][numCol] > 0)
board[numRow][numCol] -= 1;
}
}
/**
* Returns the width of the board (number of rows)
* @return int
*/
public int getBoardWidth() {
return board[0].length;
}
/**
* Returns the height of the board (number of columns)
* @return
*/
public int getBoardHeight() {
return board.length;
}
}
Game.java
import javax.swing.JButton;
import javax.swing.UIManager;
import queens.gui.GUI;
import queens.util.Debug;
public class Game extends Board {
// Variable declaration
private int gameType = 0;
private int gameCounter = 0;
private final int initChar = 0;
// End variable declaration
/**
* Creates a board of size numRows x numCols
*
* @param numRows
* @param numCols
* @param c
* @see Board
*/
public Game(int numRows, int numCols, int gameType) {
super(numRows, numCols);
this.gameType = gameType;
initialise();
}
/**
* Checks if a square at position numRow, numCol is occupied by a tile
* @param numRow
* @param numCol
* @return boolean
*/
public boolean isOccupied(int numRow, int numCol) {
if (getSquare(numRow, numCol) != initChar)
return true;
else
return false;
}
/**
* Checks if all tiles have been attacked using the correct number of tiles
* for that particular game type (Rooks, Bishops, Queens)
* @return boolean
*/
public boolean hasWon() {
// Check Rooks and Queens
if (gameType == 1 || gameType == 3) {
if (getCounter() < 8 && boardFull()) {
Debug.print("You failed to complete the puzzle. \nClick reset to try again.");
return true; // stop the game
}
else if (getCounter() == 8) {
for (int i = 0; i < getBoardWidth(); i++) {
for (int k = 0; k < getBoardHeight(); k++) {
if (getSquare(i, k) == initChar) {
Debug.print("You failed to complete the puzzle2. \nClick reset to try again.");
return true; // stop the game
}
}
}
Debug.print("CONGRATULATIONS YOU SOLVED THE PUZZLE!!");
return true;
}
}
// check bishops
else if(gameType == 2) {
if (getCounter() < 14 && boardFull()) {
Debug.print("You failed to complete the puzzle. \nClick reset to try again.");
return true; // stop the game
}
else if (getCounter() == 14) {
for (int i = 0; i < getBoardWidth(); i++) {
for (int k = 0; k < getBoardHeight(); k++) {
if (getSquare(i, k) == initChar) {
Debug.print("You failed to complete the puzzle2. \nClick reset to try again.");
return true; // stop the game
}
}
}
Debug.print("CONGRATULATIONS YOU SOLVED THE PUZZLE!!");
return true;
}
}
return false;
}
/**
* Unset the buttons on the interface based on whether the square is under attack or not
* @param btns 2D matrix of the chess board (JButtons)
*/
public void unset(JButton[][] btns) {
for (int i = 0; i < getBoardWidth(); i++) {
for (int k = 0; k < getBoardHeight(); k++) {
// Check if the square is under attack
if (getSquare(i,k) == 0) {
btns[i][k].setEnabled(true);
btns[i][k].setIcon(null);
btns[i][k].setEnabled(true);
btns[i][k].setBackground(UIManager.getColor("Button.background"));
}
}
}
}
/**
*
* @return 'int' of number of tiles placed
*/
public int getCounter() {
return gameCounter;
}
/**
* Decrease the tile counter by 1
*/
public void decCounter() {
this.gameCounter--;
GUI.updateCounter(getCounter());
}
/**
*
* Increments the number of tiles placed to the board.
*/
public void incCounter() {
this.gameCounter++;
GUI.updateCounter(getCounter());
}
/**
* Resets the number of tiles placed to 0
*/
public void resetCounter() {
this.gameCounter = 0;
}
/**
* Removes the current game type (Rooks, Bishops, Queens) forcing reselection
*/
public void resetGameType() {
this.gameType = 0;
}
}
GameType.java
import javax.swing.JButton;
public interface GameType {
/**
* Places a character on a specific square
* @param numRow Number of rows in the board
* @param numCol Number of columns in the board
* @return boolean
*/
public boolean placeMark(JButton[][] btns, int numRow, int numCol);
/**
* Adds the square to the GUI and associated attacked squares
* @param btns Buttons array from the GUI
* @param numRow Number of rows in the board
* @param numCol Number of columns in the board
*/
public void addComponent2GUI(JButton[][] btns, int numRow, int numCol);
/**
* Add the square to the board at the specified position
* @param numRow Number of rows in the board
* @param numCol Number of columns in the board
*/
public void addComponent(int numRow, int numCol);
/**
* Unset a square including all associated under attack squares (checking for overlaps with other tiles)
* @param btns 2D matrix of the chess board (interface)
* @param numRow Row number we want to remove
* @param numCol Column number we want to remove
*/
public void unset(JButton[][] btns, int numRow, int numCol);
}
Bishops.java
import java.awt.Color;
import java.awt.Insets;
import java.net.URL;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import queens.game.GameType;
import queens.game.Game;
import queens.gui.GUI;
import queens.util.Debug;
public class Bishops extends Game implements GameType {
/**
* Initialises the board
* @param row Number of rows in the board
* @param col Number of columns in the board
* @param gameType The selected game mode
*/
public Bishops(int row, int col, int gameType) {
super(row, col, gameType);
}
/**
* Places a character on a specific square
* @param numRow Number of rows in the board
* @param numCol Number of columns in the board
* @return boolean
*/
public boolean placeMark(JButton[][] btns, int numRow, int numCol) {
if (isValidCoord(numRow, numCol)) {
if (isOccupied(numRow, numCol)) {
Debug.print("Error: Square already occupied, please try again.");
return false;
}
else {
addComponent(numRow, numCol);
addComponent2GUI(btns, numRow, numCol);
hasWon(); // re-check if they've now won (so they don't have to place another square)
return true;
}
}
return false;
}
/**
* Adds the square to the GUI and associated attacked squares
* @param btns Buttons array from the GUI
* @param numRow Number of rows in the board
* @param numCol Number of columns in the board
*/
public void addComponent2GUI(JButton[][] btns, int numRow, int numCol) {
btns[numRow][numCol].setEnabled(false);
btns[numRow][numCol].setBackground(Color.GREEN);
btns[numRow][numCol].setMargin(new Insets(0,0,0,0));
URL imageLoc = GUI.class.getResource("images/black-bishop-2d-icon.png"); // look in the same location as Rooks class
btns[numRow][numCol].setIcon(new ImageIcon(imageLoc));
// left diagonal starting from the square clicked to board width (Direction: \)
for (int i = numRow, k = numCol; i < getBoardWidth(); i++, k++)
{
if (isValidCoord(i, k))
btns[i][k].setEnabled(false);
}
// left diagonal starting from the square clicked and going backwards to 0 (Direction: \)
for (int c = numRow, j = numCol; c >= 0; c--, j--)
{
if (isValidCoord(c, j))
btns[c][j].setEnabled(false);
}
// right diagonal starting from the square clicked to board width (Direction: /)
for (int i = numRow, k = numCol; i < getBoardWidth(); i++, k--)
{
if (isValidCoord(i, k))
btns[i][k].setEnabled(false);
}
// right diagonal starting from the square clicked and going backwards to 0 (Direction: /)
for (int c = numRow, j = numCol; c >= 0; c--, j++)
{
if (isValidCoord(c, j))
btns[c][j].setEnabled(false);
}
}
/**
* Add the square to the board at the specified position
* @param numRow Number of rows in the board
* @param numCol Number of columns in the board
*/
public void addComponent(int numRow, int numCol) {
setSquare(numRow, numCol);
incCounter();
// left diagonal starting from the square clicked to board width (Direction: \)
for (int i = numRow, k = numCol; i < getBoardWidth(); i++, k++)
{
if (isValidCoord(i, k))
setSquare(i, k);
}
// left diagonal starting from the square clicked and going backwards to 0 (Direction: \)
for (int c = numRow, j = numCol; c >= 0; c--, j--)
{
if (isValidCoord(c, j))
setSquare(c, j);
}
// right diagonal starting from the square clicked to board width (Direction: /)
for (int i = numRow, k = numCol; i < getBoardWidth(); i++, k--)
{
if (isValidCoord(i, k))
setSquare(i, k);
}
// right diagonal starting from the square clicked and going backwards to 0 (Direction: /)
for (int c = numRow, j = numCol; c >= 0; c--, j++)
{
if (isValidCoord(c, j))
setSquare(c, j);
}
}
/**
* Unset a square including all associated under attack squares (checking for overlaps with other tiles)
* @param btns 2D matrix of the chess board (interface)
* @param numRow Row number we want to remove
* @param numCol Column number we want to remove
*/
public void unset(JButton[][] btns, int numRow, int numCol) {
decCounter();
// left diagonal starting from the square clicked to board width (Direction: \)
for (int i = numRow, k = numCol; i < getBoardWidth(); i++, k++)
{
if (isValidCoord(i, k))
unsetSquare(i, k);
}
// left diagonal starting from the square clicked and going backwards to 0 (Direction: \)
for (int c = numRow, j = numCol; c >= 0; c--, j--)
{
if (isValidCoord(c, j))
unsetSquare(c, j);
}
// right diagonal starting from the square clicked to board width (Direction: /)
for (int i = numRow, k = numCol; i < getBoardWidth(); i++, k--)
{
if (isValidCoord(i, k))
unsetSquare(i, k);
}
// right diagonal starting from the square clicked and going backwards to 0 (Direction: /)
for (int c = numRow, j = numCol; c >= 0; c--, j++)
{
if (isValidCoord(c, j))
unsetSquare(c, j);
}
// Unset the buttons on the interface
unset(btns);
}
}
Queens.java
import java.awt.Color;
import java.awt.Insets;
import java.net.URL;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import queens.game.GameType;
import queens.game.Game;
import queens.gui.GUI;
import queens.util.Debug;
public class Queens extends Game implements GameType {
/**
* Initialises the board
* @param row Number of rows in the board
* @param col Number of columns in the board
* @param gameType The selected game mode
*/
public Queens(int row, int col, int gameType) {
super(row, col, 1);
}
/**
* Places a character on a specific square
* @param numRow Number of rows in the board
* @param numCol Number of columns in the board
* @return boolean
*/
public boolean placeMark(JButton[][] btns, int numRow, int numCol) {
if (isValidCoord(numRow, numCol)) {
if (isOccupied(numRow, numCol)) {
Debug.print("Error: Square already occupied, please try again.");
return false;
}
else {
addComponent(numRow, numCol);
addComponent2GUI(btns, numRow, numCol);
hasWon(); // re-check if they've now won (so they don't have to place another square)
return true;
}
}
return false;
}
/**
* Adds the square to the GUI and associated attacked squares
* @param btns Buttons array from the GUI
* @param numRow Number of rows in the board
* @param numCol Number of columns in the board
*/
public void addComponent2GUI(JButton[][] btns, int numRow, int numCol) {
btns[numRow][numCol].setEnabled(false);
btns[numRow][numCol].setBackground(Color.GREEN);
btns[numRow][numCol].setMargin(new Insets(0,0,0,0));
URL imageLoc = GUI.class.getResource("images/black-queen-2d-icon.png"); // look in the same location as GUI class
btns[numRow][numCol].setIcon(new ImageIcon(imageLoc));
/*
* Rooks:
* Loop while i is less than 8 (board width)
*/
for (int i = 0; i < getBoardWidth(); i++)
{
/* Disable the whole column (including the one we clicked on) */
btns[i][numCol].setEnabled(false);
/* Disable the whole row (including the one we clicked on) */
btns[numRow][i].setEnabled(false);
}
/*
* Bishops:
* Loop from the square clicked in an X formation (e.g compass: NW, SE, NE, SW)
*/
// left diagonal starting from the square clicked to board width (Direction: \)
for (int i = numRow, k = numCol; i < getBoardWidth(); i++, k++)
{
if (isValidCoord(i, k))
btns[i][k].setEnabled(false);
}
// left diagonal starting from the square clicked and going backwards to 0 (Direction: \)
for (int c = numRow, j = numCol; c >= 0; c--, j--)
{
if (isValidCoord(c, j))
btns[c][j].setEnabled(false);
}
// right diagonal starting from the square clicked to board width (Direction: /)
for (int i = numRow, k = numCol; i < getBoardWidth(); i++, k--)
{
if (isValidCoord(i, k))
btns[i][k].setEnabled(false);
}
// right diagonal starting from the square clicked and going backwards to 0 (Direction: /)
for (int c = numRow, j = numCol; c >= 0; c--, j++)
{
if (isValidCoord(c, j))
btns[c][j].setEnabled(false);
}
}
/**
* Add the square to the board at the specified position
* @param numRow Number of rows in the board
* @param numCol Number of columns in the board
*/
public void addComponent(int numRow, int numCol) {
setSquare(numRow, numCol);
incCounter();
/*
* Rooks:
* Loop while i is less than 8 (board width)
*/
for (int i = 0; i < getBoardWidth(); i++)
{
/* Disable the whole column (including the one we clicked on) */
setSquare(i, numCol);
/* Disable the whole row (including the one we clicked on) */
setSquare(numRow, i);
}
/*
* Bishops:
* Loop from the square clicked in an X formation (e.g compass: NW, SE, NE, SW)
*/
// left diagonal starting from the square clicked to board width (Direction: \)
for (int i = numRow, k = numCol; i < getBoardWidth(); i++, k++)
{
if (isValidCoord(i, k))
setSquare(i, k);
}
// left diagonal starting from the square clicked and going backwards to 0 (Direction: \)
for (int c = numRow, j = numCol; c >= 0; c--, j--)
{
if (isValidCoord(c, j))
setSquare(c, j);
}
// right diagonal starting from the square clicked to board width (Direction: /)
for (int i = numRow, k = numCol; i < getBoardWidth(); i++, k--)
{
if (isValidCoord(i, k))
setSquare(i, k);
}
// right diagonal starting from the square clicked and going backwards to 0 (Direction: /)
for (int c = numRow, j = numCol; c >= 0; c--, j++)
{
if (isValidCoord(c, j))
setSquare(c, j);
}
}
/**
* Unset a square including all associated under attack squares (checking for overlaps with other tiles)
* @param btns 2D matrix of the chess board (interface)
* @param numRow Row number we want to remove
* @param numCol Column number we want to remove
*/
public void unset(JButton[][] btns, int numRow, int numCol) {
decCounter();
/*
* Rooks:
* Loop while i is less than 8 (board width)
*/
for (int i = 0; i < getBoardWidth(); i++)
{
/* Disable the whole column (including the one we clicked on) */
unsetSquare(i, numCol);
/* Disable the whole row (including the one we clicked on) */
unsetSquare(numRow, i);
}
/*
* Bishops:
* Loop from the square clicked in an X formation (e.g compass: NW, SE, NE, SW)
*/
// left diagonal starting from the square clicked to board width (Direction: \)
for (int i = numRow, k = numCol; i < getBoardWidth(); i++, k++)
{
if (isValidCoord(i, k))
unsetSquare(i, k);
}
// left diagonal starting from the square clicked and going backwards to 0 (Direction: \)
for (int c = numRow, j = numCol; c >= 0; c--, j--)
{
if (isValidCoord(c, j))
unsetSquare(c, j);
}
// right diagonal starting from the square clicked to board width (Direction: /)
for (int i = numRow, k = numCol; i < getBoardWidth(); i++, k--)
{
if (isValidCoord(i, k))
unsetSquare(i, k);
}
// right diagonal starting from the square clicked and going backwards to 0 (Direction: /)
for (int c = numRow, j = numCol; c >= 0; c--, j++)
{
if (isValidCoord(c, j))
unsetSquare(c, j);
}
// Unset the buttons on the interface
unset(btns);
}
}
Rooks.java
import java.awt.Color;
import java.awt.Insets;
import java.io.File;
import java.net.URL;
import java.util.Arrays;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.UIManager;
import queens.game.GameType;
import queens.game.Game;
import queens.gui.GUI;
import queens.util.Debug;
public class Rooks extends Game implements GameType {
/**
* Initialises the board
* @param row Number of rows in the board
* @param col Number of columns in the board
* @param gameType The selected game mode
*/
public Rooks(int row, int col, int gameType) {
super(row, col, gameType);
}
/**
* Places a character on a specific square
* @param numRow Number of rows in the board
* @param numCol Number of columns in the board
* @return boolean
*/
public boolean placeMark(JButton[][] btns, int numRow, int numCol) {
if (isValidCoord(numRow, numCol)) {
if (isOccupied(numRow, numCol)) {
Debug.print("Error: Square already occupied, please try again.");
return false;
}
else {
addComponent(numRow, numCol);
addComponent2GUI(btns, numRow, numCol);
hasWon(); // re-check if they've now won (so they don't have to place another square)
return true;
}
}
return false;
}
/**
* Adds the square to the GUI and associated attacked squares
* @param btns Buttons array from the GUI
* @param numRow Number of rows in the board
* @param numCol Number of columns in the board
*/
public void addComponent2GUI(JButton[][] btns, int numRow, int numCol) {
btns[numRow][numCol].setBackground(Color.GREEN);
btns[numRow][numCol].setMargin(new Insets(0,0,0,0));
URL imageLoc = GUI.class.getResource("images/black-rook-2d-icon.png"); // look in the same location as GUI class
btns[numRow][numCol].setIcon(new ImageIcon(imageLoc));
/* Loop while i is less than 8 (board width) */
for (int i = 0; i < getBoardWidth(); i++)
{
/* Disable the whole column (including the one we clicked on) */
btns[i][numCol].setEnabled(false);
/* Disable the whole row (including the one we clicked on) */
btns[numRow][i].setEnabled(false);
}
}
/**
* Add the square to the board at the specified position
* @param numRow Number of rows in the board
* @param numCol Number of columns in the board
*/
public void addComponent(int numRow, int numCol) {
setSquare(numRow, numCol);
/* Increase the tile counter by one */
incCounter();
for (int i = 0; i < getBoardWidth(); i++)
{
// Make sure we don't overwrite the square that was clicked
if (i != numRow)
{
/* Disable the whole column (including the one we clicked on) */
setSquare(i, numCol);
}
// Make sure we don't overwrite the square that was clicked
if (i != numCol)
{
/* Disable the whole row (including the one we clicked on) */
setSquare(numRow, i);
}
}
}
/**
* Unset a square including all associated under attack squares (checking for overlaps with other tiles)
* @param btns 2D matrix of the chess board (interface)
* @param numRow Row number we want to remove
* @param numCol Column number we want to remove
*/
public void unset(JButton[][] btns, int numRow, int numCol)
{
decCounter();
for (int i = 0; i < getBoardWidth(); i++)
{
unsetSquare(i, numCol);
unsetSquare(numRow, i);
}
// Unset the buttons on the GUI
unset(btns);
}
}
Help.java
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.*;
public class Help extends JFrame
{
public Help()
{
setTitle("Help");
setResizable(false);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel pnl = new JPanel();
setContentPane(pnl);
JTextArea helpTxt = new JTextArea(
"The aim of the Eight Queens problem is "
+ "to place 8 Queens on the chess board, so that no "
+ "Queen threatens the territory of another Queen.\n\n"
+ "The game can also be played with different chess"
+ "peices .e.g 8 Rooks can be placed on the board (trivial "
+ "to solve!)... or 14 Bishops can be placed on the board.");
helpTxt.setEditable(false);
helpTxt.setLineWrap(true); // wrap lines
helpTxt.setWrapStyleWord(true); // force words that don't fit on the line to move to the next one
helpTxt.setBorder(BorderFactory.createMatteBorder(1,1,1,1,Color.LIGHT_GRAY));
helpTxt.setPreferredSize(new Dimension(300, 150));
pnl.add(helpTxt);
pack();
setVisible(true);
}
}
GUI.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import queens.game.Game;
import queens.game.type.*;
import queens.util.Debug;
public class GUI extends JFrame implements ActionListener {
private int board_size = 8;
JButton[][] btns;
JComboBox gameModes = new JComboBox(new String[] {
"Rooks", "Bishops", "Queens"
});
static JProgressBar progressBar = null;
JButton resetButton = new JButton("Reset");
JButton solveButton = new JButton("Solve");
private JMenuItem resGame = new JMenuItem("Reset Game");
private JMenuItem exit = new JMenuItem("Exit");
private JMenuItem rooksMenu = new JMenuItem("Rooks");
private JMenuItem bishopsMenu = new JMenuItem("Bishops");
private JMenuItem queensMenu = new JMenuItem("Queens");
private JMenuItem aboutMenu = new JMenuItem("About");
private Game game;
private Rooks rooks = null; // initialise to null so we know its not in use
private Bishops bishops = null;
private Queens queens = null;
private int gameType;
public GUI(int boardSize) {
// Game components
board_size = boardSize;
// Initialise GUI components
setTitle("8 Queens Puzzle");
//setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
// Set the background panel (content pane) to which we add our components
JPanel bgPnl = new JPanel(new BorderLayout());
setContentPane(bgPnl);
/**
* JMenu Components initialised below
*/
JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);
// Create File menu
JMenu fileMenu = new JMenu("File");
resGame.addActionListener(this);
fileMenu.add(resGame);
exit.addActionListener(this);
fileMenu.add(exit);
menuBar.add(fileMenu);
// Create Game Modes menu
JMenu gameMenu = new JMenu("Game Modes");
rooksMenu.addActionListener(this);
gameMenu.add(rooksMenu);
bishopsMenu.addActionListener(this);
gameMenu.add(bishopsMenu);
queensMenu.addActionListener(this);
gameMenu.add(queensMenu);
menuBar.add(gameMenu);
// Help menu
JMenu helpMenu = new JMenu("Help");
aboutMenu.addActionListener(this);
helpMenu.add(aboutMenu);
menuBar.add(helpMenu);
/**
* Northern panel of the GUI consisting of game information initialised here
*/
JPanel topPanel = new JPanel(new BorderLayout());
JLabel title = new JLabel("8 - Queens Puzzle", JLabel.CENTER); // Title of the GUI
title.setFont(new Font("sansserif", Font.BOLD, 32)); // Set the font to large
topPanel.add(title, BorderLayout.NORTH);
JLabel gameModeLabel = new JLabel("Select a game mode: ");
gameModeLabel.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); // set padding around the element
topPanel.add(gameModeLabel, BorderLayout.WEST);
gameModes.setPreferredSize(new Dimension(130, 20)); // set size of component
gameModes.addActionListener(this);
gameModes.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); // set padding around the element (matching label)
topPanel.add(gameModes, BorderLayout.EAST);
bgPnl.add(topPanel, BorderLayout.NORTH); // Add panel to the content pane
/**
* Game grid initialised and managed here
*/
JPanel gridPanel = new JPanel(new GridLayout(board_size + 1, board_size));
btns = new JButton[board_size][board_size];
for (int i = 0; i < board_size; i++) {
for (int k = 0; k < board_size; k++) {
btns[i][k] = new JButton(" ");
btns[i][k].setPreferredSize(new Dimension(50, 50));
final int numRow = i, numCol = k; // provide variable access to actionlistener class
// Add a mouse listener to detect when the disabled buttons are clicked
btns[i][k].addMouseListener(new MouseListener()
{
public void mouseClicked(MouseEvent e) {
/* Unset button event */
if (!btns[numRow][numCol].isEnabled() && btns[numRow][numCol].getBackground() == Color.GREEN)
{
if (gameType == 1 && rooks != null)
rooks.unset(btns, numRow, numCol);
else if (gameType == 2 && bishops != null)
bishops.unset(btns, numRow, numCol);
else if (gameType == 3 && queens != null)
queens.unset(btns, numRow, numCol);
}
else
{
/* Game events.. */
if(gameType != 0) // ensure game type is selected to avoid exception errors..
{
if (!game.hasWon())
{
if (gameType == 1 && rooks != null)
rooks.placeMark(btns, numRow, numCol);
else if(gameType == 2 && bishops != null)
bishops.placeMark(btns, numRow, numCol);
else if(gameType == 3 && queens != null)
queens.placeMark(btns, numRow, numCol);
}
}
else
Debug.print("Please select a game type");
}
}
public void mousePressed(MouseEvent e) { }
public void mouseReleased(MouseEvent e) { }
public void mouseEntered(MouseEvent e) { }
public void mouseExited(MouseEvent e) { }
});
gridPanel.add(btns[i][k]);
}
}
bgPnl.add(gridPanel, BorderLayout.CENTER);
/**
* Content to be displayed at the bottom of the GUI
*/
JPanel bottomPnl = new JPanel(new BorderLayout());
// create new panel to house the progress bar components
JPanel internalPnl1 = new JPanel(new BorderLayout());
JLabel progressLabel = new JLabel("Your progress: ");
internalPnl1.add(progressLabel, BorderLayout.NORTH);
progressBar = new JProgressBar(0, 0); // we'll initiaise the maximum value when the game type is selected
progressBar.setValue(0);
progressBar.setStringPainted(true); // enable custom messages to be written
progressBar.setString("0"); // write message to the progress bar
internalPnl1.add(progressBar, BorderLayout.SOUTH);
// add panel to the bottom house
bottomPnl.add(internalPnl1, BorderLayout.NORTH);
JPanel internalPnl2 = new JPanel(new FlowLayout());
resetButton.addActionListener(this);
internalPnl2.add(resetButton);
solveButton.addActionListener(this);
internalPnl2.add(solveButton);
bottomPnl.add(internalPnl2, BorderLayout.SOUTH);
bgPnl.add(bottomPnl, BorderLayout.SOUTH); // add bottom panel to the content pane
/**
* Finish up
*/
pack();
}
public void actionPerformed(ActionEvent e)
{
/* File Menu */
if (e.getSource() == resGame || e.getSource() == resetButton)
{
resetGame();
}
else if(e.getSource() == exit)
{
System.exit(0);
}
else if (e.getSource() == aboutMenu)
{
Help h = new Help();
}
/* Game modes (from menu bar and dropdown) */
else if (e.getSource() == rooksMenu ||
(e.getSource() == gameModes && gameModes.getSelectedItem() == "Rooks"))
{
gameType = 1;
game = rooks = new Rooks(board_size, board_size, gameType);
progressBar.setMaximum(8);
disableGameTypes();
}
else if (e.getSource() == bishopsMenu ||
(e.getSource() == gameModes && gameModes.getSelectedItem() == "Bishops"))
{
gameType = 2;
game = bishops = new Bishops(board_size, board_size, gameType);
progressBar.setMaximum(13);
disableGameTypes();
}
else if (e.getSource() == queensMenu ||
(e.getSource() == gameModes && gameModes.getSelectedItem() == "Queens"))
{
gameType = 3;
game = queens = new Queens(board_size, board_size, gameType);
progressBar.setMaximum(8);
disableGameTypes();
}
/* Buttons */
else if (e.getSource() == solveButton)
{
throw new UnsupportedOperationException("Not yet implemented: solve feature");
}
}
/**
* Enable all game type buttons
*/
private void enableGameTypes() {
gameModes.setEnabled(true);
}
/**
* Disable all game type buttons (stop user causing problems)
*/
private void disableGameTypes() {
gameModes.setEnabled(false);
}
/**
* Update the information label with the new number of pieces placed to the board
* @param num Number of tiles placed on the board
*/
public static void updateCounter(int num) {
if (num < progressBar.getValue()) {
int update = progressBar.getValue() - 1;
progressBar.setValue(update);
progressBar.setString(Integer.toString(update));
}
else if (num > progressBar.getValue()) {
int update = progressBar.getValue() + 1;
progressBar.setValue(update);
progressBar.setString(Integer.toString(update));
}
}
/**
* Completely reset the interface and back-end (Board)
* All buttons, information labels and game type reset to their original state
* @see Board
*/
private void resetGame() {
for (int i = 0; i < btns[0].length; i++) {
for (int k = 0; k < btns.length; k++) {
btns[i][k].setIcon(null);
btns[i][k].setEnabled(true);
btns[i][k].setBackground(UIManager.getColor("Button.background"));
}
}
gameType = 0; // reset game type (force re-check to avoid bugs..)
progressBar.setValue(0);
progressBar.setString("0");
enableGameTypes(); // re-enable all the GUI components
// reset backend
game.initialise(); // reset the board to default character
game.resetCounter();
game.resetGameType();
}
}
Main.java
import queens.gui.GUI;
public class Main
{
/**
* Size of the board (force only one variable to create a square (same width + height)
*/
private static final int BOARD_SIZE = 8;
/**
* Main Class invokes the GUI
* @param args
*/
public static void main(String[] args)
{
GUI i = new GUI(BOARD_SIZE);
i.setVisible(true);
}
}