Connect 4 - Part 1

Overview

The goal of this project is to design a simple version of the "Connect Four" game. For the ones who have never heard of this game at all, wikipedia provides a good description.

The idea for the overall design is the following:

  • Everything that has to do with the graphical display of the game should go into one class. In our case this will be a class called Connect4Board.

  • The logic of the game (such as keeping track of the discs, finding sequences of four discs, determining the winner and so forth) should be contained in another class. We'll call it Connect4Logic.

  • Finally, another class is needed. The display and the logic modules alone don't make up a program. We need to integrate both of them and give the user a chance to interact with the game ("user interface"). We'll call this classConnect4Game.

This is how it should look when classes are complete (click to enlarge)

As you can see, Connect4Game will use Connect4Board and Connect4Logic.

Connect4Logic doesn't use any other class. It is basically self-contained.

Connect4Board on the other hand uses the two classes Circle and Square, which both require Canvas. Circle, Square, and Canvas are the same classes that we already used in the Shapes Assignment.

The interesting point to notice here is that Connect4Board and Connect4Logic are independent of each other. They don't need each other and they don't interact. This makes the programming process a lot easier. We can concentrate on one class without having to do the other one at the same time.

Starting the Project

Create a new project "Connect4" and bring in Circle.java, Square.java, and Canvas.java from Assignment 1. Having these, you should be ready to go. On to part 1, the graphical display...

1. Part: The Graphical Display

The goal of the first part is to develop the class Connect4Board, which manages the graphical output. Looking at Figure 1, we can identify following components and functionalities:

  • The board should be a blue rectangle with white circles showing the locations where discs can be placed.

  • Discs are either red or black, depending on the player who inserted them. Disc are placed in the white circles.

  • When inserted into a column, discs start piling up from the bottom row upwards.

  • Note: When you play the real game, gravity takes care of this. When playing the Java game, it has to be your program code that makes sure that discs don't "hang in the air".

Now how do we do this? It is recommended that you develop your class Connect4Board incrementally, building it piece by piece, and testing it every time you have added a new feature.

So, go ahead and create a new class Connect4Board. Then start filling in the code.

Blue Background with White Circles

As you might have noticed, we don't have a way to draw a rectangle. But that's no problem. A rectangle can easily be composed by using a bunch of squares. To do so, carry out the following steps. Make sure that once you have implemented a step, you test it carefully before going on to the next one!

1. Task

Think about how you can draw one blue square with a white circle inside. From now on, let's refer to such a square/circle combination as "tile".

  • To start out, you first might want to overload the Square and Circle constructors so you can set the location at the time when you create a new object. That will be really helpful!

  • In BlueJ, create a new object of type Square and one of type Circle. Use the new constructors you wrote earlier and any other methods to make them overlap. Then change their size and color them appropriately. Write down the sequence of method calls that you had to carry out.

  • Now, inside the Connect4Board class, create a new method, whose only purpose it is to create a new Square and a new Circle object and draw a tile at a specified location on the screen.

  • How do you write this method? Do you think this method needs to have parameters?

  • This method will later be used to draw the individual tiles, which make up the whole board.

  • Once you have this method, test it out by creating an object of type Connect4Board and calling the method that you just wrote. Does it draw the tile at a location that you specified?

  • Call this method again. Does it place another tile on the screen? How can you place two tiles next to each other? After you figured this one out, go on to the next task.

2. Task

Now that we have the method that draws one tile, let's think about how we can draw the whole board.

  • Create a new method, which you might call for example drawBoard(). Inside this method, we will place all the code necessary to draw the board.

  • From earlier, you should know how to draw two tiles next to each other. How about a whole bunch of them? The standard board has 6 rows and 7 columns. Can you draw a board like this by calling your method from earlier?

  • Note, you really don't want to call the method 42 times. Therefore, you should use loops.

  • To start out, write a loop that draws the tiles of only one row.

  • Then, draw the board line by line. How do you do this? Nested loops come to mind!

3. Task

Now create two constructors. The default constructor should draw a board with 6 rows and 7 columns. Another constructor should take two integer parameters, which specify the number of rows and the number of columns of the board. This way, it will be possible to create boards of different size.

Hint 1: It is very helpful to have fields that store the number of rows and columns.

Hint 2: Inside your constructor you can call other methods of your class, such as drawBoard().

Placement of Discs

We will need to write a method that inserts a disc into a certain column and places it in the appropriate row.

However, before we do this, we will implement a helper method, which is easier to implement. Remember, we program in baby steps, so we don't get overwhelmed.

4. Task

Write a method that places a disc in a specified location, using a specified color. The location should be specified by row and column. Rows are specified by an integer number, where the rows are enumerated from bottom to top, starting with row number 1. Columns are specified the same way, starting with column number 1 on the left side.

Hint 1: You can call your method whatever you like.

Hint 2: The method needs to have parameters.

Hint 3: On how to use colors in Java, see Shapes Lab.

Hint 4: In order to use colors in Java, you have to import the package java.awt. You do this by adding the following code as the first line in your Connect4Board class: import java.awt.*;

5. Task

Now we write the method that places the disc in the correct row. This method will make use of the method that you just wrote (the helper method).

The header of the new method should be exactly as follows:

public void insertDisc(int column, int player)

where column is the column (enumerated from left to right, starting with 1) in which the disc should be placed. Furthermore, player specifies one of two players (either 1 or 2), which in turn affects the color of the inserted disc (red or black).

Note: The newly inserted disc will be placed in the row closest to the bottom, which does not yet have a disc in it. Therefore, before we can call the method that actually places the disc in the right spot, we need to determine in which row the disc will end up. How can we do this? How can we remember, which row in a certain column is the first empty one?

My suggestion is to use an array, which stores for each column the number of the highest row that is already filled. At the beginning, each entry is obviously 0, since no discs have been entered, yet. Every time a disc is entered into a certain column, the respective value in this array has to be incremented.

Hint: Be aware, rows and columns on the board are numbered from 1 upwards, while array index values start at 0.

Milestone for 1. Part

You should now have a working Connect4Board class. You should be able to create boards of various size and you should be able to insert a disc into a certain column calling the appropriate method. The interface of your classConnect4Board should look exactly like the image at the top of this page. You can check this in BlueJ by selecting the "Interface" view from the drop down menu on the top right corner (by default it shows "Implementation").

In order to hide your helper methods, which are only used inside your class and should never be called by another object from outside the class, you can declare them as "private" instead of "public".

Deliverables:

  • Submit the file Connect4Board.java which contains your Connect4Board class.

  • Submit the modified files Square.java and Circle.java.

  • Only one version per team needs to be submitted.

Documentation

You must document any code that you created or modified (e.g., your Square and Circle classes). Indicate which methods/constructors you wrote (or the whole class if you did) in a comment. Include both your name and your partner's in a comment. You must also include a comment indicating how much time each partner spent typing. Remember that each partner should type half the time and watch half the time and that you should use one computer for the two of you. You should use javadoc (/** this method does this */) to describe each method. You will lose up to 15 points if you do not have comments (especially how long you and your partner spent typing, not a percentage, but number of minutes or hours).

MOVE ON TO PART 2