Shazer2
Junior Member   Medals: 3
Aspiring developer.
|
 |
«
Posted
2012-01-03 04:12:11 » |
|
I designed a TicTacToe console game, and I'm trying to figure out how to check if somebody has one. My current code for the game is below. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| package tictactoe;
import java.util.Scanner;
public class TicTacToe { private String[][] board = new String[3][3]; private String turn = "O"; private int turns = 0; public void gameLoop() { for (int y = 0; y < 3; y++) { board[y][0] = " "; board[y][1] = " "; board[y][2] = " "; for (int x = 0; x < 3; x++) { board[0][x] = " "; board[1][x] = " "; board[2][x] = " "; } } while (true) { try { Scanner scan = new Scanner(System.in); System.out.println(" | | "); System.out.println(" " + board[0][0] + " | " + board[0][1] + " | " + board[0][2] + " "); System.out.println("______|______|______"); System.out.println(" | | "); System.out.println(" " + board[1][0] + " | " + board[1][1] + " | " + board[1][2] + " "); System.out.println("______|______|______"); System.out.println(" | | "); System.out.println(" " + board[2][0] + " | " + board[2][1] + " | " + board[2][2] + " "); System.out.println(" | | "); if (turns != 9) { if (scan.hasNextInt()) { int input = scan.nextInt(); if (!board[input/3][input%3].equals(" ")) { System.out.println("Place already taken."); } else { board[input/3][input%3] = turn; turn(); } } } else if (turns == 9) { System.out.println(checkWin()); System.exit(0); } } catch (Exception ex) { ex.printStackTrace(); } } } public String turn() { if (turn == "O") { setTurns(getTurns() + 1); return turn = "X"; } setTurns(getTurns() + 1); return turn = "O"; }
public String checkWin() { } public int getTurns() { return turns; }
public void setTurns(int turns) { this.turns = turns; } } |
I'm not sure how to check for the win, all I know is that I will need to loop through the board array to check if there is 3 in a row horizontally, vertically or diagonally. ~Shazer2
|
"When you want to be successful as bad as you want to breathe, then you will be successful." - Eric Thomas
|
|
|
Riven
|
 |
«
Reply #1 - Posted
2012-01-03 04:37:48 » |
|
On a sidenote: this is extremely dangerous: as for example 1 2 3
| "O" != "OO".substring(0,1) "O" != ""+"O" "O" != "o".toUpperCase() |
because they are equal in contents but different objects. to reliably check strings for equality, you must use
|
|
|
|
Shazer2
Junior Member   Medals: 3
Aspiring developer.
|
 |
«
Reply #2 - Posted
2012-01-03 04:40:10 » |
|
Ah, I'll fix that up. Thanks Riven. Any idea on checking the winner?
~Shazer2
|
"When you want to be successful as bad as you want to breathe, then you will be successful." - Eric Thomas
|
|
|
Games published by our own members! Check 'em out!
|
|
Riven
|
 |
«
Reply #3 - Posted
2012-01-03 05:40:04 » |
|
there are 3+3+2 ways to win: 3x horizontal, 3x vertical, 2x diagonal so first you need to check whether all strings in the 3 horizontal/vertical lines are equal: using: board[ y ][ x ] 1 2 3 4 5 6 7
| lineH0 = board[0][0].equals(board[0][1]) && board[0][0].equals(board[0][2]); lineH1 = board[1][0].equals(board[1][1]) && board[1][0].equals(board[1][2]); lineH2 = board[2][0].equals(board[2][1]) && board[2][0].equals(board[2][2]);
lineV0 = board[0][0].equals(board[0][0]) && board[0][0].equals(board[2][0]); lineV1 = board[0][1].equals(board[0][1]) && board[0][1].equals(board[2][1]); lineV2 = board[0][2].equals(board[0][2]) && board[0][2].equals(board[2][2]); |
you can see the repetition here... so let's write a loop: 1 2 3 4 5
| for(int i=0; i<3; i++) { boolean h = board[i][0].equals(board[i][1]) && board[i][0].equals(board[i][2]); boolean v = board[0][i].equals(board[1][i]) && board[0][i].equals(board[2][i]); } |
etc etc etc Adding a check for diagonal is simple, just like adding the check that it's not an empty line.
|
|
|
|
Riven
|
 |
