Plan and done for February-19-2018

What will I learn today?

FreeCodeCamp projects: TicTacToe - start coding.

Done

TicTacToe app

Challenges

  1. How to implement game engine - what is the algorithm inside it?
  2. What is a winning in terms of algorithmical calculation - how to calculate that I have winning condition on the board?
  3. How to find which player's turn next?
  4. What is 'empty' value in an Array generated by new Array(number)?
  5. After implementation of minimax I've found myself with an utility value but without moves - how could I add to minimax return any sugestions on the next move?
  6. How to pass a parameter to an event callback function?
  7. How to make the engine work in async with UI and prevent itching in a player interaction with the game?
  8. How to restart the game after we've got either winning or draw conditions?

Solutions

  1. Algo - minimax as it described in the Wiki page. Another explanations are at Youtube - academic, less formal.

  2. SO gives the algorithm to estimate an answer. I have alternative approach - find masks which represent winning, transform board into binary representation and apply mask to it. If result is the same as mask applied - here's winning position. The question: what is efficiency for each approach? For SO algo the complexity is O(n), n - is dimension of the board. For my approach - O(n^2 + n).

  3. I can track the current player or just get it from the board state. I'll use reduce for it: array.reduce((res,elm) => elm ? res + 1 : res,0).

  4. Unbelievably long search why my toString didn't work the right way - it just silently swallowed empty values. Here is a good snippet to detect empty values in Array.

  5. I shouldn't - I've implemented the separate chooseMove() function where I initialize all available moves with their utility values and than I just choose the best or any depending whether utility equal for multiple values or not.

  6. We can either bind this with additional paramenter to the function - take a look here. I've tried to use an arrow function as a callback, but it prevents me from removing listener down the road. Final approach is to make cells distinguishable by id and communicate through the DOM:

    boardCells.forEach((cell, ndx) =>
      cell.addEventListener('click', e => this.handleBoardClick(e, ndx)),
    );
    
  7. The broad article states that there are two available options: split intensive function into pieces and run every along with browser animation frames routine or use WebWorkers. As the MDN article says:

    The worker thread can perform tasks without interfering with the user interface.

    I should try the approach, but later, when all bugs will be fixed and the game will be ready. And I've found another option - Web Animation API.

  8. I've implemented it as reinitialization of the whole application - the same routine which is called once an app starts. But here I've encountered another problem - multiple event handler calls and it escalates with each actual trigger. Looks like I add more and more identical handlers with each restart.

    I've solved it by light reengineering the code: I don't need to reinitialize the whole app on reset, just draw the clear board and add all event listeners;