So I’ve been in the process of getting started with writing the tic-tac-toe game. I have a good UI, I have a process that checks who wins (user or computer) I’m just not sure how to get the computer moves started - I’ve read about the minimax algo though I’m not understanding it and am unsure what the best way to implement a computer move would be. Does anyone have ideas on getting started? Is someone willing to pair code with me?
Code on GitHub: https://github.com/nsuchy/freecodecamp-build-a-tic-tac-toe-game
Some Notes on my code:
The current code is mostly checking against the text content of each button that has a unique, if needed the code can be include some sort of array of input for easy iteration to decide a move. On each button click, the button’s text is updated - checked for a win - then the computer will move - and again check for a win. I’ve included these notes to help whoever wants to help further understand what my code is trying to do.
Hey, I feel you. The min/max algo can be pretty tough to understand at first. I for one, was not able/willing to make sense of it when I was working on my TTT project. I ended up going with the very low tech method of just making the computer select a random square each time. It’s not elegant, or even a very good solution, but it works.
One of these days I am going to revisit the project and get min/max working… and make it prettier to look at
What if the randomly selected square is in use? How do you deal with that?
I wrote a function that would check to see if the square was empty or not. There needs to be some way to make sure each move is unique any ways.
I assuming you used some sort of loop to just keep trying until you found an usued to square? That doesn’t sound like a good way of winning.
Yep, you got that right! It is a pretty crap solution. But it is a solution…
That being said, I took a glance at some of your code and have a couple suggestions to DRY it out.
You can combine all the individual onClick functions into one by using a selector that gets every square (ie getElementsByClassName) and puts them into an array. You can then use a forEach to bind your click function to each square.
You could also refactor how you deal with picking a winner. I used an array or arrays of the win cons, and an array for each player’s moves and then compared the moves to the win cons array at the end of every turn.
Both of these require you to have track whose turn it is as they will need to reference that value to either mark a square, or push the moves into the correct arrays.
Of course, if what you have is working already…
it’s like any other problem - if can’t grok it keep breaking it down till you do - there are many ways to break down a problem - you could reduce the problem size - you could reduce the problem scope - you could partition the problem
the first and most important step of problem-solving is to have a clear statement of the problem - there’s little hope of solving anything if it’s not clear what you’re solving - and if you find a solution how will you tell it’s correct
once one or more subproblems are clearly stated then pick a subproblem and describe a general solution on paper using everyday language with no or minimal programming terminology
let’s say we start with trying to win at tictactoe - I hope it’s apparent this is too vague for a problem statement - we need to break it down
what does winning at tictactoe mean - well it means we reach a winning state of the game - what is the state - the state has our mark in certain patterns on the board
what are the patterns - the patterns are one row or one column or one diagonal full of our marks
that’s too many patterns - how about we just go for a full row win
the game proceeds turn by turn - we need to figure out what the move should be if a full row is the goal - this means we need to know if a row is empty or has just our marks at the time of a move - if there’s a choice clearly we should prefer a row with the most number of our marks - this kind of gets us somewhere
there’s a problem if we just focus on filling a row with our marks - the opponent could be filling a row too and win before we can fill one row - we should think about not losing in addition to winning - how do we not lose - well we prevent the opponent from reaching a winning pattern
the subproblem statement now is - pick a square to mark knowing the state of the game with the objectives of preventing the opponent from winning and we trying to fill one row with our mark
rinse and repeat