Monday, August 25, 2014

[Programming] Classic Tic-Tac-Toe

Data Structures Using Java
Abstract
This is a simple tic-tac-toe game between two players by using X's and O's. Players are suppose to input x and y coordinates based on the coordinates of a 2-D array, so they can place their pieces. A winner is declared when there are either three X's or O's in a diagonal, horizontal, or vertical row. If a player places a piece on an occupied spot, their turn is skipped.
Introduction
There are seven distinct java classes, one main class as a tester, and one enum. The seven java classes consists of accessor and mutator methods. The main class is a tester to make sure the game functions. The enum changes the status of the game for when it ends. I also used superclasses and subclasses because the subclass which is the Tic-Tac-Toe board inherits data and behavior from the superclass which creates the board.
Source Code
GameBoard.java
import java.awt.Dimension;

/**
 * A superclass for the board of the classical game of tic-tac-toe.
 */
public class GameBoard {
    /**
  * the size of this GameBoard
  */
 Dimension Size;
 
 /**
  * GameBoard constructor initializes the Size object.
  * 
  * @param newWidth the width value for the Size object
  * @param newHeight the height value for the Size object
  */
 public GameBoard(int newWidth, int newHeight)
 {
  Size = new Dimension(newWidth, newHeight);
 }
        
        public GameBoard()
        {
            Size = new Dimension(0, 0);
        }
 
 /**
  * Accessor method.
  * 
  * @return the width of this GameBoard
  */
 public int GetWidth()
 {
  return (int)Size.getWidth();
 }
 
 /**
  * Accessor method.
  * 
  * @return the height of this GameBoard
  */
 public int GetHeight()
 {
  return (int)Size.getHeight();
 }
 
 /**
  * Mutator method. Sets the Size property.
  * 
  * @param newWidth the new width of this GameBoard
  * @param newHeight the new height of this GameBoard
  */
 public void SetSize(int newWidth, int newHeight)
 {
  Size.setSize(newWidth, newHeight);
 }
}
GamePiece.java
import java.awt.Point;

public class GamePiece
{
 /**
  * The name of this GamePiece
  */
 private String Name;
 
 /**
  * The position on the GameBoard of this GamePiece
  */
 private Point Position;
 
 /**
  * Constructor
  * 
  * @param newName the name value for this GamePiece
  * @param newX the new X position for this GamePiece
  * @param newY the new Y position for this GamePiece
  */
 public GamePiece(String newName, int newX, int newY)
 {
  Name = newName;
  Position = new Point(newX, newY);
 }
 
 /**
         * The toString method which gives information on the name of the
         * game piece and location.
  */
 public String toString()
 {
  return "GamePiece [Name:" + Name + ", Position:(" + Position + ")]";
 }
 
 /**
  * Accessor for the Name property.
  * 
  * @return the name of this GamePiece
  */
 public String GetName()
 {
  return Name;
 }
 /**
  * Mutator for the Name property
  * 
  * @param newName the new name for this GamePiece
  */
 public void SetName(String newName)
 {
  Name = newName;
 }
 
 /**
  * Accessor for the Position property
  * 
  * @return the position of this GamePiece as a Point
  */
 public Point GetPosition()
 {
  return Position;
 }
 /**
  * Mutator for the Position property.
  * 
  * @param newX the new X position
  * @param newY the new Y position
  */
 public void SetPosition(int newX, int newY)
 {
  Position.setLocation(newX, newY);
 }
 
}
GamePlayer.java
public class GamePlayer
{
 private int id;
 private String Name;
 private int Score;

 /**
  * Constructor
  * 
  * @param newId unique integer identifier for this player
  * @param newName the name for this player
  * @param newScore this player's score
  */
 public GamePlayer(int newId, String newName, int newScore)
 {
  id = newId;
  Name = newName;
  Score = newScore;
 }
 
 // Accessor and mutator methods for id
 public int GetId()
 {
  return id;
 }
 public void SetId(int newId)
 {
  id = newId;
 }
 
 // accessor and mutator methods for name
 public String GetName()
 {
  return Name;
 }
 public void SetName(String newName)
 {
  Name = newName; 
 }
 
 // accessor and mutator methods for score
 public int GetScore()
 {
  return Score;
 }
 public void SetScore(int newScore)
 {
  Score = newScore;
 }
 
 /**
  * Add the IncrementAmount to this player's Score
  * 
  * @param IncrementAmount the amount to add to this player's score
  */
 public void IncrementScore(int IncrementAmount)
 {
  Score += IncrementAmount;
 }
}
GameStatus.java
public enum GameStatus
{
 ON, WIN_PLAYER_1, WIN_PLAYER_2, DRAW 
};
LetsPlay.java

