Advertisement
Nattack

Untitled

Mar 31st, 2017
259
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 11.05 KB | None | 0 0
  1. /**
  2.  * Connect Four
  3.  *
  4.  * A gravity based game of what is more or less Tic-Tac-Toe
  5.  *
  6.  * @author RJ Trenchard, 100281657
  7.  *
  8.  */
  9.  
  10. public class AE8_20_100281657 {
  11.    
  12.     // Constants, States
  13.     public static enum Tile { EMPTY, RED, BLACK }
  14.     public static enum GameState { SETUP, DRAW, PLAY, CHECK, GAMEOVER, RESET, END }
  15.     public static final int SIZE_X = 7; // board size
  16.     public static final int SIZE_Y = 6;
  17.     public static final int WIN_CONDITION = 4; // how many need to match before a win
  18.    
  19.     /**
  20.      * initBoard
  21.      *
  22.      * initial setup of the game board
  23.      *
  24.      * @return      2-Dimensional array that holds the game board
  25.      */
  26.     public static Tile[][] initBoard() {
  27.         Tile[][] board = new Tile[SIZE_Y][SIZE_X];
  28.         board = resetBoard(board);
  29.         return board;
  30.     }
  31.    
  32.    
  33.     /**
  34.      * resetBoard
  35.      *
  36.      * resets the board to empty
  37.      *
  38.      * @param board     2-Dimensional array that holds the game board
  39.      * @return          Returns an empty board based on the board we fed it
  40.      */
  41.     public static Tile[][] resetBoard( Tile[][] board ) {
  42.         for (int i = 0; i < board.length; i++)
  43.             for (int j = 0; j < board[0].length; j++)
  44.                 board[i][j] = Tile.EMPTY;
  45.         return board;
  46.     }
  47.  
  48.     /**
  49.      * tileToString
  50.      *
  51.      * returns a string representation of the Tile enum.
  52.      *
  53.      * @param tile  The tile to represent
  54.      * @return      The string representation
  55.      */
  56.     public static String tileToString(Tile tile) {
  57.         switch (tile) {
  58.             case RED:            return "R";
  59.             case BLACK:          return "B";
  60.             case EMPTY: default: return " ";
  61.         }
  62.     }
  63.    
  64.     /**
  65.      * findTopEmpty
  66.      *
  67.      * retrieves the topmost empty tile of a particular index
  68.      *
  69.      * @param board     2-Dimensional array that holds the game board
  70.      * @param index     the index to check.
  71.      * @return          returns an int pointing to the topmost tile, or -1 if the tile is invalid.
  72.      */
  73.     public static int findTopEmpty(Tile[][] board, int index) {
  74.         if (index < board[0].length) {
  75.             for (int i = 0; i < board.length; i++)  // traverse down the board until we find something
  76.                 if (board[i][index] != Tile.EMPTY)
  77.                     return i - 1;
  78.             // if it is empty, return the top element index
  79.             return board.length -1;
  80.         }
  81.         // if it is out of bounds, return -1
  82.         return -1;
  83.     }
  84.    
  85.    
  86.     /**
  87.      * findTopTile
  88.      *
  89.      * retrieves the topmost tile of a particular index
  90.      *
  91.      * @param board     2-Dimensional array that holds the game board
  92.      * @param index     the index to check.
  93.      * @return          returns an int pointing to the topmost tile, or -1 if the tile is invalid.
  94.      */
  95.    
  96.     public static int findTopTile(Tile[][] board, int index) {
  97.         if (index < board[0].length) {
  98.             for (int i = 0; i < board.length; i++)  // traverse down the board until we find something
  99.                 if (board[i][index] != Tile.EMPTY)
  100.                     return i;
  101.             // if it is empty, return the top element index
  102.             return board.length -1;
  103.         }
  104.         // if it is out of bounds, return -1
  105.         return -1;
  106.     }
  107.    
  108.     /**
  109.      * playPuck
  110.      *
  111.      * attempts to play a puck on the game board
  112.      *
  113.      * @param board     2-Dimensional array that holds the game board
  114.      * @param index     which index we will play the puck
  115.      * @param player    which player is playing the puck
  116.      * @return          returns true if the puck can be played in that slot
  117.      */
  118.     public static boolean playPuck(Tile[][] board, int index, int player) {
  119.         Tile playerTile = (player == 0) ? Tile.RED:Tile.BLACK; //kind of messy, in the future lets use a struct-like object!
  120.         int top = findTopEmpty(board, index);
  121.         if (top < board.length && top > -1) {
  122.             board[top][index] = playerTile;
  123.             return true;
  124.         }
  125.         else return false;
  126.  
  127.     }
  128.    
  129.     /**
  130.      * checkWin
  131.      *
  132.      * Checks the board to see if a winner exists.
  133.      *
  134.      * @param board     2-Dimensional array that holds the game board
  135.      * @param index     the index to start checking
  136.      * @return          returns true if a winning combination has been found.
  137.      */
  138.     public static boolean checkWin(Tile[][] board, int index) {
  139.         if (    checkDirection(board, index, 1, 0) ||   // check x
  140.                 checkDirection(board, index, 0, 1) ||   // check y
  141.                 checkDirection(board, index, 1, 1) ||   // check x, y
  142.                 checkDirection(board, index, -1, 1)     // check -x, y
  143.             )
  144.             return true;
  145.         else return false;
  146.     }
  147.    
  148.     /**
  149.      * checkDirection
  150.      *
  151.      * Directional checking for matches
  152.      *
  153.      * @param board         2-Dimensional array that holds the game board
  154.      * @param index         which index we will check
  155.      * @param xDirection    the x direction to check, can be 1, 0, or -1
  156.      * @param yDirection    the y direction to check, can be 1, 0, or -1
  157.      * @return              returns true if four match.
  158.      */
  159.     public static boolean checkDirection(Tile[][] board, int index, int xDirection, int yDirection) {
  160.         // this one took a while.
  161.        
  162.         // set up all the variables we'll need.
  163.         int top         = findTopTile(board, index);
  164.         Tile last       = board[top][index];
  165.         int count       = 0;
  166.         boolean isSame  = true;
  167.         int xOpposite   = xDirection * -1;
  168.         int yOpposite   = yDirection * -1;
  169.         int x           = index;
  170.         int y           = top;
  171.        
  172.         // find the first boundary
  173.         while ( isSame && count < 4 ) {
  174.             if (    y >= 0 && y < board.length &&
  175.                     x >= 0 && x < board[0].length &&
  176.                     last == board[y][x])
  177.             {
  178.                 count++;
  179.                 x+=xDirection;
  180.                 y+=yDirection;
  181.             } else isSame = false;
  182.         }
  183.        
  184.         // reset/re-step variables
  185.         x       +=xOpposite;
  186.         y       +=yOpposite;
  187.         isSame  = true;
  188.         count   = 0;
  189.        
  190.         // find the second boundary, return true if we find four matching tiles.
  191.         while ( isSame ) {
  192.             if (    y >= 0 && y < board.length &&
  193.                     x >= 0 && x < board[0].length &&
  194.                     last == board[y][x])
  195.             {
  196.                 count++;
  197.                 x+=xOpposite;
  198.                 y+=yOpposite;
  199.             } else isSame = false;
  200.             if ( count == 4 ) return true;
  201.         }      
  202.         // if nothing matches, return false
  203.         return false;
  204.     }
  205.    
  206.     /**
  207.      * drawOptions
  208.      *
  209.      * Prints all valid options
  210.      *
  211.      * @param player    The player that is going to play
  212.      */
  213.     public static void drawOptions(int player) {
  214.         System.out.println( "Options:\nQ - Quit\nD - Redraw\n1-7 - Play your coin\n");
  215.         System.out.print( "Player " + (player+1) + " select your option: ");
  216.     }
  217.    
  218.     /**
  219.      * drawTitle
  220.      *
  221.      * Prints the board header
  222.      */
  223.     public static void drawTitle() {
  224.         System.out.println("\n******************************\n*********CONNECT FOUR*********\n******************************");
  225.     }
  226.    
  227.     /**
  228.      * congratsPlayer
  229.      *
  230.      * Prints the winning message
  231.      *
  232.      * @param playerNum     The winner
  233.      * @param winCount      2 dimensional array of the winning numbers
  234.      */
  235.     public static void congratsPlayer( int playerNum, int[] winCount ) {
  236.         System.out.println(
  237.                 "Player " + (playerNum + 1) + " wins!\n\n"
  238.                 + "  Player 1: " + winCount[0] + "\n"
  239.                 + "  Player 2: " + winCount[1]);
  240.     }
  241.    
  242.     /**
  243.      * drawBoard
  244.      *
  245.      * Formats a board and prints a string to console
  246.      *
  247.      * @param board     A 2 dimensional array of type "Tile" that holds all the game pieces.
  248.      */
  249.     public static void drawBoard(Tile[][] board) {
  250.         StringBuilder strBoard = new StringBuilder();
  251.         StringBuilder strPlayBuilder = new StringBuilder();
  252.         StringBuilder strRowBuilder = new StringBuilder();
  253.         StringBuilder strIndexBuilderTop = new StringBuilder();
  254.         for (int i = 0; i < board.length; i++) {
  255.             for (int j = 0; j < board[0].length; j++) {
  256.                 strPlayBuilder.append("|" + tileToString( board[i][j]));
  257.                 strRowBuilder.append("--");
  258.                 strIndexBuilderTop.append(" " + Integer.toString(j+1));
  259.             }
  260.             strPlayBuilder.append("|\n");
  261.             strRowBuilder.append("-\n");
  262.             strIndexBuilderTop.append('\n');
  263.             if (i == 0) // use function currying to condense this. Should be safe since the form should never change.
  264.                 strBoard.append( strIndexBuilderTop ).append( strRowBuilder ).append( strPlayBuilder ).append( strRowBuilder );
  265.             else
  266.                 strBoard.append( strPlayBuilder ).append( strRowBuilder );
  267.             strPlayBuilder = new StringBuilder();
  268.             strRowBuilder = new StringBuilder();
  269.         }
  270.         System.out.println(strBoard);
  271.     }
  272.    
  273.     /**
  274.      * Connect Four
  275.      *
  276.      * This could be done in much less lines, surely,
  277.      * but for the sake of this assignment let's make
  278.      * things a bit more verbose
  279.      *
  280.      * @param args      does nothing!
  281.      */
  282.     public static void main(String[] args) {
  283.         // Connect four
  284.        
  285.         // initial declaration of variables
  286.         GameState state         =   GameState.SETUP;
  287.         java.util.Scanner input =   new java.util.Scanner ( System.in );
  288.         String parseBuffer      =   new String();
  289.         Tile[][] board          =   initBoard();
  290.         int[] winCount          =   {0,0};
  291.         int player              =   0;
  292.         boolean running         =   true;
  293.         int choice              =   0;
  294.        
  295.         // Main game loop
  296.         while (running) {
  297.             switch (state) {
  298.            
  299.                     // setup of the game board, also resets the score.
  300.                 case SETUP:
  301.                     board       =   initBoard();
  302.                     winCount[0] =   0;
  303.                     winCount[1] =   0;
  304.                     player      =   0;
  305.                     state       =   GameState.DRAW;
  306.                     break;
  307.                    
  308.                     // resets the game board for another game
  309.                 case RESET:
  310.                     board       =   resetBoard( board );
  311.                     player      =   0;
  312.                     state       =   GameState.DRAW;
  313.                     break;
  314.                    
  315.                     // draw the game board
  316.                 case DRAW:
  317.                     drawTitle();
  318.                     drawBoard(board);
  319.                     state = GameState.PLAY;
  320.                     break;
  321.                    
  322.                     // plays a puck, or gets a different option
  323.                 case PLAY:
  324.                     /*
  325.                      * Options:
  326.                      *  Q to quit
  327.                      *  D to redraw
  328.                      *  1-7 to play
  329.                      * */
  330.                     drawOptions( player );
  331.                     parseBuffer = input.nextLine();
  332.                     if (parseBuffer.isEmpty())
  333.                         System.out.println("Invalid input!");
  334.                     else if (parseBuffer.equalsIgnoreCase( "Q" ))
  335.                         state = GameState.END;
  336.                     else if (parseBuffer.equalsIgnoreCase( "D" ))
  337.                         state = GameState.DRAW;
  338.                     else if ( Character.isDigit( parseBuffer.charAt(0) ) ) {
  339.                         choice = Character.getNumericValue( parseBuffer.charAt(0) );
  340.                         if (choice < board[0].length || choice > 1)
  341.                             state = GameState.CHECK;
  342.                         else
  343.                             System.out.println("Invalid range!");
  344.                     }
  345.                     else System.out.println("Invalid input!");
  346.                     break;
  347.  
  348.                     // check if we can play that disk. If we can, play it, otherwise ask for input again                   
  349.                 case CHECK:
  350.                     if (playPuck(board, (choice -1), player))
  351.                     {
  352.                         if (checkWin( board, (choice -1) )) {
  353.                             winCount[player]++;
  354.                             state = GameState.GAMEOVER;
  355.                         } else {
  356.                             player ^= 1; // obligatory XOR player swap
  357.                             state = GameState.DRAW;
  358.                         }
  359.                     } else {
  360.                         System.out.println("That choice is invalid, try again.");
  361.                         state = GameState.PLAY;
  362.                     }
  363.                     break;
  364.                    
  365.                     // handle the end of game
  366.                 case GAMEOVER:
  367.                     drawBoard(board);
  368.                     congratsPlayer( player, winCount );
  369.                     System.out.print("Play again? (Y = Play again, N = Quit, R = Reset score): ");
  370.                     parseBuffer = input.nextLine();
  371.                     if (parseBuffer.equalsIgnoreCase( "Y" ))
  372.                         state = GameState.RESET;
  373.                     else if (parseBuffer.equalsIgnoreCase( "N" ) || parseBuffer.equalsIgnoreCase( "Q" ))
  374.                         state = GameState.END;
  375.                     else if (parseBuffer.equalsIgnoreCase( "R"))
  376.                         state = GameState.SETUP;
  377.                     else System.out.println("Invalid Input!");
  378.                     break;
  379.                    
  380.                     // quit the game
  381.                 case END: default:
  382.                     System.out.println("Game ended.");
  383.                     input.close();
  384.                     running = false;
  385.                     break;
  386.                    
  387.             }
  388.         }
  389.     }
  390. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement