Multiplayer Tic-Tac-Toe Game in Python
Skills:
AI Pair Programming80%
Key Takeaways
Creates a multiplayer Tic-Tac-Toe game in Python using sockets
Full Transcript
[Music] what is going on guys welcome back in this video we're going to build a multiplayer tic-tac-toe game in python and we're not going to use pi game to do that we're not going to build a fancy ui around it we're going to use a command line we're going to use the command line only for that because the focus of today's video should be on the sockets on the networking on the connection and on the game logic not on the ui around it even though building a ui around it wouldn't be too complicated but it would distract today from the network content so if you really want to see a video on the ui of a tic-tac-toe game as well let me know in the comment section down below if a lot of you guys are interested i might make a second video on that as well the goal of today's video is that we want to have a python script that we can run across two different machines so these machines can be in the same network they can be uh they can connect over the internet so they one guy can be in australia one guy in europe doesn't matter they can play tic-tac-toe together of course if you want to run this via the internet you need to set up your firewall properly and all that this is not part of today's tutorial but we're going to build a python script that can connect to computers and they can then play tic-tac-toe via the command line this is the go and for that we're going to get right into the code we're going to only need two libraries for that and they're going to be uh core python modules the first one is socket and the second one is threading now threading i actually use this in my prepared code with the following idea i thought that we want to have one thread for processing our user input and one thread for getting the actions of the from the opponent but then i thought actually you know when i'm when when it's my turn i'm putting something into the command line when it's my opponent's turn uh turn i'm receiving so actually we wouldn't need multiple threads we can just uh change the states and and do it like that but uh yeah for this video we're going to do it with reading i just wanted to mention that i don't think that you actually need the threading module so you would actually be able to do this with socket only as well i think so so let's start with what was that with a simple [Music] tic tac toe class and we're going to start with the constructor with the init function and we're going to say self dot board and we're going to initialize the board now what you see here all the time is get up copilot i didn't disable it for that video um it's just suggesting what i might do here sometimes we're going to use it sometimes we're going to ignore it it's not necessarily part of the tutorial in this case it uh suggests that we create a list full of zeros or lists of zeros we don't want to do that because we want to do spaces so we're going to just ignore this and do it like that now in this case it auto-completes this so we want to have uh three rows and inside of these three rows we want to have three empty fields like that then we're going to also say basic stuff like whose turn is it we're going to start with x the u is going to be the x by default and then the opponent is going to be oh now you might say okay how do we decide that if two people run the script both are x uh we're going to set uh we're going to give x to the one who hosts the game and o to the one who connects to the game so we're going to have this client being able to host the game and to connect to a game so then we're going to also set a winner in the beginning to none we're going to set game over to false and we're going to also have a counter for the turns because we want to be able to determine a tie so if all fields are full uh so basically the counter is uh if the counter is nine we're going to have a tie if there's no winner and the first function we're going to write is the host game function the host game function is self-explanatory we're going to pass a host we're going to pass a port and we're going to open up a socket listening for incoming connections accepting connections and then handling them so we're going to basically say server equal socket socket dot af inet actually we need socket.socket socket afi net socket stock stream because we want to have a tcp socket tcp internet socket then we're going to bind the socket to a tuple of host and port and we're going to say server dot listen for one connection and what we want to do then is we want to accept the next connection so client and address is going to be server accept and then we're going to say self dot uh dot u is going to be x because you're hosting self dot opponent is going to be o and we're going to start a new thread threading dot thread uh target is going to be the function why is this blocking right now come on self dots what are we going to call this what did i call this handle connection self handle connection which is a function we don't have yet and the arguments for that are going to be just a client we're going to start this thing immediately and then we're going to close the server socket because we don't need to wait for more connections when we have one this is not a server that handles multiple games this is just one client and that's it so we don't have a loop and we can also close the server right away uh now what we need is we need to also define a connect to game function so connect to game which is going to be the opposite so one client has to run host game and one client has to run connect game and they have to specify of course the same target so here we're going to also say host port we're going to say client equals socket now we can use the auto completion here it's also again an internet tcp socket uh and we're going to connect this time to host and port like that and actually this time we're going to say self u equals o and self opponent is going to be x and what we want to do then is we want to say threading thread target is self-handle connection and client again and we want to start this so it's actually calling the same function which is exactly why i set that we can do this in a single thread because we don't there there's not much difference we just need to change the states here so now let's go ahead and write the handle connection function this is going to be actually most of the game logic now the game logic itself is going to be in another function but this is going to be the connection logic which uh calls the game logic so we're going to have client here um and we want to do is want to say okay while self or while not self dot game over so while while the game is not uh over we have created this here while this is not the case now actually here we have a suggestion we're not going to use such big suggestion blocks because then you know i wouldn't need to do a tutorial we're going to do it ourselves we're going to say if it's my turn so if self.turn equals self.u so if it's your turn right now what we're going to do is we're going to uh apply our move or we're going to first get our move from the command line so we're going to say move equals input enter a move and the format is going to be uh basically row column like that so essentially if you want to place it in the upper left you would say 0 0 first row middle would be 0 1 and so on so this is going to be the move now we're going to say if and we're going to use a function here that we haven't defined yet we're going to call this uh check valid move so we're going to check if this move is even valid right now uh now in order to do that we're going to split this move on the co on the on the comma so that we can actually get the individual um coordinates as as a tuple or array um so if the move is valid we're going to apply it so we're going to say oh of course we need this to be self.check valid move and this to be self dot apply move we're going to apply the move uh and we're going to use move split again and we're going to specify that it's going to be our symbol so we want to make the move but we want to make it with our symbol um then we want to change the turn so the turn is going to be um self opponent so it's going to be their turn now and we want to send this to the client so we want to send client send move and we're going to encode this using utf-8 so the idea is again uh we have this game loop we say okay if it's my turn right now i'm going to uh be able to give an input here um and yeah and then we're going to check if the move is valid if it's valid we're going to apply it we're going to change the turn and we're going to send the move that we just made to the client now if it's not our move or first of all actually let's let's handle an invalid move we're going to just print invalid move like that now the question is no we should be able to enter another move because we're in the loop right that that shouldn't be a problem um now if it's not our move if it's not our turn what we're going to do is we're going to say the data is whatever we receive from the client so client receive 1024 bytes and then we're going to say if there is no data we're going to break so we're going to get out of this loop else if there is data uh maybe we should also close the client here um if there is data what we're going to do is we're going to say self dot apply move and we're going to decode the data uh actually we can take the suggestion here we're going to decode the data using utf-8 we're going to split it again on the comma and this time we're going to make the move for the opponent so it's the same thing we did here but this time we also decode the data that we got from the socket and of course self.turn is going to be set to self done to you because it's now our turn again so as you can see this loop is constantly switching between this and this and this and this all the time and here we process our move here we get the uh move of the opponent and both clients in this case are updating their field to be the same as uh that of the opponent and if for some reason we get out of the loop we say client close now i'm not sure if this is going to cause any problems because essentially we're closing here already then we're breaking out of the loop and closing again so this might cause some issues now actually if we break out of the loop we're closing anyway so let's just delete this here um yeah so the next function we're going to implement is the apply move function which is just going to set uh which is just going to um put the symbol at the respective position this is not going to be a too complicated function so we're going to say def actually is this we need to put this here def apply move and it's going to be self then the move and then the player and what want to do here is want to say if self game over so if the game is over already we're going to return otherwise if it's not game over we're going to increase the counter by one so that when we reach 9 we know it's a tie if there's no winner then we're going to say self dot board and here we want to say this is actually already a good suggestion we want to get um the first part of the move and the second part of the move which is an array of strings in this case we're going to type cast it into integers we're going to just assume that the input is valid uh and we're going to set this to the player so the symbol actually um and then we want to do is want to say self.printboard now this is going to be another function we have not implemented yet the functions are um building on top of each other so because of that uh we're going to need to we're going to need to use them before we define them so we're going to print the board after we made the move so that we see what's currently up and then we're going to check if there's a winner so if self dot winner uh or actually first of all we need to check we need to check if there's a winner so self this is actually look gitup copilot knows what i want to do check for winner this is what we're going to do and then if self dot winner equals self come on dot u then we're going to print you win alif uh self dot winner self opponent you lose and if there is no winner so if we don't have um if the winner is not the opponent if the winner is not you then we're going to say it is a tie but only this is only the case if the counter is equal to 9 because otherwise we don't have a tie because we can still take actions uh let me just see if i didn't mess up anything uh we're going to say self check for winner actually we should do it like that if there is a winner so let's rename this to self check if one check if the game is one in general if it is one we're going to check who won and otherwise we're going to just say okay is the counter equal to nine then it's a tie if there's no winner otherwise basically do nothing in all of these cases also exit so quit the script basically and that should be it that is the apply move function nothing too complicated here uh let's now go ahead and define the check if one function or actually maybe we should define the check check valid move function first which is also what github copilot suggests so let's do it we're going to check if the move is valid how do we check if the move is valid very simple we just this is a one-liner we just return uh if the board at this point is empty so if this here is actually a blank space so the return value is going to be the boolean of the expression if the self board at this position is empty and we don't need that last bracket here i think and we don't need that as well there you go this is our check valid move function then the check if one function is going to be quite simple as well we want to pass self here uh it's basically just going to check all scenarios for winning so do we have some rows do we have some columns or do we have diagonals so uh we're going to say 4 i or actually 4 row in range 3 and we're going to say if self dot board 0 or actually row 0 equals self board row 1 equals self board row 2 and it's not equal to an empty string not to an empty string to a blank space this means that we have a row so in this case we would say self.winner equals whatever we have at this position like that so the logic is the following we go through all the rows we look if there's a row where uh each field has the same symbol and if this is the case and of course this symbol is not the default symbol then this symbol is the winner um and then we can say self.gameover equals true to stop the loop and then we can just return true because there is a winner um then we can do the same for the columns i actually didn't want to write this but get up co-pilot did so let's just use it then again we're going to say if self dot board in this case i think we need to do it in a different way we need to say self board zero column one column and two columns so not row zero row one row two but zero column one column two columns so um the the variable that we have here the control variable is going to be in the second and the second set of square brackets and here we're going to also say self.winner equals self.board zero column self.gameover equals true and return true there you go and last but not least you want to check for diagonals i want to check for 0 0 1 1 2 2 which is what uh they're doing here what get up co-pilot is suggesting here uh in this case also as well self.winner is going to be the first one self.gameover is going to be true and we're going to return true and then last but not least if self dot board 0 2 so basically the other diagonal a 0 2 means first row last then in the middle again and then last row first item if those are equal we're going to also say self winner equals self board zero two self game over equals true and return true otherwise we're going to return false that is the function now let's go ahead and define i think we only need one more function right because we have everything else implemented we only need the print board function this should be quite easy this is just def print board i think it up copilot will suggest this already where essentially or actually this is not how i want to do it so let's get rid of that how i want to do it is i want to say four row in range three i want to print with a separator so i want to say uh space then this pipe symbol space and then i want to join on that so dot join uh self board the respective row and then what i want to do is if the row is the last row uh if the row is not the last row so if this row is not equal to 2 then i want to print uh this separator for the rows which is that uh the idea is that we want to have the separators within the row and then we want to separate the individual rows but we don't want to do this for the last row because we didn't do it for the first row or above the first row so this is how we're going to print the board and i think we're actually done so let's try this first locally then we're going to try it with a second laptop um now first of all we need to we need to copy that and have two scripts because one script is going to uh to host and one script is going to connect so we're going to copy it's just a refactor copy file we're going to copy this to name main2py uh and in the main py we're going to just host the server so we're going to say game equals tic tac toe like that and then game connect to game localhost and some port and then we're going to go to main2 no not running editing and we're going to actually say game equals tic tac toe now of course you can also implement a menu so that you can choose um in a menu in a command line menu if you want to host or connect this is maybe more user friendly and then want to say here game dot connect to game also localhost same port as before so now let's go ahead and see if this works we're going to open up two command lines so one here and one here we're going to navigate to the directory oh actually this is not the directory this is the directory so we're going to run main py first because this is the server and then we're going to go here and say python main two python [Music] what's the problem here oh i used connect to game both we need to use host game here there you go so let's run this here again let's run this here again now you can see here enter a move now let's start with zero zero you can see i got this here now it's my turn here let's go with one one there you go now i can go with zero one here now i can go with two one here and now i can win here by saying zero two there you go you win uh in this case we didn't get a you lose here why is that we didn't get a you lose we need to think about this here all right i found a simple way to fix this all we need to do is we need to take this client send here and put it above the apply move because when we apply the move we have this section where we win or lose and then we exit which of course means that when we do that we exit and we don't send this anymore so by sending this first before exiting we make sure that the other side also gets our move and then of course they also can process their win or loss so we need to do this in both scripts here there you go and now this should work so if i now go and say python main and python main two zero zero one one [Music] zero one two two zero two you win you lose there you go now let's go for uh the other one so let's go for second player wins like that now we're going to go with one zero and here we're going to go with two one there you go you win you lose it works now let's test the tie if it works and then we're going to test it with a second machine so uh enter a move zero zero we're going to say here zero one here we're going to say zero two here we're going to say one zero here we're going to say um one one then one two now we need to be careful because we don't want to have the diagonal so what we want to do is we want to go in to the middle now actually okay the problem is that i already won this is this is stupid let's let's go ahead into this again i accidentally won for x so let's go again and let's go with two zero it's a tie there you go all right so now we're going to try this with my second laptop here so i have this linux machine here as well in addition to the windows machine that i'm recording on so what we're going to do first here is we want to know our ip address using ipconfig and you can see here that my p address locally is 192.168 so we want to actually host on that ip address so i want to change this here to 192 1680206 and of course i also have the main 2py file on my linux machine here we also want to connect to that address so we're going to say i'm going to change localhost in here to the same address i'm not going to record this by the way i'm just going to do this there you go and now for some reason it seems like it only works on the windows subsystem for linux for me even though it was not the case yesterday with a prepared code so maybe for you it also works in the cmd on windows i think that's not a problem with the script but something with linux maybe what you want to do is you want to direct the windows subsystem for linux to the directory and then you want to say python3 main py like that so it's going to start the server now i'm going to connect to the server and there you go so you can play zero zero now i can say zero one now i can say zero uh let's go with one zero now i can go with zero two and here i can now say uh two zero there you go you win and here i got you lose so it also works across two machines now if you want to do this in the internet obviously what you need to do is you need to specify the private ip for hosting so in here this would be the same you host on your private ip but if i want to connect with this laptop from australia for example what i need to do is i need to specify for connecting uh the public ip address of this computer so uh whatever you get when you go to myip.is and of course you need to set up the firewall to work uh properly so you need to allow the connection but this is how you build a simple multiplayer tic tac toe game in python so that's it for today's video hope you enjoyed hope you learned something if so let me know by hitting the like button leaving a comment in the comment section down below and of course don't forget to subscribe to this channel and hit the notification bell to not miss a single future video for free other than that thank you much for watching see you next video and bye [Music] you
Original Description
Today we build a multiplayer Tic-Tac-Toe game in Python using sockets.
◾◾◾◾◾◾◾◾◾◾◾◾◾◾◾◾◾
📚 Programming Books & Merch 📚
🐍 The Python Bible Book: https://www.neuralnine.com/books/
💻 The Algorithm Bible Book: https://www.neuralnine.com/books/
👕 Programming Merch: https://www.neuralnine.com/shop
🌐 Social Media & Contact 🌐
📱 Website: https://www.neuralnine.com/
📷 Instagram: https://www.instagram.com/neuralnine
🐦 Twitter: https://twitter.com/neuralnine
🤵 LinkedIn: https://www.linkedin.com/company/neuralnine/
📁 GitHub: https://github.com/NeuralNine
🎙 Discord: https://discord.gg/JU4xr8U3dm
🎵 Outro Music From: https://www.bensound.com/
Watch on YouTube ↗
(saves to browser)
Sign in to unlock AI tutor explanation · ⚡30
Playlist
Uploads from NeuralNine · NeuralNine · 0 of 60
← Previous
Next →
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
Visualizing Stock Data With Candlestick Charts in Python
NeuralNine
Python Beginner Tutorial #1 - Installation and First Program
NeuralNine
Python Beginner Tutorial #2 - Variables and Data Types
NeuralNine
Python Beginner Tutorial #3 - Operators and User Input
NeuralNine
Python Beginner Tutorial #4 - If Statements and Conditions
NeuralNine
Python Beginner Tutorial #5 - Loops
NeuralNine
Python Beginner Tutorial #6 - Sequences and Collections
NeuralNine
Python Beginner Tutorial #7 - Functions
NeuralNine
Python Beginner Tutorial #8 - Exception Handling
NeuralNine
Python Beginner Tutorial #9 - File Operations
NeuralNine
Python Beginner Tutorial #10 - String Functions
NeuralNine
Python Intermediate Tutorial #1 - Classes and Objects
NeuralNine
Python Intermediate Tutorial #2 - Inheritance
NeuralNine
Python Intermediate Tutorial #3 - Multithreading
NeuralNine
Python Intermediate Tutorial #4 - Synchronizing Threads
NeuralNine
Python Intermediate Tutorial #5 - Events and Daemon Threads
NeuralNine
Python Intermediate Tutorial #6 - Queues
NeuralNine
Python Intermediate Tutorial #7 - Sockets and Network Programming
NeuralNine
Python Intermediate Tutorial #8 - Database Programming
NeuralNine
Python Intermediate Tutorial #9 - Recursion
NeuralNine
Python Intermediate Tutorial #10 - XML Processing
NeuralNine
Python Intermediate Tutorial #11 - Logging
NeuralNine
Python Data Science Tutorial #1 - Anaconda and PyCharm Setup
NeuralNine
Python Data Science Tutorial #2 - NumPy Arrays
NeuralNine
Python Data Science Tutorial #3 - Numpy Functions
NeuralNine
Python Data Science Tutorial #4 - Plotting Functions With Matplotlib
NeuralNine
Python Data Science Tutorial #5 - Subplots and Multiple Windows
NeuralNine
Python Data Science Tutorial #6 - Matplotlib Styling
NeuralNine
Python Data Science Tutorial #7 - Bar Charts with Matplotlib
NeuralNine
Python Data Science Tutorial #8 - Pie Charts with Matplotlib
NeuralNine
Python Data Science Tutorial #9 - Plotting Histograms with Matplotlib
NeuralNine
Python Data Science Tutorial #10 - Scatter Plots with Matplotlib
NeuralNine
Python Data Science Tutorial #11 - 3D Plotting with Matplotlib
NeuralNine
Python Data Science Tutorial #12 - Pandas Series
NeuralNine
Python Data Science Tutorial #13 - Pandas Data Frames
NeuralNine
Python Data Science Tutorial #14 - Pandas Statistics
NeuralNine
Python Data Science Tutorial #15 - Pandas Sorting and Functions
NeuralNine
Python Data Science Tutorial #16 - Pandas Merging Data Frames
NeuralNine
Python Data Science Tutorial #17 - Pandas Queries
NeuralNine
Python Machine Learning Tutorial #1 - What is Machine Learning?
NeuralNine
Python Machine Learning Tutorial #2 - Linear Regression
NeuralNine
Python Machine Learning Tutorial #3 - K-Nearest Neighbors Classification
NeuralNine
Python Machine Learning #4 - Support Vector Machines
NeuralNine
Python Machine Learning Tutorial #5 - Decision Trees and Random Forest Classification
NeuralNine
Python Machine Learning Tutorial #6 - K-Means Clustering
NeuralNine
Python Machine Learning Tutorial #7 - Neural Networks
NeuralNine
Python Machine Learning Tutorial #8 - Handwritten Digit Recognition with Tensorflow
NeuralNine
Generating Poetic Texts with Recurrent Neural Networks in Python
NeuralNine
Stock Portfolio Visualization with Matplotlib in Python
NeuralNine
Analyzing Coronavirus with Python (COVID-19)
NeuralNine
Making Text Images Readable Again with Python and OpenCV
NeuralNine
Neural Networks Simply Explained (Theory)
NeuralNine
Motion Filtering with OpenCV in Python
NeuralNine
Top 5 Programming Languages To Learn in 2020
NeuralNine
Simple TCP Chat Room in Python
NeuralNine
Image Classification with Neural Networks in Python
NeuralNine
Edge Detection with OpenCV in Python
NeuralNine
S&P 500 Web Scraping with Python
NeuralNine
Simple Sentiment Text Analysis in Python
NeuralNine
Introduction - Algorithms & Data Structures #1
NeuralNine
More on: AI Pair Programming
View skill →Related Reads
📰
📰
📰
📰
Your AI Knows Everything About React. It Knows Nothing About Your React Project.
Dev.to AI
I Built a Free AI Architect to Stop Spaghetti Code in GitHub Actions
Dev.to AI
Alibaba Bans Employees From Using Claude Code Following Security Concerns
Medium · AI
Cursor Pricing 2026: Free vs Pro vs Ultra — Which Plan?
Dev.to AI
🎓
Tutor Explanation
DeepCamp AI