Four-In-A-Line

My first program (2020)

---
This program is intended to be an assignment for the module ITP3914 Programming
offered by the Vocational Training Council.

This is my first program—the code may be rudimentary, but it holds special meaning for me.

Special thanks go to Mr CHOU Siu Chuen Nelson, the then lecturer of this module,
as well as our first lecturer of the programme.
Mr CHOU is one of the most influential teachers on my journey to become a software engineer.

---

FourInALine Game

The FourInALine class implements an application that enables users to play the classic Four-in-a-Line game against another human player.

Objective

The main goal of the game is to be the first to align four successive discs from the same player vertically, horizontally, or diagonally.

Additional Challenge

Beyond the basic assignment requirements, this implementation offers an enhanced challenge by allowing users to manually adjust the grid size. Players can set the number of rows and columns, with options ranging from 4 to 10, adding an extra layer of strategy to the game.

---
/**
* <h1>Four-in-a-Line!</h1>
* The FourInALine class implements an application that
* allows user to play the classic Four-in-a-Line game against another human.
* <p>
* The objective of the game is to make successive four discs
* from the same player aligned vertically, horizontally,
* or diagonally before the opponent doing the same likewisely.
* <p>
* This program is designed to allow users manually adjust
* number of rows and columns of the grid, both ranged from 4 to 10,
* to make the game more challenging.
* <p>
* This program is intended to be an assignment
* for ITP3914 Programming offered by
* the Hong Kong Institute of Vocational Education.
* <p>
*
* @author CHEUNG Man Lai (200427569) / HDSE (IT114105) 1C
* @version 1.0
* @since 2020-11-29
*/

import java.util.Scanner;

public class FourInALine {
    /*
        This is the main method of the program
        which initialises the variables required and
        calls the four methods used in the program:

        1. <b>initialCheck</b> which check if numRow and/or numCol is inputted correctly
        2. <b>display</b> which display the grid
        3. <b>validate</b> which validates if the move from the players is valid
        4. <b>checkWinner</b> which check if there is a winner
    */
    public static void main(String[] args) {
        // Create a Scanner object for console input
        Scanner kb = new Scanner(System.in);

        // Declare variables
        int numRow;        // Variable for Number of Rows,
        int numCol;        // Variable for Number of Columns
        int disc;            // Variable storing the input from user
        int count = 0;        // Variable to count the total number of moves taken
        char player = '1';    // Set starting player, default value: 1

        // Prompt welcome message
        for (int i = 0; i < 69; i++)
            System.out.print("*");
        System.out.println("\n\t\tWelcome to Four-in-a-Line! <version 1.0> ");
        System.out.println("\tYour opinion is appreciated: 200427569@stu.vtc.edu.hk");
        for (int i = 0; i < 69; i++)
            System.out.print("*");

        // While loop for initial setup
        while (true) {
            // Ask the player if grid size adjustment is required
            System.out.print("\nPress 9 to start game or 10 if you wish to adjust grid size. ");
            int start = kb.nextInt();    // Variable to store player's choice on grid adjustment

            if (start == 9) {
                numRow = 6;            // default game: numRow = 6
                numCol = 7;        // default game: numCol = 7
                break;                // Break while-loop to start game
            } else if (start == 10) {    // Takes numRow and numCol values from player
                System.out.print("Number of rows? Please input a number ranged from 4 to 10. ");
                numRow = kb.nextInt();
                System.out.print("Number of colums? Please input a number ranged from 4 to 10. ");
                numCol = kb.nextInt();

                // call the initialCheck method to check if the input is valid
                if (initialCheck(numRow, numCol))
                    break;        // break the loop if true is returned
                else
                    continue;    // continue the loop if it is checked to be invalid
            } else        // If the value entered is not 9 or 10, prompt error message
                System.out.print("Wrong input! Please try again.");
            continue;    // continue the loop if it is checked to be invalid
        }

        // Prompt grid size message
        for (int i = 0; i < 69; i++)
            System.out.print("*");
        System.out.println("\nInitialising grid with Rows 0-" + (numRow - 1) +
                " and Columns 0-" + (numCol - 1) + ".");

        char[][] grid = new char[numRow][numCol];        // Initialising the grid which is a 2d array
        for (int row = 0; row < grid.length; row++)
            for (int col = 0; col < grid[0].length; col++)
                grid[row][col] = '0';

        // Player to drop a disc
        while (count < numRow * numCol) {    // While-loop ends if the grid is full

            display(grid);    // To call method display to show the grid

            do {            // Prompt message to ask player to input column

                System.out.print("Player " + player + " type a column (0-" + (numCol - 1) +
                        ") or " + (numRow + 3) + " to quit current game: ");  // default value to quit game: 9 (6+3)

                disc = kb.nextInt();    // Update the variable disc which stores player's move via Scanner kb

                if (disc == numRow + 3) {    // To check if the player decides to quit game
                    System.out.print("Bye Bye!");
                    return;
                }

            } while (validate(disc, grid, numCol)); // To call method validate to check if the input is valid

            // Drop the disc
            for (int row = 0; row < grid.length; row++) {
                if (grid[row][disc] == '0') {
                    grid[row][disc] = player;
                    break;
                }
            }

            // Switch players
            if (checkWinner(player, grid)) // No player switch if method checkWinner returns true
                break;
            else if (player == '1')
                player = '2';
            else
                player = '1';

            count++; // Count if this grid is full

        } // Loop ends when variable count reaches its maximum value (numRow*numCol)

        // Display grid when the above loop ends
        display(grid);

        // Display winner after the while loop breaks or ends because count reaches max value
        if (checkWinner(player, grid)) {
            if (player == '1')
                System.out.print("Player 1 win this game!");
            else
                System.out.print("Player 2 win this game!");
        }
        // No winner if checkWinner returns false and variable count reaches its max value
        else
            System.out.print("Draw game! Thanks for playing.");

    }