import java.util.Scanner;

public class LetsPlay {

   public static void main(String[] args)
 {
  TicTacToeGame t = new TicTacToeGame();
  t.StartNewGame();

  Scanner user_input = new Scanner(System.in);  
  
  while(t.GetGameState() == GameStatus.ON)
  {
   System.out.println("Player " + t.GetCurrentPlayer() + ":");
   t.Print();
   
   System.out.println("  x coordinate for next move:");
   String UserInput = user_input.next();
   int x = Integer.parseInt(UserInput);

   System.out.println("  y coordinate for next move:");
   UserInput = user_input.next();
   int y = Integer.parseInt(UserInput);
   
   if( x >= 0 && x < 3 && y >= 0 && y < 3 )
   {
    t.MakeMove(x, y);
   }

   t.CheckForWin();
   t.NextTurn();
  }
  if( t.GetGameState() == GameStatus.DRAW ) System.out.println("Game resulted in a draw.");
  else if( t.GetGameState() == GameStatus.WIN_PLAYER_1) System.out.println("Player 1 won.");
  else if( t.GetGameState() == GameStatus.WIN_PLAYER_2) System.out.println("Player 2 won.");
  t.Print();
 }
    
}
TicTacToeBoard.java
import java.awt.Point;
import java.util.ArrayList;
import java.util.Arrays;

public class TicTacToeBoard extends GameBoard
{
 /**
  * The pieces in this game.
  */
 ArrayList GamePieces;

 /**
  * Constructor. Instantiate the GamePieces ArrayList.
  */
 public TicTacToeBoard()
 {
            /*created a default constructor in the GameBoard class 
            to connect the superclass constructor with the TTTBoard
            */
            super();
            GamePieces = new ArrayList<>();
 }

 /**
  * empty out the GamePieces ArrayList
  */
 public void Reset()
 {
            //emptys the ArrayList
            GamePieces.clear();
 }

 
 /**
  * Fill a space with the newPiece, IF THAT SPACE IS EMPTY.
  * 
  * @param x the first, horizontal coordinate for the next move 
  * @param y the second, vertical coordinate for the next move
  * @newPiece the piece to place at the location
  */
 public void AddPiece(int x, int y, TicTacToePiece newPiece)
 {
            /*
            Get the GameBoard and if the empty spot which is a dash
            is empty then add that piece
            */
            String[][] tBoard = GetGameBoard();
            if(tBoard[y][x].equals("-"))
            {
            GamePieces.add(newPiece);
            }
 }

 /**
  * Get a GamePiece
  * 
  * @param x the first, horizontal coordinate for the next move 
  * @param y the second, vertical coordinate for the next move
  * @return the game piece at position x, y. or null if there is none
  */
 public TicTacToePiece GetPieceAt(int x, int y)
 {
             /*Get my GamePiece's index and get its x y position
              check to see if the position's x and y are the same 
              as the x and y in the parameter
            if it is then return the piece
            */
            
            for(int i = 0; i<GamePieces.size(); i++)
            {
                TicTacToePiece piece = GamePieces.get(i);
                Point location = piece.GetPosition();
                if(location.getX()==x && location.getY() == y)
                {
                    return piece;
                }
            }
            return null;
 }

 /**
  * Checks the board for win or draw conditions and update the GameState property appropriately.
  * 
  * @return the GameStatus of this game
  */
 public GameStatus CheckForWin()
 {
            /*
            Use the check for three strings to find the win
            by using an empty string and add up the 8 wins 
            to see if it is "XXX" or "OOO".
            */
            GameStatus GameState = GameStatus.ON;
            String[][] tBoard = GetGameBoard();
            String d = "";
            for(int i = 0; i<=2; i++)
            {
                String a = "";
                String b = "";
                String c = "";
                for(int j = 0; j<=2; j++)
                {
                    //check for horizontals
                    a += tBoard[i][j];
                    //verticals
                    b += tBoard[j][i];
                    //the \ diagonal
                    c += tBoard[j][j];
                    if(i+j == 2)
                    {
                    //the / diagonal
                    d += tBoard[i][j];
                    }
                }
                GameState = CheckStringForThree(a);
                if(GameState.equals(GameStatus.WIN_PLAYER_1)|| GameState.equals(GameStatus.WIN_PLAYER_2))
                {
                    return GameState;
                }
                GameState = CheckStringForThree(b);
                if(GameState.equals(GameStatus.WIN_PLAYER_1)|| GameState.equals(GameStatus.WIN_PLAYER_2))
                {
                    return GameState;
                }
                GameState = CheckStringForThree(c);
                if(GameState.equals(GameStatus.WIN_PLAYER_1)|| GameState.equals(GameStatus.WIN_PLAYER_2))
                {
                    return GameState;
                }
                GameState = CheckStringForThree(d);
                if(GameState.equals(GameStatus.WIN_PLAYER_1)|| GameState.equals(GameStatus.WIN_PLAYER_2))
                {
                    return GameState;
                }
                
            }
            
         
            //Check to see if there's 5 of X's O's to call Draw
            int x = 0;
            int o = 0;
            for(int i = 0; i<=2; i++)
            {
                for(int j = 0; j<=2; j++)
                {
                    if(tBoard[i][j] == "X")
                    {
                        x += 1;
                    }
                    if(tBoard[i][j] == "O")
                    {
                        o += 1;
                    }
                }            
            }
            
            if(x ==5)
            {
                return GameState = GameStatus.DRAW;
            }
            if(o == 5 )
              {
                  return GameState = GameStatus.DRAW;
              }
            
            return GameState;
 }
        
