Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (513)
Games in Android Showcase (120)
games submitted by our members
Games in WIP (577)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  TicTacToe -- Check winner?  (Read 5591 times)
0 Members and 1 Guest are viewing this topic.
Offline Shazer2

Junior Duke


Medals: 3


Aspiring developer.


« Posted 2012-01-03 03: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
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 816
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #1 - Posted 2012-01-03 03:37:48 »

On a sidenote: this is extremely dangerous:
1  
if (turn == "O") {

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
1  
if(turn.equals("O"))

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline Shazer2

Junior Duke


Medals: 3


Aspiring developer.


« Reply #2 - Posted 2012-01-03 03: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!
Legends of Yore - The Casual Retro Roguelike
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 816
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #3 - Posted 2012-01-03 04: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]);
   // if H or V is true, we have a row/column with the same chars - that means either a winner, or they are all empty
}

etc etc etc

Adding a check for diagonal is simple, just like adding the check that it's not an empty line.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 816
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #4 - Posted 2012-01-03 04: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];
   // if H or V is true, we have a row/column with the same ints - that means either a winner, or they are all zero
}


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("      |      |      ");
}

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline Shazer2

Junior Duke


Medals: 3


Aspiring developer.


« Reply #5 - Posted 2012-01-03 05: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
Offline ra4king

JGO Kernel


Medals: 350
Projects: 3
Exp: 5 years


I'm the King!


« Reply #6 - Posted 2012-01-03 08: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];
}

//Check for diagonals here

return 0;

Offline Shazer2

Junior Duke


Medals: 3


Aspiring developer.


« Reply #7 - Posted 2012-01-03 08: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
Offline ra4king

JGO Kernel


Medals: 350
Projects: 3
Exp: 5 years


I'm the King!


« Reply #8 - Posted 2012-01-03 08:30:26 »

If you still want to use Strings, make it return "0".

Offline Shazer2

Junior Duke


Medals: 3


Aspiring developer.


« Reply #9 - Posted 2012-01-03 08: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!
Legends of Yore - The Casual Retro Roguelike
Offline ra4king

JGO Kernel


Medals: 350
Projects: 3
Exp: 5 years


I'm the King!


« Reply #10 - Posted 2012-01-03 08:33:43 »

if(checkWin().equals("X"))
    .... x wins
else if(checkWin().equals("O"))
    .... o wins
else
    .... tie

Offline Shazer2

Junior Duke


Medals: 3


Aspiring developer.


« Reply #11 - Posted 2012-01-03 08:37:23 »

Alright, now what about diagonals? Sad

~Shazer2

"When you want to be successful as bad as you want to breathe, then you will be successful." - Eric Thomas
Offline ra4king

JGO Kernel


Medals: 350
Projects: 3
Exp: 5 years


I'm the King!


« Reply #12 - Posted 2012-01-03 08:40:11 »

You're checking each separately.
They should be easy enough if you think about it Wink

Offline ReBirth
« Reply #13 - Posted 2012-01-03 09: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.

Offline Shazer2

Junior Duke


Medals: 3


Aspiring developer.


« Reply #14 - Posted 2012-01-03 09: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
Offline sproingie

JGO Kernel


Medals: 202



« Reply #15 - Posted 2012-01-03 19: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.


Offline Riven
« League of Dukes »

JGO Overlord


Medals: 816
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #16 - Posted 2012-01-03 19:53:42 »

X is 1, O is 0, the board is a nine bit int.
Each cell has three possible states Cranky

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.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline ra4king

JGO Kernel


Medals: 350
Projects: 3
Exp: 5 years


I'm the King!


« Reply #17 - Posted 2012-01-03 19:55:23 »

Using OO with tic-tac-toe = overkill Tongue

Offline Riven
« League of Dukes »

JGO Overlord


Medals: 816
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #18 - Posted 2012-01-03 19:56:06 »

Using OO with tic-tac-toe = overkill Tongue
Unless you want to get the job done and get a good grade (if applicable).

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline ra4king

JGO Kernel


Medals: 350
Projects: 3
Exp: 5 years


I'm the King!


« Reply #19 - Posted 2012-01-03 19:58:50 »

Blegh, school assignments.... persecutioncomplex

Offline counterp

Senior Duke


Medals: 11



« Reply #20 - Posted 2012-01-03 20:54:47 »

you don't necessarily win in 9 turns
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 816
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #21 - Posted 2012-01-03 21:42:17 »

you don't necessarily win in 9 turns
nobody claimed that

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline ra4king

JGO Kernel


Medals: 350
Projects: 3
Exp: 5 years


I'm the King!


« Reply #22 - Posted 2012-01-03 21:52:56 »

Good eye! Smiley

Offline Shazer2

Junior Duke


Medals: 3


Aspiring developer.


« Reply #23 - Posted 2012-01-04 01: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
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 816
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #24 - Posted 2012-01-04 01: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.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline loom_weaver

JGO Coder


Medals: 17



« Reply #25 - Posted 2012-01-04 02:17:07 »

Using OO with tic-tac-toe = overkill Tongue

OOX ... take that!
Offline Shazer2

Junior Duke


Medals: 3


Aspiring developer.


« Reply #26 - Posted 2012-01-04 02: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
Offline ra4king

JGO Kernel


Medals: 350
Projects: 3
Exp: 5 years


I'm the King!


« Reply #27 - Posted 2012-01-04 13:43:28 »

Try
1  
2  
3  
else if(turns == 9) {
    // tie!
}

Offline Shazer2

Junior Duke


Medals: 3


Aspiring developer.


« Reply #28 - Posted 2012-01-04 21: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
Offline ReBirth
« Reply #29 - Posted 2012-01-05 11: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 Wink

Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

Longarmx (52 views)
2014-10-16 18:59:02

Norakomi (42 views)
2014-10-16 06:22:06

Norakomi (32 views)
2014-10-16 06:20:20

lcass (37 views)
2014-10-15 07:18:58

TehJavaDev (68 views)
2014-10-13 15:39:48

TehJavaDev (66 views)
2014-10-13 15:35:47

TehJavaDev (59 views)
2014-10-13 15:32:37

BurntPizza (73 views)
2014-10-11 14:24:42

BurntPizza (45 views)
2014-10-11 14:10:45

BurntPizza (85 views)
2014-10-11 13:30:10
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 13:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 13:36:02

List of Learning Resources
by Longor1996
2014-08-16 01:40:00

List of Learning Resources
by SilverTiger
2014-08-05 10:33:27

Resources for WIP games
by CogWheelz
2014-08-01 07:20:17

Resources for WIP games
by CogWheelz
2014-08-01 07:19:50

List of Learning Resources
by SilverTiger
2014-07-31 07:29:50

List of Learning Resources
by SilverTiger
2014-07-31 07:26:06
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!