Stuck at 958 combinations - java

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.

Related

Assessing whether 2 inputted variable values can sum to a inputted value

I'm working on a small program where a method takes 3 int's bigCount smallCount and goal.
These variables are supposed to represent the number of bags of flour in 2 sizes, the bigCount weight value is 5 kilos per bag, smallCount weight value is 1 kilo per bag and goal is the goal weight of the box that would contain the bags.
for example bigCount = 1, bigCount = 1, smallCount = 0, goal = 4
Should return a value of false since bigCount is given the value of 1 and 1 value in bigCount is representative of a 5 kilo bag and thus the bags that you have would never fit into a box with the weight requirement of 4.
At first, I tried to create a bunch of if and else if statements that would return a true value if the values of bigCount and smallCount could be added in a combination to sum to the weight given in the goal variable.
I feel like there is a much smarter way to go about this but I can't figure out an algorithm that could simply wrap all this up without all these if and else if statements. Currently, the logic for some of these if statements is incorrect and not catching all the scenarios to make it work properly.
public static boolean canPack(int bigCount, int smallCount, int goal){
boolean isPackable = false;
int bigBKilo = bigCount*5;
int smallBKilo = smallCount*1;
int remain5 = goal %5;
int remainTest = 6 %5;
int sum = bigBKilo+smallBKilo;
if( bigCount < 0 || smallCount < 0 || goal <0){
isPackable = false;
}else{
if(remain5 > 0 && remain5 <= smallCount && smallCount >= goal) {
isPackable = true;
}
else if(remain5 == 0 && bigCount > 0){
isPackable = true;
}
else if(bigCount == 0 && smallCount >= goal){
isPackable = true;
}
else if(smallCount ==0 && remain5 == 0){
isPackable = true;
}
else if(sum == goal){
isPackable = true;
}
else if(bigBKilo < goal && remain5 <= smallCount){
isPackable = true;
}
else if(bigCount == 0 && smallCount < goal){
isPackable = false;
}
else{
isPackable = false;
}
}
return isPackable;
}//end method
One possible way to solve the problem with some math is as follows:
Pick the biggest bag
Try to fit as many of them in the box as possible (limited by box goal and amount of bags available) - by doing some math
Calculate amount of space remaining in the box after those operations
Pick second biggest bag
Try to fit as many of those in the remaining space as possible
Repeat until you run out of bags or remaining space is 0
I think you should be able to implement this algorithm on your own.

Problems with while loops

I'm working on a project at the moment that's building a digitised version of a board game, and i'm having an issue with a while loop thats not doing as i expected.
Basically, if the player has 1 stone left in his/her hand, and the next pit is not empty, they pick up the next pits stones and continue doing so, until the next pit is empty.
Now, my code continues while the next pit is empty and while one stone is remaining in their hand, however, it doesn't pick up the next pits stones if it isn't empty, it just adds one until the next pit is empty.
So my code is almost there, just not quite. So i'm looking for some help to improve the current code (a big comment above the code that needs work).
Let me know if the explanation is poor, i'll do my best to re-write it.
Cheers
while(hand == 1 && pit.next.stones != 0 && pit.next.pit == false) {
int stones = pit.next.stones;
for(int i = stones; i >= 1; i--) {
hand++;
}
while(Hand >= 1 && pit.next.stones != 0) {
hand--;
addPieces(pit.next);
pit = pit.next;
}
}
Rather than having mutli-nested loops. You should probably just update the stones in hand and stones in the pit and let the main loop continue as normal since the main loop is just the main game logic loop: grab stones, drop in pits, grab more stones and repeat?, ???, profit!
Eg:
Instead of:
while(hand >= 1 && pit.next != null) {
// ...
while (hand == 1 && pit.next.stones != 0 && pit.next.pit == false) {
int stones = pit.next.stones;
for (int i = stones; i >= 1; i--) {
hand++;
}
while (hand >= 1 && pit.next.stones != 0) {
hand--;
addPieces(pit.next);
pit = pit.next;
}
}
do something like:
while(hand >= 1 && pit.next != null) {
// ...
if(hand == 1 && pit.next.stones > 0 && pit.next.pit == false) {
// update stones in hand
hand += pit.next;
// update stones in pit
pit.next.stones = 0;
}
// let main loop continue
}
(Note: I'm not 100% on the rules you are going for, just tried to follow what you said)

Tic Tac Toe winner [duplicate]

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()))

How to check if three numbers are guessed?

