Last week, I went through the solutions of the first three tasks at tic-tac-toe game tutorial. This time, I will cover up the rest. Please see the list of tasks again:

  1. Display the location for each move in the format (col, row) in the move history list.
  2. Bold the currently selected item in the move list.
  3. Rewrite Board to use two loops to make the squares instead of hardcoding them.
  4. Add a toggle button that lets you sort the moves in either ascending or descending order.
  5. When someone wins, highlight the three squares that caused the win.
  6. When no one wins, display a message about the result being a draw.

If you’d like to take a look at the initial article, please check this one out.

Task #4 Add a toggle button to sort the moves

I must admit that I struggled with this task a bit, because I couldn’t make my mind whether I should reverse the history in this.state or in a copy of history array. After my first implementation, I realised that things get fuzzy when you mingle with the state quite often. Because, making changes in the state side-effects the other functions inside Game.js. So, I threw away my first code and followed a brand new plan.

To start with, we definitely need a new state attribute for the sorting choice. I added it to my constructor with default value ascending.

Screen Shot 2019-02-28 at 23.46.28.png
Add this.state.sortASC to the constructor of Game.js

 

We surely need a new function to toggle the sorting direction. This function will be called each time the user clicks on our sort button. So, I added toggleSort() inside Game component.

Screen Shot 2019-02-28 at 23.47.59.png
Add toggleSort() function

It is time to make some changes at rendering now. Since I do not want to reverse this.state.history, I get a copy of history and reverse it if sorting direction is descending. Also, please note that I also reverse the move value inside map(step, move).

Screen Shot 2019-02-28 at 23.52.44.png
Get a copy of history and reverse the copy

Next change inside the render creates our toggle button. I have been too lazy to add some SVG images and work on CSS. Therefore, I used UTF-8 arrows 🙂 And do you remember the toggleSort() function? This is a good time to use it.

Screen Shot 2019-02-28 at 23.55.33
Implement sortButton with an arrow

The last snippet is a piece of cake.

Screen Shot 2019-03-01 at 00.00.24
Add sortButton and use unordered list if you like

Ta taaa!!! Below is the outcome. If you’d like to see the commit, click here.

toggle sort tic-tac-toe react game
Tic-tac-toe game with sorting

Task #5 When someone wins, highlight the three squares that caused the win.

As we go further, the tasks become a bit more challenging. So, this implementation requires changes on all components. I will follow bottom to top approach. That means we will see the implementation sequence as following:

  1. Square.js
  2. Board.js
  3. Game.js

Square component is called by Board and it is responsible of rendering the boxes. Assume that Square.js receives an additional prop parameter which is boolean. And this input helps rendering the given box with gray background color or not. See the code below:

Screen Shot 2019-03-02 at 13.53.24
Add winnerSquare className if the boolean is true

And we certainly make this minor change inside index.css.

Screen Shot 2019-03-02 at 13.58.52.png
index.css

After these changes, we are done with the Square component. The next stop is Board. Let us first establish our previous assumption for the Square. Consider that renderSquare() function will pass the boolean to the Square.

Screen Shot 2019-03-02 at 14.00.53
renderSquare should get a second input: winnerSquare

And our createTheBoard() function still calls the previous function inside two for-loops. Assume that we have a handy function which figures out if the current square box is a winner box. So, call it accordingly.

Screen Shot 2019-03-02 at 14.05.18
this.isWinnerSquare(arrayPos)

And it is time to keep our promises again. Implement isWinnerSquare(). But see that we again make a new assumption here. Assume that Board will receive the winner coordinates from Game.js. If the coordinates are null, boolean is false. If current square box position is one of the winners, boolean is true. Simple huh?

“If you can’t write it down in English, you can’t code it.” – Peter Halpern

Screen Shot 2019-03-02 at 14.06.37
Implement isWinnerSquare(…)

We are about to finalise the implementation. calculateWinner(…) knows which lines are the winner squares. Instead of returning the name of the winner, it’d better start sending an object which keeps both the coordinates and the winner name.

Screen Shot 2019-03-02 at 14.12.29
calculateWinner will send the coordinates and the winner name.

As the final touch, I edited the use of winner object and the result is astonishing 🙂 See the commit here.

When someone wins, highlight the three squares that caused the win
When someone wins, highlight the three squares that caused the win.

Task #6 When no one wins, display a message about the result being a draw.

The last task is kind of easy. I see that the draw happens when all squares have some X or O value, but the calculateWinner function yet does not return a winner. So, I insert my check inside the if scope:

Screen Shot 2019-03-02 at 14.44.33
Game is a draw

If you are curious about the commit, check it here. And below is the final output of our tic-tac-toe game:

When no one wins, display a message about the result being a draw
Enhanced version of tic-tac-toe game

As you see, the winner of the last game is neither X or O, because the real winner is YOU who puts effort to learn React.

Sercan Leylek / OSLO

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s