This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 6 years ago.
I have created an x-o game with GUI and almost finished it, but I have difficulties declaring the winner, I managed to do it manually but it took alot of code lines and it looks messy, here's what I did:
if((buttons[0].getText()=="X" && buttons[1].getText()=="X" && buttons[2].getText()=="X") ||
(buttons[0].getText()=="X" && buttons[3].getText()=="X" && buttons[6].getText()=="X") ||
(buttons[4].getText()=="X" && buttons[8].getText()=="X" && buttons[2].getText()=="X") ||
(buttons[0].getText()=="O" && buttons[1].getText()=="O" && buttons[2].getText()=="O") ||
(buttons[0].getText()=="O" && buttons[3].getText()=="O" && buttons[6].getText()=="O") ||
(buttons[4].getText()=="O" && buttons[8].getText()=="O" && buttons[2].getText()=="O") ||
(buttons[2].getText()=="X" && buttons[5].getText()=="X" && buttons[8].getText()=="X") ||
(buttons[1].getText()=="X" && buttons[4].getText()=="X" && buttons[7].getText()=="X") ||
(buttons[6].getText()=="X" && buttons[7].getText()=="X" && buttons[8].getText()=="X") ||
(buttons[2].getText()=="O" && buttons[5].getText()=="O" && buttons[8].getText()=="O") ||
(buttons[1].getText()=="O" && buttons[4].getText()=="O" && buttons[7].getText()=="O") ||
(buttons[6].getText()=="O" && buttons[7].getText()=="O" && buttons[8].getText()=="O") ||
(buttons[3].getText()=="X" && buttons[4].getText()=="X" && buttons[5].getText()=="X") ||
(buttons[3].getText()=="O" && buttons[4].getText()=="O" && buttons[5].getText()=="O") ||
(buttons[0].getText()=="X" && buttons[4].getText()=="X" && buttons[8].getText()=="X") ||
(buttons[0].getText()=="O" && buttons[4].getText()=="O" && buttons[8].getText()=="O") )
So I wanted to shorten this and add it in a loop, but it didnt work.
for(int i=0;i<9;i++)
{
if(i%3==0){
y+=50; x=40;
}
buttons[i]=new JButton();
buttons[i].setSize(50, 50);
buttons[i].setLocation(x, y);
int temp=i;
buttons[temp].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String currentPlayer = turnCount % 2 == 0 ? "X" : "O";
buttons[temp].setText(currentPlayer);
buttons[temp].setFont(new Font("Arial", Font.PLAIN, 30));
buttons[temp].setMargin(new Insets(0, 0, 0, 0));
buttons[temp].setEnabled(false);
turnCount++;
if(buttons[temp].getText()==buttons[temp+1].getText())
{
System.out.println("GAME OVER!");
for(int i=0;i<9;i++)
buttons[i].setEnabled(false);
turnCount = 0;
}
}
});
myForm.add(buttons[i]);
x+=50;
}
It should print the code inside the if statement whenever 2 following buttons have the same value, but it doesn't work.
This is exactly what needs to be changed somehow
if(buttons[temp].getText()==buttons[temp+1].getText())
Thank you.
If temp=i and he just instanciated buttons[i],, then buttons[temp+1] is null at this moment. Also, when temp reaches 8, buttons[temp+1] will be out of bound (I suspect your Button array is of size 9 ?)
Plus this won't be a condition for victory, you just test if the next button is of the same value, which means:
XX-
O--
---
Will be a victory for X.
As you can see from you big if, your duplicating too much code, you can do:
/**Checks if player X or O won **/
public boolean isWinner(Button[] buttons){
return playerWins(buttons, 'X') || playerWins(buttons, 'O');
}
/**Checks if a player has 3 buttons aligned **/
private boolean playerWins(Button[] buttons, char player) {
return lineWin(buttons,player,0,1,2) ||
lineWin(buttons,player,0,3,6) ||
lineWin(buttons,player,3,4,5); //TODO add the 5 others conditions
}
/** Checks if the buttons at i,j and k belongs the player **/
private boolean buttonsBelongToPlayer(Button[] buttons, char player, int i, int j, int k) {
return buttons[i].getText()==player && buttons[j].getText()==player && buttons[k].getText()==player;
}
Strings should be compared using equals(), not ==.
So:
if(buttons[temp].getText().equals(buttons[temp+1].getText()))
Related
Currently I am working on a little personal project to help myself learn about coding.
I'm wondering for future reference if I can combine logical operators of different types in a single if statement.
For example if I had
if (n == 0 || n == 1 && m == 0 || m == 1) {
doSomething();
}
Would it check if either parts of the left side are true, then if either parts of the right are true, or would it do something similar to checking if both of the middle ones are true?
Does using parenthesis change anything
For example
if ((n == 0 || n == 1) && (m == 0 || m == 1)) {
doSomething();
}
Edit:
From a suggestion I tried it out, but when i put three variables it started acting weird
Here's my test:
int n = 1;
int m = 1;
int o = 1;
if (n == 0 || n == 1 && m == 0 || m == 1 && o == 0 || o == 1) {
System.out.println("True");
}
else {
System.out.println("False");
}
if ((n == 0 || n == 1) && (m == 0 || m == 1) && (o == 0 || o == 1)) {
System.out.println("True");
}
else {
System.out.println("False");
}
if all of them are 1 or 0, they both evaluate true, if n or m is not 1 or 0 the top evaluates true but the bottom does not.
However if o is not 0 or 1 both of them are false.
I have found that parenthesis do in fact make a difference, but I can't quite tell why it's acting the way it is.
&& has a higher precedence then ||, so n == 0 || n == 1 && m == 0 || m == 1 equals n == 0 || (n == 1 && m == 0) || m == 1. You may check the precedence table here.
I am trying to design a Tic-Tac-Toe game in Java. I must point out that I am a complete beginner in Java. So I am trying to generate all possible combinations of the game, then store it in a file. We know that there are 255168 possible combinations. Anyway here is my code:
import java.io.*;
import java.util.Random;
import java.util.Arrays;
public class generator2 {
public static void main(String[] args) {
Random r=new Random();
String s;
String store[] = new String[255168];
int count=0;
int i=0;
int a[][]=new int[3][3];
int wf;
int flag=0;
char b;
while(count<255168)
{
s="";
b='X';
flag=0;
for(int[] row : a)Arrays.fill(row, 0);
wf=0;
i=0;
while(wf==0)
{
int r1=r.nextInt(3)+0;
int r2=r.nextInt(3)+0;
if(a[r1][r2]==0)
{
i++;
if(flag==0) {a[r1][r2]=1;flag=1;}
else {a[r1][r2]=2;flag=0;}
if(a[0][0]==1 && a[0][1]==1 && a[0][2]==1 || a[1][0]==1 && a[1][1]==1 && a[1][2]==1 || a[2][0]==1 && a[2][1]==1 && a[2][2]==1 || a[0][0]==1 && a[1][0]==1 && a[2][0]==1 || a[0][1]==1 && a[1][1]==1 && a[2][1]==1 || a[0][2]==1 && a[1][2]==1 && a[2][2]==1 || a[0][0]==1 && a[1][1]==1 && a[2][2]==1 || a[0][2]==1 && a[1][1]==1 && a[2][0]==1)
{
b='W';
wf=1;
break;
}
else if(a[0][0]==2 && a[0][1]==2 && a[0][2]==2 || a[1][0]==2 && a[1][1]==2 && a[1][2]==2 || a[2][0]==2 && a[2][1]==2 && a[2][2]==2 || a[0][0]==2 && a[1][0]==2 && a[2][0]==2 || a[0][1]==2 && a[1][1]==2 && a[2][1]==2 || a[0][2]==2 && a[1][2]==2 && a[2][2]==2 || a[0][0]==2 && a[1][1]==2 && a[2][2]==2 || a[0][2]==2 && a[1][1]==2 && a[2][0]==2)
{
b='L';
wf=1;
break;
}
else if(i==9)
{
b='T';
wf=1;
break;
}
}
}
s+=b;
for(i=0;i<3;i++)
for(int j=0;j<3;j++)
s+=String.valueOf(a[i][j]);
if(repeat(s,store,count)) {store[count]=s;count++;s="";System.out.println(count);}
else {continue;}
}
// for(i=0;i<958;i++)
// {
// System.out.println(store[i]);
// }
}
public static boolean repeat(String s,String[] a,int count){
int flag=0;
for(int i=0;i<count;i++)
{
if(a[i].equals(s)) {flag=1;break;}
}
if(flag==1)return false;
else return true;
}
}
Format of stored string:
First Character: W-Player1 Win.. L-Player2 Win.. T-Tie
next 9 characters represent board layout:
211012012 represents
2 1 1
0 1 2
0 1 2
Note that 0 is for position still not filled by any player. As we can see Player1 wins in above game so the string is stored is W211012012.
Theoretically this method should generate all possible unique combinations(255168), but it is not. It generates 958 combinations and then the program is just stuck.
Actually I think you should be happy to know that 958 is the correct answer for the number of legal endgame states.
https://archive.ics.uci.edu/ml/machine-learning-databases/tic-tac-toe/tic-tac-toe.names
255168 is correct when you keep track of the order of each player's moves -- not just the final end state. You are computing the valid final end game states.
Take your example of W211012012. There are 108 ways to accomplish W211012012 when considering the order of each player's moves. Player 1's top right move can't be last and other 3 moves can be in any order for 3*3!. Player 2's three moves can be in any order for 3!. 108=3*3!*3!.
If instead you want to calculate all 255168 combinations when the order of the moves matters consider representing your state strings differently. Maybe [WLT](1,row,col)(2,row,col)(1,row,col)... or any other way that would encode the order of the moves.
You are simulating all possible games by having 2 players play randomly and keeping track of unique games. That's one way to do it, and a good exercise, but not particularly efficient. You could also use a searching algorithm like DFS https://en.m.wikipedia.org/wiki/Depth-first_search to explore the search space.
this is more of a logic question than syntax but I'm sure you guys have better ways to do it than me anyway. So I have some pieces (JLabels) on a board (11x11 Grid of JPanels on a JPanel) all in a frame. I'm trying to highlight the "possible moves" for these pieces (I.E. how many panels they can cross in a move) very similar to in many online chessgames. I have the logic that checks if movement follows the rules, and it works perfect, I just can't seem to figure out how to find all of those legal moves at once and use them.
This is the code that I use to check if movement is legal:
public void movePieces(MouseEvent me)
{
MouseEvent e = me;
if (turnCount%2 == 1 && pieceCheck[(e.getY()/yInc)][(e.getX()/xInc)])
{
if (playerOne && (logic[(e.getY()/yInc)][(e.getX()/xInc)] == 0 || logic[(e.getY()/yInc)][(e.getX()/xInc)] == 2 || logic[(e.getY()/yInc)][(e.getX()/xInc)] == 4))
{
otherCount = logic[(e.getY()/yInc)][(e.getX()/xInc)];
tempX = e.getX();
tempY = e.getY();
paintPossible(tempX, tempY);
turnCount++;
}
if (!playerOne && (logic[(e.getY()/yInc)][(e.getX()/xInc)] == 1 || logic[(e.getY()/yInc)][(e.getX()/xInc)] == 3 || logic[(e.getY()/yInc)][(e.getX()/xInc)] == 5))
{
otherCount = logic[(e.getY()/yInc)][(e.getX()/xInc)];
tempX = e.getX();
tempY = e.getY();
turnCount++;
}
}
else if ((turnCount%2 == 0 && logic[(e.getY()/yInc)][(e.getX()/xInc)] == -1 && !pieceCheck[(e.getY()/yInc)][(e.getX()/xInc)]) && (Math.abs(tempX - e.getX()) <= xInc && (Math.abs(tempY - e.getY()) <= yInc) || ((Math.abs(tempX - e.getX()) <= 2*xInc) && (Math.abs(tempY - e.getY()) < yInc/4)) || ((Math.abs(tempX - e.getX()) < xInc/4) && (Math.abs(tempY - e.getY()) <= 2*yInc))))
{
panels[(e.getY()/yInc)][(e.getX()/xInc)].add(pieces[otherCount]);
logic[(e.getY()/yInc)][(e.getX()/xInc)] = otherCount;
pieceCheck[(e.getY()/yInc)][(e.getX()/xInc)] = true;
pieceCheck[tempY/yInc][tempX/xInc] = false;
panels[tempY/yInc][tempX/xInc].setBackground(veryDarkGray);
panels[tempY/yInc][tempX/xInc].setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
playerOne = !playerOne;
turnCount++;
}
....
}
Basically the first if-statement and what's inside is for when you first click a piece, and then if it's your turn then it will set that piece as the next in line to put down, and grab the X-Y coordinates of where it is.
The else-if then activates the next time you click due to the rotation of my turnCount, and makes sure there's no piece where you're clicking and that the space is within a certain# of pixels to where your piece is before you move.
I need to take that same checking of validity in where you can move, and apply it in a separate method that will loop through the 2d array of JPanels that is my board and color the valid moves. The method would be called where "paintPossible(tempX, tempY)" is, and in the same spot in the "if" below.
I'm trying to solve a problem which uses a 2D array, the problem of a rat in a maze.
While checking the conditions trying to compile, it finds an Array index out of bounds exception... how can I check the values so it doesn't go out of the array bounds?
static void solveMaze(){
int nSteps = 0; // Number of steps.
int x = 0; int y = 0; // Starting point.
boolean mazeCompleted = false;
while (!mazeCompleted){
if(x == maze.mazeMatrix.length && y == maze.mazeMatrix.length)
mazeCompleted = true;
else if(maze.mazeMatrix[x+1][y] == 0){ // Move right.
maze.mazeMatrix[x+1][y] = 2;
x++; nSteps++;
}
else if(maze.mazeMatrix[x-1][y] == 0){ // Move left.
maze.mazeMatrix[x-1][y] = 2;
x--; nSteps++;
}
else if(maze.mazeMatrix[x][y+1] == 0){ // Move down.
maze.mazeMatrix[x][y+1] = 2;
y++; nSteps++;
}
else if(maze.mazeMatrix[x][y-1] == 0){ // Move up.
maze.mazeMatrix[x][y-1] = 2;
y--; nSteps++;
}
}
maze.printMatrix();
System.out.println("Maze COMPLETE! - With a total of " + nSteps + " steps.");
}
Tried before with two "for" loops to prevent the out of bounds but I just can't go diagonal in this problem.
You have a pretty crucial bug in your program. You will never reach the end of the maze!
if(x == maze.mazeMatrix.length && y == maze.mazeMatrix.length)
references indices that are out of bounds! It should be
if(x == maze.mazeMatrix.length - 1 && y == maze.mazeMatrix.length - 1)
You also need to check to see whether you can & should move before you try to move there. I.E. :
while (!mazeCompleted){
boolean moveRight = (x + 1 < mazeMatrix.length && maze.mazeMatrix[x+1][y] == 0 ? true : false);
boolean moveLeft = (x - 1 >= 0 && maze.mazeMatrix[x-1][y] == 0 ? true : false);
boolean moveUp = (y + 1 < mazeMatrix[x].length && maze.mazeMatrix[x][y+1] == 0 ? true : false);
boolean moveDown = (y - 1 >= 0 && maze.mazeMatrix[x][y-1] == 0 ? true : false);
And:
else if(moveRight) { // Move right.
maze.mazeMatrix[x+1][y] = 2;
x++; nSteps++;
}
etc. Although it does seem like this is something that should be solved recursively, as if there are any loops in the maze you will end up getting stuck and infinite looping.
I'm trying to work with more GUI stuff but I'm having problem with something. I have an array of JLabels. Each of them contain 1 number from 0 to 7. I'm making the numbers "light up" by changing the background color from black to green. Is there any way to make all the even numbers "light up" while keeping all the odd numbers dark and then vice versa? I tried using a timer but my algorithm isn't working as it should. Below is the code for the method that configures the timer. Thanks
public void configureAlternatingTimer() {
if (this.timer != null) {
this.timer.stop();
}
this.timer = new Timer(100, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
for (int i = 0; i <= 8; i++) {
if (i == 0 || i == 2 || i == 4 || i == 6) {
lights[1].setBackground(Color.black);
lights[3].setBackground(Color.black);
lights[5].setBackground(Color.black);
lights[7].setBackground(Color.black);
lights[i].setBackground(Color.green);
}
if (i == 1 || i == 3 || i == 5 || i == 7) {
lights[0].setBackground(Color.black);
lights[2].setBackground(Color.black);
lights[4].setBackground(Color.black);
lights[6].setBackground(Color.black);
lights[i].setBackground(Color.green);
}
if(i==8) {
return;
}
}
}
});
this.timer.start();
}
Also, I'm trying to simulate a "larson scanner" which would light up to 7 then go back down to 0 then repeat. I can get it to go from 0 to 7 it's just the going back down part that I'm having trouble with. Thanks
Drop the for-loop, it's preventing the Event Dispatching Thread from processing repaint requests
Instead, each time that the actionPerformed method is called, update some kind of counter and then take action on it, for example...
this.timer = new Timer(100, new ActionListener() {
private int sequence = 0;
public void actionPerformed(ActionEvent evt) {
if (sequence % 2 == 0) {
lights[1].setBackground(Color.black);
lights[3].setBackground(Color.black);
lights[5].setBackground(Color.black);
lights[7].setBackground(Color.black);
lights[sequence].setBackground(Color.green);
} else {
lights[0].setBackground(Color.black);
lights[2].setBackground(Color.black);
lights[4].setBackground(Color.black);
lights[6].setBackground(Color.black);
lights[sequence].setBackground(Color.green);
}
sequence++;
if (sequence > 7) {
// This seems to be important...?
}
}
});
Updated based on comments
This should show all odds or all evens...
Timer timer = new Timer(500, new ActionListener() {
private int sequence = 0;
#Override
public void actionPerformed(ActionEvent e) {
System.out.println(sequence + "; " + (sequence % 2));
for (int index = 0; index < lights.length; index++) {
if (index % 2 == 0 && sequence % 2 == 0 || index % 2 != 0 && sequence % 2 != 0) {
lights[index].setBackground(Color.GREEN);
} else {
lights[index].setBackground(Color.BLACK);
}
}
sequence++;
if (sequence > 7) {
sequence = 0;
}
}
});
To determine if you have an even or odd number, you should think about using modulus operator % to determine if a number is odd or even. The modulus will return the remainder of a number after it has been divided.
For example:
4 / 2 = 2r0
5 / 2 = 2r1
6 / 2 = 3r0
7 / 2 = 3r1
so on and so forth...
if(i % 2 == 0) {
// even
} else {
// odd
}