        /**
  * Create a Board[][] array. 
  * 
  * @return a two dimensional array of Strings
  */
 private String[][] GetGameBoard()
 {
            /* Create a String[][] with "-" 
            *then search through the ArrayList "GamePieces"
            *to get the position, so I can insert 
            *whichever symbol, "X" or "O" comes next
            */
            
            String[][] Board = new String[3][3];
            for(int i = 0; i<=2; i++)
            {
                for(int j = 0; j<=2; j++)
                {
                    Board[i][j] = "-";
                }
            }
            
            for(int i = 0; i<GamePieces.size(); i++)
            {
                TicTacToePiece a;
                a = GamePieces.get(i);
                Point p = a.GetPosition();
                int x = (int)p.getX();
                int y = (int)p.getY();

                String itSymbol = a.GetSymbol();
                Board[y][x] = itSymbol;
                     
            }
            return Board;
 }
 
 /**
  * Checks a string for win conditions. If three in a row occur, then it returns the proper GameState.
  * This is a helper function that I used, but is not required for you to implement.
  * 
  * @param Input a representation of a row, column, or diagonal in the game. 
  * 
  * @return the proper GameStatus for a row, column, or diagonal represented by the Input String
  *         "---" would indicate an entirely free row, column or diagonal, in which case it should return GameStatus.ON.
  *         "000" indicates a row, column, or diagonal that has been won by player 1.
  *         "111" indicates a row, column, or diagonal that has been won by player 2.
  */
 private GameStatus CheckStringForThree(String Input)
 {
            /*
            Check if the Input is "XXX" or "OOO"
            */
            GameStatus GameState = GameStatus.ON;
            if(Input.equals("XXX"))
            {
                return GameState = GameStatus.WIN_PLAYER_1;
            }
            else if(Input.equals("OOO"))
            {
                return GameState = GameStatus.WIN_PLAYER_2;
            }
            return GameState;
            
 }
 
 /**
  * Print the game board to stdout.
  * 0 should be used to represent moves by player 1.
  * 1 should be used to represent moves by player 2.
  * - should be used to represent a free space.
  * One blank space should occur between each space.
  */
 public void Print()
 {
             String[][] tBoard = GetGameBoard();       
            for(int i = 0; i < tBoard.length; i++)
        {
            for(int j = 0; j < tBoard[i].length; j++)
            {
                System.out.print(tBoard[i][j] + " ");
            }
            System.out.println();
        }
 }

}
TicTicToeGame.java
/**
 * Allow the calling program to play a game of TicTacToe.
 * 
 */
public class TicTacToeGame
{
 TicTacToeBoard t;

 /**
  * The player with the current turn. Should be 0 or 1.
  */
 private int CurrentPlayerIndex;
 
 private TicTacToePlayer Player1;
 private TicTacToePlayer Player2;
 
 /**
  *  @see GameStatus
  */
 private GameStatus GameState;
 
 /**
  * Constructor. Instantiate the Board array and fill it with the String "-". Reset the CurrentPlayerIndex and the GameState.
  */
 public TicTacToeGame()
 {
  t = new TicTacToeBoard();
  
  CurrentPlayerIndex = 1;
  GameState = GameStatus.ON;
  
  Player1 = new TicTacToePlayer(1, "Player 1", 0, "X");
  Player2 = new TicTacToePlayer(2, "Player 2", 0, "O");
 }
 