«
Reply #4 - Posted
2012-01-03 05:47:56 » |
|
As you can see, you mixed 'visuals' and 'logic' and it is going to be extremely annoying to code with all these strings. Why don't you make board an int[][] and make the empty cells 0, and the players: 1 & 2 Suddenly your code would become a lot more readable: 1 2 3 4 5
| for(int i=0; i<3; i++) { boolean h = board[i][0]==board[i][1] && board[i][0]==board[i][2]; boolean v = board[0][i]==board[1][i] && board[0][i]==board[2][i]; } |
when you visualize the board, you simply write: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| private String getLabelForPlayer(int p) { if(p == 1) return "X"; if(p == 2) return "O"; throw new IllegalArgumentException("ehmpf"); }
private String getLabelForCell(int x, int y) { int cell = board[y][x]; if(cell == 0) return " "; return getLabelForPlayer(cell); }
private void drawBoardRow(int y) { System.out.println(" " + getLabelForCell(0,y) + " | " + getLabelForCell(1,y) + " | " + getLabelForCell(2,y) + " "); }
private void drawBoard() { System.out.println(" | | "); drawBoardRow(0); System.out.println("______|______|______"); drawBoardRow(1); System.out.println("______|______|______"); drawBoardRow(2); System.out.println(" | | "); } |
|
|
|
|
Shazer2
Junior Member   Medals: 3
Aspiring developer.
|
 |
«
Reply #5 - Posted
2012-01-03 06:57:52 » |
|
I know how my code works though, but I do need to optimize in future if I want to get anywhere. I'll see if I can take that win check code in. Thanks.
Also, I understand that boolean check if iterating through each cell on the board, but how do we determine who has the pieces there? This is very confusing for me, sorry I might need some extra explanation if you're willing to help.
~Shazer2
|
"When you want to be successful as bad as you want to breathe, then you will be successful." - Eric Thomas
|
|
|
ra4king
|
 |
«
Reply #6 - Posted
2012-01-03 09:20:56 » |
|
How about you make checkWin() return either 0 for tie, 1 for X and 2 for O? Then inside the for loop: 1 2 3 4 5 6 7 8 9 10 11 12 13
| for(int i = 0; i < 3; i++) { boolean h = ... boolean v = ... if(h) return board[i][0]; if(v) return board[0][i]; }
return 0; |
|
|
|
|
Shazer2
Junior Member   Medals: 3
Aspiring developer.
|
 |
«
Reply #7 - Posted
2012-01-03 09:23:43 » |
|
So I either need to make board an int, or return a string for 0 instead.
~Shazer2
|
"When you want to be successful as bad as you want to breathe, then you will be successful." - Eric Thomas
|
|
|
ra4king
|
 |
«
Reply #8 - Posted
2012-01-03 09:30:26 » |
|
If you still want to use Strings, make it return "0".
|
|
|
|
Shazer2
Junior Member   Medals: 3
Aspiring developer.
|
 |
«
Reply #9 - Posted
2012-01-03 09:32:20 » |
|
Ah yes. Now, how do I tell who has 3 lined up? As of now it only really returns whether one or the other is lined up vertically or horizontally.
~Shazer2
|
"When you want to be successful as bad as you want to breathe, then you will be successful." - Eric Thomas
|
|
|
Games published by our own members! Check 'em out!
|
|
ra4king
|
 |
«
Reply #10 - Posted
2012-01-03 09:33:43 » |
|
if(checkWin().equals("X")) .... x wins else if(checkWin().equals("O")) .... o wins else .... tie
|
|
|
|
Shazer2
Junior Member   Medals: 3
Aspiring developer.
|
 |
«
Reply #11 - Posted
2012-01-03 09:37:23 » |
|
Alright, now what about diagonals?  ~Shazer2
|
"When you want to be successful as bad as you want to breathe, then you will be successful." - Eric Thomas
|
|
|
ra4king
|
 |
«
Reply #12 - Posted
2012-01-03 09:40:11 » |
|
You're checking each separately. They should be easy enough if you think about it 
|
|
|
|
ReBirth
|
 |
«
Reply #13 - Posted
2012-01-03 10:49:08 » |
|
Repeat Riven's way for diagonal. Write them in stupid way and see the pattern of... index number for example... then turn into loop. I never try to create board game though.
and I'm here not to stalk you ra4king. geez.
|
|
|
|
Shazer2
Junior Member   Medals: 3
Aspiring developer.
|
 |
«
Reply #14 - Posted
2012-01-03 10:52:08 » |
|
Yay, I got it to work.
Many thanks to ra4king and Riven.
~Shazer2
|
"When you want to be successful as bad as you want to breathe, then you will be successful." - Eric Thomas
|
|
|
sproingie
|
 |
«
Reply #15 - Posted
2012-01-03 20:35:21 » |
|
X is 1, O is 0, the board is a nine bit int. Write a bitmask for each win condition and test that the bitwise AND of the condition and the board XOR the mask is zero.
That's if I wanted to be clever. Truth is, I'd just hardwire the logic with some 'if' statements.
|
|
|
|
|
Riven
|
 |
«
Reply #16 - Posted
2012-01-03 20:53:42 » |
|
X is 1, O is 0, the board is a nine bit int. Each cell has three possible states  You can only use this approach by setting 1 = current player & 0 = anything else, and unleach your bitmasks on that. If I were to do it, it would do it totally different, properly, with a Player class, etc.
|
|
|
|
ra4king
|
 |
«
Reply #17 - Posted
2012-01-03 20:55:23 » |
|
Using OO with tic-tac-toe = overkill 
|
|
|
|
Riven
|
 |
«
Reply #18 - Posted
2012-01-03 20:56:06 » |
|
Using OO with tic-tac-toe = overkill  Unless you want to get the job done and get a good grade (if applicable).
|
|
|
|
ra4king
|
 |
«
Reply #19 - Posted
2012-01-03 20:58:50 » |
|
Blegh, school assignments.... 
|
|
|
|
counterp
|
 |
«
Reply #20 - Posted
2012-01-03 21:54:47 » |
|
you don't necessarily win in 9 turns
|
|
|
|
|
Riven
|
 |
«
Reply #21 - Posted
2012-01-03 22:42:17 » |
|
you don't necessarily win in 9 turns
nobody claimed that
|
|
|
|
ra4king
|
 |
«
Reply #22 - Posted
2012-01-03 22:52:56 » |
|
Good eye! 
|
|
|
|
Shazer2
Junior Member   Medals: 3
Aspiring developer.
|
 |
«
Reply #23 - Posted
2012-01-04 02:41:38 » |
|
Well 9 squares = 9 moves doesn't it? :/ Unless I'm mistaken.
~Shazer2
|
"When you want to be successful as bad as you want to breathe, then you will be successful." - Eric Thomas
|
|
|
Riven
|
 |
«
Reply #24 - Posted
2012-01-04 02:43:51 » |
|
That all the cells are filled, doesn't mean there is a winner, it can be a tie. In the same way, you can win when there are less than 9 cells filled, so you have to call you checkWin( ) method after every turn, not after 9 turns.
|
|
|
|
loom_weaver
|
 |
«
Reply #25 - Posted
2012-01-04 03:17:07 » |
|
Using OO with tic-tac-toe = overkill  OOX ... take that!
|
|
|
|
|
Shazer2
Junior Member   Medals: 3
Aspiring developer.
|
 |
«
Reply #26 - Posted
2012-01-04 03:27:22 » |
|
That's true, Riven. I'm having a problem, I dropped in my win check after each turn and now when I do check the win (place the final mark in a row of 3) it checks the win, before it's placed (redraw of board). So I am checking the win correctly but it is checking the win before the final piece is drawn to the board. The board is drawn BEFORE the last move. EDIT: I fixed the drawing issue. Now, when checking for a tie or win I have the following check. 1 2 3 4 5 6 7 8 9 10 11 12
| public void actualCheckWin() { if (checkWin().equals("X")) { System.out.println("X wins!"); System.exit(0); } else if (checkWin().equals("O")) { System.out.println("O wins!"); System.exit(0); } else { System.out.println("It's a tie!"); System.exit(0); } } |
The else gets called straight away on the first move. I'm not sure why. ~Shazer2
|
"When you want to be successful as bad as you want to breathe, then you will be successful." - Eric Thomas
|
|
|
ra4king
|
 |
«
Reply #27 - Posted
2012-01-04 14:43:28 » |
|
Try 1 2 3
| else if(turns == 9) { } |
|
|
|
|
Shazer2
Junior Member   Medals: 3
Aspiring developer.
|
 |
«
Reply #28 - Posted
2012-01-04 22:06:46 » |
|
Ah good point, because I just assumed I didn't need that variable anymore and removed it conpletely. However I shall re-add it when I get home.
|
"When you want to be successful as bad as you want to breathe, then you will be successful." - Eric Thomas
|
|
|
ReBirth
|
 |
«
Reply #29 - Posted
2012-01-05 12:39:01 » |
|
What variable? you meant "turns"? although if it's not matter on logic, I think it's good to show it for player 
|
|
|
|
|