While I was writing the code for the quiz game, I used a JOptionPane setting it to click a yes and allowing the game to restart. With the below code, I was able to get a new window showing the result and giving options to wether cohoe between to reset the game or to exit. This is the code down below and by adding 'frame.setVisible(isEnabled));', I were able to get rid of the new window by clicking the reset button but the game window only showed me the very last page of the quiz, not allowing me to do the quiz again. I want the game to be started at its very first page , what should I do in this case?
for (int i = 0; i < question.getAnswers().length; i++) {
answersButtons[i] = new JButton(String.valueOf((char) ('A' + i))); // This will set the buttons text to A, B, C, D
answersButtons[i].addActionListener(e -> { //ActionListener using Java 8 lambdas
if (e.getActionCommand().charAt(0) - 'A' == question.getCorrectAnswer() - 1) { //Here we check if the button clicked was the one with the correct answer, converting the text from A-D to 0-3 and compare it to the index - 1 from the question model
correctAnswers++; //Increase the correctAnswer + 1
answerLabels[e.getActionCommand().charAt(0) - 'A'].setBackground(Color.GREEN); //Set the background color to green if it was correct
} else {
answerLabels[e.getActionCommand().charAt(0) - 'A'].setBackground(Color.RED); //Or red otherwise
}
if (currentQuestion == totalQuestions - 1) { //If we reach the end of questions, show the results screen
int input = JOptionPane.showConfirmDialog(pane, new ResultsPane(correctAnswers, totalQuestions), "Results", JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE, null);
if (input == JOptionPane.YES_OPTION) {
frame.setVisible(isEnabled());
frame.setVisible(true);
//Reset everything and show your GUI again
} else {
frame.dispose(); //If user says they don't want to retry, dispose the frame.
}
} else {
timer.start(); //Start the timer that will display the results for half a second.
}
});
}
Full code below :
import java.awt.BorderLayout;
Import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.RootPaneContainer;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIManager;
// main class, contains the CardLayout
public class MainGamw {
int c = 15;
private JFrame frame;
private QuestionPane[] cards;
private JPanel pane;
private CardLayout cl;
private JLabel timerLabel;
private JLabel timeNumber;
private List<QuizQuestion> questions;
private Timer temporaryTimer;
public static void main(String[] args) {
// place the program on the EDT using Java 8 lambdas
SwingUtilities.invokeLater(new MainGamw()::createAndShowGUI);
}
private void createAndShowGUI() {
frame = new JFrame(getClass().getSimpleName()); //the class name and set it as the frame's title
frame.getContentPane().setBackground(new Color(204,229,255));
frame.setPreferredSize(new Dimension(600,350));
frame.pack();
cl = new CardLayout(); //Create a new CardLayout
pane = new JPanel(cl); //Set the CardLayout to this JPanel
pane.setBackground(new Color(204,229,255));
pane.setVisible(true);
temporaryTimer = new Timer(500, event -> { //The timer to show the result of the answer for half second before switching to the new one.
c--;
timeNumber.setText(String.valueOf(c));
cl.next(pane); //This moves the CardLayout to the next one
temporaryTimer.stop(); //We stop this timer when we switch to the next card.
});
generateQuestionsAndAnswers(); //We populate the model of questions with their answers here.
cards = new QuestionPane[questions.size()];
for (int i = 0; i < cards.length; i++) {
cards[i] = new QuestionPane(questions.get(i), i, pane, cl, cards.length, frame, temporaryTimer); //We create a new QuestionPane and send some information as parameters
pane.add(cards[i], "question" + i); //We add the card to the CardLayout pane
}
timerLabel = new JLabel(" Time: ");
timerLabel.setFont(new Font("PT Serif",Font.PLAIN,16));
timeNumber = new JLabel();
timeNumber.setFont(new Font("PT Serif",Font.PLAIN,16));
timeNumber.setText(String.valueOf(c));
UIManager.put("OptionPane.okButtonText", "Start Quiz"); //We change the "OK" from the JOptionPane button to "Start Quiz"
int option = JOptionPane.showConfirmDialog(frame, new JLabel("Click button to start quiz"),
"Welcome", JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, null);
if (option == JOptionPane.OK_OPTION) {
//Start your timer for the first question
}
frame.add(pane); //We add the CardLayout pane to our JFrame's CENTER position
frame.add(timerLabel, BorderLayout.SOUTH); //And the timerLabel at the bottom
frame.add(timeNumber, BorderLayout.WEST);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true); //
}
private Object size(int i, int j) {
// TODO Auto-generated method stub
return null;
}
//We create an ArrayList of QuizQuestion that each has their own question, the possible answers and the correct answer (index + 1)
private void generateQuestionsAndAnswers() {
questions = new ArrayList<>();
questions.add(new QuizQuestion("Select the official name of the coronavirus.", new String[] {"COVID-19","Sars-CoV-2","Zaire ebolavirus","Influenza"}, 1));
questions.add(new QuizQuestion("When did the corona virus first ecountered?", new String[] {"2018","2020","2017","2019"}, 4));
questions.add(new QuizQuestion("What is the percentage of people recovering from the coronavirus?", new String[] {"63%","71%","80%","76%"}, 3));
questions.add(new QuizQuestion("Which below is NOT the symptom of coronavirus?", new String[] {"Fever","Blurred vision","Dry Cough","Nasal Congestion"}, 2));
questions.add(new QuizQuestion("Which part of the human body does the coronavirus attach itself to?", new String[] {"Red Blood Cells", "Antigens", "White Blood Cells", "Ace-2 recpetors in the airways"}, 4));
questions.add(new QuizQuestion("How many hour can the coronavirus survive on plastic and stainless steel surfaces?", new String[] {"4-8 hours", "72 hours and more", "45-60 hours", "90 hours and more" }, 2));
questions.add(new QuizQuestion("Which human organs in the body does the coronavirus attack?", new String[] {"Liver", "Lungs", "Heart", "Kidney" }, 2));
questions.add(new QuizQuestion("How large is the coronavirus?", new String[] {"8000 billionths of metre in diameter", "800 billionths of metre in diameter","80 billionths of metre in diameter","8 billionths of metre in diameter" }, 3));
questions.add(new QuizQuestion("Which is a safe distance to stay apart from people? ", new String[] {"3 feet(1 meter)", "2 feet(60 cm)", "1 foot (30cm)", "4.2 feet(1.3 meter)"}, 1));
questions.add(new QuizQuestion("Who has the highest risk of getting infected by coronvirus?", new String[] {"Children", "Pregnant Women", "People over 60 years of age", "30-40 years agr of men"}, 3));
questions.add(new QuizQuestion("When should face masks be worn?", new String[] {"Public Transport", "Confined or Crowed spaces", "Small restaurants or shops", "All of the above"}, 4));
questions.add(new QuizQuestion( "Which is more effective for removing the coronavirus from your hands?", new String[] {"Soap and water", "Alcohol-based hand sanitiser","Detergent", "Face cleanser"}, 1));
questions.add(new QuizQuestion("Which industry includes workers with increased exposure-risk?", new String[] {"Health care", "Airline operations", "Waste management", "All of the above"}, 4));
questions.add(new QuizQuestion("What is the period of quartine?", new String[] {"21 days","7 days", "14 days", "6 days"}, 3));
questions.add(new QuizQuestion("What is the name of the city where coronavirus was first detected?", new String[] {"Wuhan", "Hubei", "Hunan","Shanghai"}, 1));
}
}
#SuppressWarnings("serial")
class ResultsPane extends JPanel { //This is a class that will create a simple JPanel with vertical alignment to add the number of correct answers, accuracy and a text for the user if they want to retry
public ResultsPane(int correctAnswers, int totalQuestions) {
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
float percentage = ((float) (correctAnswers) / (float) (totalQuestions)) * 100;
add(new JLabel("Correct Answers: " + correctAnswers + " / " + totalQuestions));
add(new JLabel("Accuracy: " + percentage + "%"));
add(new JLabel("Want to Retry?"));
}
}
#SuppressWarnings("serial")
class QuestionPane extends JPanel { //This is the pane in which each card will be displayed
private JButton[] answersButtons; //Array of buttons for the answers instead of 4 individual buttons
private JLabel questionLabel;
private JLabel questionNumber;
private JLabel[] answerLabels; //Same for the labels
private static int correctAnswers = 0; //This is static to count all the correct answers in all the instances
public QuestionPane(QuizQuestion question, int currentQuestion, JPanel pane, CardLayout cl, int totalQuestions, JFrame frame, Timer timer) { //Probably this isn't the most elegant solution to send multiple objects as parameters here, as it makes the program tightly coupled.
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
questionNumber = new JLabel("Question " + (currentQuestion + 1), SwingConstants.LEFT);
questionNumber.setFont(new Font("PT Serif",Font.BOLD,16));
questionNumber.setHorizontalAlignment(JLabel.LEFT);
//We set the question number on top and center the text
questionLabel = new JLabel(question.getQuestion());
questionLabel.setFont(new Font("PT Serif",Font.BOLD,15));
questionLabel.setAlignmentX(LEFT_ALIGNMENT);
// We set the question text to this label
answerLabels = new JLabel[question.getAnswers().length];
//We create our array of 4 labels and 4 buttons below
answersButtons = new JButton[question.getAnswers().length];
for (int i = 0; i < question.getAnswers().length; i++) {
answersButtons[i] = new JButton(String.valueOf((char) ('A' + i))); // This will set the buttons text to A, B, C, D
answersButtons[i].addActionListener(e -> { //ActionListener using Java 8 lambdas
if (e.getActionCommand().charAt(0) - 'A' == question.getCorrectAnswer() - 1) { //Here we check if the button clicked was the one with the correct answer, converting the text from A-D to 0-3 and compare it to the index - 1 from the question model
correctAnswers++; //Increase the correctAnswer + 1
answerLabels[e.getActionCommand().charAt(0) - 'A'].setBackground(Color.GREEN); //Set the background color to green if it was correct
} else {
answerLabels[e.getActionCommand().charAt(0) - 'A'].setBackground(Color.RED); //Or red otherwise
}
if (currentQuestion == totalQuestions - 1) { //If we reach the end of questions, show the results screen
int input = JOptionPane.showConfirmDialog(pane, new ResultsPane(correctAnswers, totalQuestions), "Results", JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE, null);
if (input == JOptionPane.YES_OPTION) {
frame.setVisible(isEnabled());
frame.setVisible(true);
//Reset everything and show your GUI again
} else {
frame.dispose(); //If user says they don't want to retry, dispose the frame.
}
} else {
timer.start(); //Start the timer that will display the results for half a second.
}
});
}
add(questionNumber, BorderLayout.EAST); //Add the question number
add(questionLabel, BorderLayout.EAST); //The question text
for (int i = 0; i < question.getAnswers().length; i++) {
JPanel answerPane = new JPanel(new FlowLayout(FlowLayout.LEFT)); //Create a new JPanel for each label and button and make them left aligned
answerPane.add(answersButtons[i]); //Add every button
answerLabels[i] = new JLabel(question.getAnswers()[i]); //Create a new label with each answer's text
answerLabels[i].setOpaque(true); //Make them opaque (for the background colors later)
answerPane.add(answerLabels[i]); //And add them to the pane
add(answerPane); //Then add the pane to the wrapping pane
}
}
}
//A simple model for your questions.
class QuizQuestion {
private String question;
private String[] answers;
private int correctAnswer;
public QuizQuestion(String question, String[] answers, int correctAnswer) {
super();
this.question = question;
this.answers = answers;
this.correctAnswer = correctAnswer;
}
public String getQuestion() {
return question;
}
public void setQuestion(String question) {
this.question = question;
}
public String[] getAnswers() {
return answers;
}
public void setAnswers(String[] answers) {
this.answers = answers;
}
public int getCorrectAnswer() {
return correctAnswer;
}
public void setCorrectAnswer(int correctAnswer) {
this.correctAnswer = correctAnswer;
}
}
If you want to restart the game with a new JFrame instance, following code will help:
if (input == JOptionPane.YES_OPTION) {
frame.dispose();
MainGamw mainGame = new MainGamw();
mainGame.createAndShowGUI(); // Make sure you change method access to public
} else {
frame.dispose(); //If user says they don't want to retry, dispose the frame.
}
If you want to restart your game, with the existing JFrame instance, you need to modify your code slightly:
Create the JFrame separately (you may keep it as it is)
Separate the creation of child components of the JFrame (Cards, Panels etc) in a different method. Pass the JFrame instance as parameter.
Write following code, at result Confirm Dialog:
if (input == JOptionPane.YES_OPTION) {
frame.getContentPane().removeAll();
// Call the method as described #2
} else {
frame.dispose(); //If user says they don't want to retry, dispose the frame.
}
I am completing a past paper exam question and it asks to create an applet that displays a green square in the center, with three buttons + , - and reset, however, I am trying to make it that when any button is clicked the program should essentially figure out which button was pressed. I know you would use e.getSource() but I am not sure how to go about this.
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Square extends JApplet {
int size = 100;
public void init() {
JButton increase = new JButton("+");
JButton reduce = new JButton("-");
JButton reset = new JButton("reset");
SquarePanel panel = new SquarePanel(this);
JPanel butPanel = new JPanel();
butPanel.add(increase);
butPanel.add(reduce);
butPanel.add(reset);
add(butPanel, BorderLayout.NORTH);
add(panel, BorderLayout.CENTER);
ButtonHandler bh1 = new ButtonHandler(this, 0);
ButtonHandler bh2 = new ButtonHandler(this, 1);
ButtonHandler bh3 = new ButtonHandler(this, 2);
increase.addActionListener(bh1);
reduce.addActionListener(bh2);
reset.addActionListener(bh3);
}
}
class SquarePanel extends JPanel {
Square theApplet;
SquarePanel(Square app) {
theApplet = app;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.green);
g.fillRect(10, 10, theApplet.size, theApplet.size);
}
}
class ButtonHandler implements ActionListener {
Square theApplet;
int number;
ButtonHandler(Square app, int num) {
theApplet = app;
number = num;
}
public void actionPerformed(ActionEvent e) {
switch (number) {
case 0:
theApplet.size = theApplet.size + 10;
theApplet.repaint();
break;
case 1:
if (theApplet.size > 10) {
theApplet.size = theApplet.size - 10;
theApplet.repaint();
}
break;
case 2:
theApplet.size = 100;
theApplet.repaint();
break;
}
}
Not the best way to do it, but based on your current code, you could simply compare the object references. You'd need to pass in references to the buttons or access them some other way. e.g.
if(e.getSource() == increase) { \\do something on increase}
Another alternative would be to check the string of the button, e.g.
if(((JButton)e.getSource()).getText().equals("+")){ \\do something on increase}
You can use strings in a switch statement in Java 8, but if you're using Java 7 or lower, it has to be an if statement.
You can use if then else statement as in the sample below
if(e.getSource()==bh1){
//your codes for what should happen
}else if(e.getSource()==bh2){
}else if(e.getSource()==bh3){
}else if(e.getSource()==bh4){
}
OR even in a switch case statement
i have a problem i can't solve.
I want this:
When i open the gui, i will show a random number and a button that says "change number".
Then, when the button is clicked, i want that the previous random number change into another random number and so on.
This is my code:
public class RandomDisplayPanel extends JPanel {
public RandomDisplayPanel() {
JPanel panel = new JPanel();
add(panel);
JPanel inside = new JPanel();
panel.setBackground(Color.yellow);
JButton sendButton = new JButton("Send");
Random generator = new Random();
int num;
num = generator.nextInt(100) +1;
JLabel numero = new JLabel("" + num);
inside.add(numero);
inside.add(sendButton);
panel.add(inside);
sendButton.addActionListener(new RandomDisplayPanel.RandomListener());
}
private class RandomListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
Random generator = new Random();
int num;
num = generator.nextInt(100) +1;
}
}
}
How can i do that? thank you in advance :)
You can pass the (JLabel) number to the listener as follow:
sendButton.addActionListener(new RandomDisplayPanel.RandomListener(number));
private class RandomListener implements ActionListener {
private JLabel target;
public RandomListener(JLabel target) {
this.target = target;
}
#Override
public void actionPerformed(ActionEvent e) {
Random generator = new Random();
int num;
num = generator.nextInt(100) +1;
this.target.setText(String.valueOf(num));
}
}
Hope this helps!
You need to effectively call numero.setText(num) inside of your ActionPreformed method. I would recommend maybe adding a checking statement similar to this..
if(e.getSource() == sendButton) {
numero.setText(num);
}
There is another problem I see, being that you might not be able to know the values of numero or sendButton. Offhand you could make them public variables in your main class, or you could pass them as parameters.
Add numero.setText(num + ""); inside your listener.
EDIT : Declare the JLabel numero as a class variable and it will work.
To get a random number you can use Math.random(); and multiply it with 10 and add 1 for example. (Then it is between 1 and 10)
To set the button text then use
Button myButton=(Button)this.findViewById(R.id.yourButtonsID);
myButton.setText(yourRandomNumber);
This is my first attempt at using a GUI layout in Java. I am trying to create a simple memory card game, where the user flips over two cards, and tries to get a match, and if there's no match they flip back over, if there's a match they stay flipped until you get all the matches. I might have made it hard on myself though in that I made the whole game dynamic to the constructor variables that define the number of columns and rows of cards. I thought this was better than hard-coding a certain value in, but now I'm having trouble putting the images in my img folder onto my cards.
I understand that variables of variables are not permitted in Java & this is really hard for me to adapt to as a ColdFusion developer. Can you help me think of ways to accomplish this this the proper way in Java?
Here is a simplified version of my code.
import javax.swing.JFrame;
public class MemoryApp
{
public static void main(String args[])
{
//Creates a new game with 3 columns and 4 rows
final CardGame myGame = new CardGame(3, 4);
javax.swing.SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI(myGame.getCols(), myGame.getRows());
}
});
}
private static void createAndShowGUI(int c, int r) {
//Create and set up the window.
Window frame = new Window("GridLayoutDemo", c, r);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Set up the content pane.
frame.addComponentsToPane(frame.getContentPane());
//Display the window.
frame.pack();
frame.setVisible(true);
}
}
Card game class:
public class CardGame
{
private int cols, rows;
public CardGame(int c, int r)
{
cols = c;
rows = r;
}
public int getCols(){
return cols;
}
public int getRows(){
return rows;
}
}
The window with the grid layout:
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSeparator;
public class Window extends JFrame
{
private int cols, rows;
GridLayout windowGrid = new GridLayout(1,1);
public Window(String t, int c, int r)
{
super(t);
cols = c;
rows = r;
windowGrid.setColumns(c);
windowGrid.setRows(r);
}
public void addComponentsToPane(final Container pane)
{
final JPanel compsToExperiment = new JPanel();
compsToExperiment.setLayout(windowGrid);
JPanel controls = new JPanel();
controls.setLayout(new GridLayout(cols,rows));
int countCard = (cols * rows) / 2;
/**
* Add buttons to experiment with Grid Layout.
* This is where I'd like to be able to loop through
* countCard and create the required number of buttons
* as well as put images on the buttons like so:
*
* ImageIcon image1 = new ImageIcon(getClass().getResource("card1.png"));
* through
* ImageIcon image1 = new ImageIcon(getClass().getResource("card" & cardCount & ".png"));
*
* Below is how I would attempt this in ColdFusion- I know
* the variable of variables syntax is invalid, it is just
* to show you what I mean.
*/
// for(int i = 0; i < countCard; i++;)
// {
// compsToExperiment.add(new JButton("../img/card" & i & ".png"));
// ImageIcon variables["image" & i] = new ImageIcon(getClass().getResource("card" & i & ".png"));
// imageButton.setIcon(variables["image" & i]);
// etc. with ButtonClickEventHandler, haven't gotten that far yet
// }
pane.add(compsToExperiment, BorderLayout.NORTH);
pane.add(new JSeparator(), BorderLayout.CENTER);
}
}
Based on the code commented-out code that you posted so far, one approach could be like this:
public class Window extends JFrame
{
...
// A java.util.List that stores all the buttons, so
// that their icons may be changed later
private List<JButton> buttons = new ArrayList<JButton>();
// A java.util.List that stores all the ImageIcons that
// may be placed on the buttons
private List<ImageIcon> imageIcons = new ArrayList<ImageIcon>();
public void addComponentsToPane(final Container pane)
{
...
for(int i = 0; i < countCard; i++;)
{
// String concatenation is done with "+" in Java, not with "&"
String fileName = "card" + i + ".png";
// Create the icon and the button containing the icon
ImageIcon imageIcon = new ImageIcon(getClass().getResource(fileName));
JButton button = new JButton(imageIcon);
// Add the button to the main panel
compsToExperiment.add(button);
// Store the button and the icon in the lists
// for later retrieval
imageIcons.add(imageIcon);
buttons.add(button);
// Attach an ActionListener to the button that will
// be informed when the button was clicked.
button.addActionListener(createActionListener(i));
}
}
private ActionListener createActionListener(final int cardIndex)
{
return new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
clickedCardButton(cardIndex);
}
};
}
private void clickedCardButton(int cardIndex)
{
System.out.println("Pressed button for card "+cardIndex);
// Here you can change the icons of the buttons or so...
JButton button = buttons.get(cardIndex);
ImageIcon imageIcon = imageIcons.get(cardIndex);
....
}
You mentioned that this is your first attempt to build a GUI with Java. So I assume that this is only intended for "practicing". If your intention was to build a "real application", you should rather consider some Model-View-Controller (MVC) approach for this.
I just need to get it to alternate between "X" and "O" for the turns but it's only giving me X's.
import java.awt.GridLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.*;
public class tictactoe {
public static final int FRAME_WIDTH = 700;
public static final int FRAME_HEIGHT = 200;
public static void main(String[] args)
{
int slots = 9;
final JButton[] gameButton = new JButton[9];
JPanel ticTacToeBoard = new JPanel();
ticTacToeBoard.setLayout(new GridLayout(3, 3));
JButton clearButtons = new JButton("New Game");
for (int i = 0; i < slots; i++)
{
gameButton[i] = new JButton();
ticTacToeBoard.add(gameButton[i]);
final int countTurns = i;
gameButton[i].addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Object clicked = e.getSource();
int turns = 1;
for (int p = 0; p < 9; p++)
{
if(clicked == gameButton[countTurns] && turns < 10)
{
if (!(turns % 2 == 0))
{
((JButton)e.getSource()).setText("X");
turns++;
}
else
{
((JButton)e.getSource()).setText("O");
turns++;
}
}
}
}
});
final int integerHack = i;
clearButtons.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
gameButton[integerHack].setText("");
}
});
}
JButton exit = new JButton("Exit");
exit.setActionCommand("EXIT");
exit.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
if (cmd == "EXIT")
{
System.exit(FRAME_WIDTH);
}
}
});
JPanel rightPanel = new JPanel();
JLabel wonLabel = new JLabel();
rightPanel.setLayout(new GridLayout(1, 3));
rightPanel.add(wonLabel);
rightPanel.add(clearButtons);
rightPanel.add(exit);
JFrame mainFrame = new JFrame();
mainFrame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
mainFrame.setVisible(true);
mainFrame.setLayout(new GridLayout(1,2));
mainFrame.add(ticTacToeBoard);
mainFrame.add(rightPanel);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Look at your actionPerformed method. Every time a click happens, you set turns to 1. As a result, !(turns % 2 == 0) will always evaluate true, and you'll always draw an X.
Just by quickly looking at your code, I would guess it is because your turn variable is local in all the ActionListener objects. Therefore, the turn variable is always 1 and you always run into the first if case. So the turn variable is always recreated on the stack as soon as you get a callback in the actionPerformed method. For a quick fix and test, try to put the turn variable in the tictactoe class and see if that helps.
The trouble is with the turns variable in your actionPerformed. If you want to keep a track of it you should move that out from your method.
Firstly, as the other people have also said, you want "turns" to be initialized outside all your loops.
Secondly, I would like to point out a typo:
if(clicked == gameButton[countTurns] && turns < 10)
should be
if(clicked == gameButton[p] && turns < 10)
...unless you really want to change each button's text from X to O nine times each time a button is clicked.
But even fixing that typo is pointless. Why loop through to find a specific button when it doesn't matter which specific button it is? All the buttons have the same action handler, anyway, just nine separate copies of it, because you are creating nine identical copies each time around.
Instead, because all the buttons do the same thing, you should have one action handler for all the buttons. If you're not sure how that's done, you create it outside your button making loop and assign it to a variable, and then you put in that variable when you assign each button's action handler, e.g.
gameButton[i].addActionListener(myActionListener);