Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * Connect Four
- *
- * A gravity based game of what is more or less Tic-Tac-Toe
- *
- * @author RJ Trenchard, 100281657
- *
- */
- public class AE8_20_100281657 {
- // Constants, States
- public static enum Tile { EMPTY, RED, BLACK }
- public static enum GameState { SETUP, DRAW, PLAY, CHECK, GAMEOVER, RESET, END }
- public static final int SIZE_X = 7; // board size
- public static final int SIZE_Y = 6;
- public static final int WIN_CONDITION = 4; // how many need to match before a win
- /**
- * initBoard
- *
- * initial setup of the game board
- *
- * @return 2-Dimensional array that holds the game board
- */
- public static Tile[][] initBoard() {
- Tile[][] board = new Tile[SIZE_Y][SIZE_X];
- board = resetBoard(board);
- return board;
- }
- /**
- * resetBoard
- *
- * resets the board to empty
- *
- * @param board 2-Dimensional array that holds the game board
- * @return Returns an empty board based on the board we fed it
- */
- public static Tile[][] resetBoard( Tile[][] board ) {
- for (int i = 0; i < board.length; i++)
- for (int j = 0; j < board[0].length; j++)
- board[i][j] = Tile.EMPTY;
- return board;
- }
- /**
- * tileToString
- *
- * returns a string representation of the Tile enum.
- *
- * @param tile The tile to represent
- * @return The string representation
- */
- public static String tileToString(Tile tile) {
- switch (tile) {
- case RED: return "R";
- case BLACK: return "B";
- case EMPTY: default: return " ";
- }
- }
- /**
- * findTopEmpty
- *
- * retrieves the topmost empty tile of a particular index
- *
- * @param board 2-Dimensional array that holds the game board
- * @param index the index to check.
- * @return returns an int pointing to the topmost tile, or -1 if the tile is invalid.
- */
- public static int findTopEmpty(Tile[][] board, int index) {
- if (index < board[0].length) {
- for (int i = 0; i < board.length; i++) // traverse down the board until we find something
- if (board[i][index] != Tile.EMPTY)
- return i - 1;
- // if it is empty, return the top element index
- return board.length -1;
- }
- // if it is out of bounds, return -1
- return -1;
- }
- /**
- * findTopTile
- *
- * retrieves the topmost tile of a particular index
- *
- * @param board 2-Dimensional array that holds the game board
- * @param index the index to check.
- * @return returns an int pointing to the topmost tile, or -1 if the tile is invalid.
- */
- public static int findTopTile(Tile[][] board, int index) {
- if (index < board[0].length) {
- for (int i = 0; i < board.length; i++) // traverse down the board until we find something
- if (board[i][index] != Tile.EMPTY)
- return i;
- // if it is empty, return the top element index
- return board.length -1;
- }
- // if it is out of bounds, return -1
- return -1;
- }
- /**
- * playPuck
- *
- * attempts to play a puck on the game board
- *
- * @param board 2-Dimensional array that holds the game board
- * @param index which index we will play the puck
- * @param player which player is playing the puck
- * @return returns true if the puck can be played in that slot
- */
- public static boolean playPuck(Tile[][] board, int index, int player) {
- Tile playerTile = (player == 0) ? Tile.RED:Tile.BLACK; //kind of messy, in the future lets use a struct-like object!
- int top = findTopEmpty(board, index);
- if (top < board.length && top > -1) {
- board[top][index] = playerTile;
- return true;
- }
- else return false;
- }
- /**
- * checkWin
- *
- * Checks the board to see if a winner exists.
- *
- * @param board 2-Dimensional array that holds the game board
- * @param index the index to start checking
- * @return returns true if a winning combination has been found.
- */
- public static boolean checkWin(Tile[][] board, int index) {
- if ( checkDirection(board, index, 1, 0) || // check x
- checkDirection(board, index, 0, 1) || // check y
- checkDirection(board, index, 1, 1) || // check x, y
- checkDirection(board, index, -1, 1) // check -x, y
- )
- return true;
- else return false;
- }
- /**
- * checkDirection
- *
- * Directional checking for matches
- *
- * @param board 2-Dimensional array that holds the game board
- * @param index which index we will check
- * @param xDirection the x direction to check, can be 1, 0, or -1
- * @param yDirection the y direction to check, can be 1, 0, or -1
- * @return returns true if four match.
- */
- public static boolean checkDirection(Tile[][] board, int index, int xDirection, int yDirection) {
- // this one took a while.
- // set up all the variables we'll need.
- int top = findTopTile(board, index);
- Tile last = board[top][index];
- int count = 0;
- boolean isSame = true;
- int xOpposite = xDirection * -1;
- int yOpposite = yDirection * -1;
- int x = index;
- int y = top;
- // find the first boundary
- while ( isSame && count < 4 ) {
- if ( y >= 0 && y < board.length &&
- x >= 0 && x < board[0].length &&
- last == board[y][x])
- {
- count++;
- x+=xDirection;
- y+=yDirection;
- } else isSame = false;
- }
- // reset/re-step variables
- x +=xOpposite;
- y +=yOpposite;
- isSame = true;
- count = 0;
- // find the second boundary, return true if we find four matching tiles.
- while ( isSame ) {
- if ( y >= 0 && y < board.length &&
- x >= 0 && x < board[0].length &&
- last == board[y][x])
- {
- count++;
- x+=xOpposite;
- y+=yOpposite;
- } else isSame = false;
- if ( count == 4 ) return true;
- }
- // if nothing matches, return false
- return false;
- }
- /**
- * drawOptions
- *
- * Prints all valid options
- *
- * @param player The player that is going to play
- */
- public static void drawOptions(int player) {
- System.out.println( "Options:\nQ - Quit\nD - Redraw\n1-7 - Play your coin\n");
- System.out.print( "Player " + (player+1) + " select your option: ");
- }
- /**
- * drawTitle
- *
- * Prints the board header
- */
- public static void drawTitle() {
- System.out.println("\n******************************\n*********CONNECT FOUR*********\n******************************");
- }
- /**
- * congratsPlayer
- *
- * Prints the winning message
- *
- * @param playerNum The winner
- * @param winCount 2 dimensional array of the winning numbers
- */
- public static void congratsPlayer( int playerNum, int[] winCount ) {
- System.out.println(
- "Player " + (playerNum + 1) + " wins!\n\n"
- + " Player 1: " + winCount[0] + "\n"
- + " Player 2: " + winCount[1]);
- }
- /**
- * drawBoard
- *
- * Formats a board and prints a string to console
- *
- * @param board A 2 dimensional array of type "Tile" that holds all the game pieces.
- */
- public static void drawBoard(Tile[][] board) {
- StringBuilder strBoard = new StringBuilder();
- StringBuilder strPlayBuilder = new StringBuilder();
- StringBuilder strRowBuilder = new StringBuilder();
- StringBuilder strIndexBuilderTop = new StringBuilder();
- for (int i = 0; i < board.length; i++) {
- for (int j = 0; j < board[0].length; j++) {
- strPlayBuilder.append("|" + tileToString( board[i][j]));
- strRowBuilder.append("--");
- strIndexBuilderTop.append(" " + Integer.toString(j+1));
- }
- strPlayBuilder.append("|\n");
- strRowBuilder.append("-\n");
- strIndexBuilderTop.append('\n');
- if (i == 0) // use function currying to condense this. Should be safe since the form should never change.
- strBoard.append( strIndexBuilderTop ).append( strRowBuilder ).append( strPlayBuilder ).append( strRowBuilder );
- else
- strBoard.append( strPlayBuilder ).append( strRowBuilder );
- strPlayBuilder = new StringBuilder();
- strRowBuilder = new StringBuilder();
- }
- System.out.println(strBoard);
- }
- /**
- * Connect Four
- *
- * This could be done in much less lines, surely,
- * but for the sake of this assignment let's make
- * things a bit more verbose
- *
- * @param args does nothing!
- */
- public static void main(String[] args) {
- // Connect four
- // initial declaration of variables
- GameState state = GameState.SETUP;
- java.util.Scanner input = new java.util.Scanner ( System.in );
- String parseBuffer = new String();
- Tile[][] board = initBoard();
- int[] winCount = {0,0};
- int player = 0;
- boolean running = true;
- int choice = 0;
- // Main game loop
- while (running) {
- switch (state) {
- // setup of the game board, also resets the score.
- case SETUP:
- board = initBoard();
- winCount[0] = 0;
- winCount[1] = 0;
- player = 0;
- state = GameState.DRAW;
- break;
- // resets the game board for another game
- case RESET:
- board = resetBoard( board );
- player = 0;
- state = GameState.DRAW;
- break;
- // draw the game board
- case DRAW:
- drawTitle();
- drawBoard(board);
- state = GameState.PLAY;
- break;
- // plays a puck, or gets a different option
- case PLAY:
- /*
- * Options:
- * Q to quit
- * D to redraw
- * 1-7 to play
- * */
- drawOptions( player );
- parseBuffer = input.nextLine();
- if (parseBuffer.isEmpty())
- System.out.println("Invalid input!");
- else if (parseBuffer.equalsIgnoreCase( "Q" ))
- state = GameState.END;
- else if (parseBuffer.equalsIgnoreCase( "D" ))
- state = GameState.DRAW;
- else if ( Character.isDigit( parseBuffer.charAt(0) ) ) {
- choice = Character.getNumericValue( parseBuffer.charAt(0) );
- if (choice < board[0].length || choice > 1)
- state = GameState.CHECK;
- else
- System.out.println("Invalid range!");
- }
- else System.out.println("Invalid input!");
- break;
- // check if we can play that disk. If we can, play it, otherwise ask for input again
- case CHECK:
- if (playPuck(board, (choice -1), player))
- {
- if (checkWin( board, (choice -1) )) {
- winCount[player]++;
- state = GameState.GAMEOVER;
- } else {
- player ^= 1; // obligatory XOR player swap
- state = GameState.DRAW;
- }
- } else {
- System.out.println("That choice is invalid, try again.");
- state = GameState.PLAY;
- }
- break;
- // handle the end of game
- case GAMEOVER:
- drawBoard(board);
- congratsPlayer( player, winCount );
- System.out.print("Play again? (Y = Play again, N = Quit, R = Reset score): ");
- parseBuffer = input.nextLine();
- if (parseBuffer.equalsIgnoreCase( "Y" ))
- state = GameState.RESET;
- else if (parseBuffer.equalsIgnoreCase( "N" ) || parseBuffer.equalsIgnoreCase( "Q" ))
- state = GameState.END;
- else if (parseBuffer.equalsIgnoreCase( "R"))
- state = GameState.SETUP;
- else System.out.println("Invalid Input!");
- break;
- // quit the game
- case END: default:
- System.out.println("Game ended.");
- input.close();
- running = false;
- break;
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement