JavaScript Tic Tac Toe Project Tutorial – Unbeatable AI w/ Minimax Algorithm

A full web development tutorial for beginners that demonstrates how to create an unbeatable tic tac toe game using vanilla JavaScript, HTML, and CSS. Learn the Minimax algorithm!

⌨ Part 1: Introduction (0:00)
Code: none

⌨ Part 2: HTML (2:58)

⌨ Part 3: CSS (4:23)

⌨ Part 4: JavaScript: Basic Setup (10:28)

⌨ Part 5: JavaScript: Determine Winner (20:32)

⌨ Part 6: JavaScript: Basic AI & Winner Box (30:45)

⌨ Part 7: JavaScript: Minimax Algorithm (39:25)

Special thanks to David Daly and myloginistaken who found a mistake where the game sometimes incorrectly shows a tie game. The ‘Part 7’ GitHub code now contains this fix.

🔗Minimax article:

🐦 Beau Carnes on Twitter:

Learn to code for free and get a developer job:

Read hundreds of articles on technology:

And subscribe for new programming videos every day:


Knowledge and Learning center says:


Emre Tekince says:

Hi, I think you should use better editor or ide to see errors. I’m using webstorm. Also you can use “includes” instead of “indexOf”

Desi S. says:

I know you can pause the tutorial at any point but it’s funny to see how fast you type when you know what you’re doing and typing.. I promise it looked like you were FF lol.. In comparison to me who can type but I have no clue yet lol

Oliver Mensah says:

Doing more of projects like this will help us a lot

Ian Ross says:

Love it! This might now be my favorite video on this channel. The more like this the better.

myloginistaken says:

In 0:10 why does it say “tie game” if O clearly won?

Also in 0:16, why doesn’t the AI put X in the bottom in order to win?

James Reynolds says:

I’m not sure if this is the best place to post this but here goes. I am having trouble with my minimax logic. There are some fringe instances of it not making the best move.

If for example you play the following moves by index you will win but it says that you tied. First human move at position index 1, next move 2, next move 7, next move 5, at this point the AI should play position 8 to block but instead it plays position 6. If the human player then plays 8 that makes three in a row in the right column but it says tie. Where did I go wrong? The AI should not lose so something is not right.

EwokPanda says:

0 -> 2 -> 7 -> 5 -> 8 = I win
Btw, with all of the newbies trying to learn as much as they can, I feel like you should be really trying to focus on best practices, like consistency in your for loops of using let.

dasp125 says:

I have done the tutorial and there are no errors, but the O and X does not print onto the screen. Could it be something to do with the browser? I have checked the code against your and it is correct.

Johnathan F says:

Why don’t you actually cover minimax in the minimax section? smh…

Jimmy Tu says:

I was trying to understand the code as I was testing around before the min/max function was added. When the bestMoves is just calling the first index. If I go on cell 3, 4, 6 and I’m suppose to be the winner it shows computer as a winner.

After adding the minimax function I was able to beat the AI by going to these cells in this order [5, 6, 0, 1, 7] even tho there is a but that shows it as a tie. Nonetheless it was a helpful video maybe you can make one to address and fix some issues to better logic in checking wins and the order.

EverJouleSky says:

This is so helpful. Its simple but creates an end project which feels like you’ve accomplished something

Tapan Anand says:

You could have simply centered the board by using margin-left: 50px auto; on the table

Keep moving forward says:

thank you….
sorry if i hurt you… 😀

Donovan Peralta says:

Nice tutorial. A couple of things: that’s an awful way of centering simple elements like a table. You could have used “auto” for the left and right margins. Also, that class of “cell” was unnecessary. Even in the CSS you targeted the cells by their tag name. Why not do the same in the JS? Still, I think you did a great job. Keep up the good work.

Uzee says:

its awesssssssome………!!!! Is there any way to win this game…!!!! :-O :-O :-O

EwokPanda says:

I’ve fixed the algorithm: Due to the nature of recursively finding more possible winning moves when choosing another spot over the winning spot for the AI (many times, it could win, but doesn’t choose the winning spot), I’ve added a third parameter to the function – a weighted counter to multiply the score.

function minimax(newBoard, player, counter = 256) {
counter = counter/2

return: {score: 20*counter}

let result = minimax(newBoard, huPlayer, counter);

let result = minimax(newBoard, aiPlayer, counter);

Now the AI really does always win.

ahmad abdolsaheb says:

Great explanation. I wish this video was around when I did my tic tac toe. It took me more than 20 tries just to wrap my head around minimax. :..)

Chris Jones says:

I encountered a syntax error which I cannot account for at line 34. CANNOT SET PROPERTY ‘INNERTEXT’ OF NULL.

Michael Pimentel Jr says:

You my friend are a genius! Love this. keep it up!

Directional says:

lol tic-tac-toe took an hour to make gj!

Joel Longie says:

Great video!

vineet kapoor says:

Thank you for the video!
Just a small question, Why are we using ‘==’ instead of ‘===’ @35:21 ln:66 & 74? Isn’t it better to use ‘===’?

SkyGamer says:

hi what plugin did u get???

Umbrelluck says:

Hello) Great tutorial! Can I translate it into Ukrainian and post it on my YouTube chanel?

Joffrey Lannister says:

anyone else getting an error ‘cannot read property ‘style’ of null at the ‘startgame’ function?

Chris Jones says:

Most of the books on the subject are obfuscating and lacking in sufficient examples and projects to master the concepts. I have a book called ‘A Smarter Way to Learn Javascript’ on the way from Amazon. I’m not giving up in general, but I lack the experience and knowledge to comb through this code to find the problem. I can make the example work by using a method that is simpler to me.

B R says:

If someone has done this on can you please link me to the page. I don’t know what I did wrong and currently asking for help.

Xun Guo says:

may i know the complexity of this search algorithm? and is there any limitation of this search strategy?

John Barbakadze says:

Thank you Beau. I found that after taking the FreeCodeCamp front-end courses those videos are really helping to get deeper into understanding JavaScript even though I have to watch them some times. I would certainly buy you a beer.

Lino9026 says:

Man not much can match the feeling of getting to the end result and it works!!! I love that feeling of accomplishment! Thanks man! Definitely make more of these!

Šimon Buryan says:

great tutorial, however i checked the gih hub repo and there are 0 comments in the JS code, zou have comments in the tutorial, bus still might be better do always add comments in the JS code you are writing…

payskin says:

4:05 Why on Earth do you use the onClick ‘attribute’? o.O Especially in camel case?! The idea of unobtrusive JS is 15+ years old. Writing a simple click event handler is 1 minute tops. You’re kind of teaching here, making an example, you should not use age old anti-patterns in your HTML. 🙁

12:20 0-3-6 is not the diagonal win, it’s the first column vertical win

Kenneth Brisco says:

My ai is still beatable with your tutorial. Thanks for trying though

Luis M Serrano says:

I loved this tutorial, thank you so much!

M R says:

I am a beginner and I am breaking down the code line by line. I am totally stuck at the code of reduce, 22:00 on the video. I understand it is reducing down the array but what is a.concat(i) exactly doing or if false (a, [ ]) , anybody?

Anton Smid says:

It’s a great tutorial, I really enjoy it and wish you do more of this sort – but at 39:02 you actually win. It’ s not a Tie game…
And after implementing minimax you win again at 44:45 – and the display Tie game is wrong…

You can always win, if you play 1, 3, 8, 6, 9 sequence (up left 1, down right 9).

Anton Smid says:

Hi , just dl the code from GIT and it works OK! Great. I made it a little more human by changing the bestSpot() function like this (so you have a chance to win – sometimes 🙂 ):

function bestSpot() {
var coin = Math.random();

if (coin > 0.8) {
return emptySquares()[0]; // before minMax
return minimax(origBoard, aiPlayer).index; // for MiniMax implementation

 Write a comment


Do you like our videos?
Do you want to see more like that?

Please click below to support us on Facebook!