This app allows the user to enter their name and play a Tic-Tac-Toe game against a computer opponent. The user plays as "X" and taps on the game board to make their moves. After each turn, the computer will randomly select a move.
- Create a project named TicTacToe in Xcode.
- Create a new screen in
Main.storyboardfor entering the user’s name and starting the game. - Create a new Swift file called BoardViewController.swift.
- Create a new
UIViewControllerclass named BoardViewController.
- Navigate to the initial screen (ViewController) in
Main.storyboard. - Select the initial ViewController and go to the Editor menu.
- Embed the ViewController in a
UINavigationController:- Click on "Embed In" and select "Navigation Controller".
- Open the assistant editor to view both the storyboard and the ViewController code side by side.
- Add a
UITextFieldfor the user to enter their name. - Add a
UIButtonlabeled "Start Game" to begin the Tic-Tac-Toe game. - Use stack views and/or constraints to arrange the UI elements properly.
- Connect the UI elements to the
ViewControllerclass:- Create an
@IBOutletfor theUITextField, e.g.,@IBOutlet weak var nameTextField: UITextField!. - Create an
@IBActionfor the "Start Game" button.
- Create an
-
In the action method for the "Start Game" button, navigate to
BoardViewControllerprogrammatically:@IBAction func startGameTapped(_ sender: UIButton) { guard let name = nameTextField.text, !name.isEmpty else { return } let boardVC = BoardViewController() boardVC.playerName = name navigationController?.pushViewController(boardVC, animated: true) }
-
Add a property in
BoardViewController.swiftto receive the player's name:var playerName: String?
- In BoardViewController.swift, create outlets for the 9 game board buttons (
UIButton). - Add a
UILabelto display the game status (e.g., "Player X's turn" or "Player wins!"). - Connect these UI elements to the
BoardViewControllerclass.
-
Initialize a 2D array in
BoardViewController.swiftto represent the game board:var board: [[Player?]] = [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]] var currentPlayer: Player = .x var gameActive: Bool = true
-
Create an enum for Player:
enum Player { case x, o }
- Implement the action method for the buttons in
BoardViewController.swift:@IBAction func buttonTapped(_ sender: UIButton) { guard gameActive else { return } let row = sender.tag / 3 let col = sender.tag % 3 if board[row][col] == nil { board[row][col] = currentPlayer sender.setTitle("X", for: .normal) // User always plays as X if checkForWinner() { statusLabel.text = "\(playerName ?? "Player") wins!" gameActive = false return } currentPlayer = .o // Switch to computer computerMove() } }
- Implement random move logic for the computer opponent:
func computerMove() { var emptyCells: [(Int, Int)] = [] for i in 0..<3 { for j in 0..<3 { if board[i][j] == nil { emptyCells.append((i, j)) } } } if let randomCell = emptyCells.randomElement() { let (row, col) = randomCell board[row][col] = .o let button = self.view.viewWithTag(row * 3 + col) as? UIButton button?.setTitle("O", for: .normal) if checkForWinner() { statusLabel.text = "Computer wins!" gameActive = false } else { currentPlayer = .x // Switch back to user statusLabel.text = "\(playerName ?? "Player")'s turn" } } }
- Add a function to check for win conditions:
func checkForWinner() -> Bool { // Check rows, columns, and diagonals for i in 0..<3 { if let first = board[i][0], first == board[i][1], first == board[i][2] { return true } if let first = board[0][i], first == board[1][i], first == board[2][i] { return true } } if let first = board[0][0], first == board[1][1], first == board[2][2] { return true } if let first = board[0][2], first == board[1][1], first == board[2][0] { return true } return false }
- Add a reset button to the game board.
- Implement reset functionality in
BoardViewController.swift:@IBAction func resetGame(_ sender: UIButton) { board = [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]] currentPlayer = .x gameActive = true statusLabel.text = "\(playerName ?? "Player")'s turn" for i in 0..<3 { for j in 0..<3 { let button = self.view.viewWithTag(i * 3 + j) as? UIButton button?.setTitle("", for: .normal) } } }
- Run the app in the simulator or on a physical device:
- Ensure the user can enter their name.
- Verify the player turns alternate correctly.
- Check that the computer plays random moves.
- Validate that win and draw conditions are correctly detected.
- Implement score tracking for the player and computer.
- Enhance the AI to make smarter moves.
- Improve the UI with animations or sound effects.
Here are the concepts learned from the Tic-Tac-Toe exercise along with relevant links to the Apple Swift documentation:
1. UIKit Fundamentals
2. Storyboard and Interface Builder
3. Programmatic Navigation
4. User Input Handling
5. Data Management
6. Game Logic Implementation
7. State Management
8. Dynamic UI Updates
9. Functionality and Code Organization
10. Testing and Debugging
11. Bonus Concepts
These resources will provide a solid foundation for understanding each concept and implementing them in your own iOS applications.