    /*
        This is the initialCheck method of the program
        which check if numRow and numCol is ranged from 4 to 10.
        Program ends and prompt message to ask user to reconsider
        if method returns true.
    */
    public static boolean initialCheck(int numRow, int numCol) {
        // numRow and numCol must be ranged from 4 to 10
        if ((numRow >= 4 && numRow <= 10) &&
                (numCol >= 4 && numCol <= 10))
            return true; // Return true if the input is in ranged
        else // Prompt error message if the above condition is not fulfilled
            System.out.print("Wrong input! Number must be ranged from 4 to 10. Please reconsider.");
        return false; // Return false if the above condition is not fulfilled
    }

    /*
        This is the display method of the program
        which updates the grid after each move.
    */
    public static void display(char[][] grid) {
        // Draw row number and the vertical partition line
        for (int row = grid.length - 1; row >= 0; row--) {
            System.out.print(row + " | ");
            // Draw the grid with input
            for (int col = 0; col < grid[0].length; col++) {
                System.out.print(grid[row][col]);
                System.out.print(" ");
            }
            System.out.println();
        }

        // Draw column number and the horizontal partition line
        System.out.print("  +");
        for (int i = 0; i < grid[0].length; i++)
            System.out.print("--");
        System.out.println();
        System.out.print("    ");
        for (int i = 0; i < grid[0].length; i++)
            System.out.print(i + " ");
        System.out.println();
    }

    /*
        This is the validate method of the program
        which checks after each input from player to
        see if it is a valid move. It retruns true if:
        1. the input is not within range, or
        2. the targeted column is full
    */
    public static boolean validate(int column, char[][] grid, int numCol) {
        // Is the number for column within range?
        if (column < 0 || column >= grid[0].length) {
            System.out.println("Range of column should be 0 to " + (numCol - 1) + "!");
            return true;
        }

        // Is the targeted column full?
        if (grid[grid.length - 1][column] != '0') {
            System.out.println("Column " + column + " is full!");
            return true;
        }

        return false; // return false if neither of the above conditions is fulfilled

    }

    /*
        This is the checkWinner method of the program
        which checks if there is a winner after each input from player.
        The method performs 4 checks and returns true if there is a winner.
        1. horizontal check
        2. vertical check
        3. downward diagonal check
        4. upward diagonal check
    */
    public static boolean checkWinner(char player, char[][] grid) {
        // Horizontal check if successive four discs aligned
        // Check col value smaller than (grid[0].length - 3)
        // to avoid array out of bound exception
        for (int row = 0; row < grid.length; row++)
            for (int col = 0; col < grid[0].length - 3; col++)
                if (grid[row][col] == player &&
                        grid[row][col + 1] == player &&
                        grid[row][col + 2] == player &&
                        grid[row][col + 3] == player)
                    return true;

        // Vertical check if successive four discs aligned
        // Check row value smaller than (grid.length - 3) and
        // check col value smaller than (grid[0].length - 3)
        // to avoid array out of bound exception
        for (int row = 0; row < grid.length - 3; row++)
            for (int col = 0; col < grid[0].length; col++)
                if (grid[row][col] == player &&
                        grid[row + 1][col] == player &&
                        grid[row + 2][col] == player &&
                        grid[row + 3][col] == player)
                    return true;

        // Downward diagonal check if successive four discs aligned
        // row checks start from 3 to avoid array out of bound exception
        for (int row = 3; row < grid.length; row++)
            for (int col = 0; col < grid[0].length - 3; col++)
                if (grid[row][col] == player &&
                        grid[row - 1][col + 1] == player &&
                        grid[row - 2][col + 2] == player &&
                        grid[row - 3][col + 3] == player)
                    return true;

        // Upward diagonal check if successive four discs aligned
        // Check row and col value smaller than (grid.length - 3)
        // to avoid array out of bound exception
        for (int row = 0; row < grid.length - 3; row++)
            for (int col = 0; col < grid[0].length - 3; col++)
                if (grid[row][col] == player &&
                        grid[row + 1][col + 1] == player &&
                        grid[row + 2][col + 2] == player &&
                        grid[row + 3][col + 3] == player)
                    return true;

        return false; // Return false if there is no winner
    }
}
---
Connect Four might be an easy program to develop but it holds special significance for me as it is the first program that I developed myself.