Hi everyone on this community.
I'm a Java newbie. This is no homework, I'm really passionate about programming and I really want to learn more. I am stuck with one exercise.
Basically I have to create a simple lottery game.
The user has to input one number from 0 to 999, a three digit number.
If the guess is exactly the same, the prize is 10.000 $,
If the guess is about the same (digits guessed but not in order) the
prize is 3,000 $
If the guess is not really the same (digits guessed == 1) the prize
is 1,000 $.
Here's my code so far: I don't know how to deal with condition 2 and 3. Could I have some hint or comment?
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Please enter a three digit number");
int guess = input.nextInt();
//generate number:
int lottery = (int)(Math.random() * 1000);
if ((guess > 999) || (guess < 100)) {
System.out.println("The number is not a three digit number. The system will exit NOW.");
System.exit(1);
}
else {
// extract digits from lottery number
int lotteryDigit1 = lottery / 100;
int lotteryDigits = lottery % 100;
int lotteryDigit2 = lottery / 10;
int lotteryDigit3 = lottery % 10;
// extract digits from guessed number
int guessDigit1 = guess / 100;
int remainingDigits = guess % 100;
int guessDigit2 = guess / 10;
int guessDigit3 = guess % 10;
System.out.println("The lottery number is: " + lottery);
// check the guess:
if (guess == lottery) {
System.out.println("Exactly what the number was.");
}
else if {
// digits guessed, but not in exact order (eg. 332 = 233)
}
else if {
// only one digit is guessed (eg. 332 = 442)
}
}
}
}
Could I have some comment on the code? Is it readable or horribly written? I really don't have a clue since I am really just new to programming. Thanks.
With an array, you can count how many digits the real number and the guessed number contains, and perform comparisons with that. First make two arrays of length 10 (one slot for each digit), then increase each relevant "slot" by 1 for every digit in the real number. Do the same for the guess, and compare.
I'm recommending this approach because it will scale for guesses with 4, 5, or even 15 digits, whereas coding these checks by hand will quickly turn into a problem with lots of duplicate code.
If, for some reason, you're not allowed to use arrays, you could manually do the counting - it sounds tempting to check if each digit exists in the other set of digits, but you'll run into trouble with duplicate digits (consider 112, which, when compared to 122, would contain "all" the digits; just not in the right amounts!). This will lead to a lot of duplicate code.
It'd be something like this...
int matchingDigits = 0;
if ( guessDigit1 == lotteryDigit1 || guessDigit1 == lotteryDigit2 || guessDigit1 == lotteryDigit3) {
matchingDigits++;
}
if ( guessDigit2 == lotteryDigit1 || guessDigit2 == lotteryDigit2 || guessDigit2 == lotteryDigit3) {
matchingDigits++;
}
if ( guessDigit3 == lotteryDigit1 || guessDigit3 == lotteryDigit2 || guessDigit3 == lotteryDigit3) {
matchingDigits++;
}
As you can see, it's a lot of duplicate code, and it doesn't properly handle the 112 vs 122 case. To properly handle that, you'd have to split each check apart and cross out numbers you've already "used"... which is possible, but leads to really lengthy code.
Here's how you'd do it...
boolean digit1Used = false;
boolean digit2Used = false;
boolean digit3Used = false;
int matchingDigits = 0;
if ( guessDigit1 == lotteryDigit1) {
matchingDigits++;
digit1Used = true;
} else if ( guessDigit1 == lotteryDigit2) {
matchingDigits++;
digit2Used = true;
} else if ( guessDigit1 == lotteryDigit3) {
matchingDigits++;
digit3Used = true;
}
if ( guessDigit2 == lotteryDigit1 && !digit1Used) {
matchingDigits++;
digit1Used = true;
} else if ( guessDigit2 == lotteryDigit2 && !digit2Used) {
matchingDigits++;
digit2Used = true;
} else if ( guessDigit2 == lotteryDigit3 && !digit3Used) {
matchingDigits++;
digit3Used = true;
}
if ( guessDigit3 == lotteryDigit1 && !digit1Used) {
matchingDigits++;
} else if ( guessDigit3 == lotteryDigit2 && !digit2Used) {
matchingDigits++;
} else if ( guessDigit3 == lotteryDigit3 && !digit3Used) {
matchingDigits++;
}
Note that I left out the checks for digitUsed in the first checks and the sets for digitUsed for the third set of checks - because we're not going to use them anymore. As you can see, it's really long AND it's basically faking arrays. Hence why it's not recommended to do so.
Imagine that solution for a 15 digit array! It'd be (N + 1 + (N*3*N) + N + N) lines long - 15 for digitUsed declarations, 1 for the matching digits, 15 digit comparisons of 3 lines for 15 digits, plus 15 closing braces and 15 blank lines in between - a total of 721 lines! That's why you should use arrays for this, and not checking it by hand.
If you've learned about methods already, I suggest you put the digit matcher in a separate function; that way you can keep your digit matching logic and the result-to-prize matching logic somewhat separated.
It’s not going to be nice code. For the second bullet, guessing all the digits but not in the right order, you may write a class like:
public class ThreeDigitNumber {
int digit1;
int digit2;
int digit3;
public ThreeDigitNumber(int number) {
digit1 = number / 100;
int remainingDigits = number % 100;
digit2 = remainingDigits / 10;
digit3 = remainingDigits % 10;
}
public int getDigit1() {
return digit1;
}
public int getDigit2() {
return digit2;
}
public int getDigit3() {
return digit3;
}
boolean isDigitGuessed(int digit) {
if (digit == digit1) {
// allow digit to be guessed only once, so set to a non-digit value when returning true
digit1 = -1;
return true;
}
if (digit == digit2) {
digit2 = -1;
return true;
}
if (digit == digit3) {
digit3 = -1;
return true;
}
return false;
}
}
Now you can test whether all digits have been guessed:
ThreeDigitNumber lotteryTdn = new ThreeDigitNumber(lottery);
ThreeDigitNumber guessTdn = new ThreeDigitNumber(guess);
boolean allDigitsGuessed = false;
if (lotteryTdn.isDigitGuessed(guessTdn.getDigit1())) {
if (lotteryTdn.isDigitGuessed(guessTdn.getDigit2())) {
if (lotteryTdn.isDigitGuessed(guessTdn.getDigit3())) {
allDigitsGuessed = true; // 3000 $ won
}
}
}

