Problems with TicTacToe game in java? using getText().equals() with jButtons - java

Not to sure about why this code is not working as intended and hoping you could help me figure it out. I am working on a tictactoe game from a series of tutorials that use jbuttons. What i have is a method in my main class that "checksforwin" each time a button is clicked. Using print statements i found that my method does run each time a button is clicked however the getText().equals("_") conditions do not operate properly.
This code is part of my tictactoe.java and all works properly. this event is copied 9 times for each button.
public void button1ActionPerformed(ActionEvent e) {
if(button1.getText().equals("")){
if(Main.playerTurn==true){
button1.setText("X");
Main.checkforwin();
Main.playerTurn = false;
}else{
button1.setText("O");
Main.checkforwin();
Main.playerTurn = true;
}
}
}
This code is part of my main.java which houses the checkforwin method. The check for win chunk of code is repeated multiple times for each possible win in tictactoe for both the player 1 and computer(player2).
public class Main {
public static boolean playerTurn = true;
public static boolean playerWon = false;
public static boolean computerWon = false;
public static tictactoe board = new tictactoe();
public static void checkforwin(){
System.out.println("testing1");
//horizontal row 1
if(board.button1.getText().equals("X")){
System.out.println("testing2");
if(board.button2.getText().equals("X")){
if(board.button3.getText().equals("X")){
playerWon = true;
computerWon = false;
System.out.println("Player 1 won");
}
}
}
}
The method will output testing1 every time a button is clicked, however it will never print inside the conditions.
Any help or advice would be greatly appreciated thanks!

My guess is its not picking up the button text change - after the button text change (button1.setText("X");) etc - you need to add it to the panel again, so panel.add(button1); or whatever they're stored on

I was taking a quick look at your coding and not entirely sure, but "maybe" you should try using AND operator in your conditional IF statement? For example:
if(board.button1.getText().equals("X") && board.button2.getText().equals("X") && board.button3.getText().equals("X")){
playerWon = true;
computerWon = false;
System.out.println("Player 1 won");
}
You could use these types of conditional statements to say either player/computer has won, providing the horizontal or vertical buttons equal X or O.
There is probably a more efficient way though to do it though, but this is the first thought that occurred to me so you could try it out!
I hope it helps!

Related

is there a better way to swap players symbols?

I'm making XO game by JavaFX, so I need a way to swap between "X"s and "O"s with each new turn, could you please check what I've come up with and tell if there a better way to swap them
boolean turnSwaper=true;
public void play(ActionEvent e){
String player="";
if(turnSwaper){
player="X";
turnSwaper=false;
}else {
player="O";
turnSwaper=true;
}
Button pressed=(Button)e.getSource();
pressed.setText(player);
pressed.setDisable(true);
}

Using break to stop the moving lines in java

I am completely new to java and I have one problem I am trying to resolve. I am using ACM Library for my purpose. My goal is the following:
Move Label 1
Move Label 2
Compare label 1's and label 2's position (when the text hits and its on each other) "Using 'if' statement"
Once on top, stop it by using break statement.
Restart the cycle.
If someone could help me out by explaining how this can be implemented. That would be awesome. I am trying to learn. Thank you!
import acm.graphics.GLabel;
import acm.program.CommandLineProgram;
import acm.program.GraphicsProgram;
public class Main extends GraphicsProgram {
public void run( )
{
int label1_xy = 50;
int label2_xy = 200;
GLabel label1 = new GLabel("Hello World.");
add(label1, label1_xy,label1_xy);
GLabel label2 = new GLabel("Goodbye World.");
add(label2, label2_xy,label2_xy);
while (true)
{
label1.move(10,10);
pause(500);
label2.move(-10,-10);
break;
}
}
}
Move Label 1
Move Label 2
You have done these two.
Compare label 1's and label 2's position (when the text hits and its on each other) "Using 'if' statement"
Once on top, stop it by using break statement.
You can compare the position of those two labels by trying to retrieve the "bound" of the object. example :
label1.move(10,10);
pause(500);
if (label1.getBounds().getX() == label2.getBounds().getX()
&& label1.getBounds().getY() == label2.getBounds().getY()) {
break;
} else {
label2.move(-10,-10);
}
Restart the cycle
You can restart this by putting another while block for the run() code or maybe just call the run() (beware of the StackOverflowError here).

JButton already selected when window loads - infinite loop

I have an array of JButtons which are displayed on a window when it is loaded up.
For some reason, when the window loads, the first button seems to be already selected and so puts my programme into an infinite loop.
I know that to stop this infinite loop I should change the condition in my while(true) loop, but am unsure what conditions to put in.
So I thought another way round would be to figure out why one of the buttons is already selected.
actionPerformed method - this gets the name of the button selected which I made to be a string to represent co-ordinates. It then turns the co-ordinates into integers which can be obtained by the HumanPlayer class with the getXInt and getYInt methods. The board and pieces are already set up in other classes, I know it all works because i've already created a text version, this is now the GUI version I am working on.
It's just a case of enabling the user to select a button without the while(true) loop getting stuck.
The Screen class:
public void actionPerformed(ActionEvent e) {
JButton piece = (JButton) e.getSource();
String xy = piece.getName();
String x = xy.substring(0,1);
String y = xy.substring(2,3);
xInt = Integer.parseInt(x);
yInt = Integer.parseInt(y);
}
public int getXInt() {
return xInt;
}
public int getYInt() {
return yInt;
}
HumanPlayer class which gets the information of the piece selected and checks whether it can be moved.
//Sets up new instance of Screen class which is where the window displaying the buttons is set up (this contains the getXInt and getYInt methods are- so the HumanPlayer class can retrieve the piece which has been selected.
Screen s = new Screen(board);
public boolean makeMove() {
int fromXCo , fromYCo, toXCo, toYCo;
Piece p;
ArrayList<Move> moves = null;
while (true){
//reads x and y co-ordinate
System.out.println("Click on a piece to move");
//takes information from which button is clicked from other class
fromXCo = s.getXInt();
fromYCo = s.getYInt();
p = board.getPiece(fromXCo, fromYCo);
System.out.println("Your selected piece is " + p.getChar());
//looks through available moves for piece
moves = p.availableMoves();
//if no moves available, asks for new co-ordinates.
if (moves == null)
{
System.out.println("No moves available for this piece \n");
continue;
}
break;
}
So the output is a continuous:
Click on a piece to move
Your selected piece is r
There are no available moves for this piece...

when shooting constantly repeats and goes faster every key stroke

Ok so i'm going to try to explain this, well I created a shoot method in a class that contains my bluespell, and all of it's constructors, well the problem is when I press space once it constantly shoots without me pressing it again, and if I press it twice the speed at which it fires doubles and it starts to contain more than one x and y position on my grid I just want the spell to fire when fired and I only need one item because I don't want there to be more than one instance of it on the grid I want it to be that the player cannot fire until the spell has left the grid, here's my code thanks oh and I only have it called in my key released seeing as it should only do it once the key has been released, but if that should change please let me know thanks :)
public void shootSpell(){
final BlueSpell b = new BlueSpell(GoodGuy.getx(), GoodGuy.gety() +1, BlueSpellWizard());
int delay = 100;
ActionListener taskPerformed = new ActionListener(){
public void actionPerformed(ActionEvent e){
if(b.gety() != 19){
WizardCells[b.getx()][b.gety()].setIcon(null);
WizardCells[b.getx()][b.changey(b.gety()+1)].setIcon(b.getIcon());
}
else{
WizardCells[b.getx()][b.gety()].setIcon(null);
b.changex(GoodGuy.getx());
b.changey(GoodGuy.gety() +1);
}
}
};
new Timer(delay, taskPerformed).start();
else if(key == KeyEvent.VK_SPACE){
GoodSpell.shootSpell();
}
Do not use a Timer! Your task should not repeat every 100 milliseconds. If I understand your code, you should run the code from your ActionListener in a new thread.
// Something like this,
new Thread(new Runnable() {
public void run() {
if (b.gety() != 19) {
WizardCells[b.getx()][b.gety()].setIcon(null);
WizardCells[b.getx()][b.changey(b.gety() + 1)].setIcon(b
.getIcon());
} else {
WizardCells[b.getx()][b.gety()].setIcon(null);
b.changex(GoodGuy.getx());
b.changey(GoodGuy.gety() + 1);
}
}
}).start();
You also need to do a check if the spell is currently in view/activate prior to initiating a new spell in the shoot() method...
public void shootSpell(){
//do a check here if a spell is already running!
final BlueSpell b = new BlueSpell(GoodGuy.getx(), GoodGuy.gety() +1, BlueSpellWizard());
int delay = 100;
//......
So in your method that is updating the spell going accross the screen you either need to have a flag in there if its still active, or if you are running it in a new thread, save that thread to a global var and check to see if the thread is running prior instantiating a new BlueSpell()

Properly implementing a delay in a game

This is a follow up to a previous question I had. I have a Battleships game with two boards. When the user clicks on the computer board an action occurs, along these lines:
public void mouseClicked(MouseEvent e)
// Get coordinates of mouse click
if (//Set contains cell) {
/add Cell to set of attacked cells
//Determine if set contains attacked cell.
// If yes, hit, if no, miss.
checkForWinner();
The checkForWinner method determines if the game has been won yet. If it hasn't it calls a nextTurn method which changes the current turn. If the currentTurn is set to Computer, a ComputerMove() method is automatically called.
When that method finishes, it again checksforWinner, changes turn and waits for the user to click on the grid to start the cycle again.
Ideally, I'd like to have sound effects, or at the very least a pause between moves. However, no matter how I use Thread.sleep, or TimerTask, or anything else, I can't get it to function correctly.
If I use a simple Thread.sleep(500) in the CheckforWinner method, or in the ComputerMove method, all that happens is the human's go is delayed for the set amount of time. As soon as his move is executed the computer's move is completed immediately.
I know very little about threads but I assume this is because all the initiation of the bouncing back and forth between methods begins with a method in the mouse listener.
Given the set up of my system, is there a way to implement a delay without radically changing things?
Edit: May as well include the classes:
public void checkForWinner() {
if (human.isDefeated())
JOptionPane.showMessageDialog(null, computer.getName() + " wins!");
else if (computer.isDefeated())
JOptionPane.showMessageDialog(null, human.getName() + " wins!");
else
nextTurn();
}
public void nextTurn() {
if (currentTurn == computer) {
currentTurn = human;
} else {
currentTurn = computer;
computerMove();
}
}
public void computerMove() {
if (UI.currentDifficulty == battleships.UI.difficulty.EASY)
computerEasyMove();
else
computerHardMove();
}
public void computerEasyMove() {
// Bunch of code to pick a square and determine if its a hit or not.
checkForWinner();
}
Ideally, I'd like to have sound effects, or at the very least a pause between moves. However, no matter how I use Thread.sleep, or TimerTask, or anything else, I can't get it to function correctly.
You should be using a Swing Timer. Something like:
Timer timer = new Timer(1000, new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
currentTurn = computer;
computerMove();
}
});
timer.setRepeats(false);
timer.start();

Categories