Creating a Connect-Four Game in Java

Problem:

Connect four is a two-player board game in which the players alternately drop colored disks into a seven-column, six-row vertically suspended grid, as shown below.
                                                 
The objective of the game is to connect four same-colored disks in a row, a column, or a diagonal before your opponent can do likewise. The program prompts two players to drop a RED or YELLOW disk alternately. Whenever a disk is dropped, the program re-displays the board on the console and determines the status of the game (win, draw, or continue).


Output:

| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
---------------
Drop a red disk at column (0–6): 
0
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
|R| | | | | | |
---------------
Drop a yellow disk at column (0–6): 
1
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
|R|Y| | | | | |
---------------
Drop a red disk at column (0–6): 
2
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
|R|Y|R| | | | |
---------------
Drop a yellow disk at column (0–6): 
3
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
|R|Y|R|Y| | | |
---------------
Drop a red disk at column (0–6): 
4
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
|R|Y|R|Y|R| | |
---------------
Drop a yellow disk at column (0–6): 
3
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | |Y| | | |
|R|Y|R|Y|R| | |
---------------
Drop a red disk at column (0–6): 
2
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | |R|Y| | | |
|R|Y|R|Y|R| | |
---------------
Drop a yellow disk at column (0–6): 
1
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| |Y|R|Y| | | |
|R|Y|R|Y|R| | |
---------------
Drop a red disk at column (0–6): 
2
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | |R| | | | |
| |Y|R|Y| | | |
|R|Y|R|Y|R| | |
---------------
Drop a yellow disk at column (0–6): 
1
| | | | | | | |
| | | | | | | |
| | | | | | | |
| |Y|R| | | | |
| |Y|R|Y| | | |
|R|Y|R|Y|R| | |
---------------
Drop a red disk at column (0–6): 

1
| | | | | | | |
| | | | | | | |
| |R| | | | | |
| |Y|R| | | | |
| |Y|R|Y| | | |
|R|Y|R|Y|R| | |
---------------
Drop a yellow disk at column (0–6): 
2
| | | | | | | |
| | | | | | | |
| |R|Y| | | | |
| |Y|R| | | | |
| |Y|R|Y| | | |
|R|Y|R|Y|R| | |
---------------
Drop a red disk at column (0–6): 
4
| | | | | | | |
| | | | | | | |
| |R|Y| | | | |
| |Y|R| | | | |
| |Y|R|Y|R| | |
|R|Y|R|Y|R| | |
---------------
Drop a yellow disk at column (0–6): 
3
| | | | | | | |
| | | | | | | |
| |R|Y| | | | |
| |Y|R|Y| | | |
| |Y|R|Y|R| | |
|R|Y|R|Y|R| | |
---------------
Drop a red disk at column (0–6): 
4
| | | | | | | |
| | | | | | | |
| |R|Y| | | | |
| |Y|R|Y|R| | |
| |Y|R|Y|R| | |
|R|Y|R|Y|R| | |
---------------
Drop a yellow disk at column (0–6): 
3
| | | | | | | |
| | | | | | | |
| |R|Y|Y| | | |
| |Y|R|Y|R| | |
| |Y|R|Y|R| | |
|R|Y|R|Y|R| | |
---------------
The yello player won.

Solution:
 import java.util.Scanner;
  
//This will be.. a huge code so we will have to make
//lots of methods for each aspect of the game
public class ConnectFour
{
  //We need to first create the basic visual pattern 
  public static String[][] createPattern()
  {
    //Although the game is more like a table of 6
    //columns and 6 rows, we're going to have to make
    //a 2D array of 7 rows and 15 columns because graphically
    //there's an extra row to show the ___ at the bottom
    //and you have double the columns that show | | | 
    //between each number 
     String[][] f = new String[7][15];
    
    //Time to loop over each row from up to down
    for (int i =0;i<f.length;i++)
    {
      
       //Time to loop over each column from left to right
       for (int j =0;j<f[i].length;j++)
      {
        //Note how it is always the even column
        //that has the border and the odd column
        //between them that will be either empty or
        //have a number 
        if (j% 2 == 0) f[i][j] ="|";
        else f[i][j] = " ";
        
        //Time to make our lowest row
        if (i==6) f[i][j]= "-";
      }
      
    }
    return f;
  }
  
  //Yes, we even need to make a new method for visually
  //printing our game, but at least it's not hard to do
  public static void printPattern(String[][] f)
  {
    for (int i =0;i<f.length;i++)
    {
      for (int j=0;j<f[i].length;j++)
      {
        System.out.print(f[i][j]);
      }
      System.out.println();
    }
  }
  
  //Here's are basic move, making the lowest empty row
  //of a specific column have a Red
  public static void dropRedPattern(String[][] f)
  {
    //We need to have the user tell us what column he wants
    //to drop a red into
    //Note: the user isn't supposed to know that we have 15 columns
    //starting at index 0 till 14 but just 6 nice ones
    System.out.println("Drop a red disk at column (0–6): ");
    Scanner scan = new Scanner (System.in);
    
    //Thankfully, there's a simple formula for converting a 1-2-3-4-5-6 
    //user column number into a 1-3-5-7-9-11-13
    int c = 2*scan.nextInt()+1;
   
    //Now that we know our column, we have to loop
    //over each row from the bottom to the top
    //till we find the first  empty space, drop, and
    //then finish (i.e., break) the move
    //Note: although as coders we're used to starting from 
    //0 to the end, here that wouldn't work so well because
    //it would involve multiple if statements, but try it out
    //on your own if you want to
    for (int i =5;i>=0;i--)
    {
      if (f[i][c] == " ")
      {
        f[i][c] = "R";
        break;
      }
      
    }
  }
  
  //Same as the above step, just yellow
  public static void dropYellowPattern(String[][] f)
  {
    System.out.println("Drop a yellow disk at column (0–6): ");
    Scanner scan = new Scanner (System.in);
    int c = 2*scan.nextInt()+1;
    for (int i =5;i>=0;i--)
    {
      if (f[i][c] == " ")
      {
        f[i][c] = "Y";
        break;
      }
      
    }
  }
  

  //Here's where it gets hard.
  //That's because there are basically four patterns
  //of Reds or Yellows that can win the game
  //One pattern is a horizontal line of four Rs or Ys,
  //another is a vertical line, another is a left-up to right-down
  //diagonal line, and the last is left-down to right-up diagonal,
  //We thus need to code for each type of line
  //and the various places where the line can be
  public static String checkWinner(String[][] f)
  {
    
    //Time to look for the first type of winning line,
    //a horizontal line
    //This line can be on any row, so let's loop over 
    //each row starting from 0 to 5 (since 6 is just ___)
    for (int i =0;i<6;i++)
    {
      //On every row, the four-dotted line can look like
      //----_ _,  _----_, or _ _----
      //Here, _ can be an empty space or one of the colors 
      //and - is not empty space  AND every - has the same
      // color (R or Y)
      //Note: since our R/Y/Empty's can only be in odd places,
      //because of how we created the pattern in the first
      //method, then our count has to be incremented by 2 
      //and will start from 0 (which will be 1, ----_ _) 
      //and stop at 6 (which will be 7, _ _----)
      for (int j=0;j<7;j+=2)
      {
        if ((f[i][j+1] != " ")
        && (f[i][j+3] != " ")
        && (f[i][j+5] != " ")
        && (f[i][j+7] != " ")
        && ((f[i][j+1] == f[i][j+3])
        && (f[i][j+3] == f[i][j+5])
        && (f[i][j+5] == f[i][j+7])))

        //If we found a same-colored pattern, we'll return 
        //the color so that we will know who won
          return f[i][j+1];  
      }
    }
    
    //For a vertical line, let's first loop over each
    //odd-numbered column by incrementing with 2
    //and check for consecutive boxes in the same column
    //that are the same color
    //Note: make sure you understand the horizontal line's
    //codes first or else everything below this point will 
    //make no sense to you
    for (int i=1;i<15;i+=2)
    {
      //Of course, our lines will look like ----__ but reversed
      //and there is need to our rows by 2 but just one
      //and we have to start at the vertical version of ----__ and 
      //and stop at _ _ ---- so it's from 0 to 2
      for (int j =0;j<3;j++)
      {
            if((f[j][i] != " ")
            && (f[j+1][i] != " ")
            && (f[j+2][i] != " ")
            && (f[j+3][i] != " ")
            && ((f[j][i] == f[j+1][i])
            && (f[j+1][i] == f[j+2][i])
            && (f[j+2][i] == f[j+3][i])))
              return f[j][i];  
      }  
    }
    
    //For the left-up to right-down diagonal line
    //We'll have to loop over the 3 uppermost
    //rows and then go from left to right column-wise
    for (int i=0;i<3;i++)
    {
      
      //As expected, our uppermost box will start from 1
      //and increase by 2 until it becomes 7 (the 3rd box
      //on a row)
      //Note how we used 1 instead 0 for the count here
      //There's no real reason to use 1 instead of 0 or 
      //vice versa, since we're still using an odd index
      //for the columns and incrementing by 2
      for (int j=1;j<9;j+=2)
      {
            if((f[i][j] != " ")
            && (f[i+1][j+2] != " ")
            && (f[i+2][j+4] != " ")
            && (f[i+3][j+6] != " ")
            && ((f[i][j] == f[i+1][j+2])
            && (f[i+1][j+2] == f[i+2][j+4])
            && (f[i+2][j+4] == f[i+3][j+6])))
              return f[i][j];  
      }  
    }
    
    //Similar to the method above, but we're just reversing our
    //trajectory, i.e. we're starting from the rightmost column
    //instead of the leftmost like we did above
    for (int i=0;i<3;i++)
    {
      for (int j=7;j<15;j+=2)
      {
            if((f[i][j] != " ")
            && (f[i+1][j-2] != " ")
            && (f[i+2][j-4] != " ")
            && (f[i+3][j-6] != " ")
            && ((f[i][j] == f[i+1][j-2])
            && (f[i+1][j-2] == f[i+2][j-4])
            && (f[i+2][j-4] == f[i+3][j-6])))
              return f[i][j];  
      }  
    }
    
    //If after going over the table and we find no
    //same colored lines, then we have to return something
    //that says that we didn't find a winning color :P
    return null;
  }
  