Keeping track of JButtons generated in a for loop

I am working on a Java tic-tac-toe game but I'm having trouble keeping track of my JButtons because I'm using a for loop to create 9 buttons:
for(int i=0;i<button.length;i++){
button[i] = new JButton();
button[i].setText(Integer.toString(i+1));
frame.add(button[i]);
button[i].addActionListener(this);
}
I want to check if my button text matches (in rows/columns/diagonal) and if so, display that you win.
Here is all my code:
public class TicTacToe extends Board implements ActionListener{
JButton button[] = new JButton[9];
boolean win = false;
int count = 0;
String letter = "";
public TicTacToe(){
//create + add JButtons to JFrame
for(int i=0;i<button.length;i++){
button[i] = new JButton();
button[i].setText(Integer.toString(i+1));
frame.add(button[i]);
button[i].addActionListener(this);
}
}
public void actionPerformed(ActionEvent e) {
for(int i=0;i<button.length;i++){
if(i%2 == 0){
letter = "X";
}else{
letter = "O";
}
if(e.getSource() == button[i]){
button[i].setText(letter);
button[i].setEnabled(false);
count = i+1;
}
//check win
if(){ //<---------------NEED HELP HERE. THANK YOU
win = true;
JOptionPane.showMessageDialog(null, "YOU WIN");
}
}
}
}
How can I keep track of dynamically created JButtons?
The win conditions for tic tac toe are:
X - - - X - - - X
X - - or - X - or - - X
X - - - X - - - X
private boolean colWinner() {
for (int i = 0; i < 3; i++) {
String mark = button[i].getText();
if (mark.equals(button[i+3].getText()) &&
mark.equals(button[i+6].getText()) {
return true;
}
}
return false;
}
or
X X X - - - - - -
- - - or X X X or - - -
- - - - - - X X X
private boolean rowWinner() {
for (int i = 0; i < 3; i++) {
String mark = button[3*i].getText();
if (mark.equals(button[3*i+1].getText()) &&
mark.equals(button[3*i+2].getText()) {
return true;
}
}
return false;
}
or
X - - - - X
- X - or - X -
- - X X - -
private boolean diagWinner() {
String mark = button[4].getText();
return
(mark.equals(button[0].getText()) && mark.equals(button[8].getText()) ||
(mark.equals(button[2].getText()) && mark.equals(button[6].getText());
}
This naive approach checks all possible win conditions, which isn't really necessary if you are checking for wins after each turn. You only need to check the conditions for:
the row the new mark was made
the col the new mark was made
one diagonal if the mark is in a corner or both diagonals if the mark is in the center.
I'll leave it to you to figure that out.
First I will answer your question, but judging by your code (or lack thereof), I will then address some other things I think you should be aware of as a Java programmer working with Graphical User Interfaces (GUIs) and Java Swing.
Part 1: The Answer
There are two approaches I can think of to solve this.
The following code uses a two-dimensional array of pieces to represent the 3x3 board of JButtons (note sure why you don't use a 2D array, actually very confused on why you don't). Additionally, it assumed that the text of all JButtons is initially set to "." since this is much easier than checking if the text is one of 9 different string numbers.
Approach A: Static Cases
Since the board is so small, it's feasible to simply check for each of the cases where a player would win the tic tac toe game and verify if one of them is true. The following graphic illustrates the eight cases that result in a winning outcome for a player.
Note that "O" can just as easily be substituted for "X" below, the important thing is that each one belongs to the same player. Additionally, any "." marks are just placeholders, as it doesn't matter whether this actually represents "X," "O," or "null" on the board.
// Case 1
// if each location across the top row is not empty
if (board[0][0].getText() != "." && board[0][1].getText() != "." && board[0][2].getText() != ".") {
// if each location has the same text
if (board[0][0].getText() == board[0][1].getText() &&
board[0][0].getText() == board[0][2].getText()) {
// if the player is X then X is winner, else player is O and O is winner
if (board[0][0].player() == Player.X)
return Status.X_WINNER;
else if (board[0][0].player() == Player.O)
return Status.O_WINNER;
}
}
This can then be repeated seven times to achieve our goal. However, this is a lot of repetitive code, and clever programmers will attempt to avoid this when possible.
But, there's also the case of a tie or "cat's game" in tic tac toe, and how do we address this? Well, if there are no winning cases present AND the board is full of pieces, then we have a stalemate.
Approach B: Dynamic Checking
I'll admit, this method is a behemoth and I'm sure it could use some smart refactoring, but it's functional and solves the problem dynamically. There are many conditionals to try and make the algorithm more efficient by only continuing when absolutely necessary.
Note that I check the surrounding neighbors of a piece, which is critical for properly checking if a diagonal has won the game.
// track if game won
boolean won = false;
// constant for board width and height
int BOARD_SIZE = 3;
// track pieces on board
int numPieces = 0;
// track who won
String winner = "";
// loop through the board first time
for (int row1 = 0; row1 < board.length; row1++) {
for (int col1 = 0; col1 < board.length; col1++) {
// if piece exists here
if (board[row1][col1].getText() != ".") {
// increment number of pieces on board
numPieces++;
// check pieces around first piece
for (int row2 = row1 - 1; row2 <= row1 + 1; row2++) {
for (int col2 = col1 - 1; col2 <= col1 + 1; col2++) {
// ensure within bounds of board
if ((row2 >= 0 && row2 < BOARD_SIZE) && (col2 >= 0 && col2 < BOARD_SIZE)) {
// ignore checking with first piece (itself)
if (board[row2][col2] != board[row1][col1]) {
// if second piece equal to first piece
if (board[row2][col2].getText() == board[row1][col1].getText()) {
// check pieces around second piece
for (int row3 = row2 - 1; row3 <= row2 + 1; row3++) {
for (int col3 = col2 - 1; col3 <= col2 + 1; col3++) {
// ensure within bounds of board
if ((row3 >= 0 && row3 < BOARD_SIZE) && (col3 >= 0 && col3 < BOARD_SIZE)) {
// ignore checking pieces we already have
if (board[row3][col3] != board[row2][col2] && board[row3][col3] != board[row1][col1]) {
// if third piece equal to first piece (and so also equal to second)
if (board[row3][col3].getText() == board[row1][col1].getText()) {
// if three pieces are all on same row
if (row1 == row2 && row1 == row3) {
if (board[row1][col1].getText() == "X")
winner = "X";
else
winner = "O";
won = true;
break;
}
// else if three pieces are all on same column
else if (col1 == col2 && col1 == col3) {
if (board[row1][col1].getText() == "X")
winner = "X";
else
winner = "O";
won = true;
break;
}
// else if three pieces are all on different rows and columns (winning diagonal)
else if ((row1 != row2 && row1 != row3 && row2 != row3) && (col1 != col2 && col1 != col3 && col2 != col3)) {
if (board[row1][col1].getText() == "X")
winner = "X";
else
winner = "O";
won = true;
break;
}
}
}
}
}
}
}
}
}
}
}
}
}
}
if (winner == "X") {
JOptionPane.showMessageDialog(null, "X wins");
}
else if (winner == "O") {
JOptionPane.showMessageDialog(null, "O wins");
}
// if board is full and hasn't resulted in any winners
if (!won && numPieces == BOARD_SIZE * BOARD_SIZE)
JOptionPane.showMessageDialog(null, "Cats game");
Of course, less lines of code do not necessarily guarantee better performance, as we are again lucky that this is such a small board. Looping through multiple times (i.e. brute force approach) like this on a large board would spell disastrous run times, so this is another design choice to consider.
Part 2: Going Further
I don't think this can really be all your code, as your provided code can't be executed without a main method.
Additionally, if you're extending a "Board" class, you must have written your own since Java doesn't come with such a class.
Here are some things you should be aware of as a Java Swing GUI programmer.
A. Java Swing
You don't seem to have a strong grasp on Java Swing, so here's an introductory tutorial to start you off.
B. Layout Managers
Layout managers can be your friend but also your enemy when trying to configure your GUI layout. Here's a good resource for your exploration.
C. Model-View-Controller (MVC)
Decoupling dependencies is key to future management of large code bases. MVC is a popular software architectural pattern that helps reduce dependencies when dealing with user interfaces. Check this out.
D. My Implementation
You inspired me to work on my own Java Swing implementation of tic-tac-toe. Here it is!
Cheers and happy coding!

Categories