JLabel's setText() method not working properly - java

I am looking to solve the N-Queens problem, and I have pinpointed the issue that I am having. There is a JButton that is pressed to tell the user textually in the frame if their solution is correct or not. This button only seems to work when Queens have not been placed on the board. The problem seems to be the setText() method for my JLabel "ifNotSafe" is not working properly. If I put print statements under that method call, the correct message is sent to the console but the label is not changed. The label weirdly only works when Queens have not been placed on the board yet. There is also a Boxes object with an x value and a y value, and a getter method for each.
import javax.swing.*;
import javax.swing.border.LineBorder;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
/*
* Overall class to make the whole ChessBoard and all the helper methods to
* tell the user whether their solution is correct or not
*/
public class ChessBoardGUI extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
//ImageIcon queenP = new //ImageIcon(getClass().getResource("/images/queen.png"));
//Image img = queenP.getImage();
//Image newImg = img.getScaledInstance(40, 40, java.awt.Image.SCALE_SMOOTH);
ImageIcon queenPic = new ImageIcon(newImg);
private static JButton tip;
private static JButton safe;
private static JLabel ifNotSafe;
private JButton[][] chessBoxes = new JButton[8][8];
public static JPanel chessBoard;
public static ArrayList<Boxes> queensOnBoard = new ArrayList<Boxes>();
/*
* Makes the whole frame for the ChessBoard
*/
public ChessBoardGUI() {
createBoard();
createOtherThings();
setSize(500, 500);
}
/*
* Creates the Tip and Safe buttons And Label to display when the solution
* is incorrect
*/
public void createOtherThings() {
safe = new JButton("Safe?");
tip = new JButton("Tip");
ifNotSafe = new JLabel("Status of Board is displayed here...");
ButtonListen1 safeListener = new ButtonListen1();
ButtonListen2 tipListener = new ButtonListen2();
safe.addActionListener(safeListener);
tip.addActionListener(tipListener);
}
/*
* ActionListener for the safe button
*/
class ButtonListen1 implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
// Tells user which queens are not safe
if (checkSolution(queensOnBoard) == true) {
//****THIS IS WHERE THE PROBLEM IS *******
ifNotSafe.setText("This Solution is correct so far");
System.out.println("Solution is correct");
} else{
ifNotSafe.setText("This Solution is incorrect so far");
// *********Also highlight the queens that are not safe******
System.out.println("Solution is incorrect");
}
}
}
/*
* ActionListener for the tip button
*/
class ButtonListen2 implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
// ********Tells the user other places to put queens********
}
}
/*
* Creates the overall ChessBoard
*/
public void createBoard() {
GridLayout gridLayout = new GridLayout();
gridLayout.setRows(8);
gridLayout.setColumns(8);
chessBoard = new JPanel(gridLayout);
chessBoard.setSize(400, 400);
chessBoard.setBorder(new LineBorder(Color.BLACK));
chessBoard.setVisible(true);
/*
* Loops through to add each chessBox to the chessBoard
*/
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 8; y++) {
chessBoxes[x][y] = new JButton();
chessBoxes[x][y].setBorderPainted(false);
/*
* Assigns a color to every other box
*/
if ((x + y) % 2 == 0) {
chessBoxes[x][y].setBackground(Color.BLACK);
} else {
chessBoxes[x][y].setBackground(Color.WHITE);
}
chessBoxes[x][y].setOpaque(true);
chessBoard.add(chessBoxes[x][y]);
// Adds the ActionListener to each chessBox
BoxListener boxListen = new BoxListener();
chessBoxes[x][y].addActionListener(boxListen);
}
}
}
/*
* Action Listener for if the individual boxes on the ChessBoard are clicked
*/
class BoxListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
JButton button = ((JButton) e.getSource());
// Runs through a loop to find the X and Y coordinate of the
// JButton(Box) that was clicked
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 8; y++) {
if (chessBoxes[x][y] == button) {
/*
* If there is No Queen at that JButton
*/
if ((isOnBoard(queensOnBoard, x, y) == false)) {
// Makes sure the user can not place more than
// 8 Queens on the board
if (queensOnBoard.size() < 8) {
// Sets Picture of Queen on box
//button.setIcon(queenPic);
button.setText("Occupied");
// Adds box to the ArrayList of occupied boxes
queensOnBoard.add(new Boxes(x, y));
}
}
/*
* If there is a Queen at that JButton
*/
else {
removeQueen(queensOnBoard, x, y);
//button.setIcon(null);
button.setText("");
}
}
}
}
}
}
/*
* Checks if a certain Box has a Queen in it or not
*
* #param a Is the ArrayList of the Boxes currently occupied by Queens
*
* #param x Is the X coordinate of the Box that was clicked
*
* #param y Is the Y coordinate of the Box that was clicked
*/
public boolean isOnBoard(ArrayList<Boxes> a, int x, int y) {
for (int i = 0; i < a.size(); i++) {
if (((a.get(i)).getX() == x) && ((a.get(i)).getY() == y)) {
return true;
}
}
return false;
}
/*
* Removes a Queen from the GUI at the specified Box (JButton)
*
* #param a Is the ArrayList of the Boxes currently occupied by Queens
*
* #param x Is the X coordinate of the Box that was clicked
*
* #param y Is the Y coordinate of the Box that was clicked
*/
public void removeQueen(ArrayList<Boxes> a, int x, int y) {
/*
* Removes the box from the overall ArrayList of Boxes Occupied by
* queens according to the x and y location
*/
for (int i = 0; i < a.size(); i++) {
if (((a.get(i)).getX() == x) && ((a.get(i)).getY() == y)) {
queensOnBoard.remove(i);
}
}
}
/*
* Return to the user which queens need to be highlighted
*
* #param queensOnBoard Is the ArrayList of Boxes that are occupied by
* Queens currently on the ChessBoard
*/
public void conflictingQueens(ArrayList<Boxes> queensOnBoard) {
// *******Call the highlightBoxes method using the ArrayList
// Of Boxes you get from this method
}
/*
* Checks to see if solution is correct thusfar
*
* #param queensOnBoard Is the ArrayList of Boxes that are occupied by
* Queens currently on the ChessBoard
*/
public boolean checkSolution(ArrayList<Boxes> queensOnBoard) {
int size = queensOnBoard.size();
if (size < 1) {
return true;
}
if (size == 1) {
return true;
}
for (int x = 0; x < size - 1; x++) {
for (int y = 1; y < size; y++) {
// Checks if Queen is safe from horizontal attacks
if (queensOnBoard.get(x).getX() == queensOnBoard.get(y).getX()) {
return false;
// Checks if Queen is safe from vertical attacks
} else if (queensOnBoard.get(x).getY() == queensOnBoard.get(y).getY()) {
return false;
// Checks if Queen is safe from diagonal attacks
// Uses diagonalAttack(queensOnBoard) as a helper method
} // else if(){
// return false;
// }
}
}
return true;
}
/*
* Checks to see if the queen is safe from diagonal attacks
*
*
*/
// public boolean diagonalAttack(ArrayList<Boxes> queensOnBoard){
//********
// }
/*
* Highlights boxes that are conflicting with one another
*
* #param highlight Is the ArrayList of Boxes that are occupied by Queens
* currently on the ChessBoard
*/
public void highlightBoxes(ArrayList<Boxes> highlight) {
int size1 = highlight.size();
int size2 = queensOnBoard.size();
// When there aren't any queens at risk, this block
// changes the background colors of the boxes back to
// Their respective color
if ((size1 == 0) && size1 == 1) {
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 8; y++) {
chessBoxes[x][y] = new JButton();
chessBoxes[x][y].setBorderPainted(false);
/*
* Assigns a color to every other box
*/
if ((x + y) % 2 == 0) {
chessBoxes[x][y].setBackground(Color.BLACK);
} else {
chessBoxes[x][y].setBackground(Color.WHITE);
}
}
}
}
// Runs through both the highlight and queensOnBoard ArrayLists and
// changes the background for the Queens at risk
for (int b = 0; b < size2; b++) {
for (int a = 0; a < size1; a++) {
if ((highlight.get(a).getX() == queensOnBoard.get(b).getX())
&& (highlight.get(a).getY() == queensOnBoard.get(b).getY())) {
int x = queensOnBoard.get(b).getX();
int y = queensOnBoard.get(b).getY();
chessBoxes[x][y].setBackground(Color.RED);
}
}
}
}
/*
* Main method to run the program
*
* #param args Is the String of args given to the console to run the
* operations of the program
*/
public static void main(String[] args) {
JFrame frame = new ChessBoardGUI();
frame.add(chessBoard);
chessBoard.setLocation(50, 50);
JPanel panel1 = new JPanel();
panel1.add(ifNotSafe);
panel1.add(safe);
panel1.add(tip);
frame.add(panel1);
frame.setTitle("ChessBoard");
frame.setVisible(true);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
}

You may have a layout problem in that your JLabel doesn't show well because the JPanel that holds it has been added incorrectly to the GUI. Understand that a JFrame's contentPane uses BorderLayout by default, and so when adding components to it, you should specify the BorderLayout location that the component should be placed in. The grid will be placed BorderLayout.CENTER, and panel1 should be placed BorderLayout.PAGE_START. Also, the grid's preferred size should be set, and you should call pack() on your JFrame after adding all components but before making it visible or setting its location.
Other minor quibbles:
None of your current fields should be public or static.
You should be adding components to your JFrame within the non-static code and not in the main method.
If you need to expose any properties to the outside static world, give your class public getter methods which will allow you to expose only what is necessary and in a controlled manner.
Test code is below. Note that I don't have your queen images available so I created a method that you won't need, private Icon createQueenIcon(). This way your code will run on my system. Also to make the code run and compile, I created and included the necessary Boxes class. In the future, be sure that you include all that is needed for us to be able to compile and run your code!
import javax.swing.*;
import javax.swing.border.LineBorder;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.util.*;
public class ChessBoardGUI extends JFrame {
private static final long serialVersionUID = 1L;
// !! code changes below only to allow me to run your code without
// your images. !!
// ImageIcon queenP = new ImageIcon(getClass().getResource("/images/queen.png"));
// Image img = queenP.getImage();
// Image newImg = img.getScaledInstance(40, 40,
// java.awt.Image.SCALE_SMOOTH);
private ImageIcon queenPic = createQueenIcon(); //!! delete this
// all fields should be private and non-static
private JButton tip;
private JButton safe;
private JLabel ifNotSafe;
private JButton[][] chessBoxes = new JButton[8][8];
private JPanel chessBoard;
private ArrayList<Boxes> queensOnBoard = new ArrayList<Boxes>();
public ChessBoardGUI() {
createBoard();
add(chessBoard, BorderLayout.CENTER); // Do this here
// !! createOtherThings(); // get rid of -- put in constructor
safe = new JButton("Safe?");
tip = new JButton("Tip");
ifNotSafe = new JLabel("Status of Board is displayed here...");
ButtonListen1 safeListener = new ButtonListen1();
ButtonListen2 tipListener = new ButtonListen2();
safe.addActionListener(safeListener);
tip.addActionListener(tipListener);
// !! add the panel1 here!
JPanel panel1 = new JPanel();
panel1.add(ifNotSafe);
panel1.add(safe);
panel1.add(tip);
add(panel1, BorderLayout.PAGE_START); // using BorderLayout constants
// !! setSize(500, 500);
}
// !! so I can use images without having an image
// !! you won't need this
private Icon createQueenIcon() {
int w = 40;
BufferedImage img2 = new BufferedImage(w, w, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = img2.createGraphics();
g2.setColor(new Color(183, 65, 14));
g2.fillRect(0, 0, w, w);
g2.setColor(new Color(255, 215, 0));
Font font = new Font(Font.SANS_SERIF, Font.BOLD, 30);
g2.setFont(font);
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
FontMetrics fontMetrics = g2.getFontMetrics();
int textX = (w - fontMetrics.charWidth('Q')) / 2;
int textY = (w - fontMetrics.getHeight()) / 2 + fontMetrics.getAscent();
g2.drawString("Q", textX, textY);
g2.dispose();
return new ImageIcon(img2);
}
class ButtonListen1 implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if (checkSolution(queensOnBoard) == true) {
// ****THIS IS WHERE THE PROBLEM IS ******* !!
ifNotSafe.setText("This Solution is correct so far");
System.out.println("Solution is correct");
} else {
ifNotSafe.setText("This Solution is incorrect so far");
// *********Also highlight the queens that are not safe******
System.out.println("Solution is incorrect");
}
}
}
/*
* ActionListener for the tip button
*/
class ButtonListen2 implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
}
}
/*
* Creates the overall ChessBoard
*/
public void createBoard() {
GridLayout gridLayout = new GridLayout();
gridLayout.setRows(8);
gridLayout.setColumns(8);
chessBoard = new JPanel(gridLayout);
chessBoard.setPreferredSize(new Dimension(640, 640));
chessBoard.setBorder(new LineBorder(Color.BLACK));
chessBoard.setVisible(true);
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 8; y++) {
chessBoxes[x][y] = new JButton();
chessBoxes[x][y].setBorderPainted(false);
if ((x + y) % 2 == 0) {
chessBoxes[x][y].setBackground(Color.BLACK);
} else {
chessBoxes[x][y].setBackground(Color.WHITE);
}
chessBoxes[x][y].setOpaque(true);
chessBoard.add(chessBoxes[x][y]);
BoxListener boxListen = new BoxListener();
chessBoxes[x][y].addActionListener(boxListen);
}
}
}
class BoxListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
JButton button = ((JButton) e.getSource());
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 8; y++) {
if (chessBoxes[x][y] == button) {
if ((isOnBoard(queensOnBoard, x, y) == false)) {
if (queensOnBoard.size() < 8) {
button.setIcon(queenPic);
queensOnBoard.add(new Boxes(x, y));
}
}
/*
* If there is a Queen at that JButton
*/
else {
removeQueen(queensOnBoard, x, y);
button.setIcon(null);
}
}
}
}
}
}
/*
* Checks if a certain Box has a Queen in it or not
*
* #param a Is the ArrayList of the Boxes currently occupied by Queens
*
* #param x Is the X coordinate of the Box that was clicked
*
* #param y Is the Y coordinate of the Box that was clicked
*/
public boolean isOnBoard(ArrayList<Boxes> a, int x, int y) {
for (int i = 0; i < a.size(); i++) {
if (((a.get(i)).getX() == x) && ((a.get(i)).getY() == y)) {
return true;
}
}
return false;
}
/*
* Removes a Queen from the GUI at the specified Box (JButton)
*
* #param a Is the ArrayList of the Boxes currently occupied by Queens
*
* #param x Is the X coordinate of the Box that was clicked
*
* #param y Is the Y coordinate of the Box that was clicked
*/
public void removeQueen(ArrayList<Boxes> a, int x, int y) {
/*
* Removes the box from the overall ArrayList of Boxes Occupied by
* queens according to the x and y location
*/
for (int i = 0; i < a.size(); i++) {
if (((a.get(i)).getX() == x) && ((a.get(i)).getY() == y)) {
queensOnBoard.remove(i);
}
}
}
/*
* Return to the user which queens need to be highlighted
*
* #param queensOnBoard Is the ArrayList of Boxes that are occupied by
* Queens currently on the ChessBoard
*/
public void conflictingQueens(ArrayList<Boxes> queensOnBoard2) {
}
/*
* Checks to see if solution is correct thusfar
*
* #param queensOnBoard Is the ArrayList of Boxes that are occupied by
* Queens currently on the ChessBoard
*/
public boolean checkSolution(ArrayList<Boxes> queensOnBoard2) {
int size = queensOnBoard2.size();
if (size < 1) {
return true;
}
if (size == 1) {
return true;
}
for (int x = 0; x < size - 1; x++) {
for (int y = 1; y < size; y++) {
if (queensOnBoard2.get(x).getX() == queensOnBoard2.get(y).getX()) {
return false;
} else if (queensOnBoard2.get(x).getY() == queensOnBoard2.get(y).getY()) {
return false;
}
}
}
return true;
}
/*
* Checks to see if the queen is safe from diagonal attacks
*/
/*
* Highlights boxes that are conflicting with one another
*
* #param highlight Is the ArrayList of Boxes that are occupied by Queens
* currently on the ChessBoard
*/
public void highlightBoxes(ArrayList<Boxes> highlight) {
int size1 = highlight.size();
int size2 = queensOnBoard.size();
if ((size1 == 0) && size1 == 1) {
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 8; y++) {
chessBoxes[x][y] = new JButton();
chessBoxes[x][y].setBorderPainted(false);
/*
* Assigns a color to every other box
*/
if ((x + y) % 2 == 0) {
chessBoxes[x][y].setBackground(Color.BLACK);
} else {
chessBoxes[x][y].setBackground(Color.WHITE);
}
}
}
}
for (int b = 0; b < size2; b++) {
for (int a = 0; a < size1; a++) {
if ((highlight.get(a).getX() == queensOnBoard.get(b).getX())
&& (highlight.get(a).getY() == queensOnBoard.get(b).getY())) {
int x = queensOnBoard.get(b).getX();
int y = queensOnBoard.get(b).getY();
chessBoxes[x][y].setBackground(Color.RED);
}
}
}
}
public static void main(String[] args) {
// !! create the GUI in a Swing thread-safe manner
SwingUtilities.invokeLater(() -> createGui());
}
public static void createGui() {
JFrame frame = new ChessBoardGUI();
// !! frame.add(chessBoard); // not here
// !! chessBoard.setLocation(50, 50);
// !! this does not belong within main
// !! JPanel panel1 = new JPanel();
// panel1.add(ifNotSafe);
// panel1.add(safe);
// panel1.add(tip);
// frame.add(panel1);
frame.setTitle("ChessBoard");
frame.pack(); // !! call this to have your GUI size itself
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private static class Boxes {
private int x;
private int y;
public Boxes(int x, int y) {
this.x = x;
this.y = y;
}
public int getY() {
return x;
}
public int getX() {
return y;
}
}
}

Related

How to update the position of snakes and ladders in an 2D array code?

public class ChutesAndLadders2d {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[][] numbersOnBoard = new int [6][6];
boardSetUpA (numbersOnBoard);
printTwoD(numbersOnBoard);
}
public static void boardSetUpA (int[][]twoD) {
//Square with even size
//even rows
for (int row = 0;row<twoD.length; row ++) {
if (row %2 ==0) {
int num = twoD.length*(twoD.length-row);
for (int col = 0; col<twoD[row].length; col ++ ) {
twoD[row][col] = num;
num--;
}
}//
else {
int num = twoD.length*(twoD.length-(row + 1))+ 1;
for (int col = 0; col<twoD[row].length; col ++ ) {
twoD[row][col] = num;
num++;
}
}
}//for row
}//
public static void printTwoD(int [][] array){
for (int row = 0; row < array.length; row++){
for (int column = 0; column < array[row].length; column++){
System.out.print(array[row][column] + "\t");
}
System.out.println();
}
}
public static void boardDetails(String[][]board) {
for (int row = 0;row<board.length; row++){
for (int col = 0;col<board[row].length; col++){
if( col+2 == row||col+1 == row*2 ){
board[row][col] = "Lad"; // Append value
}
else if (col*2 == row|| row*2 == col){
board[row][col] = "Cht";// Append value
}
else {
board[row][col] = " ";
}
}
board[board.length-1][0] = "Start";
if (board.length%2 ==0) {
board[0][0] = "End";}
else {
board[0][board.length-1]="End";
}
}
}
public static void printBoard (int[][]twoD, String[][]strTwoD) {
//Printing
for (int row = 0;row<twoD.length;row++) {
for (int col = 0;col<twoD[row].length;col++) {
System.out.print(twoD[row][col] + " "+strTwoD[row][col]+"\t\t");
}
System.out.println("\n");
}
}
}
This is the starter code I have for setting up the snakes and ladders game. I also tried to set the chutes/snakes and ladders on the board but it is not printing. How should I fix it and how do I develop this code to have three methods: update the moves of a player once he reaches a snake, a ladder, and once he rolls his die, from one place to another?
Is it possible to implement a Shutes & Ladders game using a 2D Array? For sure! Does that make sense in an object-oriented language such as Java? I dont know ....
What do you need for that?
A square board with e.g. 36 playing fields.
Connections between two playing fields. (shutes and ladders)
Pawns and a dice.
A renderer that outputs the playing field (as text or graphics).
A program that allows input and connects everything to a functioning game.
Here is an example that works with a List instead of an Array. That can certainly be changed if it is necessary for your purposes.
I hope this is of some help to you.
P.S .: After the start, the board is displayed with field numbers. Shutes are shown as red lines. Ladders as green lines. Keys 1-6 on the keyboard simulate rolling the dice..
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyAdapter;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import javax.swing.*;
public class ChutesAndLadders2d {
public static void main(String[] args) {
JFrame frame = new JFrame("Chutes and Ladders 2D");
Game game = new ChutesAndLadders2d().new Game();
game.setPreferredSize(new Dimension(400, 400));
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setContentPane(game);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
#SuppressWarnings("serial")
class Game extends JPanel{
private final Font defaultFont = new Font("Arial", Font.PLAIN, 16);
private final BasicStroke stroke = new BasicStroke(4f);
private static final int SCALE = 64;
// board and pawns
private final Board board = new Board(6);
private final List<Pawn> pawns = new ArrayList<>();
public Game(){
setFocusable(true); // receive Keyboard-Events
addKeyListener(new KeyAdapter(){
#Override
public void keyTyped(KeyEvent e) {
char c = e.getKeyChar();
if(c >= '1' && c <= '6'){
int steps = Integer.parseInt(Character.toString(c));
Pawn pawn = pawns.get(0);
pawn.move(steps);
Field field = board.get(pawn.fieldIndex);
if(field.targetKind() != Kind.NONE){
pawn.move(field.getTarget().index - field.index);
}
repaint();
}
}
});
board.connect(5, 12); // Ladder 5 -> 12
board.connect(8, 4); // Shute 8 -> 4
board.connect(15, 32); // Ladder 15 -> 32
board.connect(35, 17); // Shute 35 -> 17
board.connect(23, 30); // Ladder 23 -> 30
pawns.add(new Pawn(Color.BLUE, board.size() - 1));
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
setFont(defaultFont);
for(Field field : board){
Point p = field.getLocation();
g2d.drawRect(p.x * SCALE, p.y * SCALE, SCALE, SCALE);
g2d.drawString(field.text, p.x * SCALE + 24, p.y * SCALE + 40);
}
for(Field field : board){
if(field.targetKind() != Kind.NONE){
g2d.setColor(field.targetKind() == Kind.LADDER ? Color.GREEN : Color.RED);
g2d.setStroke(stroke);
Point source = field.getLocation();
Point target = field.getTarget().getLocation();
g2d.drawLine(source.x * SCALE + 40, source.y * SCALE + 24, target.x * SCALE + 40, target.y * SCALE + 24);
}
}
for(Pawn pawn : pawns){
Point loc = board.get(pawn.fieldIndex).getLocation();
g2d.setColor(pawn.color);
g2d.fillOval(loc.x * SCALE + 32, loc.y * SCALE + 32, 16, 16);
}
}
}
class Board implements Iterable<Field>{
private final List<Field> fields = new ArrayList<>();
public Board(int size){
for(int index = 0; index < size * size; index++)
fields.add(new Field(index, size));
}
public Field get(int index){
return fields.get(index);
}
public void connect(int startFieldnumber, int targetFieldnumber){
get(startFieldnumber - 1).setTarget(get(targetFieldnumber - 1));
}
#Override
public Iterator<Field> iterator() {
return fields.iterator();
}
public int size(){
return fields.size();
}
}
class Field{
final int index;
final String text;
final int size;
private Field target;
public Field(int index, int size){
this.index = index;
this.size = size;
text = "" + (index + 1);
}
public void setTarget(Field target){
if(target == this) return;
this.target = target;
}
public Field getTarget(){
return target;
}
public Kind targetKind(){
if(target == null) return Kind.NONE;
return index < target.index ? Kind.LADDER : Kind.SHUTE;
}
public Point getLocation(){
int x = index % size;
int y = index / size;
if(y % 2 != 0) x = size - x - 1;
return new Point(x, size - y - 1);
}
}
class Pawn{
int fieldIndex = 0;
int maxIndex;
Color color;
public Pawn(Color color, int maxIndex){
this.color = color;
this.maxIndex = maxIndex;
}
public void move(int steps){
fieldIndex += steps;
if(fieldIndex < 0) fieldIndex = 0;
if(fieldIndex > maxIndex) fieldIndex = maxIndex;
}
}
enum Kind{
NONE, SHUTE, LADDER
}
}

AI vs. AI simulation too fast

I am developing a Tic Tac Toe version that uses different AI and ML techniques in java but I'm having some problem with slowing down the simulation.
Basically I would like to see the game as if it was played by two normal player while now as soon as I run it I get the final game state.
Here is my code:
Board.java
package com.nicolagheza.tictactoe;
public class Board {
// package access
Cell[][] cells; // 2D array of ROWS-by-COLS Cell instances
/** Constructor to initialize the game board */
public Board() {
cells = new Cell[GameMain.ROWS][GameMain.COLS]; // allocate the array
for (int row = 0; row < GameMain.ROWS; row++) {
for (int col = 0; col < GameMain.COLS; col++) {
cells[row][col] = new Cell(row, col); // allocate element of array
}
}
}
/** Initialize (or re-initialize) the game board */
public void init() {
for (int row = 0; row < GameMain.ROWS; row++) {
for (int col = 0; col < GameMain.COLS; col++) {
cells[row][col].clear(); // clear the cell content
}
}
}
/** Return true if it is a draw (i.e., no more EMPTY cell) */
public boolean isDraw() {
for (int row = 0; row < GameMain.ROWS; row++) {
for (int col = 0; col < GameMain.COLS; col++) {
if (cells[row][col].content == Seed.EMPTY) {
return false; // an empty seed found, not a draw, exit
}
}
}
return true; // no empty cell, it's a draw
}
/** Return true if the player with "seed" has won after placing at (seedRow, seedCol) */
public boolean hasWon(Seed seed, int seedRow, int seedCol) {
return (cells[seedRow][0].content == seed // 3-in-the-row
&& cells[seedRow][1].content == seed
&& cells[seedRow][2].content == seed
|| cells[0][seedCol].content == seed // 3-in-the-column
&& cells[1][seedCol].content == seed
&& cells[2][seedCol].content == seed
|| seedRow == seedCol // 3-in-the-diagonal
&& cells[0][0].content == seed
&& cells[1][1].content == seed
&& cells[2][2].content == seed
|| seedRow + seedCol == 2 // 3-in-the-opposite-diagonal
&& cells[0][2].content == seed
&& cells[1][1].content == seed
&& cells[2][0].content == seed);
}
}
GameState.java
package com.nicolagheza.tictactoe;
public enum GameState {
PLAYING, DRAW, CROSS_WON, NOUGHT_WON
}
GameMain.java
package com.nicolagheza.tictactoe;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class GameMain extends JPanel{
// Named-constants for the game board
public static final int ROWS = 3; // ROWS by COLS cells
public static final int COLS = 3;
public static final String TITLE = "Tic Tac Toe";
// Name-constants for the various dimensions used for graphics drawing
public static final int CELL_SIZE = 100; // cell width and height (square)
public static final int CANVAS_WIDTH = CELL_SIZE * COLS; // the drawing canvas
public static final int CANVAS_HEIGHT = CELL_SIZE * ROWS;
public static final int GRID_WIDTH = 8; // Grid-line's width
public static final int GRID_WIDHT_HALF = GRID_WIDTH / 2; // Grid-line's half-width
// Symbols (cross/nought) are displayed inside a cell, with padding from border
public static final int CELL_PADDING = CELL_SIZE / 6;
public static final int SYMBOL_SIZE = CELL_SIZE - CELL_PADDING * 2;
public static final int SYMBOL_STROKE_WIDTH = 8; // pen's stroke width
private Board board; // the game board
private BoardView boardView;
private AIPlayer aiPlayer1;
private AIPlayer aiPlayer2;
private GameState currentState; // the current state of the game
private Seed currentPlayer; // the current player
private JLabel statusBar; // for displaying status message
/** Constructor to setup the UI and game components */
public GameMain() {
// This JPanel fires MouseEvent
this.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
int mouseX = e.getX();
int mouseY = e.getY();
// Get the row and column clicked
int rowSelected = mouseY / CELL_SIZE;
int colSelected = mouseX / CELL_SIZE;
if (currentState == GameState.PLAYING) {
if (rowSelected >= 0 && rowSelected < ROWS
&& colSelected >= 0 && colSelected < COLS
&& board.cells[rowSelected][colSelected].content == Seed.EMPTY) {
board.cells[rowSelected][colSelected].content = currentPlayer; // move
updateGame(currentPlayer, rowSelected, colSelected); // update currentState
}
} else { // game over
initGame();
}
// Refresh the drawing canvas
repaint();
currentPlayer = (currentPlayer == Seed.CROSS) ? Seed.NOUGHT : Seed.CROSS;
}
});
// Setup the status bar (JLabel) to display status message
statusBar = new JLabel(" ");
statusBar.setFont(new Font(Font.DIALOG_INPUT, Font.BOLD, 14));
statusBar.setBorder(BorderFactory.createEmptyBorder(2, 5, 4, 5));
statusBar.setOpaque(true);
statusBar.setBackground(Color.LIGHT_GRAY);
setLayout(new BorderLayout());
add(statusBar, BorderLayout.SOUTH);
setPreferredSize(new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT + 30));
board = new Board(); // allocate the game-board
boardView = new BoardView(board.cells);
initGame();
initAI();
}
private void initAI() {
aiPlayer1 = new AIPlayerRuleBased(board);
aiPlayer1.setSeed(Seed.CROSS);
aiPlayer2 = new AIPlayerTableLookup(board);
aiPlayer2.setSeed(Seed.NOUGHT);
}
/** Initialize the game-board contents and the current-state */
public void initGame() {
for (int row = 0; row < ROWS; ++row) {
for (int col = 0; col < COLS; ++col) {
board.cells[row][col].content = Seed.EMPTY; // all cells empty
}
}
currentState = GameState.PLAYING; // ready to play
currentPlayer = Seed.CROSS; // cross plays first
}
public void makeAIMove(AIPlayer player) {
int[] move = player.move();
if (move != null) {
System.out.println("Player " + player.mySeed + " row: " + move[0] + " col: " + move[1]);
board.cells[move[0]][move[1]].content = player.mySeed;
updateGame(currentPlayer, move[0], move[1]);
repaint();
currentPlayer = (currentPlayer == Seed.CROSS) ? Seed.NOUGHT : Seed.CROSS;
}
}
/** Update the currentState after the player with "theSeed" has placed on (row, col) */
public void updateGame(Seed theSeed, int row, int col) {
if(board.hasWon(theSeed, row, col)) { // check for win
currentState = (theSeed == Seed.CROSS) ? GameState.CROSS_WON : GameState.NOUGHT_WON;
} else if (board.isDraw()) { // check for draw
currentState = GameState.DRAW;
}
// Otherwise, no change to current state (PLAYING).
}
/** Custom painting codes on this JPanel */
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g); // fill background
setBackground(Color.WHITE); // set its background color
boardView.paint(g); // ask the game board to paint itself
// Print status-ba message
if (currentState == GameState.PLAYING) {
statusBar.setForeground(Color.BLACK);
if (currentPlayer == Seed.CROSS) {
statusBar.setText("X's Turn");
} else {
statusBar.setText("O's Turn");
}
} else if (currentState == GameState.DRAW) {
statusBar.setForeground(Color.RED);
statusBar.setText("It's a Draw! Click to play again.");
} else if (currentState == GameState.CROSS_WON) {
statusBar.setForeground(Color.RED);
statusBar.setText("'X' Won! Click to play again.");
} else if (currentState == GameState.NOUGHT_WON) {
statusBar.setForeground(Color.RED);
statusBar.setText("'O' Won! Click to play again.");
}
}
public void getNextState() {
if (currentPlayer == aiPlayer1.mySeed) {
makeAIMove(aiPlayer1);
}
if (currentPlayer == aiPlayer2.mySeed) {
makeAIMove(aiPlayer2);
}
}
/** The entry "main" method */
public static void main(String args[]) {
// Run GUI construction codes in Event-Dispatching thread for thread safety
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame(TITLE);
// Set the content-pane of the JFrame to an instance of main JPanel
GameMain game = new GameMain();
frame.setContentPane(game);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
while (game.currentState == GameState.PLAYING) {
game.getNextState();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
}
}
AIPlayer.java
package com.nicolagheza.tictactoe;
public abstract class AIPlayer {
protected int ROWS = GameMain.ROWS; // number of rows
protected int COLS = GameMain.COLS; // number of cols
protected Cell[][] cells; // the board's ROWs-by-COLs array of Cells
protected Seed mySeed; // computer's seed
protected Seed oppSeed; // opponent's seed
/** Constructor with reference to game board */
public AIPlayer(Board board) {
cells = board.cells;
}
/** Set/change the seed used by computer and opponent */
public void setSeed(Seed seed) {
this.mySeed = seed;
oppSeed = (mySeed == Seed.CROSS) ? Seed.NOUGHT : Seed.CROSS;
}
public abstract int[] move();
}
AIPlayerRuleBased.java
package com.nicolagheza.tictactoe;
import java.util.ArrayList;
import java.util.List;
public class AIPlayerRuleBased extends AIPlayer {
/**
* Constructor with reference to game board
*
* #param board
*/
public AIPlayerRuleBased(Board board) {
super(board);
}
private List<int[]> generatePossibleMoves() {
List<int[]> nextMoves = new ArrayList<int[]>();
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
if (cells[row][col].content == Seed.EMPTY)
nextMoves.add(new int[] {row, col});
}
}
return nextMoves;
}
#Override
public int[] move() {
List<int[]> nextPossibleMoves = generatePossibleMoves();
// Rule 1: If I have a winning move, take it.
for (int[] nextMove : nextPossibleMoves) {
// Try this move
cells[nextMove[0]][nextMove[1]].content = mySeed;
if (hasWon(mySeed)) {
cells[nextMove[0]][nextMove[1]].content = Seed.EMPTY; // Undo move
return nextMove;
}
cells[nextMove[0]][nextMove[1]].content = Seed.EMPTY; // Undo move
}
// Rule 2: If the opponent has a winning move, block it
for (int[] nextMove: nextPossibleMoves) {
// Try this move
cells[nextMove[0]][nextMove[1]].content = oppSeed;
if (hasWon(oppSeed)) {
cells[nextMove[0]][nextMove[1]].content = Seed.EMPTY; // Undo move
return nextMove;
}
cells[nextMove[0]][nextMove[1]].content = Seed.EMPTY; // Undo move
}
// Moves {row, col} in order of preferences. {0,0} at top-left corner
int[][] preferredMoves = {
{1,1}, {0,0}, {0,2}, {2,0}, {2,2},
{0,1}, {1,0}, {1,2}, {2,1}};
for (int[] move : preferredMoves) {
if (cells[move[0]][move[1]].content == Seed.EMPTY) {
return move;
}
}
assert false : "No empty cell?!";
return null;
}
private int[] winningPatterns = {
0b111000000, 0b000111000, 0b000000111, // rows
0b100100100, 0b010010010, 0b001001001, // cols
0b100010001, 0b001010100 // diagonals
};
/** Returns true if thePlayer wins */
private boolean hasWon(Seed thePlayer) {
int pattern = 0b000000000; // 9-bit pattern for the 9 cells
for (int row = 0; row < ROWS; ++row) {
for (int col = 0; col < COLS; ++col) {
if (cells[row][col].content == thePlayer) {
pattern |= (1 << (row * COLS + col));
}
}
}
for (int winningPattern : winningPatterns) {
if ((pattern & winningPattern) == winningPattern) return true;
}
return false;
}
}
I tried with thread.sleep but it wont work.
(Posted on behalf of the OP).
I solved my issue using Javax.swing.Timer. Here is how I did it in case someone else is interested:
new javax.swing.Timer(TIMER_DELAY, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (game.currentState != GameState.PLAYING)
return;
game.getNextState();
}
}).start();

Make cells' contents in a grid ''listen'' to closest cells

I'm a newbie in programming and I need some lights and help.I'm developing a game in which two players have to play with tokens (say red and blue) by placing them in cells (75x75 grid). The goal is to "capture" opponent's tokens by surrounding them. (See the image, which is the actual game output, the surrounding is drawn by hand)
To do so, I need to make the tokens "listen" to neighborhood, meaning other cells in the grid. A token has to check for itself in the grid(what is its position in the grid) and check of there is another token close to it, checks it color (blue or red) then,a in certain conditions, trigger the capturing mechanism
[![Game board with tokens][1]][1]
What I have done, technically:
Created the grid ( Grid/board is a 2 dimensional array of Token objects.)
The token (which is an enumeration: EMPTY, BLUE_TOKEN, RED_TOKEN.
A currentPlayer is also a Token .
When it's the user turn, they select an empty cell at which they point. They place the currentPlayer into the grid/board at cell rowSelected, colSelected then repaint the canvas with the newly added cell in the grid/board.
Now i'm stuck on how to make the tokens listen the next cell surrounding them in order to see if there is an opponent or an ally.
PS: I've posted the same here, got downgraded because i didn't respect rules (ignorant I was)
Here is my code:
import javax.swing.JFrame;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
public class Phagocyte extends JFrame {
public static final int ROWS = 75;
public static final int COLS = 75;
public static final int CELL_SIZE = 18;
public static final int CANVAS_WIDTH = CELL_SIZE * COLS;
public static final int CANVAS_HEIGHT = CELL_SIZE * ROWS;
public static final int GRID_WIDTH = 8;
public static final int GRID_WIDHT_HALF = GRID_WIDTH / 2;
// Symbols (Blue token/Red Token) are displayed inside a cell with padding from borders
public static final int CELL_PADDING = CELL_SIZE / 5;
public static final int SYMBOL_SIZE = CELL_SIZE - CELL_PADDING * 2;
public static final int SYMBOL_STROKE_WIDTH = 3;
//This represent the various states of the game
public enum GameState {
PLAYING, DRAW, BLUE_TOKEN_WON, RED_TOKEN_WON //Haven't created a scenario yet
}
private GameState currentState; // The current state of the game
//This represent the Tokens and cell contents
public enum Token {
EMPTY, BLUE_TOKEN, RED_TOKEN
}
private Token currentPlayer; // The current player (whether red or blue)
private Token[][] board ; // This is the game board of cells (ROWS by COLS)
private DrawCanvas canvas;
private JLabel statusBar;
/**The components of the the game and the GUI are setup here */
public Phagocyte() {
canvas = new DrawCanvas();
canvas.setPreferredSize(new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT));
canvas.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
int mouseX = e.getX();
int mouseY = e.getY();
// Here to get the row and column that is clicked
int rowSelected = mouseY / CELL_SIZE;
int colSelected = mouseX / CELL_SIZE;
if (currentState == GameState.PLAYING) {
if (rowSelected >= 0 && rowSelected < ROWS && colSelected >= 0
&& colSelected < COLS && board[rowSelected][colSelected] == TOKEN.EMPTY) {
board[rowSelected][colSelected] = currentPlayer;
updateGame(currentPlayer, rowSelected, colSelected);
// Here's to switch player
currentPlayer = (currentPlayer == Token.BLUE_TOKEN) ? Token.RED_TOKEN : Token.BLUE_TOKEN;
}
} else {
initGame();
}
// Drawing canvas are refresh
repaint();
}
});
// Setup the status bar (JLabel) to display status message
statusBar = new JLabel(" ");
statusBar.setFont(new Font(Font.DIALOG_INPUT, Font.BOLD, 15));
statusBar.setBorder(BorderFactory.createEmptyBorder(2, 5, 4, 5));
Container cp = getContentPane();
cp.setLayout(new BorderLayout());
cp.add(canvas, BorderLayout.CENTER);
cp.add(statusBar, BorderLayout.NORTH);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setTitle("Phagocyte by esQmo");
setVisible(true);
board = new Token[ROWS][COLS];
initGame();
}
/** The game board contents and the status are initialised here*/
public void initGame() {
for (int row = 0; row < ROWS; ++row) {
for (int col = 0; col < COLS; ++col) {
board[row][col] = Token.EMPTY;
}
}
currentState = GameState.PLAYING;
currentPlayer = Token.RED_TOKEN;
}
/*this part need some improvements since hasWon and isDraw are not yet definied*/
public void updateGame(Token theToken, int rowSelected, int colSelected) {
if (hasWon(theToken, rowSelected, colSelected)) {
currentState = (theToken == Token.RED_TOKEN) ? GameState.RED_TOKEN_WON : GameState.BLUE_TOKEN_WON;
} else if (isDraw()) {
currentState = GameState.DRAW;
}
}
/** This is supposed to return true if it is a draw (no more empty cell for exemple) */
/** need to be improved **/
/* public boolean isDraw() {
for (int row = 0; row < ROWS; ++row) {
for (int col = 0; col < COLS; ++col) {
if (board[row][col] == Token.EMPTY) {
return false;
}
}
}
return true;
} */
/**Need to implement a Win scenario as well **/
public boolean hasWon(Token theToken, int rowSelected, int colSelected){
//
}
class DrawCanvas extends JPanel {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
setBackground(Color.WHITE);
//Grid lines
g.setColor(Color.LIGHT_GRAY);
for (int row = 1; row < ROWS; ++row) {
g.fillRoundRect(0, CELL_SIZE * row - GRID_WIDHT_HALF,
CANVAS_WIDTH-1, GRID_WIDTH, GRID_WIDTH, GRID_WIDTH);
}
for (int col = 1; col < COLS; ++col) {
g.fillRoundRect(CELL_SIZE * col - GRID_WIDHT_HALF, 0,
GRID_WIDTH, CANVAS_HEIGHT-1, GRID_WIDTH, GRID_WIDTH);
}
// This draw the Tokkens in the cells if they are not empty
Graphics2D g2d = (Graphics2D)g;
g2d.setStroke(new BasicStroke(SYMBOL_STROKE_WIDTH, BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND));
for (int row = 0; row < ROWS; ++row) {
for (int col = 0; col < COLS; ++col) {
int x1 = col * CELL_SIZE + CELL_PADDING;
int y1 = row * CELL_SIZE + CELL_PADDING;
if (board[row][col] == Token.RED_TOKEN) {
int x2 = (col + 1) * CELL_SIZE - CELL_PADDING;
int y2 = (row + 1) * CELL_SIZE - CELL_PADDING;
g2d.setColor(Color.RED);
g2d.drawOval(x1, y1, SYMBOL_SIZE, SYMBOL_SIZE);
g2d.fillOval(x1, y1, SYMBOL_SIZE, SYMBOL_SIZE);
} else
if (board[row][col] == Token.BLUE_TOKEN) {
g2d.setColor(Color.BLUE);
g2d.drawOval(x1, y1, SYMBOL_SIZE, SYMBOL_SIZE);
g2d.fillOval(x2, y1, SYMBOL_SIZE, SYMBOL_SIZE);
}
}
}
// Print status-bar message
if (currentState == GameState.PLAYING) {
statusBar.setForeground(Color.BLACK);
if (currentPlayer == Token.RED_TOKEN) {
statusBar.setText("Red, it's your move");
statusBar.setForeground(Color.RED);
} else {
statusBar.setText("Blue, it's your move");
statusBar.setForeground(Color.BLUE);
statusBar.addMouseMotionListener(null);
}
} else if (currentState == GameState.DRAW) {
statusBar.setForeground(Color.RED);
statusBar.setText("It's a draw!");
} else if (currentState == GameState.RED_TOKEN_WON) {
statusBar.setForeground(Color.RED);
statusBar.setText("Red wow!");
} else if (currentState == GameState.BLUE_TOKEN_WON) {
statusBar.setForeground(Color.BLUE);
statusBar.setText("Blue Won! ");
}
}
}
public static void main(String[] args){
SwingUtilities.invokeLater(() -> {
Phagocyte phagocyte = new Phagocyte();
});
}
}
I'm unable to post image, due to my reputation :'(

Java user input to change board space of Tic-Tac-Toe with GUI

I am having trouble figuring out how to get user input to change the rows and columns of my two player Tic-Tac-Toe game to an arbitrary size. Im not sure how to use the scanner class so that the user can input the desired size of the board space by inputting the number of rows and columns. The input should affect the GUI display
Here is the code
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Scanner;
/**
* Tic-Tac-Toe: Two-player Graphics version with Simple-OO
*/
#SuppressWarnings("serial")
public class TTTGraphics2P extends JFrame {
// Named-constants for the game board
public static final int ROWS = 3; // ROWS by COLS cells
public static final int COLS = 3;
// Named-constants of the various dimensions used for graphics drawing
public static final int CELL_SIZE = 100; // cell width and height (square)
public static final int CANVAS_WIDTH = CELL_SIZE * COLS; // the drawing canvas
public static final int CANVAS_HEIGHT = CELL_SIZE * ROWS;
public static final int GRID_WIDTH = 8; // Grid-line's width
public static final int GRID_WIDHT_HALF = GRID_WIDTH / 2; // Grid-line's half-width
// Symbols (cross/nought) are displayed inside a cell, with padding from border
public static final int CELL_PADDING = CELL_SIZE / 6;
public static final int SYMBOL_SIZE = CELL_SIZE - CELL_PADDING * 2; // width/height
public static final int SYMBOL_STROKE_WIDTH = 8; // pen's stroke width
// Use an enumeration (inner class) to represent the various states of the game
public enum GameState {
PLAYING, DRAW, CROSS_WON, NOUGHT_WON
}
private GameState currentState; // the current game state
// Use an enumeration (inner class) to represent the seeds and cell contents
public enum Seed {
EMPTY, CROSS, NOUGHT
}
private Seed currentPlayer; // the current player
private Seed[][] board ; // Game board of ROWS-by-COLS cells
private DrawCanvas canvas; // Drawing canvas (JPanel) for the game board
private JLabel statusBar; // Status Bar
/** Constructor to setup the game and the GUI components */
public TTTGraphics2P() {
canvas = new DrawCanvas(); // Construct a drawing canvas (a JPanel)
canvas.setPreferredSize(new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT));
// The canvas (JPanel) fires a MouseEvent upon mouse-click
canvas.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) { // mouse-clicked handler
int mouseX = e.getX();
int mouseY = e.getY();
// Get the row and column clicked
int rowSelected = mouseY / CELL_SIZE;
int colSelected = mouseX / CELL_SIZE;
if (currentState == GameState.PLAYING) {
if (rowSelected >= 0 && rowSelected < ROWS && colSelected >= 0
&& colSelected < COLS && board[rowSelected][colSelected] == Seed.EMPTY) {
board[rowSelected][colSelected] = currentPlayer; // Make a move
updateGame(currentPlayer, rowSelected, colSelected); // update state
// Switch player
currentPlayer = (currentPlayer == Seed.CROSS) ? Seed.NOUGHT : Seed.CROSS;
}
} else { // game over
initGame(); // restart the game
}
// Refresh the drawing canvas
repaint(); // Call-back paintComponent().
}
});
// Setup the status bar (JLabel) to display status message
statusBar = new JLabel(" ");
statusBar.setFont(new Font(Font.DIALOG_INPUT, Font.BOLD, 15));
statusBar.setBorder(BorderFactory.createEmptyBorder(2, 5, 4, 5));
Container cp = getContentPane();
cp.setLayout(new BorderLayout());
cp.add(canvas, BorderLayout.CENTER);
cp.add(statusBar, BorderLayout.PAGE_END); // same as SOUTH
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack(); // pack all the components in this JFrame
setTitle("Tic Tac Toe");
setVisible(true); // show this JFrame
board = new Seed[ROWS][COLS]; // allocate array
initGame(); // initialize the game board contents and game variables
}
/** Initialize the game-board contents and the status */
public void initGame() {
for (int row = 0; row < ROWS; ++row) {
for (int col = 0; col < COLS; ++col) {
board[row][col] = Seed.EMPTY; // all cells empty
}
}
currentState = GameState.PLAYING; // ready to play
currentPlayer = Seed.CROSS; // cross plays first
}
/** Update the currentState after the player with "theSeed" has placed on
(rowSelected, colSelected). */
public void updateGame(Seed theSeed, int rowSelected, int colSelected) {
if (hasWon(theSeed, rowSelected, colSelected)) { // check for win
currentState = (theSeed == Seed.CROSS) ? GameState.CROSS_WON : GameState.NOUGHT_WON;
} else if (isDraw()) { // check for draw
currentState = GameState.DRAW;
}
// Otherwise, no change to current state (still GameState.PLAYING).
}
/** Return true if it is a draw (i.e., no more empty cell) */
public boolean isDraw() {
for (int row = 0; row < ROWS; ++row) {
for (int col = 0; col < COLS; ++col) {
if (board[row][col] == Seed.EMPTY) {
return false; // an empty cell found, not draw, exit
}
}
}
return true; // no more empty cell, it's a draw
}
/** Return true if the player with "theSeed" has won after placing at
(rowSelected, colSelected) */
public boolean hasWon(Seed theSeed, int rowSelected, int colSelected) {
return (board[rowSelected][0] == theSeed // 3-in-the-row
&& board[rowSelected][1] == theSeed
&& board[rowSelected][2] == theSeed
|| board[0][colSelected] == theSeed // 3-in-the-column
&& board[1][colSelected] == theSeed
&& board[2][colSelected] == theSeed
|| rowSelected == colSelected // 3-in-the-diagonal
&& board[0][0] == theSeed
&& board[1][1] == theSeed
&& board[2][2] == theSeed
|| rowSelected + colSelected == 2 // 3-in-the-opposite-diagonal
&& board[0][2] == theSeed
&& board[1][1] == theSeed
&& board[2][0] == theSeed);
}
/**
* Inner class DrawCanvas (extends JPanel) used for custom graphics drawing.
*/
class DrawCanvas extends JPanel {
#Override
public void paintComponent(Graphics g) { // invoke via repaint()
super.paintComponent(g); // fill background
setBackground(Color.WHITE); // set its background color
// Draw the grid-lines
g.setColor(Color.LIGHT_GRAY);
for (int row = 1; row < ROWS; ++row) {
g.fillRoundRect(0, CELL_SIZE * row - GRID_WIDHT_HALF,
CANVAS_WIDTH-1, GRID_WIDTH, GRID_WIDTH, GRID_WIDTH);
}
for (int col = 1; col < COLS; ++col) {
g.fillRoundRect(CELL_SIZE * col - GRID_WIDHT_HALF, 0,
GRID_WIDTH, CANVAS_HEIGHT-1, GRID_WIDTH, GRID_WIDTH);
}
// Draw the Seeds of all the cells if they are not empty
// Use Graphics2D which allows us to set the pen's stroke
Graphics2D g2d = (Graphics2D)g;
g2d.setStroke(new BasicStroke(SYMBOL_STROKE_WIDTH, BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND)); // Graphics2D only
for (int row = 0; row < ROWS; ++row) {
for (int col = 0; col < COLS; ++col) {
int x1 = col * CELL_SIZE + CELL_PADDING;
int y1 = row * CELL_SIZE + CELL_PADDING;
if (board[row][col] == Seed.CROSS) {
g2d.setColor(Color.RED);
int x2 = (col + 1) * CELL_SIZE - CELL_PADDING;
int y2 = (row + 1) * CELL_SIZE - CELL_PADDING;
g2d.drawLine(x1, y1, x2, y2);
g2d.drawLine(x2, y1, x1, y2);
} else if (board[row][col] == Seed.NOUGHT) {
g2d.setColor(Color.BLUE);
g2d.drawOval(x1, y1, SYMBOL_SIZE, SYMBOL_SIZE);
}
}
}
// Print status-bar message
if (currentState == GameState.PLAYING) {
statusBar.setForeground(Color.BLACK);
if (currentPlayer == Seed.CROSS) {
statusBar.setText("X's Turn");
} else {
statusBar.setText("O's Turn");
}
} else if (currentState == GameState.DRAW) {
statusBar.setForeground(Color.RED);
statusBar.setText("It's a Draw! Click to play again.");
} else if (currentState == GameState.CROSS_WON) {
statusBar.setForeground(Color.RED);
statusBar.setText("'X' Won! Click to play again.");
} else if (currentState == GameState.NOUGHT_WON) {
statusBar.setForeground(Color.RED);
statusBar.setText("'O' Won! Click to play again.");
}
}
}
/** The entry main() method */
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Input the number of rows");
int userInputNumber = ROWS;
// Run GUI codes in the Event-Dispatching thread for thread safety
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TTTGraphics2P(); // Let the constructor do the job
}
});
}
}

resize required to view images in java applet

I'm working with java images for the first time and having a problem viewing them when the applet loads. If I resize the window they display fine. I feel like this is a common first-timer error. Has anyone else encountered this? Any idea what the fix could be? What I believe to be the pertinent parts of the code are listed below. Thanks for any and all help with this...
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
import java.util.*;
public class example extends JApplet implements Runnable
{
boolean updating;
Thread thread;
private int width, height;
Table aTable; //used to create and store values
private AudioClip[] sounds = new AudioClip[4]; //array to hold audio clips
private int counter = 0; //counter for audio clip array
private Image GameImage;
private Graphics GameGraphics;
public example() //set up applet gui
{
this.resize(new Dimension(600, 500));
//setup table
aTable = new Table(50, 50, 50, 50, 16, 16, getImage("images/FLY.gif", Color.white),
getImage("images/FlySwatter.gif", Color.white)); //Table must be square or flyswatter wont move straight
//add cordTxtFlds to bottom of screen
//this.add(cordTxtFlds, BorderLayout.SOUTH);
super.resize(800, 600);
repaint();
}
public void init()
{
width = getSize().width;
height = getSize().height;
GameImage = createImage(width, height);
GameGraphics = GameImage.getGraphics();
// Automatic in some systems, not in others
GameGraphics.setColor(Color.black);
repaint();
validate();
//show the greeting
ImageIcon icon = new ImageIcon("images/FLY.gif",
"a fly");
repaint();
validate();
}
/** Description of paint(Graphics g)
*
* Function draws table and sets the table color
* #param g graphics object used to draw table
* #return void
*/
public void paint(Graphics g)
{
GameGraphics.clearRect(0, 0, getWidth(), getHeight());
aTable.draw(GameGraphics);
g.drawImage(GameImage, 0, 0, this);
}
public void update(Graphics g)
{
paint(g);
validate();
}
public void start()
{
thread = new Thread(this);
thread.start();
}
public void stop()
{
updating = false;
}
public void run()
{
while(updating)
{
aTable.update();
}
}
//returns a transparent image.
//color is made transparent
private Image getImage(String imgPath, final Color color)
{
Image img = Toolkit.getDefaultToolkit().getImage(imgPath);
ImageFilter filter = new RGBImageFilter() {
// the color we are looking for... Alpha bits are set to opaque
public int markerRGB = color.getRGB() | 0xFFFFFF;
public final int filterRGB(int x, int y, int rgb) {
if ( ( rgb | 0xFF000000 ) == markerRGB ) {
// Mark the alpha bits as zero - transparent
return 0x00FFFFFF & rgb;
}
else {
// nothing to do
return rgb;
}
}
};
ImageProducer ip = new FilteredImageSource(img.getSource(), filter);
img = Toolkit.getDefaultToolkit().createImage(ip);
return img;
}
}
and the class which handles the drawing (in drawValues())
import java.awt.*;
import java.util.Random;
public class Table extends Panel
{
private char[][]values = new char[10][10]; //probably better to use array of integer values(0 or 1)
private Point[]coordLoc;// = new Point[100]; //stores the x & y coordinates of points on the grid
private boolean[]itemMarker; //stores the truth value of wether or not an item
// is located at the coresponding point in cordLoc array
private int [][]coords;// = new int [100][2];
Image itemImg; // stores the item image
private int Rows; // stores number of rows
private int Columns; // stores number of columns
private int BoxWidth ; // stores the width of a box
private int BoxHeight; // stores the height of a box
public Point Pos = new Point(); // creates a new point to draw from
private int tableHeight; // stores the height of the table
private int tableWidth; // stores the width of the table
private int numOfGridLocs;
/** Description of public Table( x, y, width, height, col, rows, X, O)
*
* Constructor function
* #param x contains an x-coordinate of the table
* #param y contains a y-coordinate of the table
* #param width contains the width of a box in the table
* #param height contains the height of a box in the table
* #param col contains the number of columns in the table
* #param rows contains the number of rows in the table
* #param itemImg contains the "target" image ie: ant, fly, ... unicorn
* #return none
*/
public Table(int x, int y, int width, int height, int col, int rows, Image itemImg, Image swatterImg)
{
/*set values*/
numOfGridLocs = (col - 1) * (rows - 1);
//initialize arrays
coordLoc = new Point[numOfGridLocs];
for(int i = 0; i < numOfGridLocs; i++)
coordLoc[i] = new Point();
Rows = rows;
Columns = col;
BoxWidth = width;
BoxHeight = height;
Pos.x = x;
Pos.y = y;
this.itemImg = itemImg;
tableHeight = Rows*BoxHeight;
tableWidth = Columns*BoxWidth;
itemMarker = new boolean[numOfGridLocs];
coords = new int [numOfGridLocs][2];
this.setValues();
mapGrid();
}
/** Description of draw(Graphics g)
*
* Function draws the lines used in the table
* #param g object used to draw the table
* #return none
*/
public void draw(Graphics g)
{
Graphics2D g2=(Graphics2D)g;
//draw flyswatter
drawValues(g2); //draw values
//draw vertical table lines
for (int i = 0 ; i <= Columns ; i++)
{
//make center line thicker
if(i == Rows/2)
g2.setStroke(new BasicStroke(2));
else
g2.setStroke(new BasicStroke(1));
g2.drawLine(i*BoxWidth + Pos.x, Pos.y, i*BoxWidth + Pos.x, tableHeight+Pos.y);
}
//draw horizontal table line
for(int i = 0 ; i <= Rows ; i++)
{
//make center line thicker
if(i == Rows/2)
g2.setStroke(new BasicStroke(2));
else
g2.setStroke(new BasicStroke(1));
g2.drawLine(Pos.x, i*BoxHeight + Pos.y, tableWidth+Pos.x, i*BoxHeight + Pos.y);
}
drawLables(g);
}
/** Description of drawLables(Graphics g)
*
* Function draws the Lables of the Table
* #param g object used to draw the table
* #return none
*/
private void drawLables(Graphics g)
{
String Lable;
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
Font font = new Font("Serif", Font.PLAIN, 10);
g2.setFont(font);
int xLabel = this.Columns/2 * -1;
int yLabel = this.Rows/2;
//draw Row lables
for (int i = 0 ; i <= Rows ; i++)
{
Lable = "" + yLabel;
g2.drawString(Lable, Pos.x - 25, Pos.y + BoxHeight*i);
yLabel--;
}
//draw Column lables
for (int i = 0 ; i <= Columns ; i++)
{
Lable = "" + xLabel;
g2.drawString(Lable, Pos.x + BoxWidth*i - 5, Pos.y - 20 );
xLabel++;
}
}
/** Description of randomChangeFunc()
*
* Function randomly determines which table value to change
* #param none
* #return void
*/
public int getX(int XCordinate)
{
int x = XCordinate+Columns/2;
if(x < 0) x *= -1; //x must be positive
x *= BoxWidth;
x += Pos.x;
return x-BoxWidth/2;
}
//returns Position of Y-cordinate
public int getY(int YCordinate)
{
int y = YCordinate -Rows/2;
if (y < 0) y *= -1; //y must be positive
y *= BoxHeight;
y += Pos.y;
return y-BoxHeight/2;
}
/** Description of getValue( col, row )
*
* Function draws the lines used in the table
* #param col contains a column coordinate
* #param row contains a row coordinate
* #return returns table coordinates
*/
public char getValue(int col, int row)
{
return values[row][col];
}
/** Description of isDrawable( x, y )
*
* Function returns true if (x,y) is a point in the table
* #param x contains a table column
* #param y contains a table row
* #return boolean if (x,y) is a point in the table
*/
public boolean isDrawable(int x, int y)
{
if((this.getRow(y)!=-1)||(this.getColumn(x)!=-1))
return true;
else
return false;
}
private void drawValues(Graphics g)
{
for(int i = 0; i < numOfGridLocs; i++)
if(itemMarker[i])
g.drawImage(itemImg,coordLoc[i].x+1, coordLoc[i].y+1, BoxWidth-1, BoxHeight-1, null);
g.setColor(Color.black); // set color of table to black
}
//sets the randomized boolean values in itemMarker array
private void setValues()
{
double probOfItem = .25;
for(int count = 0; count < numOfGridLocs; count++){
itemMarker[count] = randomBool(probOfItem);
if(itemMarker[count])
System.out.println("true");
else
System.out.println("false");
}
}
//returns random boolean value, p is prob of 'true'
private boolean randomBool(double p)
{
return (Math.random() < p);
}
public int getColumn(int x)
{
x += (BoxWidth/2); //aTable.getX/Y returns in the middle of squares not at upper left point
int offsetx=0;
for (int i = 0 ; i < Columns*2 ; i++)
{
offsetx = i*BoxWidth;
if((x>=Pos.x+offsetx)&& (x<Pos.x+offsetx+BoxWidth))
return i-Columns;
}
return -100;
}
public int getRow(int y)
{
int offsety=0;
y += (BoxHeight/2); //aTable.getX/Y returns in the middle of squares not at upper left point
for (int i = 0 ; i < Rows*2 ; i++) {
offsety = i * BoxHeight;
if((y >= (offsety+Pos.y))&& (y < (offsety+BoxHeight+Pos.y)))
{
return ((i)*-1)+Rows;
}
}
return -100;
}
public boolean isValidGuess(int x, int y)
{
if ((x > Columns/2) || (x < Columns/2*-1) || (y > Rows/2) || (y < Rows/2*-1))
return false;
return true;
}
/** Description of randomChangeFunc()
*
* Function randomly determines which table value to change
* #param none
* #return void
*/
public void randomChangeFunc()
{
//get random row and column
Random rand=new Random();
int randRow = rand.nextInt(Rows); // gets and holds a random column
int randCol = rand.nextInt(Columns); // gets and holds a random column
System.out.println("randRow = " + randRow + " randCol = " + randCol);
if(values[randRow][randCol] == 'X')
values[randRow][randCol] = 'O';
else if(values[randRow][randCol] == 'O')
values[randRow][randCol] = 'X';
else
System.out.println("ERROR SWAPPING SQUARE VALUE"); // error message
}
private void mapGrid() //set values for coordLoc array
{
//set counter variables
int count = 0;
int index = 0;
//loop through all points, assigning them to the coordLoc array
for (int r=0; r < Rows-1; r++)
for (int c=0; c < Columns-1; c++) {
//the width/height / 2 places the points on grid line intersections, not the boxes they create
coordLoc[count].x = Pos.x + (BoxWidth) * c + (BoxWidth/2); // record x-point
coordLoc[count].y = Pos.y + (BoxHeight) * r + (BoxHeight/2); // record y-point
System.out.println(coordLoc[count].getX() + ", " + coordLoc[count].getY());
count++;
} //end inner for
//set positive x coord values for coords array
int y_axisBeginingIndex = (Rows - 2)/2;
for(int greaterIndex = 0; greaterIndex < ((Rows) / 2); greaterIndex++){
for(int minorIndex = 0; minorIndex < (Rows - 1); minorIndex++){
index = y_axisBeginingIndex + greaterIndex + ((Rows - 1) * minorIndex);
coords[index][0] = greaterIndex;
}
}
//set negative x coord values for coords array
for(int greaterIndex = -1; greaterIndex > (0-((Rows) / 2)); greaterIndex--){
for(int minorIndex = 0; minorIndex < (Rows - 1); minorIndex++){
index = y_axisBeginingIndex + greaterIndex + ((Rows - 1) * minorIndex);
coords[index][0] = greaterIndex;
}
}
//set positive y values for coords array
int x_axisBeginingIndex = (Rows - 1) * ((Rows / 2) - 1);
for(int greaterIndex = 0; greaterIndex < ((Rows) / 2); greaterIndex++){
for(int minorIndex = 0; minorIndex < (Rows - 1); minorIndex++){
index = x_axisBeginingIndex + minorIndex;
coords[index][1] = greaterIndex;
}
x_axisBeginingIndex -= (Rows - 1);
}
//set negative y values for coords array
x_axisBeginingIndex = (Rows - 1) * ((Rows / 2) - 1) + (Rows - 1);
for(int greaterIndex = -1; greaterIndex > (0-((Rows) / 2)); greaterIndex--){
for(int minorIndex = 0; minorIndex < (Rows - 1); minorIndex++){
index = x_axisBeginingIndex + minorIndex;
coords[index][1] = greaterIndex;
}
x_axisBeginingIndex += (Rows - 1);
}
//print out the x and y coords
for(int i = 0; i < numOfGridLocs; i++){
System.out.println("[" + i + "] -> x = " + coords[i][0] + " y = " + coords[i][1]);
}
}
public boolean thereIsAnItemAt(int index){
return itemMarker[index];
}
public boolean bugsLeft(){
boolean thereAreBugsLeft = false;
for(int i = 0; i < numOfGridLocs; i++)
if(itemMarker[i])
thereAreBugsLeft = true;
return thereAreBugsLeft;
}
void update()
{
this.repaint();
}
}
Been stumped on this for weeks. Thanks again...
What I believe to be the pertinent
parts of the code are listed below.
By definition when you have a problem you don't know what part of the code is (or isn't) relevant. That is why you need to post a SSCCE that demonstrates the problem so we can see what you are doing.
The fact that is work "after" a resize means the problem is not with the painting. The problem could be that the images aren't loaded in which case you should be using:
drawImage(...., this);
The "this" instead of "null" notifies the panel to repaint the image when the image gets fully loaded.
Or maybe, you added the panel to the frame after the frame was visible and forgot to use
panel.revalidate().
By resizing the frame you force a revalidation.
The point is we are guessing. So save us time and post a SSCCE next time.
Sorry still too much code.
You need to read the article on Painting in AWT and Swing. Your code is a mixture of both.
Basically, as you where told in your last posting custom painting is done by overriding the paintComponent(...) method of JPanel. So you do the custom painting and then add the JPanel to the JApplet. I gave you a link to the Swing tutorial in your last posting and it also contains a section on how to write an Applet.
You should be extending JPanel, not Panel.
Also, you should NOT be overriding the paint() and upated() method of JApplet, this is old AWT code and should NOT be used with Swing.
Read the article and fix the problems first.
The answer is changing the draw() method in the class that extends JPanel to paintComponent() and switching the last parameter in the call to drawImage() to 'this' instead of 'null'. Worked instantly and perfectly!

Categories