I have created a basic Tic-Tac-Toe class which displays 9 buttons showing random images on it(each run time - different sequences). The main method is there in another test class, which is just a frame creator. In addition to this, I want to add some event handling. I have added 'ActionListener' to the buttons & want to add some logic in 'actionPerformed' method. Each time I click on any button it should change an image continuously in order X -> O -> Blank -> X. I am not sure that which logic will fit here to flip images in above order(for e.g. for-loop,switch etc.). The code is as follows :
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class TicTacToe extends JFrame {
public JButton[][] labels = new JButton[3][3];
public ImageIcon[] icons = new ImageIcon[3];
public int r, c;
public TicTacToe() {
// TODO Auto-generated constructor stub
setLayout(new GridLayout(3, 3));
for (r = 0; r < labels.length; r++) {
for (c = 0; c < labels.length; c++) {
int random = (int)(Math.random() * 3 + 0);
System.out.println(random);
JButton s = new JButton(this.icons[random]);
this.add(s);
this.labels[r][c] = s;
if (random == 0) {
System.out.println("Cross Image Icon");
labels[r][c].setIcon(new ImageIcon("C:\\Users\\yogesh\\workspace\\hw3pandarey\\src\\hw3pandarey\\cross_symbol.gif"));
add(labels[r][c]);
validate();
} else if (random == 1) {
System.out.println("Not Image Icon");
labels[r][c].setIcon(new ImageIcon("C:\\Users\\yogesh\\workspace\\hw3pandarey\\src\\hw3pandarey\\zero_symbol.gif"));
add(labels[r][c]);
validate();
} else if (random == 2) {
System.out.println("Keep it blank");
labels[r][c].setIcon(new ImageIcon());
add(labels[r][c]);
validate();
}
labels[r][c].addActionListener(new ButtonListener());
}
}
} // end of TicTacToe constructor
public class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
} // end of actionPerformed method
} // end of ButtonListener class
} // end of TicTacToe class
import javax.swing.*;
public class TicTacToeTest {
public static void main(String[] args) {
TicTacToe frame = new TicTacToe();
frame.setTitle("Let's play a random tic-tac-toe game !!!!!");
frame.setSize(400, 400);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
} //end of main method
} // end of test class
You can use the method setText to put an X or O on the JButton like so.
All you need to add if a variable that will know if it's X or O turn.
Hopefully this help
public class ButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
Object src = e.getSource();
for(int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if(src==labels[i][j]&&labels[i][j].getText()==""){
//if X turn
labels[i][j].setText("X");
}
//if O turn
//labels[i][j].setText("O");
}
}
}// end of actionPerformed method
} // end of ButtonListener class
So I added 'switch' inside 'for' loops, so that each time I click a button it flips an image in particular order. I wanted the same images to flip not any text, so I used 'setIcon()' method. For that I created three ImageIcon objects in main class.A counter is added for three different cases & it keeps looping.
My final answer code is as follows :
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class TicTacToe extends JFrame
{
public JButton[][] labels = new JButton[3][3];
public ImageIcon[] icons = new ImageIcon[3];
byte value=0;
public ImageIcon x= new ImageIcon("C:\\Users\\yogesh\\workspace\\hw3pandarey\\src\\hw3pandarey\\cross_symbol.gif");
public ImageIcon o= new ImageIcon("C:\\Users\\yogesh\\workspace\\hw3pandarey\\src\\hw3pandarey\\zero_symbol.gif");
public ImageIcon n= new ImageIcon("");
public TicTacToe()
{
// TODO Auto-generated constructor stub
setLayout(new GridLayout(3,3));
for(int r=0; r<labels.length ; r++)
{
for(int c=0; c<labels.length ; c++)
{
int random = (int)(Math.random() * 3 + 0);
System.out.println(random);
JButton s = new JButton(this.icons[random]);
this.add(s);
this.labels[r][c] = s;
if(random == 0)
{
System.out.println("Cross Image Icon");
labels[r][c].setIcon(new ImageIcon("C:\\Users\\yogesh\\workspace\\hw3pandarey\\src\\hw3pandarey\\cross_symbol.gif"));
add(labels[r][c]);
validate();
}
else if(random == 1)
{
System.out.println("Not Image Icon");
labels[r][c].setIcon(new ImageIcon("C:\\Users\\yogesh\\workspace\\hw3pandarey\\src\\hw3pandarey\\zero_symbol.gif"));
add(labels[r][c]);
validate();
}
else if(random == 2)
{
System.out.println("Keep it blank");
labels[r][c].setIcon(new ImageIcon());
add(labels[r][c]);
validate();
}
labels[r][c].addActionListener(new ButtonListener());
}
}
} // end of TicTacToe constructor
public class ButtonListener implements ActionListener
{
#Override
public void actionPerformed(ActionEvent e)
{
// TODO Auto-generated method stub
for(int r = 0; r < 3; r++) {
for (int c = 0; c < 3; c++) {
if(e.getSource()==labels[r][c])
{
value++;
value%=3;
switch(value)
{
case 0:
labels[r][c].setIcon(n);
break;
case 1:
labels[r][c].setIcon(x);
break;
case 2:
labels[r][c].setIcon(o);
break;
} // end of switch
}// end of 'if'
} // end of inside for loop
} // end of outside for loop
} // end of actionPerformed method
} // end of ButtonListener class
} // end of TicTacToe class
Related
I'm working on a TicTacToe game at the moment as a personal project and so far I know I'm almost complete with the game except for the part where I have to check if the x or o's are equal and in a line. Here's my code below here. My problem is in the connected method, it compiles and run's, but when I tried to add the middle horizontal row after just only one JButton was pressed it said the person won which should not be the case. I think I need a method that is named isDisabled(), instead of isEnabled for the JButton, but for some reason I don't think there is such a method in the java library. I know for sure if I had isDisabled() it would work for sure
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* Created by Usman on 5/17/2016.
*/
public class TicTacToeGUI extends JPanel {
boolean turn = true;
JButton[] board;
public TicTacToeGUI() {
setLayout(new GridLayout(3,3));
board = new JButton[9];
for (int i = 0; i < board.length; i++) {
board[i] = new JButton("");
board[i].setPreferredSize(new Dimension(70, 60));
board[i].setFont(new Font("Arial", Font.PLAIN, 40));
int finalI = i;
board[i].addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(board[finalI].isEnabled()){
if(turn){
board[finalI].setText("X");
turn = !turn;
}
else{
board[finalI].setText("O");
turn = true;
}
board[finalI].setEnabled(false);
}
Connected();
}
});
add(board[i]);
}
}
public void Connected(){
int count =0;
//Horizontal top row
if((board[0].isEnabled() == board[1].isEnabled()) && (board[1].isEnabled() == board[2].isEnabled())){
System.out.println(count++);
for(int i = 0; i < board.length; i++)
board[i].setEnabled(false);
}
}
public static void main(String []args){
TicTacToeGUI game = new TicTacToeGUI();
JFrame frame = new JFrame("Tic Tac Toe");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(game);
frame.pack();
frame.setVisible(true);
}
}
Just use (!whatever.isEnabled())
The character '!' is similar to a NOT in Java. So it will behave like isDiabled()
I am creating a program to take in sets of binary digits and convert them into hammingcodes (Effectively take in 8 digits, turn into 12, print out) but i am having trouble. Currently, i am using a JTextField for the user to enter their number, then they press a JButton to enter the data. I then do funky shit with that number to put it into a list and confirm that this is the last of the numbers they wish to enter. If they click a JButton called yes (New text in button, but same button) if goes on to do what i need. But if they click the other JButton called no, it goes back and repeats the same process. My problem is after clicking no once, the program stops allowing you to press no at the step to check if you want to add another list of numbers. IT appears to skip the check all together and assume they pressed yes as it does the rest of the working out thats done after all entry is finished.
My code is a tad messy due to messing with it for a few hours.
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import javax.swing.*;
public class MainProgram extends JFrame
{
public MainProgram()
{
}
public static void main(String[] args)
{
MainProgram mp = new MainProgram();
mp.run();
}
private void run()
{
java.util.List<Integer> streamSplit = new ArrayList<>();
java.util.List<Integer> tempEight = new ArrayList<>();
java.util.List<Integer> finalStream = new ArrayList<>();
yes.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
checkYes = true;
}
});
no.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
checkNo = true;
}
});
init();
yesChange("Enter");
boolean confirm = false;
int aCheck = 0;
while (aCheck == 0)
{
confirm = false;
while (!confirm)
{
setTopText("<html>Please enter your next 8 bits. Do not enter more than 8 bits.<br> Press Enter when done</html>");
yesChange("Enter");
confirm = checkYes();
}
confirm = false;
setTopText("Digits Successfully added.");
int stream = checkInput();
do
{
streamSplit.add(stream % 10);
stream /= 10;
} while (stream != 0);
setYesNo();
setTopText("<html>Are you finished entering streams?</html>");
yesChange("YES");
noChange("NO");
aCheck = 2;
checkYes();
checkNo();
while (aCheck == 2)
{
if ( checkNo())
{
aCheck = 0;
System.out.println("CrapNo");
}
else if (checkYes())
{
aCheck = 1;
System.out.println("CrapYes");
}
}
}
int arrayLength = streamSplit.size();
int bufferLength = 8 - arrayLength % 8;
int numberOfStreams = 0;
if (bufferLength != 8)
{
numberOfStreams = arrayLength / 8 + 1;
} else
{
numberOfStreams = arrayLength / 8;
}
int tempStreams = numberOfStreams;
System.out.println(numberOfStreams + "<Streams Buffer>" + bufferLength);
while (bufferLength > 0 && bufferLength != 8)
{
streamSplit.add(0);
bufferLength--;
}
while (tempStreams > 0)
{
for (int i = 0; i < 8; i++)
{
tempEight.add(streamSplit.get(i));
}
if ((tempEight.get(0) + tempEight.get(1) + tempEight.get(3) + tempEight.get(4) + tempEight.get(6)) % 2 == 0)
{
tempEight.add(0, 0);
} else
{
tempEight.add(0, 1);
}
if ((tempEight.get(1) + tempEight.get(3) + tempEight.get(5) + tempEight.get(6) + tempEight.get(7)) % 2 == 0)
{
tempEight.add(1, 0);
} else
{
tempEight.add(1, 1);
}
if ((tempEight.get(3) + tempEight.get(4) + tempEight.get(5) + tempEight.get(8) + tempEight.get(9)) % 2 == 0)
{
tempEight.add(3, 0);
} else
{
tempEight.add(3, 1);
}
if ((tempEight.get(7) + tempEight.get(8) + tempEight.get(9) + tempEight.get(10)) % 2 == 0)
{
tempEight.add(7, 0);
} else
{
tempEight.add(7, 1);
}
tempStreams--;
for (int i = 0; i < 12; i++)
{
finalStream.add(tempEight.get(0));
tempEight.remove(0);
}
}
Collections.reverse(streamSplit);
System.out.print("Your original bit-stream was: ");
for (int i = 0; i < numberOfStreams * 2; i++)
{
for (int j = 0; j < 4; j++)
{
System.out.print(streamSplit.get(j + (i * 4)));
}
System.out.print(" ");
}
System.out.println();
System.out.print("Your new HammingCode bit-stream is: ");
for (int i = 0; i < numberOfStreams * 3; i++)
{
for (int j = 0; j < 4; j++)
{
System.out.print(finalStream.get(j + (i * 4)));
}
System.out.print(" ");
}
System.out.println();
}
public Boolean checkYes = false;
public Boolean checkNo = false;
private JFrame frame = new JFrame("Absolute Layout Example");
private JPanel contentPane = new JPanel();
private JLabel topText = new JLabel("Welcome to my Hamming Code Generator", JLabel.CENTER);
private JTextField inputText = new JTextField();
private JButton yes = new JButton("YES");
private JButton no = new JButton("NO");
public void init()
{
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
contentPane.setOpaque(true);
contentPane.setBackground(Color.WHITE);
contentPane.setLayout(null);
topText.setLocation(0, 0);
topText.setSize(400, 50);
topText.setBorder(BorderFactory.createLineBorder(Color.black));
inputText.setLocation(0,50);
inputText.setSize(400,75);
inputText.setBorder(BorderFactory.createLineBorder(Color.black));
yes.setSize(80, 40);
yes.setLocation(60, 135);
no.setSize(80, 40);
no.setLocation(260, 135);
contentPane.add(topText);
contentPane.add(inputText);
contentPane.add(yes);
contentPane.add(no);
frame.setContentPane(contentPane);
frame.setSize(400, 225);
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public void setTopText(String s)
{
topText.setText(s);
}
public void setYesNo()
{
checkYes = false;
checkNo = false;
}
public Boolean checkYes() {return checkYes;}
public Boolean checkNo() {return checkNo;}
public int checkInput()
{
String temp1 = inputText.getText();
int temp = Integer.parseInt(temp1);
return temp;
}
public void yesChange(String s)
{
yes.setText(s);
}
public void noChange(String s)
{
no.setText(s);
}
}
I find it tough to answer this question not fully knowing what your code is doing, especially the part where you "... do funky #### with that number..."
But I do know that you have significant issues with your program structure, especially within your lengthy run() method where you have numerous nested while (...) loops and do-while loops, code constructs that might seem at home within a linear processing console program but which seems out of place within an event-driven Swing GUI.
What I suggest that you do is try to use some state-dependent coding. For instance, you could give your class the boolean variables, enteringData and dataValidYet, to represent two key states: whether the user is now entering data into the JTextField, and whether that data has yet been validated yet. And then within your JButton ActionListeners, use if and if/else blocks to decide what to do on button push depending on the state of these boolean fields, and likely other key fields of the class.
For a code "skeleton" example, one that doesn't yet do anything, but hopefully will show you the structure I'm talking about:
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
#SuppressWarnings("serial")
public class StateMachine extends JPanel {
private static final String INITIAL_TITLE = "Please enter your next 8 bits. "
+ "Do not enter more than 8 bits.\n"
+ "Press Enter when done";
private static final String ARE_YOU_FINISHED = "Are you finished entering streams?";
private static final String YES = "Yes";
private static final String ENTER = "Enter";
private static final String NO = "No";
private static int GAP = 8;
private static final int COLUMNS = 30;
// this is a JTextArea built to look like a JLabel
private JTextArea topTextArea = new JTextArea(2, COLUMNS);
private JTextField dataEntryField = new JTextField(COLUMNS);
private JButton yesEnterButton = new JButton(ENTER);
private JButton noButton = new JButton(NO);
private boolean enteringData = true;
private boolean dataValidYet = false;
public StateMachine() {
yesEnterButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
yesEnterButtonActionPerfromed(e);
}
});
noButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
noButtonActionPerfromed(e);
}
});
topTextArea.setWrapStyleWord(true);
topTextArea.setLineWrap(true);
topTextArea.setFocusable(false);
topTextArea.setEditable(false);
topTextArea.setOpaque(false);
topTextArea.setText(INITIAL_TITLE);
JPanel innerButtonPanel = new JPanel(new GridLayout(1, 0, GAP, 0));
innerButtonPanel.add(yesEnterButton);
innerButtonPanel.add(noButton);
JPanel outerButtonPanel = new JPanel();
outerButtonPanel.add(innerButtonPanel);
setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
setLayout(new BorderLayout(GAP, GAP));
add(topTextArea, BorderLayout.PAGE_START);
add(dataEntryField, BorderLayout.CENTER);
add(outerButtonPanel, BorderLayout.PAGE_END);
}
protected void noButtonActionPerfromed(ActionEvent e) {
// TODO depending on state of enteringData and dataValidYet booleans
// change text in buttons, do things with JTextField data
// set state of enteringData and dataValidYet booleans
if (enteringData) {
// a no press is meaningless if entering data
return;
}
// .... more
}
private void yesEnterButtonActionPerfromed(ActionEvent e) {
// TODO depending on state of enteringData and dataValidYet booleans
// change text in buttons, do things with JTextField data
// set state of enteringData and dataValidYet booleans
if (enteringData) {
topTextArea.setText(ARE_YOU_FINISHED);
yesEnterButton.setText(YES);
yesEnterButton.setActionCommand(YES);
enteringData = false;
return;
}
// .... more
}
private static void createAndShowGui() {
StateMachine mainPanel = new StateMachine();
JFrame frame = new JFrame("State Machine");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Also, as a "side" recommendation, one unrelated to your main problem, understand that null layouts and setBounds() might seem to Swing newbies like the easiest and best way to create complex GUI's, the more Swing GUI'S you create the more serious difficulties you will run into when using them. They won't resize your components when the GUI resizes, they are a royal witch to enhance or maintain, they fail completely when placed in scrollpanes, they look gawd-awful when viewed on all platforms or screen resolutions that are different from the original one.
Note that if this were my program, I would use more indirection including creating separate classes to separate out the GUI portion of the program from the logic portion.
so my problem with this code is in the ActionListner I believe. When running the program I input a number and nothing happens. The only number that the program will run properly is when I input the number 2. I'm obviously doing something wrong in the for loop but I haven't been able to figure it out yet.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.text.*;
public class Prime implements ActionListener {
JFrame framePrime;
JPanel panelPrime;
JTextField primeTestField;
JLabel stringPrimelLabel, enterNumLabel, trueFalseLabel;
// Constructor
public Prime() {
// Create the frame and container.
framePrime = new JFrame("Prime or Not?");
panelPrime = new JPanel();
panelPrime.setLayout(new GridLayout(2, 2));
// Add the widgets.
addWidgets();
// Add the panel to the frame.
framePrime.getContentPane().add(panelPrime, BorderLayout.CENTER);
// Exit when the window is closed.
framePrime.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Show the converter.
framePrime.pack();
framePrime.setVisible(true);
}
// Create and add the widgets for converter.
private void addWidgets() {
// Create widgets.
primeTestField = new JTextField();
primeTestField.setHorizontalAlignment(JTextField.CENTER);
enterNumLabel = new JLabel("Enter a number: ",
SwingConstants.LEFT);
stringPrimelLabel = new JLabel("Is it Prime?: ",
SwingConstants.LEFT);
trueFalseLabel = new JLabel("Let's Find Out!",
SwingConstants.CENTER);
// Listen to events from Convert textfield.
primeTestField.addActionListener(this);
// Add widgets to container.
panelPrime.add(enterNumLabel);
panelPrime.add(primeTestField);
panelPrime.add(stringPrimelLabel);
panelPrime.add(trueFalseLabel);
panelPrime.setBackground(Color.red);
}
// Implementation of ActionListener interface.
public void actionPerformed(ActionEvent event) {
int n = Integer.parseInt(primeTestField.getText());
if (n == 2) {
trueFalseLabel.setText("Yes");
}
else {
for (int i = 2; 2*i < n; i++) {
if(n % i == 0){
trueFalseLabel.setText("No");
}
else {
trueFalseLabel.setText("Yes");
}
}
}
}
// main method
public static void main(String[] args) {
Prime converter = new Prime();
}
}
ActionListener for JTextField is triggered when you press enter in the text field.
Edit: If you want to do the prime check whenever the value is changed in the text field. As suggested by #MadProgrammer, you can add a DocumentListener to the document of the text field and implement the insertUpdate (called when you add a character) and removeUpdate (called when you remove a character) methods.
primeTestField.getDocument().addDocumentListener(new DocumentListener() {
#Override
public void insertUpdate(DocumentEvent e)
check();
}
#Override
public void removeUpdate(DocumentEvent e) {
check();
}
#Override
public void changedUpdate(DocumentEvent e) {
}
});
(PS: I corrected and refactored your prime check logic into a method so that it is correct & reusable)
private void check() {
int n;
try {
System.out.println(primeTestField.getText());
n = Integer.parseInt(primeTestField.getText());
} catch (Exception ex) {
return;
}
if (n == 2) {
trueFalseLabel.setText("Yes");
} else {
boolean isPrime = true;
for (int i = 2; 2 * i < n; i++) {
if (n % i == 0) {
isPrime = false;
break;
}
}
if (isPrime) {
trueFalseLabel.setText("Yes");
} else {
trueFalseLabel.setText("No");
}
}
}
import java.awt.BorderLayout;
import java.applet.Applet;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.*;
import java.awt.FlowLayout;
import java.awt.event.*;
import java.awt.*;
public class MemoryGame implements ActionListener
{
Label mostra;
public int delay = 1000; //1000 milliseconds
public void init()
{
//add(mostra = new Label(" "+0));
}
public void Contador()
{
ActionListener counter = new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
tempo++;
TempoScore.setText("Tempo: " + tempo);
}
};
new Timer(delay, counter).start();
}
public void updateHitMiss()
{
HitScore.setText("Acertou: " + Hit);
MissScore.setText("Falhou: " + Miss);
PontosScore.setText("Pontos: " + Pontos);
}
private JFrame window = new JFrame("Jogo da Memoria");
private static final int WINDOW_WIDTH = 500; // pixels
private static final int WINDOW_HEIGHT = 500; // pixels
private JButton exitBtn, baralharBtn, solveBtn, restartBtn;
ImageIcon ButtonIcon = createImageIcon("card1.png");
private JButton[] gameBtn = new JButton[16];
private ArrayList<Integer> gameList = new ArrayList<Integer>();
private int Hit, Miss, Pontos;
public int tempo = 0;
private int counter = 0;
private int[] btnID = new int[2];
private int[] btnValue = new int[2];
private JLabel HitScore, MissScore,TempoScore, PontosScore;
private JPanel gamePnl = new JPanel();
private JPanel buttonPnl = new JPanel();
private JPanel scorePnl = new JPanel();
protected static ImageIcon createImageIcon(String path)
{
java.net.URL imgURL = MemoryGame.class.getResource(path);
if (imgURL != null)
{
return new ImageIcon(imgURL);
}
else
{
System.err.println("Couldn't find file: " + path);
return null;
}
}
public MemoryGame()
{
createGUI();
createJPanels();
setArrayListText();
window.setTitle("Jogo da Memoria");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
window.setVisible(true);
Contador();
}
public void createGUI()
{
for (int i = 0; i < gameBtn.length; i++)
{
gameBtn[i] = new JButton(ButtonIcon);
gameBtn[i].addActionListener(this);
}
HitScore = new JLabel("Acertou: " + Hit);
MissScore = new JLabel("Falhou: " + Miss);
TempoScore = new JLabel("Tempo: " + tempo);
PontosScore = new JLabel("Pontos: " + Pontos);
exitBtn = new JButton("Sair");
exitBtn.addActionListener(this);
baralharBtn = new JButton("Baralhar");
baralharBtn.addActionListener(this);
solveBtn = new JButton("Resolver");
solveBtn.addActionListener(this);
restartBtn = new JButton("Recomecar");
restartBtn.addActionListener(this);
}
public void createJPanels()
{
gamePnl.setLayout(new GridLayout(4, 4));
for (int i = 0; i < gameBtn.length; i++)
{
gamePnl.add(gameBtn[i]);
}
buttonPnl.add(baralharBtn);
buttonPnl.add(exitBtn);
buttonPnl.add(solveBtn);
buttonPnl.add(restartBtn);
buttonPnl.setLayout(new GridLayout(1, 0));
scorePnl.add(HitScore);
scorePnl.add(MissScore);
scorePnl.add(TempoScore);
scorePnl.add(PontosScore);
scorePnl.setLayout(new GridLayout(1, 0));
window.add(scorePnl, BorderLayout.NORTH);
window.add(gamePnl, BorderLayout.CENTER);
window.add(buttonPnl, BorderLayout.SOUTH);
}
public void setArrayListText()
{
for (int i = 0; i < 2; i++)
{
for (int ii = 1; ii < (gameBtn.length / 2) + 1; ii++)
{
gameList.add(ii);
}
}
}
public boolean sameValues()
{
if (btnValue[0] == btnValue[1])
{
return true;
}
return false;
}
public void actionPerformed(ActionEvent e)
{
if (exitBtn == e.getSource())
{
System.exit(0);
}
if (baralharBtn == e.getSource())
{
//
}
if (solveBtn == e.getSource())
{
for (int i = 0; i < gameBtn.length; i++)
{
gameBtn[i].setText("" + gameList.get(i));
gameBtn[btnID[0]].setEnabled(false);
gameBtn[btnID[1]].setEnabled(false);
}
}
for (int i = 0; i < gameBtn.length; i++)
{
if (gameBtn[i] == e.getSource())
{
gameBtn[i].setText("" + gameList.get(i));
gameBtn[i].setEnabled(false);
counter++;
if (counter == 3)
{
if (sameValues())
{
gameBtn[btnID[0]].setEnabled(false);
gameBtn[btnID[1]].setEnabled(false);
gameBtn[btnID[0]].setVisible(false);
gameBtn[btnID[1]].setVisible(false);
Hit = Hit +1;
Pontos = Pontos + 25;
}
else
{
gameBtn[btnID[0]].setEnabled(true);
gameBtn[btnID[0]].setText("");
gameBtn[btnID[1]].setEnabled(true);
gameBtn[btnID[1]].setText("");
Miss = Miss +1;
Pontos = Pontos - 5;
}
counter = 1; //permite 2(3) clikes de cada vez
}
/*if (Pontos <= 0)
{
Pontos=0;
} */
if (counter == 1) // se carregar 1º botão
{
btnID[0] = i;
btnValue[0] = gameList.get(i);
}
if (counter == 2) // se carregar 2º botão
{
btnID[1] = i;
btnValue[1] = gameList.get(i);
}
}
}
if (restartBtn == e.getSource())
{
Hit=0;
Miss=0;
tempo=-1;
Pontos=0;
for (int i = 0; i < gameBtn.length; i++) /* what i want to implement(restart button) goes here, this is incomplete because it only clean numbers and "transforms" into regular JButton, the last two clicks
on the 4x4 grid (btnID[0] and btnID[1]), but i want to clean all the visible
numbers in the grid 4x4, and want to transform all grid 4x4 into default (or
regular color, white and blue) JButton, the grid numbers stay in same order
or position. */
{
gameBtn[btnID[0]].setEnabled(true);
gameBtn[btnID[0]].setText("");
gameBtn[btnID[1]].setEnabled(true);
gameBtn[btnID[1]].setText("");
}
/*
restartBtn.addActionListener(new ActionListener()
{
JFrame.dispatchEvent(new WindowEvent(JFrame, WindowEvent.WINDOW_CLOSING)); // this line is getting errors (MemoryGame.java:233: error: <identifier> expected
JFrame.dispatchEvent(new WindowEvent(JFrame, WindowEvent.WINDOW_CLOSING));
illegal start of type,')' expected, ';' expected all in the same line )
private JFrame window = new JFrame("Jogo da Memoria");
// something not right, i think frame is replaced by JFrame but i dont know, be
}); */
}
updateHitMiss();
}
public static void main(String[] args)
{
new MemoryGame();
}
}
</code>
Hi,
I want to add a restart button (mouse click), i am running notepadd++, when i click on restart button (recomeçar), it should restart this memory game, all counters set to zero etc, clean the grid 4x4, all numbers that were visible when i click the restart the button they all disaapear (but they are in same place or order) thus only show regular JButtons, the game should go to the starting point like when it first open the application, all numbers are not visible. (the functionality of restart button is equal to exit application and then restart).
Restart button code in lines 215 to 239, issues reported on comments between those lines.
I'm not sure if I fully understand your question, but here's what i think would help:
Add an ActionListener to your button with:
button.addActionListener(new ActionListener() {
});,
with button being the name of your JButton.
Within your ActionListener, call frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));, with frame being the name of your JFrame.
Then, run all of the methods you use to initialize your game (including the one that opens the JFrame).
Comment if you need clarification or more help.
I'm trying to make a game like bejeweled or candycrush for homework. It's almost over. but I have a little problem. Now, when I clicked, buttons that have the same icon are popping up and the above pictures are coming instead of exploding. but it's going too fast. How can I slow this event? Or can I add effects?
public class ButtonActionListener implements ActionListener {
public JButton previousButton = null;
public int numP, numC;
public JButton[] buttons=butondeneme.getButton();
#Override
public void actionPerformed(ActionEvent e){
// TODO Auto-generated method stub
JButton currentButton = (JButton)e.getSource();
if (previousButton == null) {
previousButton = currentButton;
return;
}
int numP=Integer.parseInt(((JButton)previousButton).getActionCommand());
int numC=Integer.parseInt(((JButton)currentButton).getActionCommand());
//change picture of icons that clicked
if (numP==(numC+1) || numP==(numC-1) || numP==(numC+8) || numP==(numC-8) ){
Icon previousIcon = previousButton.getIcon();
Icon currentIcon = currentButton.getIcon();
currentButton.setIcon(previousIcon);
previousButton.setIcon(currentIcon);
previousButton = null;
}
else
previousButton=null;
Random r = new Random();
int a = r.nextInt(64);
int b = r.nextInt(64);
int c = r.nextInt(64);
//buttons that have same picture are explode.
for(int i=0; i<63; i++){
if(buttons[i].getIcon().toString()==buttons[i+1].getIcon().toString() &&
buttons[i+1].getIcon().toString()== buttons[i+2].getIcon().toString() ){
//System.out.println("slm");
if(i > 7){
buttons[i].setIcon(buttons[i-8].getIcon());
buttons[i+1].setIcon(buttons[i-7].getIcon());
buttons[i+2].setIcon(buttons[i-6].getIcon());
for(int j = i; j > 0; j=j-8){
if(j > 7){
buttons[j].setIcon(buttons[j-8].getIcon());
buttons[j+1].setIcon(buttons[j-7].getIcon());
buttons[j+2].setIcon(buttons[j-6].getIcon());
}
else{
buttons[j].setIcon(buttons[a].getIcon());
buttons[j+1].setIcon(buttons[b].getIcon());
buttons[j+2].setIcon(buttons[c].getIcon());
}
}
}
else{
buttons[i].setIcon(buttons[a].getIcon());
buttons[i+1].setIcon(buttons[b].getIcon());
buttons[i+2].setIcon(buttons[c].getIcon());
}
}
}
}
}
In this class, I created frame, buttons and random icon.
public class butondeneme extends JFrame{
private JPanel grid;
public String comand;
public static JButton[] buttons;
public String imgName;
public butondeneme(){
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 640, 640);
grid=new JPanel();
grid.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
grid.setLayout(new GridLayout(8,8,5,5));
buttons = new JButton[64];
//Creating random image for buttons
ActionListener buttonActionListener = new ButtonActionListener();
for (int i = 0; i<buttons.length; i++) {
Random r = new Random();
int a = r.nextInt(9)+1;
switch(a){
case 1 : buttons[i]=new JButton(new ImageIcon("img//Cakal.png"));
break;
case 2 : buttons[i]=new JButton(new ImageIcon("img//BugsBunny.png"));
break;
case 3 : buttons[i]=new JButton(new ImageIcon("img//Pig.png"));
break;
case 4 : buttons[i]=new JButton(new ImageIcon("img//Taz.png"));
break;
case 5 : buttons[i]=new JButton(new ImageIcon("img//Sam.png"));
break;
case 6 : buttons[i]=new JButton(new ImageIcon("img//DuffyDuck.png"));
break;
case 7 : buttons[i]=new JButton(new ImageIcon("img//Tweety.png"));
break;
case 8 : buttons[i]=new JButton(new ImageIcon("img//Slyvester.png"));
break;
case 9 : buttons[i]=new JButton(new ImageIcon("img//RoadRunner.png"));
break;
}
//Adding number to find easily
comand=Integer.toString(i);
//Get ImageIcon name
imgName=((ImageIcon)buttons[i].getIcon()).toString();
buttons[i].addActionListener(buttonActionListener);
buttons[i].setActionCommand(comand);
grid.add(buttons[i]);
}
add(grid);
}
static JButton[] getButton(){
return buttons;
}
public static void main(String[] args){
butondeneme erdem=new butondeneme();
erdem.setVisible(true);
}
}
When you want to add a delay to such an "animation", then you have to use Thread.sleep(ms).
But this code is contained in the actionPerformed method, so you can't use Thread.sleep(ms) directly, because this would block the Event-Dispatch-Thread (EDT) and the GUI would become inresponsive.
So you have to perform this "animation" with an own Thread.
But you may not call Button#setIcon(...) on a different thread than the EDT.
So the actual solution is a bit tricky here - you have to "ping-pong" the responsibility between the two threads (alternatively, you could use a javax.swing.Timer, but I think this might require even more restructuring of your original code... Although I did not entirely understand what you are doing there (that is, which icons you are changing there for which reason)).
However, the general structure of such an approach could roughly look like this:
#Override
public void actionPerformed(ActionEvent e){
...
//buttons that have same picture are explode.
startAnimation();
}
private void startAnimation()
{
Thread t = new Thread(new Runnable()
{
#Override
public void run()
{
runAnimation();
}
});
t.start();
}
private int a;
private int b;
private int c;
private void runAnimation()
{
Random r = new Random();
a = r.nextInt(64);
b = r.nextInt(64);
c = r.nextInt(64);
for(int i=0; i<63; i++)
{
final int iFinal = i;
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
doAnimationStep(iFinal);
}
});
try
{
Thread.sleep(100);
}
catch (InterruptedException e)
{
Thread.currentThread().interrupt();
return;
}
}
}
private void doAnimationStep(int i)
{
String s0 = buttons[i].getIcon().toString();
String s1 = buttons[i+1].getIcon().toString();
String s2 = buttons[i+2].getIcon().toString();
if(s0.equals(s1) && s1.equals(s2))
{
//System.out.println("slm");
if(i > 7){
buttons[i].setIcon(buttons[i-8].getIcon());
buttons[i+1].setIcon(buttons[i-7].getIcon());
buttons[i+2].setIcon(buttons[i-6].getIcon());
for(int j = i; j > 0; j=j-8){
if(j > 7){
buttons[j].setIcon(buttons[j-8].getIcon());
buttons[j+1].setIcon(buttons[j-7].getIcon());
buttons[j+2].setIcon(buttons[j-6].getIcon());
}
else{
buttons[j].setIcon(buttons[a].getIcon());
buttons[j+1].setIcon(buttons[b].getIcon());
buttons[j+2].setIcon(buttons[c].getIcon());
}
}
}
else{
buttons[i].setIcon(buttons[a].getIcon());
buttons[i+1].setIcon(buttons[b].getIcon());
buttons[i+2].setIcon(buttons[c].getIcon());
}
}
}
BTW: You should not compare String objects with if (string0==string1) ... but always with if (string0.equals(string1)) ...