Skip to content

Third project in the Code Institute Full Stack Developer Course. Play Connect-4 against the computer at three different skill levels.

Notifications You must be signed in to change notification settings

bobshort4bobby4/Connect4-PP3

Repository files navigation

Connect4

(CTRL + Click to open links in new window)

The deployed site can be found here

Github repository can be accessed here

a mockup of the deployed application

Introduction

This my third project undertaken as part of the Code Institute Full Stack Diploma Course

It is a version of the classic board game Connect4, implmented using the Python coding language and deployed via heroku to the web.

It was designed by Wexler and Strongin and NOT as I believed for many years by David Bowie which is an urban myth.

The game was first sold in 1974 by MB games of Springfield MA. It was a global success and spawned many spin-offs and variations.

The rules are simple, each player has 21 checkers of the same colour, either red or yellow in the original game. The players take turns placing their checkers into a 6 by 7 grid, the grid is suspended vertically and the pieces drop to the first available position.

The winner is the first player to connect a line of four of their particular colour.

If neither player connects a line of four before the grid is full then the game is a draw.

More information regarding the game can be found at this link. Connect4 Wikipedia Page is here

User Experience/User Interface (UX/UI)

User Experience/User Interface (UX/UI)

User Stories

First Time Visitor Goals

As a first time visitor I want:

  • the rules and final aim of the game to be obvious so that I can use the site easily.
  • to be entertained and engaged with the game from the initial load so I will have a positive experience using the site.
  • the game to function correctly and gameplay to be intuitive so that I do not have any frustrating emotions using the site.
  • to be able to play the game on various different devices so that I can play when convenient.
  • to have any incorrect input rejected and the error explained clearly and quickly so I do not have any frustrating emotions using the site.
Return/frequent Visitor Goals.

As a return/frequent visitor I want:

  • to be able to gauge my performance so that I can track my skill level .
  • to be able to increase difficulty of the game so that I can challenge myself.
  • to be able to play the game on various different devices so that I can access the site when convenient.
Website's Owner Goals.

As the developer I want:

  • to provide a fun game so I feel I have produced a quality website.
  • to provide a game to stimulate mental function so that I provide a worthwhile experience for the user.
  • to encourage continued use of the game so that the site is a success.

FlowCharts

A Flowchart for the python script in shown below as well as a link to the pdf of same.

Link to Flowchart Pdf can be found here

screenshot of flowchart

WireFrames

The design is very basic and does not change, consequently I felt a one page Wireframe would be sufficent showing the basic lay-out of the site.

A link to the pdf file for the Wireframes is here.

image of desttop and mobile wireframes

Background Image

In order to add visual appeal I used a repeating tile as a background image. It is a picture of a section of the gameboard.
After deployment, taking feedback from PP2 into account I decided not to use this image and replaced it with a plain blue background.

Link to background tile

the background image tile

Features

Features

Welcome Screen

On loading the initial screen displays a title in ASCII art and some background information about the game. Brief play instructions are also included. The game pauses on this screen untill the user hits the return key.

a screen shot of the welcome screen

Level Screen

When the User presses the return key, the level screen is displayed.
This screen shows the 3 possible difficulty levels the user may choose.
This setting governs how the computer moves are picked.
The User is required to pick one from the three options of Easy, Medium or Hard.

a screenshot of the levelscreen

After the User picks a level the screen shows which player is to go first (randomly choosen by program), then pauses before clearing and displaying the initial board.

Game Screen

The game screen consists of the board display and a prompt to the User to pick a move.
The computer moves happen instantly after each User move.

a screen shot of the initial game screen

Game Over

The players take turns until the game is won or drawn.
A message is displayed stating if a win or draw, which player won and how many moves were taken by them.
The User is asked to input either quit or play again.
If the User opts to exit the finish screen is displayed and the program exits,
alternatively the program loops back to the welcome screen and a new game is initiated.

a screenshot of the game over screen

Finish Screen

If the User opts to quit a message is displayed and the program finishes.

a screen shot of the finish message

Difficulty Levels

The computer moves are calculated in different ways for each of the levels.

The first (easy level) is completely random, a random number is picked in the column range and provided that column has remaining space, the piece is dropped there.

The medium and hard levels use a simple scoring scheme which gives every position on the board a score based on that particular moves value to the computer player.
The piece is dropped in the column with the highest score.
All possible positions are scored on the hard level, some of the diagonal line slices are not scored on the medium level, thereby creating a "blind spot" for the computer.

This method of scoring is by no means perfect but offers a reasonable challenge to the casual player.

