First attempt at TicTac

Started by
16 comments, last by Reservoir Saint 13 years, 9 months ago
So here is my first attempt at my TicTacToe game! its not the best but its a start, other than the winCheck method, is there another way i should have approached this?

  import java.util.Scanner;    public class TicTac{       public static void main(String[] args){         Scanner input = new Scanner(System.in);         char[][] tGrid  = new char[3][3];         for(int i = 0; i < tGrid.length; i++)            for(int j = 0; j < tGrid.length; j++)               tGrid[j] = '*';         boolean whoTurn = whoFirst();         boolean win = false;         while(!win){            printG(tGrid);            if(winCheck(tGrid,whoTurn)){               System.out.println("Tic Tac Toe Biaaaatch!");               win = true;            }            else{               if(whoTurn) System.out.println("x's turn");               else System.out.println("o's turn");               System.out.println("Enter the row you want it in?");               int row = input.nextInt();               System.out.println("Enter the column you want it in?");               int col = input.nextInt();               if(whoTurn){                  if(isTaken(tGrid, row, col)){                     System.out.println("that space is already taken!!!");                     continue;                  }                  tGrid[row][col] = 'x';                  whoTurn = false;               }               else{                  if(isTaken(tGrid,row,col)){                     System.out.println("that space is already taken!!!");                     continue;                  }                  tGrid[row][col] = 'O';                  whoTurn = true;               }                }         }      }       public static void printG(char[][] grid){         for(int i = 0; i < grid.length; i++){            for(int j = 0; j < grid.length; j++){               System.out.print(grid[j] + " ");            }            System.out.println();         }      }       public static boolean whoFirst(){         int randNum = (int)(Math.random() * 10);         if(randNum < 5)            return true;         else             return false;      }       public static boolean isTaken(char grid[][],int row, int col){         if(grid[row][col] != '*')             return true;         else             return false;      }       public static boolean winCheck(char grid[][], boolean checkPlayer){         if(!checkPlayer){            if(grid[0][0] == 'x' && grid[0][1] == 'x' && grid[0][2] == 'x')                return true;            else if(grid[1][0] == 'x' && grid[1][1] == 'x' && grid[1][2] == 'x')                return true;            else if(grid[2][0] == 'x' && grid[2][1] == 'x' && grid[2][2] == 'x')                return true;            else if(grid[0][0] == 'x' && grid[1][0] == 'x' && grid[2][0] == 'x')                return true;            else if(grid[0][1] == 'x' && grid[1][1] == 'x' && grid[2][1] == 'x')                return true;            else if(grid[0][2] == 'x' && grid[1][2] == 'x' && grid[2][2] == 'x')                return true;            else if(grid[0][0] == 'x' && grid[1][1] == 'x' && grid[2][2] == 'x')                return true;            else if(grid[2][1] == 'x' && grid[1][1] == 'x' && grid[0][2] == 'x')                return true;            else                return false;         }         else{            if(grid[0][0] == 'O' && grid[0][1] == 'O' && grid[0][2] == 'O')                return true;            else if(grid[1][0] == 'O' && grid[1][1] == 'O' && grid[1][2] == 'O')                return true;            else if(grid[2][0] == 'O' && grid[2][1] == 'O' && grid[2][2] == 'O')                return true;            else if(grid[0][0] == 'O' && grid[1][0] == 'O' && grid[2][0] == 'O')                return true;            else if(grid[0][1] == 'O' && grid[1][1] == 'O' && grid[2][1] == 'O')                return true;            else if(grid[0][2] == 'O' && grid[1][2] == 'O' && grid[2][2] == 'O')                return true;            else if(grid[0][0] == 'O' && grid[1][1] == 'O' && grid[2][2] == 'O')                return true;            else if(grid[2][1] == 'O' && grid[1][1] == 'O' && grid[0][2] == 'O')                return true;            else                return false;         }      }   }
-When in doubt, Whip it out!-
Advertisement
There are a few places where you can make the code shorter, usually by removing duplication. For example, here:

               if(whoTurn){                  if(isTaken(tGrid, row, col)){                     System.out.println("that space is already taken!!!");                     continue;                  }                  tGrid[row][col] = 'x';                  whoTurn = false;               }               else{                  if(isTaken(tGrid,row,col)){                     System.out.println("that space is already taken!!!");                     continue;                  }                  tGrid[row][col] = 'O';                  whoTurn = true;               }


You can shorten this to:

if(isTaken(tGrid, row, col)){    System.out.println("that space is already taken!!!");    continue;}tGrid[row][col] = whoTurn ? 'x' : 'O';whoTurn = !whoTurn;  // This will toggle between true and false


Also, this:

         if(randNum < 5)            return true;         else             return false;


can be shortened to:

return randNum < 5;

The same can be done inside isTaken().

You can cleanup winCheck() in several steps. First, you can do something similar to what I did above:

public static boolean winCheck(char grid[][], boolean checkPlayer){    char move = checkPlayer ? 'x' : 'O';    if(grid[0][0] == move  && grid[0][1] == move  && grid[0][2] == move )    // etc.


This cuts the code size in half.

Then you can create helper methods to check one row/column in the board, and call those 3 times in a loop:

for (int i = 0; i < 3; ++i) {    if (checkRow(i, move)) return true;    if (checkCol(i, move)) return true;}


Finally, I would split up the main() method a bit, like creating an init() method to do the initialization, a readMove() method, and possibly a makeMove() method.

EDIT: Made a minor correction.

[Edited by - Gage64 on July 12, 2010 11:47:36 AM]
Thanks alot! im workin on the fixes as we speak, i had a question on "creating an init() method to do the initialization, a readMove() method, and possibly a makeMove() method."

i dont know what exactly would go into these methods?
init() // would this be like initializing the board?
readMove() //getting the players input?
makeMove() // i really don't know about this one?

thanks again!
-When in doubt, Whip it out!-
Heyyy,

With regard to the "makeMove()" function, I believe that the idea was that you keep all logic regarding actually setting the grid positions for X or O in a seperate function.

So perhaps most of:

if(whoTurn) System.out.println("x's turn");               else System.out.println("o's turn");               System.out.println("Enter the row you want it in?");               int row = input.nextInt();               System.out.println("Enter the column you want it in?");               int col = input.nextInt();               if(whoTurn){                  if(isTaken(tGrid, row, col)){                     System.out.println("that space is already taken!!!");                     continue;                  }                  tGrid[row][col] = 'x';                  whoTurn = false;               }               else{                  if(isTaken(tGrid,row,col)){                     System.out.println("that space is already taken!!!");                     continue;                  }                  tGrid[row][col] = 'O';                  whoTurn = true;               }                }


could be put into a seperate function called makeMove()?

Well done though, that's alot cleaner than my first Tic Tac Toe game =P

Ollie.

[EDIT] sorted out my code tags ^^
how are you gonna do the ai?

I just did a random number generator on mine. ;o
They hated on Jeezus, so you think I give a f***?!
@ollyb342: Ya I think I see what what your saying, and with that ive got another noobish question, but is the object of making all these methods ie init(),readMove() just to make the code more readable?

@Fl4sh: im gonna try that next :)

thanx all!


-When in doubt, Whip it out!-
Quote:Original post by Reservoir Saint
@ollyb342: Ya I think I see what what your saying, and with that ive got another noobish question, but is the object of making all these methods ie init(),readMove() just to make the code more readable?

@Fl4sh: im gonna try that next :)

thanx all!


Yes they are to make your code more readable. You may not see the point in this for a small program but it is still good practice to do so as it gets you thinking about how to encapsulate your code properly which is what object oriented programming is all about.

Now to completely contradict myself and just for fun I tried to rewrite your tictactoe in as few lines as possible. I wonder can anyone make it in less code? Winner gets a cookie :-)

import java.util.Scanner;public class TicTac{	public static void main(String[] args){		Scanner input = new Scanner(System.in);		char[][] tGrid  = {{'*','*','*'},{'*','*','*'},{'*','*','*'}};		boolean whoTurn = true, win = false;		while(!win){			for(int i = 0; i < 9; System.out.print(tGrid[i%3][i/3] + " " + (++i%3==0 ? "\n" : "")));			if(winCheck(tGrid,whoTurn)){				System.out.println("Tic Tac Toe Biaaaatch!");				win = true;			}			else{				System.out.println((whoTurn ? "x" : "y") + "'s turn\nEnter the row you want it in?");				int row = input.nextInt();				System.out.println("Enter the column you want it in?");				int col = input.nextInt();				if(tGrid[row][col] != '*'){					System.out.println("that space is already taken!!!");					continue;				}				tGrid[row][col] = (whoTurn ? 'X' : 'O') ;				whoTurn = !whoTurn;			}		}	}	public static boolean winCheck(char grid[][], boolean checkPlayer){		char m = checkPlayer ? 'O' : 'X';		for(int i=0;i<3;i++)		{			if(grid[0] == m && grid[1] == m && grid[2] == m)				return true;			else if(grid[0] == m && grid[1] == m && grid[2] == m)				return true;		}		return  (grid[0][0] == m && grid[1][1] == m && grid[2][2] == m) ||				(grid[2][1] == m && grid[1][1] == m && grid[0][2] == m);	}}


[Edited by - clearz on July 11, 2010 2:11:42 PM]
I managed to get it down to 22 lines by cutting it down to just enough code to play a game and streamlining it some more

public class TicTac {	static char[][] grid  = { { '*', '*','*' }, { '*', '*', '*' }, { '*', '*', '*' } };	public static void main( String[] args ) {		java.util.Scanner input = new java.util.Scanner( System.in );		boolean whoTurn = true, win = false;		while( !win ) {			for( int i = 0; i < 9; System.out.print( grid[i%3][i/3] + " " + ( ++i % 3 == 0 ? "\n" : "" ) ) );			if( ( win = winCheck( ( whoTurn ? 'O' : 'X' ) ) ) )				System.out.println("Tic Tac Toe Biaaaatch! " + ( whoTurn ? "O" : "X" ) + " wins.");			else {				System.out.println( ( whoTurn ? "X" : "O" ) + "'s turn\nEnter the row and col you want it in?" );				grid[input.nextInt()][input.nextInt()] = ( ( whoTurn = !whoTurn ) ? 'O' : 'X' ) ;			}		}	}	public static boolean winCheck(char m) {		for(int i=0;i<3;i++)			if( ( grid[0] == m && grid[1] == m && grid[2] == m ) || ( grid[0] == m && grid[1] == m && grid[2] == m ) )				return true;		return  ( grid[0][0] == m && grid[1][1] == m && grid[2][2] == m ) || ( grid[2][0] == m && grid[1][1] == m && grid[0][2] == m );	}}
Thanx clearz, and I believe you beat yourself in your own challenge! I was also checking out your winCheck methods, i like em both, but is one faster than the other at checking?
-When in doubt, Whip it out!-
I believe they both would be the same. In the second example I think that java would not bother checking if the second group of vars is true or false if everything before the || is true because it doesn't need to.

This topic is closed to new replies.

Advertisement