SwiftUI Tic Tac Toe | Multiple AI Difficulties | MVVM | Portfolio Project
VloĆŸit
- Äas pĆidĂĄn 29. 06. 2024
- Head to squarespace.com/seanallen to save 10% off your first purchase of a website or domain using code SEANALLEN.
Today we're building a Tic Tac Toe game in SwiftUI. But we are stepping it up a notch and building out the logic for our computer AI opponent to scale in difficulty. We will build the game board UI in SwiftUI, then check for win or draw conditions, then build up our AI logic and we'll finish up by refactoring into MVVM (Model View ViewModel). There's a lot to learn in this video so I hope you complete it đ.
This video kicks off my "Portfolio Project" series for iOS developers in SwiftUI. This series is all about create fun little projects to help build up your portfolio. The idea is for you build upon these projects and make them your own. Use them as a baseline.
This tutorial was created in Xcode 12.5 and Swift 5.4.
SF Symbols Video:
âą What's New in SFSymbol...
If you like my teaching or presentation style, I've started creating my own courses:
seanallen.teachable.com/
Timestamps
What Are We Building? - 0:00
Game Board UI - 1:12
Create Move Object - 9:36
Check if Square is Occupied - 17:07
Start Computer AI - Easy Mode - 20:33
AI Logic Overview - 23:16
Computer Moves - 23:37
Disable Game Board - 28:43
Win & Draw Conditions - 31:27
Win, Lose or Draw Alerts - 43:17
Making our AI Smarter - 52:35
Refactor & MVVM - 1:03:53
Recommendations - 1:17:39
Twitter:
/ seanallen_dev
Link to my book - How I Became an iOS Developer:
gumroad.com/l/sean-allen-origin
Hired.com:
hired.com/x/1n01g
Check out my podcast, iOS Dev Discussions:
itunes.apple.com/us/podcast/i...
Book and learning recommendations that help out the channel if you decide to purchase (Affiliate Links):
Ray Wenderlich Books:
store.raywenderlich.com/a/208...
Ray Wenderlich Videos:
store.raywenderlich.com/a/208...
Paul Hudson's Hacking With Swift:
gumroad.com/a/762098803
Learn Advanced Swift Here:
gumroad.com/a/656585843
Links to my iOS Dev Setup & iOS Dev Book Recommendations
www.amazon.com/shop/seanallen
#swift #softwaredeveloper #iosdeveloper - VÄda a technologie
If you enjoy my teaching/presentation stye, I've started creating my own iOS dev courses at seanallen.teachable.com. You can watch the first ~10% for free to get a feel for them.
A tip: you can watch series at flixzone. Been using it for watching lots of of movies recently.
@Eric Ibrahim definitely, I have been watching on Flixzone for since november myself :D
Every time I watch one of your videos, Iâm reminded about how much I actually want to do this for a living! Thanks for all the great lessons!
Happy to hear that, Jeff. Go get it!
"....Use the 'bang' in front....". Never fails to amuse me.
Great tutorial Sean.
Tip: (you may already have heard this one but I know it's hard to remember it when you need it) When you have multiple instances of a bunch of variables that you want to change, lets say the prefix on them, you can create multiple cursors. Click at the beginning of the first one then hold the Control and Shift key down and click in front of the others. Now you can edit them simultaneously.
I always forget that one. It's funny... I've done plenty of Xcode tips and tricks videos where I show all this stuff off, but it's hard to remember them all.
I like your "chapter" analogy when talking about refactoring. That's exactly how you should think about it.
When you see Sean posting a video you are 100% sure about the quality and the knowledge you gonna get! Awesome!! Thanks for everything Sean!
Thanks for the kind words, Christos đ
This is a super good end to end video, great job!
Thanks man!
Thanks to both of youđ
both of you guys are doing great job for iOS developer.Thank you :)
You are great! ... Nice to see you back with fire! Awesome...
đ„
great video! very comprehensive and helpful. it was just detailed enough that it didn't get boring at any point! loved it, keep up the great work!
Great video man, its been about 5 years since I worked on ios and just took another 3 hour course on the basics. This gave me a lot to play around with as a first project, thank you!
Great stuff as always Sean - love the way you do those alerts. Thank you.
Thanks Robin!
Came here looking for something else, but I found this so interesting and helpful, I stayed for it all. Great tutorial as always from Sean Allen.
For those of you too lazy to type: let winPatterns: Set = [[0,1,2], [3,4,5], [6,7,8], [0,3,6], [1,4,7], [2,5,8], [0,4,8], [2,4,6]]
Cool serious idea Sean! Excited to see these new videos.
Thanks Caleb đ
I just love watch your video x1.5 speed to enforce myself thinking faster and keeping focus all the time!
Truly a Masterpiece explaining whole life cycle of a small project. Much appreciate your efforts.. Thank You Sean!!
Oh Man! So timely for me.I have been wrestling with how to plan what goes into my VM or not while doing my coding. This process of getting it working first and then worrying about how to put it into the proper structure at the end really opened my eyes! Perfectly logical but when starting from scratch it was not so obvious to me. I always expect top-notch content from you and your courses but this one hit me right between the eyes! THANK YOU!
When I was building this video, I knew there was a lot of good nuggets in here. Happy to hear it helped with your ViewModel questions! Glad you enjoyed it.
This tutorial is clearer than crystal. Thank you very much for this portfolio project Sean đđ»
Thanks for the kind words, Joe. Happy to hear it was easy to grasp.
Beautifully explained and executed ; well done !
Enjoyable tutorial. Your concise, to-the-point instruction style, as well as your enthusiasm, adds value to your presentations. I liked learning more about the map(_:) method and about alert processing. Best of luck in your iOS dev courses.
Another great piece of awesomeness like always. Thanks Sean đ
Thanks for the kind words, Ahmad đ
It's an amazing video!
Maybe it's hard to understand for programming rookies.
But the step-by-step teaching makes more clear to know how to build an app.
NICE WORK!
Always eager to watch your videos!
I appreciate that, Omair đ
Thanks Sean for another quality video. Practical, concise and real world. Great engaging teaching style, learning lots, keep up the great work. You are one of a few who are pushing out great regular and up to date iOS stuff. Many thanks.
Thanks for the kind words đ
this is really a great video learning swiftUI and MVVM. I really appreciate your initiative to start portfolio projects because it really help us guys beginner and intermediate to learn new thing, building small apps.
Awesome video! Very clear not too much jargon to confuse we newbies. The refactoring section was the most useful. How to refactor lessons are scarce and yours made the process very clear and easy to adapt to any project. Thanks for your effort and time to share your knowledge.
Timmy!
Glad you enjoyed it, Timmy!
Very nice Sean loved every bit of the process of this tutorial...
Thanks Ruptapas! I'm experimenting with longer, more in-depth tutorials so the feedback is appreciated.
Những ca sÄ© khĂĄc cho mĂŹnh cáșŁm giĂĄc thÆ° giĂŁn khi nghe! CĂČn ÄP luĂŽn cho mĂŹnh bá» cuá»n theo tinh tháș§n bĂ i hĂĄt.
Thank you once again Sean!
Happy to help, Gabriel.
Excellent video, Sean. Thanks.
Thanks! Glad you enjoyed it.
Thankyou!, this was very helpful
Great tutorial! Really learnt something today
Glad to hear it, Kai đ
thank you for your knowledge and your time!
Happy to help!
Thanks bro! Learned a lot. Keep up the good work - maybe more of those longer vids!? đđȘđŒ
Glad you liked it! I plan on doing more of them. However, they take a TON of time to create. So it'll be like once a month or something like that.
Very nice! Perfect length - I prefer the longer but more in depth videos, and this one felt way faster than 1:18. I like seeing the thought process and steps involved, too, particularly the refactor process. Seems obvious, but I always end up refactoring everything at once, rather than step-by-step shown here. Thanks!
Thanks for the feedback on the longer video, Scott. I rarely do these long videos, but it's something I'm experimenting with and will sprinkle in from time to time. Glad you enjoyed it!
Great Video thanks for all the effort you put into that really learned somethingđ
Happy to hear you appreciate it! That one was a lot of work and while I was building it I said to myself "there's a lot of good stuff in here". Glad to see others getting value from it.
I am coming from a flutter background , i decided to try Native IOS. Your Tutorials are the best, Thank you very much. I have learnt a lot.â€
20:10 you can use if moves[i] != nil { return }
I love your way of teaching. As a computer science student who has background in other programming languages, diving headfirst into a new one (swift) by watching this is just so much better than watching a series of the basics about swift!
You don't need to learn how variables and functions etc. work in swift because HERE: you just learn that on the fly while directly seeing, how different functionalities of swift can be put together in a real world exaple (ok it is tic tac toe but still... :D )
A little improvement suggestion: If these kind of videos are ment for beginners, it may be helpful to cover unique details of swift syntax like the dots or the keywords "in", "for" used in functions. I think this is a swift thing since I have never seen something similar and I had to ask ChatGPT over and over again what these little things concretely do đ
Glad you enjoyed the tutorial. This was meant for non-beginners as it's designed to be a project someone looking for their first job might put in their portfolio. I appreciate that feedback!
All your videos should be like this :D
I love your teaching style. very concise and easy to understand
Glad you enjoyed it, Dwi.
thanks Sean Allen i enjoyed your video . you are the best while during code you have some jokes >> a lot of love
Glad you enjoy the videos, Sikandar!
Thank you!
thank you so much!!
Nice video and like your teaching style
Thank you so much đđ»
When the centerSquare is a circle4 :). Thanks for the learning though. Nice video.
Sean is on fire đ„đ
I took a 3 week break, so I was ready to get back at it đ
@@seanallen Yep I know the feeling, we do need this break from time to time. Always happy to get a notification from your channel đȘđŒđ€đŒ
As an experienced developer in other tech (Android) I appreciate your pace! I struggle with other tutorials feeling I am loosing a lot of time, so I am really grateful that I have found this one!
I have only one objection (or question) : shouldn't ViewModel be free of stuff from swiftUI (like GridItems)?
If I would do this in Android, I would leave in view all UI parts of the code.
Other that that, I congratulate you on awesome job with this series!
I like the way you wrote checkWinCondition. I was using arrays and loops ( I had exactly the same order for winPatterns though)
Thanks, I also enjoyed that when I was building. My initial thought was loops, but then working with sets came to mind and I felt that was better.
Amazing !!!!!
Thanks Jean!
just finished. interesting
It's pretty cool
Glad you liked it :)
I'm already know I'm going to like this 3 minutes in
That's awesome to hear! Let me know what you think at then end.
Great session! I like the refactoring part! I advice any software engineer to at least read about the principles of clean code. That big method that processes the moves of the player and computer couldâve been easily split up so each method is just doing ONE task and not multiple. With precise method/function names, comments get obsolet.
Great tutorial and thanks for sharing such an in-depth look into TikTakToe SwiftUI development.
Excellent presentation of how to create a game with some intelligence :-)
Congratulations... 5 *
Thanks for the kind words, Nuno. I appreciate it!
How to make a user login screen? Can you make a video about it? It would be very helpful for those who needed. Thank you đ
How else would you refactor? There are a couple of structs at the bottom of the main view controller - move those to the class too?
I thought you were quitting doing videos in programming and focusing on the financial stuff i think you said in the passed. Caught this video late but itâs definitely good to see pop up. Great video and i like the longer videos. Hope to see more like it. You were the first swift channel i followed and swift is now my main language. Appreciate you and i wanted to ask if you were going to add more content to your course on teachable(which i own) or are you coming out with a more advance course? đ€
Happy to hear you enjoy the larger videos. I have an intermediate SwiftUI course coming out in a week or so. As for the finance channel, that will be sometime after WWDC and will be a side project to the iOS dev videos. I will do both.
Canât we instead of isSquareOccupied(i) just check whether moves[i] != nil ?
This was an amazing video! Would you ever do one on how to build a quiz app?
I have a VERY long video idea list đ. That's on it... just not sure when it will happen.
@@seanallen Totally! Makes sense! Such a shame that there don't seem to be any SwiftUI tutorials on how to create a MC quiz
Super interesting and useful. I learned a number of things. One question - why am I not seeing the extract view at 1:13)? Also its hard to type along when you jump to different parts of the screen. by the time I stop the video with 5 second delay, then its a hassle to catch things at time. But I appreciate your effort here.
idk if I'm missing a point here but it seems kinda weird to me to determine the move position by rolling a dice until the result is not already occupied. Wouldn't it be more efficient to create a new array of all positions that are not already occupied and then selecting a random position from that array? Anyways, thanks a lot for the great tutorial, I really enjoyed it!
You can avoid some repetition by using do/while instead of while.
Great point, Nacho! Thanks for pointing it out (genuinely). There are certainly plenty of places my code can be improved. I noticed a lot of them while editing. However, after 2.5 hours of filming and another 4 hours of editing... I just let them be đ.
@@seanallen great video though! Not easy to put out all this code out there for thousands of people to code review.
Thanks! I've gotten used to that over the years. Thankfully, 99% of the "code review" type comments are done in a cool manner so I actually learn a lot from them.
Thanks for the great videos...I have a question, how do you keep track of the Swift tricks like the array. contain where put $0? I'm a c++ program i can easily think of doing it as if moves[i] != nil
Nice video! However your ViewModel must never be aware of SwiftUI!
I love learning --- suggest that moves[index]?.indicator != inside isSquareOccupied() would be more efficient and simplifies the learning curve for new programmers, no?
AÄiĆ«!
Hi Sean, thanks for the great tutorial. I have been playing with refactoring my swiftui project to MVVM too. In your video I am missing the model part. What would you put in the model ?
For this specific app (Tic Tac Toe) - the Move object as well as the Player enum could be considered the part of the Model. If you were asking about you specific project, that's tough to say as I know nothing about your project. In general the Model should be your objects. In the Tic Tac Toe example, the Move is one of our objects.
just saw your videos of recent its really a break through..
could you do a video using Uikit for tic tac toe? I have already I just want to see a Professional
I didnât like this implementation, so I added another case, âemptyâ to the âPlayerâ enum. Now, I can initialize the entire board[] array with Move instances with no nils in it, so:
@State private var board: [Moves] = Array(repeating: Move(player: .empty, boardIndex: -1), count: 9)
Now I donât need nil coalescing, or optional unwrapping, so changed the line:
Image(systemName: board[i].indicator) by getting rid of the â?â.
and changed the computed property getter for struct Move to:
var indicator: String {
let result = (player == .human ? âxmarkâ : (player == .computer ? âcircleâ : ââ))
return result
}
Finally, my onTapGesture is now:
onTapGesture {
let aMove: Move = Move(player: isHumansTurn ? .human : .computer, boardIndex: i)
if board[i].player == .empty {
board[i] = aMove
isHumansTurn.toggle()
didPlayerWin()
}
}
which calls a method I wrote called, âdidPlayerWin()â, which checks each row and column, and the two diagonals to see if theyâre filled with either .human or .computer and prints an appropriate message to the console (for now). If no row, column, or diagonal is filled, it checks to see if all the board has been filled (i. e., no cell contains .empty) and prints âTieâ, else it prints âGame still in progress.â
Sadly, my implementation of didPlayerWin() is far too long to print here, and involves two other helper functions which I also wrote, âcheck3squaresForX()â, and âcheck3squaresForO()â. Iâll leave to your imagination as to what these do. đ
Great tutorial. Thank you! Why write an isSquareOccupied function that scans the moves array? Couldn't you just check if moves[i] != nil?
same question here...
Moving variables to the 'GameViewModel and declaring them Published was a breaking move for me. Maybe it's a version issue?
Are you going to make other projects like this?
if let move = moves[i] {
Image(systemName: move.indicator)
.resizable()
.foregroundColor(.white)
.frame(width: 50, height: 50)
.font(.title)
}
consider this to get rid of the warning saying no systemName in Sf called ""
Worked! Thanks.
@ 52:35 is it "best practice" to move the isGameboardDisabled = true or put isGameboardDisabled = false in the resetGame function?
I get an error saying *"Cannot convert value of type '[Move?]' to expected argument type '[Move]"* at the checkWinCondition part for the human. Please help me.
if checkWinCondition(for: .human, in: moves) {
print("User wins")
return
}
determainComputerMove will go on infinite loop after the last tapped square
When developing a game (may be a 2D game or fun little game like you developed in this video) do you think it is better to use SwiftUI or spritekit. I am new to swift and have only played around with UIKit and I'm planning on learning SwiftUI or spritekit for a game I'm thinking of developing. What is your suggestion? Is it possible to make a good game using SwiftUI?
This really depends on the game. Simple games like tic tac toe are probably fine in SwiftUI. But the more serious the game, you're probably better off with a game engine.
@@seanallen Got it.Thanks.
.alert(item:content:) will be deprecated in future version of iOS
Extract Subview is gone in Xcode 12.5 for me, but you also used same...? :(
I found the issue -- command line tools was not properly set. This made *some* refactoring options not visible in project!
Code you did this in UIKit?
How to align equal signs like in 45:55?
I manually tab them over. It's extra work, but in my opinion makes the code more readable.
open source??
If someone does something like this on CZcams, it's automatically open for anyone to use. You're probably looking for a repo of the source. I haven't found one. I'm typing it in myself. It might be disrespectful to Sean to post the code without asking, it could be a part of his business plan, so I won't post without asking and I don't have the completed code yet.
@@karljay7473 Agreed, it's a tutorial at the end of the day
Hey Sean thanks for the video. Havenât watched all of it yet, but I know itâs going to be awesome. Itâd be really cool if you could take the AI one step further with something called the Minimax algorithm: www.geeksforgeeks.org/minimax-algorithm-in-game-theory-set-3-tic-tac-toe-ai-finding-optimal-move/amp/.
Iâve always wanted to implement the algorithm in Swift but could never figure out how since it involves some pretty complicated logic. Thanks!
I believe this would make an unbeatable AI tho. A game of tic tac toe should never be won if both players are making optimal moves. I kept my AI algorithm relatively simple for two reasons.
1. Ease of understanding for people early in their learning journey. Like you said, making that unbeatable AI gets pretty complicated and I didn't want to lose people.
2. I wanted to allow the AI to make mistakes so that it could be beat.
Sean Allen Gotchya. No worries. Also, do you think you can include a link to the completed project?
I'm still thinking about that. I want to avoid people just downloading the project, putting it on their Github and saying "Cool, here's a free portfolio project". Maybe I'm being too negative, but I want people who actually went through the video and learned stuff to have the reward of the code.
@@seanallen Absolutely, đđŒ
@@seanallen I second this âđ»
Is this really an AI solution?
It's an insanely basic decision-making one, but by definition... yes. I used the term "AI" mostly to communicate in the title that we will be programming the game to take actions based on the human moves.
There could be debate about this, but I always heard that it has to improve itself over time. I'm not sure where I got that from, but it's one of the things that I've heard in the past. It needs to be able to learn from what it's done in the past and improve upon that over time. AI really isn't well defined, or at least I find different definitions. Having said that, this is a great tutorial, love that Sean has embraced SwiftUI.
Thank you for your Tutorial! I was coding, till the point -to the new folder and copy from GameView to GameViewModel.. Than I was lost đ§because can't fixed all the error lines like you! So I was go back with command and Z but all was lost đ„ș...đ© because I did clean so much from -my on mistakes and was so happy and proud ,till this FukkNewFolder đż This Tutorial did stressed me so much because my Xcode makes so many redlines. Maybe I did code on this 10 hours without result đ€ĄNext time always copy all that shit I did do on an safe place !â€âđ©č (P.S.) I'm beginner and this was my first App till 13 min. to the end of this Tutorial! All other Tutorials I did was always the problem this I can't fix my mistakes or bugs in Xcode. Its so hart to learn alone, im sad and happy, im frustrated and motivated, im in love and make it again but need now pasta Best reagents from Berlin sorry for my bad english đ» much love đŠ