Details of how I implemented this scoring scheme are shown in the pseudocode below, I should say that the general method I learned from various resources on the internet but the implementation is my own. I choose to place an token (in my case '*' into the temporary board for scoring which I did not see any other implementation use (others placed their player piece), this allowed me to be more specific in the scoring process. As to the merits or disadvantages of this way of doing it I have not tested.

Easy Level

This method picks a column for the computer player on easy difficulty level.

If the choosen column not full:
      pick a random column number in range zero to six
return that column number

Medium Level

These are the steps I used to pick a column for the computer player on medium difficulty level.

computer_move_scored() Method of Player Class

Determine opposing player piece type, store in op_piece.
Determine columns which are not full, store in an array valid_cols, with a -1 entry if column full.
Determine first available position in each column, store in an array first_available_row.
For each valid column in valid_cols:
      Make a deepcopy of state of the playing board named temp_board.
      Place a '*' into the lowest empty position of that column.
      Send temp_board to player.scoring_function method.
      Append returned score to final_scores array.
Determine index of highest score in final_scores array, store in variable col.
Return col.

player.scoring_function Method of Player Class

Create score variable
For each row in temp_board:
      Create an array for each row called row_array
      For each row_array:
      Slice into sections of four positions, stored in array called slice4.
      Send each slice4 to player.scoring_logic.
      Add returned value to score.

For each column in temp_board:
      Create an array for each column called column_array
      For each column_array:
      Slice into sections of four positions, stored in array called slice4.
      Send each slice4 to player.scoring_logic.
      Add returned value to score.

For each forward-leaning diagonal column (left-hand side) in temp_board:
      Create an array for each section called diagfor_array
      For each diagfor_array:
      Slice into sections of four positions, stored in array called slice4.
      Send each slice4 to player.scoring_logic.
      Add returned value to score.

For each backward-leaning diagonal column(right-hand side) in temp_board:
      Create an array for each row called diagback_array
      For each diagback_array:
      Slice into sections of four positions, stored in array called slice4.
      Send each slice4 to player.scoring_logic.
      Add returned value to score.
Return score

player.scoring_logic Method of Player Class

Create score variable.
Add value to score for each slice4 on the following basis.
If slice4 contains:
      3 player pieces and 1 asterisk add 2000
      2 player pieces and 1 asterisk add 1000
      1 player piece and 3 empty add 100
      Is column 3 add 50.

If slice4 contains:
      3 op_piece and 1 asterisk add 10000
      3 op_piece and 1 empty add 2000
      2 op_piece add 1500

If slice4 contains op-pieces in the middle indexes and an asterisk at either index[0] or index[3] add 7000.
Return score

Hard Level

The steps are the same as the medium level except all diagonal columns are scored.

Future Features

At some point as time resources allow I would like to implement the MiniMax algorithm for the hard level. This is a recursive algorith used to determine optimal moves.
It creates a tree for each possible gameboard and backtracks through each to score each board.

It would improve the visual aspect of the program if the two types of pieces were coloured differently
and highlighted in a third colour when a line of four was made.

Technologies Used

Technologies Used

Languages Used

  • Python
  • CSS

Development Environment

I used the python-essentials-template for gitpod provided by Code Institute.

Python Libraries

random was used to generate a random integer used in the computer_move_random method of the Player Class and to determine which player should take first turn in the display_intro method of the Board Class.

copy deepcopy() used to copy board state into temp_board in computer_move_scored() method of the Player Class.

time used to pause game in the init_game() method of the Player Class.

pyfiglet used to create ASCII art text in display_intro() method of Board Class and play_again() method of Board Class.

Version Control

Git is an open source version control system and was used for this project. Github was used to store the repository.
Git is run locally whereas Github is cloud based.

Please note feedback from PP2 regarding git commit messages was received after this project was completed. Unfortunately I was not able to implement the changes suggested as commits had been made.

Forking

Forking a Github repository is the process of making a copy of any repository that you can use without affecting the original, this original is known as the "upstream repository". The process for forking a repository is set out below.

  1. Go to the Github page that hosts the repository you wish to fork.
  2. On the top-right of the page there is a button "Fork".
  3. Click this button.
  4. This creates a repository in your Github home page which is a copy of the original. You can submit and receive changes to the code by using pull requests and/or syncing with the upstream repository.

(Taken from the Github Docs guide "Forking Projects")

Cloning

Cloning a repository involves making a full copy of that repository on your local machine. This makes working on the code easier. Changes can be pushed back up to the GitHub site or changes from other sources pulled to your local copy. To make a clone follow the process below.

  1. Goto the repository page on GitHub.
  2. Above the file list click on the green button titled "Code".
  3. You can choose to download a zip file of the repository, unpack it on your local machine and open it in your IDE or,
  4. Clone using HTTPS by copying the URL under the HTTPS tab.
  5. Open a terminal window, set current directory to the one you want to contain the clone.
  6. Type git clone and paste the URL copied from the GitHub page.
  7. The repository clone will be created on your machine.

(Taken from the Github Docs guide "Cloning a repository")

Data Model

I used Object Oriented Programming to develop this program. There are four classes used in the program namely:

  • Board; a class used to represent the game board and methods relating to it.
  • Player; a class used to represent the two players in the game and methods associated with them.
  • ColumnFullError; used to raise an error if a play column is full.
  • ClearMixin; this class is used to clear the terminal. It is passed to both the Player and Board Class as a required parameter.

Applications Used

Testing

Testing

WAVE Accessibilty Tool

The deployed version was tested using this site. The first test produced one contrast error, caused by the red colour of the 'Run Program' button not contrasting well with the background image I had choosen.
I changed the button colour to blue. This adjusted site produced no errors, result is shown below.
Please note the Wave result is similar when the adjusted background version is used.

a screen shot of the WAVE test result

CSS Validation

I made minimal changes to the css integral to the template provided, namely changes to the positioning of the terminal, adding a background colour and changing the colour of the 'Run Program' to blue. I tested the body and button css fragments using the w3c validator and no errors or warning were generated.

PeP8 Linter

I submitted all python files to pep8online.com and cleared all errors and warnings.
Screen shots of the results can be found here

LightHouse Testing

The Lighthouse testing tool built in to the Chrome browser was used on the deployed web-site. A screen shot of the result is shown below.

a screen shot of the lighthouse testing result

Manual Validation of User Input

I manually tested all aspects of user input and the results are linked below.

Link to User input testing data

Testing of Win Check and Scoring Algorithms

In order to ensure the win check and scoring aspects of the program were functioning correctly. I inserted a nested for loop in the relevant scripts, which placed consecutive numbers in the array, the code and the resulting array is shown below.

a screen shot of nested loops used to fill array with test data

a screen shot of resulting array

I then put a print command in the scripts which output each slice to be assessed to the terminal. I was then able to run the program in debug mode and manually check that the correct slices were being generated at each iteration of the scoring/check win function.
An example of these terminal outputs is shown below.

a screen shot of output slices

I found several mistakes either in index assignment or in code blocks wrongly indented which were causing errors using this method.
An example is shown below where the column loop was working incorrectly causing only the first column to be scored, this was an indentation error.

a screen shot of a bug found

Testing game for achievement of User Goals.

Goal Outcome
The rules and final aim of the game to be obvious Instructions displayed on welcome screen.
To be entertained and engaged with the game from the initial load. Colour used in an effort to engage user.
The game to function correctly and gameplay to be intuitive. No logic errors in code, actions to be taken intuitive.
To be able to play the game at different difficulty levels. Three levels provided.
To have any incorrect input rejected and the error explained clearly. All User input validated and appropriate messages output to User.
To provide a fun game. Game provides a reasonable challenge and is easy to use.
To provide a game to stimulate mental function. Game play requires attention and focus.
To encourage continued use of the game. Colour used in an effort to entertain user and encourage continued use.

Issues

If the deployed game is left unattended for any period of time, it will sometimes freeze and will not take input. The browser needs to be refreshed or the 'Run Program' button clicked to start a new game. This is not an issue on a locally run version of the game. I believe this may be due to the way heroku refreshed its dyno's.

If the human player is drawn to take first turn it is still quite easy to win the game. Because the computer always scores the board using the same method it is possible to build up an knowledge as to where the piece will be placed. After repeated games it is possible to learn ways of winning every time.

Video Screen Capture Of Deployed Heroku APP.

This video clip shows the deployed app working. Please note that the original background is used in this clip, the final deployed app has a plain blue background.

Debut.1.mp4

Deployment

Heroku

Heroku

Heroku is a cloud based platform that allows the user to deploy and manage apps easily. Heroku is fully managed meaning that all the hardware/server issues are taken care of. It allows the linking of github repositories which makes deploying easier.

To deploy my project I followed the steps below.

  1. Goto the Heroku home page and open an account.

  2. Goto your dashboard and click on the 'new ' button in the top right of the screen.
    screenshot of new button

  3. From the drop down list choose 'Create new App'. a screen shot of the create new app page in heroku

  4. Choose a name for your project and the region you are in. Click 'Create App'

  5. Click on the 'Settings' tab. a screen shot of the settings tab

  6. Click 'Reveal Config Vars.

  7. Enter port and 8000 as a key:value pair and press Add

  8. Click 'add buildpack'

  9. Add the Python buildpack then the nodejs one. Click 'Save'
    a screen shot of the buildpack screen

  10. Select the 'Deploy' tab.

  11. Choose the'Connect to GitHub' option from the 'Deployment Method' section. a screen shot of the github deployment section

  12. Search for and enter the 'repo-name' in the input area.

a screen shot of the repo name input area

  1. Click 'Connect'.
  2. Choose either Enable Automatic Deploys or `Deploy Branch'. I chose the former.
  3. The site should now be deployed. Click the 'Overview' tab and the 'Latest activity' should have a 'build succeeded' message diplayed. The deployment log can be also accessed on the github repository under the 'Environments' section to the right of the page.

a screen shot of the buid succeeded

The site is now live

a picture of the deployed site

Credits

Credits

In order to learn how computers play against human opponents I used many resources on the internet, chief amongst these were Wikipedia and Keith Galli's github.

The format and method for the user input testing was learnt from a tutorial by Daisy Mc Girr.

Huge thanks to my CI Mentor Mr. Benjamin Kavanagh.

About

Third project in the Code Institute Full Stack Developer Course. Play Connect-4 against the computer at three different skill levels.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published