Welcome to the Java Programming Forums


The professional, friendly Java community. 21,500 members and growing!


The Java Programming Forums are a community of Java programmers from all around the World. Our members have a wide range of skills and they all have one thing in common: A passion to learn and code Java. We invite beginner Java programmers right through to Java professionals to post here and share your knowledge. Become a part of the community, help others, expand your knowledge of Java and enjoy talking with like minded people. Registration is quick and best of all free. We look forward to meeting you.


>> REGISTER NOW TO START POSTING


Members have full access to the forums. Advertisements are removed for registered users.

Results 1 to 4 of 4

Thread: Tic-Tac-Toe program problem help

  1. #1
    Junior Member
    Join Date
    Dec 2009
    Posts
    2
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default Tic-Tac-Toe program problem help

    Hello all, new to the forums and thought I'd ask some questions. Now I'm not new to Java (I've only taken a semester), but I haven't used it in a few years now. Though my friend approached me with an introductory program and asked if I could help him. I almost felt like embarking the whole program myself in one sitting, but I'm falling short on some issues. Here is the prompt for the Tic-Tac-Toe board game:

    http://www-rohan.sdsu.edu/~masc0500/LECS107/f09hw8.txt



    And here's my code SO FAR. Below that I'll try and explain what I'm essentially doing, method-by-method:



    [FONT="Courier New"]import sdsu.io.*;
    import java.util.Random;
     
    public class HW {
     
            /* array declarations */
        static int avail[] = new int[20];        // array of available board spaces
        static int user[] = new int[20];         // array of consumed user spaces
        static int ai[] = new int[20];           // array of consumed AI space
        static String Board[] = new String[20];  // array for game board
            /* variable declarations */
        static int x = 0;                        // user-selected space
        static int y = 0;                        // AI-selected space
        static int i = 0;                        // for "for" loops
        static int count = 0;                    // turn counter
            /* game declaration */
        static boolean game = false;             // until true, game continues
        static String name = "";                 // enter name when prompted
        static Random r = new Random();
     
        public static void main (String args []) {
                /* initialize arrays */
            for (i = 0; i < 10; i++) {
                avail[i] = i + 1;
                user[i] = 0;
                ai[i] = 0;
                Board[i] = "-";
                }
                /* Initial game prompt */
            System.out.println("Welcome to Tic Tac Toe!");
            System.out.println("");
            name = Console.readLine ("User, please enter a name: ");
            System.out.println("");
            System.out.print(name + " is X, CPU is O. ");
    	Console.readLine ("Press Enter to begin game.");
            System.out.println("");
            while (game == false) {    // game logic, play until true
                gameBoard();           // jump to game board method
                takeTurn(x);           // jump to take turn method for user
                count++;
    	    checkGame(x);          // checks if user one or Cat's game
    	    if (game == true) return;
                takeTurn(y);           // jump to take turn method for CPU
                count++;
    	    checkGame(y);          // checks if CPU won or cat's game
    	    if (game == true) return;
                }
            } // end main
     
        public static void gameBoard () {
            System.out.println(name + ", please choose an empty space.");
            System.out.println("");
            System.out.println(Board[0] + " " + Board[1] + " " + Board[2]);    // game board logic
            System.out.println(Board[3] + " " + Board[4] + " " + Board[5]);    // prints values if space is entered,
            System.out.println(Board[6] + " " + Board[7] + " " + Board[8]);    // else prints "-"
            System.out.println("");
            System.out.print("Available empty spaces: ");
                /* display available space */
            if (avail[1] != 0) System.out.println(avail[1]);
            for (i = 1; i < 8; i++) {                                          // lists which spaces are available
                if (avail[i] != 0) System.out.print(", " + avail[i]);
    	    else System.out.print("");
    	    }
            if (avail[8] != 0) System.out.println(avail[8]);
    	else System.out.println("");
            } // end gameBoard method
     
        public static void takeTurn (int turn) {
            if (turn == x) {                                // if user's turn read integer input
    	    x = Console.readInt();
                turn = x;
    	    if (turn > 9 || turn < 1) {
                    System.err.println("Out of range, please re-select.");
                    takeTurn(x);                            // recursive call
                    }
                }
            else {                                          // if AI's turn...
    	    System.out.println("");
    	    System.out.println("CPU will now select...");
    	    System.out.println("");
                if (avail[4] != 0) {                        // if AI's first turn
    	        y = 5;
    	        turn = y;
                    ai[0] = turn;
                    avail[4] = 0;                           // if middle space is empty, AI selects middle space
                    Board[4] = "O";
                    }
                else {
    	        // y = (int)Math.random() * 9 + 1; // generate random number for AI
    		y = r.nextInt(9) + 1;
    	        turn = y;
    		}
    	    }   
            while (avail[turn - 1] == 0) {                  // if space is occupied, try again
                if (turn == x) {                            // if user, re-prompt
                    x = Console.readInt("Space is unavailable. Please enter an empty space. ");
    		turn = x;
    		}
                else {
    	        // y = (int)Math.random() * 9 + 1;         // if AI, re-generate random number
    		y = r.nextInt(8) + 1;
    		turn = y;
    		}
                if (avail[turn - 1] != 0) break;           // if space is unoccupied, proceed
                }
            if (avail[turn - 1] == turn && avail[turn] != 0) {  // if space hasn't been taken,
                for (i = 0; i < 9; i++) {
                    if (turn == x) {
                        if (user[i] == 0) user[i] = turn;       // add to user list
                        }
                    else {
                        if (ai[i] == 0) ai[i] = turn;
                        }
                    }
                avail[turn - 1] = 0;
                if (turn == x) Board[turn - 1] = "X";           // mark board space with "X"
                else Board[turn - 1] = "O";                     // mark board space with "O"
                }
            } // end takeTurn method
     
        public static void checkGame (int turn) {
            if (turn == x) {                                    // user's turn
    	    // if user wins, end game
    	    }
            else {                                              // AI's turn
    	    // if CPU wins, end game
    	    }
            if (count == 9) {
    	    System.out.println("");
    	    System.out.println("CAT'S GAME!");
    	    game = true;
    	    }	
            }
     
        } // end of file[/FONT]



    Okay, so I tried to be fancy and have it so that when his program runs, it does some of the initial things like entering your name and such. As the prompt says, a user inputs a value 1 - 9 and it should put an X in that spot if it's not occupied. So most of my logic is within my takeTurn(type int) method, where the list of available spaces to choose from are in an array. If the value is chosen, that place in the array is set to 0. Now on the first turn, the CPU will take the middle if it's not already taken.

    After that, if the CPU (who picks a random number from 1 - 9 otherwise) chooses a value whose place in the array is zero, it needs to pick another random number until it finds one that's the actual value. Same with the user, only the user needs to keep inputting different numbers until it finds an available one. Only I'm getting many strange output issues. Let me show you an example (keep in mind I haven't done any logic yet for 3 in a row, so it only ends if there's a Cat's game:


    output
    [FONT="Courier New"]Welcome to Tic Tac Toe!
     
    User, please enter a name:  Brandon
     
    Brandon is X, CPU is O. Press Enter to begin game. 
     
    Brandon, please choose an empty space.
     
    - - -
    - - -
    - - -
     
    Available empty spaces: 1, 2, 3, 4, 5, 6, 7, 8, 9
    1
     
    CPU will now select...
     
    Brandon, please choose an empty space.
     
    X - -
    - O -
    O - -
     
    Available empty spaces: 2, 3, 4, 6, 8, 9
    2
     
    CPU will now select...
     
    Brandon, please choose an empty space.
     
    X X -
    - O -
    O - -
     
    Available empty spaces: 3, 4, 6, 8, 9
    3
     
    CPU will now select...
     
    Brandon, please choose an empty space.
     
    X X X
    - O -
    O - -
     
    Available empty spaces: 4, 6, 8, 9
    4
     
    CPU will now select...
     
    Brandon, please choose an empty space.
     
    X X X
    - O -
    O O -
     
    Available empty spaces: 4, 6, 9
    6
     
    CAT'S GAME![/FONT]



    So the first issue that we see is that the CPU gets to enter two values in the beginning... first the 5 spot (avail[4]), then a random spot. I don't see how this is possible because I do a specific if-else statement that should block that from happening. Then the other issue is that somehow when I choose 4, it doesn't want to print the 4. I wonder if I'm doing something strangely and if someone can help me out with this one. I tried to leave as many comments as possible and I'm sure you guys can follow since you're probably all better at Java than me, but hey... this was just a first attempt. I haven't even tried to go back at it again but frankly I don't see the cause of the issue(s).

    Secondly, I need to create some logic for whether the user wins or the CPU wins. Unless someone knows a better way, I was just going to do something with the arrays, like if the array user[] contains (1,2,3) or (4,5,6) or (2,5,8), etc. Only I don't think the array class has a .contains method, so I wasn't sure if someone else had a better approach?

    If I'm going about this entire program incorrectly, just let me know haha, I tried to do my best through one run. Thanks for your help!

    - Brandon Robinson

    P.S. The "import.sdsu.io.*" is something available here at SDSU for the Console.readInt() commands, that's all.
    Last edited by MuffinMcFluffin; December 11th, 2009 at 11:43 PM.


  2. #2
    Member
    Join Date
    Aug 2009
    Posts
    53
    Thanks
    2
    Thanked 3 Times in 2 Posts

    Default Re: Tic-Tac-Toe program problem help

    Interesting problem, however I think you need to read a little about objects, and the usage of them. Everything here is static, which is a bad idea.

    You should break down you program into classes, and give each class a responsibility to fulfill, and then work with instances (objects) of those classes.

    Looking from you code I solution could be something like this:
    -A tile class which purpose it is to keep track of a tiles status. Is it owned by a player/cpu or free.
    -A gameboard class which purpose it is to keep track of the board itself.
    -A gamelogic class which purpose it is to do logical functionality take turn etc
    -A game class which controls flow.

    I will do a implementation myself, but without the console class. I will use scanner to handle console.

  3. #3
    Junior Member
    Join Date
    Dec 2009
    Posts
    2
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default Re: Tic-Tac-Toe program problem help

    Thank you, kind sir. I'm looking forward to seeing your implementation.

  4. #4
    Member
    Join Date
    Aug 2009
    Posts
    53
    Thanks
    2
    Thanked 3 Times in 2 Posts

    Default Re: Tic-Tac-Toe program problem help

    Ok here is a very rough draft, its very late here, and Im going to sleep. I will make improvements tomorrows, mainly adding comments etc. Its made according to outline from my previous post.

    It turned out quite different from the original code, mainly due to me preferring the ArrayList class to the fixed array structure.

    public class driver {
     
    	public static void main(String[] args) {
    		Game game = new Game();
    		game.start();
    	}
    }

    public class Game {
     
    	private Gameboard gb;
    	private GameLogic gl;
     
    	public Game(){
    		gb = new Gameboard();
    		gl = new GameLogic(gb);
    	}
     
    	/**
    	 * Starts the game. Runs the flow of the game.
    	 */
    	public void start(){
    		//Start promt
    		System.out.println("Welcome to tic-tac-toe");
    		System.out.println("You will be playing X, the computer will be playing O\n");
     
    		while (gl.checkGameStatus()){
     
    			gb.printAvailSpace();
    			gl.takePlayerTurn();
    			gb.printGameBoard();
    			gl.takeCPUturn();
    			gb.printGameBoard();
     
    		}
    	}
    }

    import java.util.ArrayList;
     
     
    public class Gameboard {
     
    	private ArrayList<Tile> boardList = new ArrayList<Tile>();
     
    	public Gameboard(){
     
    		//Initializing the gameboard
            for (int i = 0; i < 10; i++) {
            	boardList.add(i, new Tile());
            }
    	}
     
    	/**
    	 * Prints the board using the overridden toString in Tile.
    	 */
        public void printGameBoard() {
            System.out.println(boardList.get(0).toString() + " " + boardList.get(1).toString() + " " + boardList.get(2).toString());    // game board logic
            System.out.println(boardList.get(3).toString() + " " + boardList.get(4).toString() + " " + boardList.get(5).toString());    // prints values if space is entered,
            System.out.println(boardList.get(6).toString() + " " + boardList.get(7).toString() + " " + boardList.get(8).toString());    // else prints "-"
            System.out.println();
     
            }
     
        /**
         *  display available space
        */
        public void printAvailSpace() {
     
            System.out.print("Available empty spaces: ");
            for (int i = 0; i < 8; i++) {
    	        if (boardList.get(i).toString().equals("-")) System.out.print( i + ", ");
    		    else System.out.print("");
    	    }
            if (boardList.get(8).toString().equals("-")) System.out.println(8);
        }
     
        /**
         * Check if a tile is already occupied by either Player or CPU
         * @param space
         * @return
         */
        public boolean isAvail(int space){
        	if (boardList.get(space).isOwnedByCPU || boardList.get(space).isOwnedByPlayer){
        		return false;
        	}
        	else return true;
     
        }
     
        public void setOwnedPlayer(int pos){
        	boardList.get(pos).setOwnedByPlayer();
        }
     
        public void setOwnedCPU(int pos){
        	boardList.get(pos).setOwnedByCPU();
        }
     
        /**
         * returns an int value according to the owner of the tile.
         * Used for checking for 3 in a line.
         * 0 for cpu
         * 1 for player
         * @param space
         * @return
         */
        public int getOwner(int pos){
        	if (boardList.get(pos).isOwnedByCPU) return 0;
        	else if (boardList.get(pos).isOwnedByPlayer) return 1;
        	else return 2;
     
        }
    }

    import java.util.Random;
    import java.util.Scanner;
     
     
    public class GameLogic {
     
    	private Scanner scan = new Scanner(System.in);
    	private Gameboard gb = new Gameboard();
    	private Random r = new Random();
    	private int totalTurns;
     
    	public GameLogic(Gameboard gameboard){
    		gb = gameboard;
    		totalTurns = 0;
    	}
     
    	/**
    	 * Handling the player move.
    	 * The player enters an int in the console.
    	 * The int is inserted to the gameboard if not occupied.
    	 */
        public void takePlayerTurn () {
        	System.out.println("select you space ");
        	int x = scan.nextInt();
        	if (gb.isAvail(x)){
        		gb.setOwnedPlayer(x);
        		totalTurns++;
        	}
        	else takePlayerTurn ();
     
        }
     
        /**
         * Handling the CPU turn.
         * CPU selects a random int between 0-9.
         * If occupied, the method is recursivly called again.
         */
        public void takeCPUturn(){
        	System.out.println("CPU is trying to make a move");
        	int x = r.nextInt(9);
        	if (gb.isAvail(x)){
        		gb.setOwnedCPU(x);
        		totalTurns++;
        	}
        	else if (totalTurns > 8) System.out.println("Cpu cant move, no available space");
        	else takeCPUturn();
        }
     
        /**
         * Checks weather the game has ended, either by finding a winner
         * or by all tiles being taken.
         * @return
         */
        public boolean checkGameStatus(){
     
        	//checking for 3 in a row
        	for (int i = 0; i < 7; i = i + 3){
            	if (gb.getOwner(i) != 2 && gb.getOwner(i) == gb.getOwner(i+1) && gb.getOwner(i+1) == gb.getOwner(i+2)){
            		if (gb.getOwner(i) == 0) System.out.println("CPU wins");
            		else System.out.println("Player wins");
            		return false;
            	}
        	}
     
        	//checking for 3 in a column
        	for (int j = 0; j < 3; j = j + 1){
            	if (gb.getOwner(j) != 2 && gb.getOwner(j) == gb.getOwner(j+3) && gb.getOwner(j+3) == gb.getOwner(j+6)){
            		if (gb.getOwner(j) == 0) System.out.println("CPU wins");
            		else System.out.println("Player wins");
            		return false;
            	}
        	}
     
        	//checking for diagonals
        	if (gb.getOwner(0) != 2 && gb.getOwner(0) == gb.getOwner(4) && gb.getOwner(4) == gb.getOwner(8)){
        		if (gb.getOwner(0) == 0) System.out.println("CPU wins");
        		else System.out.println("Player wins");
        		return false;
        	}
     
        	if (gb.getOwner(2) != 2 && gb.getOwner(2) == gb.getOwner(4) && gb.getOwner(4) == gb.getOwner(6)){
        		if (gb.getOwner(2) == 0) System.out.println("CPU wins");
        		else System.out.println("Player wins");
        		return false;
        	}
     
        	//ends the game, if all spaces are filled, but 3 in a line has not been reached
        	if (totalTurns < 9) return true;
        	System.out.println("There is no winner!");
        	return false;
        }
    }

    public class Tile {
    	boolean isOwnedByPlayer;
    	boolean isOwnedByCPU;
     
    	public Tile(){
    		isOwnedByPlayer = false;
    		isOwnedByCPU = false;
    	}
     
    	public void setOwnedByPlayer(){
    		isOwnedByPlayer = true;
    	}
     
    	public void setOwnedByCPU(){
    		isOwnedByCPU = true;
    	}
     
    	public String toString(){
    		if (isOwnedByPlayer) return "X";
    		else if (isOwnedByCPU) return "O";
    		else return "-";
    	}
    }

    Edit: Updated the code, should now be working.

    The comments and documentation is kinda blah, but you can fix that yourself should you want to.
    Also I have not set up preconditions, which you might want too, if you are handing it in as a exercise.

    Feel free to use it as your own, just be careful your teacher dont read these forums :-)

    Ohh yeah, the ai is still just randoming its moves. Thats a big one, ill leave that one to you
    Last edited by Johannes; December 26th, 2009 at 09:34 AM.