Today I wanted to challenge myself with a code challenge from @mouredev’s challenge group listed in https://github.com/mouredev/Monthly-App-Challenge-2022 .
Why this challenge?
I chose that list of challenges because I found them interesting and they are well defined so that I know where to start but at the same time they offer you options to extend the applications as far as you want.
For that reason I want to complete all the monthly challenges to see different aspects and at the same time build a portfolio of interesting projects.
Why in Flutter?
My idea is to complete all the monthly challenges in Flutter as it’s a programming language I discovered the past year and which I believe is a very good option to develop hybrid apps.
It offers you a backbone and a set of prebuilt widgets that enable you to deliver an application such as this challenge in less than a day. (Of course a big app would require more time)
Challenge requirements
The first challenge is to build a connect 4 game to be played with another person in the same device by alternating shifts with the opponent.
The challenge defined some requirements that to sum up, are:
- The board has to be 7×6
- The pieces are red for player 1 and yellow for player 2.
- The first game should start with player 1, the next one by player 2 and repeat it alternating who starts.
- The user only has to be able to play with another person in the same device (no AI, no online modes)
- A piece is added just by tapping anywhere in a column and goes to the bottom.
- The app should store the scores while opened
- There should be 2 buttons, one to restart the current match and another to reset the whole scores.
First thoughts and decisions
Taking that into account, the first thing I did was to draw what should the app look like and start asking myself some questions about the implementation.
![](https://jordivx.com/wp-content/uploads/2022/09/image-768x1024.png)
And as shown in the picture, my first question came either if using the GridView widget or if use just Column widgets.
I first thought about trying with the columns option just as it could be easier to animate the piece to reproduce the “falling” effect to reach the bottom of each column, however, I finally decided that the Grid option would give a better responsiveness and it would offer me more advantages.
Do you think I made the right decision? Or would you have done it differently?
Choosing the GridView Flutter widget
Once decided to use the GridView widget, I started by just adding a grid with the requested size and adding rounded empty containers to simulate the places where the pieces could go.
After having the board defined, I then defined an array of as many pieces as the grid had to use it as an engine for the game. That array would contain information to check if the gap is empty, or if it’s fulfilled by a player or by the other.
Right after having the board displayed and the list that would contain the board’s information, I just implemented a method that by pressing a gap, it would convert that gap to be black instead of empty.
The first version of the app
By that moment, the game was looking awful and it didn’t work as specified in the requirements, but at least I had built something in a few minutes that already worked.
![](https://jordivx.com/wp-content/uploads/2022/09/Captura-de-Pantalla-2022-09-08-a-las-19.26.45.png)
Once the method for fulfilling the gaps when clicking them was implemented, the next step was to add the logic so that if the gaps below the selected gap were empty, the “piece” should “fall” until the first empty gap.
To do that, and as I have the information about how many columns there are in the grid, I iterate over the array that contains the board information and if the value for the position clicked is a 0, I check 6 positions after the same array (number of columns) and I repeat the operation until I find something that is not a zero.
At this point on time, the application had “physics” and by clicking anywhere in any column, the user’s chip would always fall until the first available gap.
The next actions were to include a variable to set which player turn was and that variable would only contain the values 1 or 2. And according to it, now when the user clicked a gap, depending on which number had the variable, now the gap would be painted red or yellow instead of black.
Now the application looked fine and actually seemed a game, but it never ended, at the end it was just painting gaps when tapping on the columns.
The most difficult part for me
To calculate when a player wins, I added a method that would check the position of the current player’s pieces.
I think this method was the most difficult to implement as I had to figure out how the positions that I was seeing in the board were reflected in a single dimension array. How many positions would mean that a position is under another, by its side or in diagonal. And then when knowing the real positions, be able to calculate the pieces are together without empty spaces or another player’s pieces between.
![](https://jordivx.com/wp-content/uploads/2022/09/Captura-de-Pantalla-2022-09-08-a-las-19.11.28.png)
![](https://jordivx.com/wp-content/uploads/2022/09/Captura-de-Pantalla-2022-09-08-a-las-19.12.42-1024x298.png)
![](https://jordivx.com/wp-content/uploads/2022/09/Captura-de-Pantalla-2022-09-08-a-las-19.13.26-1024x215.png)
![](https://jordivx.com/wp-content/uploads/2022/09/Captura-de-Pantalla-2022-09-08-a-las-19.15.52-1024x992.png)
After building this methods, the only missing parts were the 2 buttons that would reset the game and the scores.
To reset the game I just need to put the game information array back to 0 to all its positions.
To reset the scores I just need to set the variables that control the scores for the 2 players back to zero.
And here is how the application looked at the end:
![](https://jordivx.com/wp-content/uploads/2022/09/Captura-de-Pantalla-2022-09-08-a-las-19.23.41-586x1024.png)
You can find the challenge code in https://github.com/jordivx/connect4 for further details and information.
If you have any suggestion, please add a comment here or in GitHub.
Cheers!