 /**
  * Start a new game. Reset the CurrentPlayerIndex and the GameState.
  */
 public void StartNewGame()
 {
  Player1 = new TicTacToePlayer(1, "Player 1", 0, "X");
  Player2 = new TicTacToePlayer(2, "Player 2", 0, "O");
  t.Reset();
  CurrentPlayerIndex = 1;
  GameState = GameStatus.ON;
 }
 
 /**
  * Toggle the CurrentPlayerIndex between 0 and 1.
  */
 public void NextTurn()
 {
  CurrentPlayerIndex = (CurrentPlayerIndex == 1) ? 2 : 1;
 }
 /**
  * Which player's turn is it? player 1 or player 2?
  * 
  * @return either 1 or 2
  */
 public int GetCurrentPlayer()
 {
  return CurrentPlayerIndex;
 }
 
 /**
  * Give the GameState to the calling program.
  * 
  * @return GameState
  */
 public GameStatus GetGameState()
 {
  return GameState;
 }

 /**
  * Fill a space with the CurrentPlayerIndex, which should be 0 or 1.
  * 
  * @param x the first, horizontal coordinate for the next move 
  * @param y the second, vertical coordinate for the next move
  * @newPiece the piece to place at the location
  */
 public void MakeMove(int x, int y)
 {
  TicTacToePiece newPiece;
  if( CurrentPlayerIndex == 1 )
   newPiece = new TicTacToePiece(Player1.GetName() + " Piece", x, y, CurrentPlayerIndex, Player1.GetSymbol());
  else
   newPiece = new TicTacToePiece(Player2.GetName() + " Piece", x, y, CurrentPlayerIndex, Player2.GetSymbol());
  
  if( x >= 0 && x < 3 && y >= 0 && y < 3 )
  {
   if( t.GetPieceAt(x, y) == null )
   {
    t.AddPiece(x, y, newPiece);
   }
  }
 }


 /**
  * Checks the Board[][] array for win or draw conditions and updates the GameState property appropriately.
  * 
  * @return true if the game is over. false if the game should continue.
  */
 public boolean CheckForWin()
 {
  GameState = t.CheckForWin();
  if( GameState != GameStatus.ON ) return true;
  
  // if it gets here then the game continues
  return false;
 }


 public void Print()
 {
  t.Print();
 }
}
TicTacToePiece.java
public class TicTacToePiece extends GamePiece
{
 // the player who owns this piece
 private int PlayerNumber;
 
 // the symbol for this piece, should be either X or O
 private String Symbol;
 
 /**
  * Constructor. Set all properties of this class and the superclass.
  * 
  * @param newName the new name for this piece
  * @param newX the new x position for this piece
  * @param newY the new y position for this piece
  * @param newPlayerNumber the id of the player who owns this piece
  * @param newSymbol the symbol for this piece
  */
 public TicTacToePiece(String newName, int newX, int newY, int newPlayerNumber, String newSymbol)
 {
            super(newName, newX, newY);
            this.PlayerNumber = newPlayerNumber;
            this.Symbol = newSymbol;
 }
 
 /**
  * toString
  */
 public String toString()
 {
            return super.toString();
 }
 
 // accessor and mutator methods
 public int GetPlayerNumber()
 {
            return PlayerNumber;
 }
 public void SetPlayerNumber(int newPlayerNumber)
 {
             PlayerNumber = newPlayerNumber;
 }
 
        

 // mutator: SetSymbol
        public void SetSymbol(String newSymbol)
        {
            Symbol = newSymbol;
        }
        

    // accessor and mutator methods
    // accessor: GetSymbol
        public String GetSymbol() {
            return Symbol;
        }
}
TicTacToePlayer.java
public class TicTacToePlayer extends GamePlayer
{
 // the Symbol for this player, either X or O
 private String Symbol;
 
 /**
  * Constructor. Set every property of this class and the superclass.
  * 
  * @param newId the id of this player
  * @param newName the name for this player
  * @param newScore the score for this player
  * @param newSymbol the symbol for this player, either X or O
  */
 public TicTacToePlayer(int newId, String newName, int newScore, String newSymbol )
 {
            super(newId, newName, newScore);
            this.Symbol = newSymbol;
 }

    // accessor and mutator methods
    // accessor: GetSymbol
    public String GetSymbol() {
        return Symbol;
    }
        
        
        
 // mutator: SetSymbol
 public void SetSymbol(String newSymbol)
 {
               Symbol = newSymbol;
 }

 public void IncrementScore()
 {
            super.IncrementScore(1);
 }
}
Result
The Board:
image
Placing the coordinates:
image
Winner:
image

No comments:

Post a Comment