  //The easy part: using these methods
  public static void main (String[] args)
  {
    //Time to make a pattern
    String[][] f = createPattern();
    //Time to make a condition for our game to keep on
    //playing
    boolean loop = true;
    //We need something to keep track of whose turn it is
    int count = 0;
    printPattern(f);
    while(loop)
    {
       //Let's say that Red gets the first turn and thus
       //every other turn 
       if (count % 2 == 0) dropRedPattern(f);
       else dropYellowPattern(f);
       count++;//We need to keep track of the turns
       printPattern(f);
       //Let's say we want to check for a winner during every
       //turn made and say who it is
       if (checkWinner(f) != null)
       {
          if (checkWinner(f) == "R")
             System.out.println("The red player won.");
          else if (checkWinner(f)== "Y")
            System.out.println("The yello player won.");
         //Well, if someone one, then the game has to end
         loop = false;
    }
  }
}
}


7 comments :

  1. Thank you for your post, I have to do exactly the same thing for an assignment, and your solution works, whereas mine does not. I will now try to work out the differences. Thanks again.

    ReplyDelete
  2. I personally don't like to fill an array with the spacers.
    I prefer to add such things in the to.String() method,
    just before it's printed out, as they have no value in the rest of the code.

    ReplyDelete
  3. Thank you so much for the code. It was really helpful. I just had a question. How would you handle the ArrayIndexOutofBounds exception in this program?

    ReplyDelete
  4. The code compiles and runs but the board won't print again after 1 move.

    ReplyDelete
  5. Thank you so much for the code. It was really helpful.

    ReplyDelete
  6. thank you for the code may i ask what algo did you use in here?

    ReplyDelete

Follow Me

If you like our content, feel free to follow me to stay updated.

Subscribe

Enter your email address:

We hate spam as much as you do.

Upload Material

Got an exam, project, tutorial video, exercise, solutions, unsolved problem, question, solution manual? We are open to any coding material. Why not upload?

Upload

Copyright © 2012 - 2014 Java Problems  --  About  --  Attribution  --  Privacy Policy  --  Terms of Use  --  Contact