Skip to content

Instantly share code, notes, and snippets.

@chaitanyaSoni96
Last active October 27, 2024 18:19
Show Gist options
  • Save chaitanyaSoni96/ecd9ae8fdd8aa600fc3e78e0d4e222d4 to your computer and use it in GitHub Desktop.
Save chaitanyaSoni96/ecd9ae8fdd8aa600fc3e78e0d4e222d4 to your computer and use it in GitHub Desktop.

TicTacToe

Overview

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.


Challenge 1: Project Setup

  • Create a project named TicTacToe in Xcode.

Challenge 2: Main Screen Setup

  • Create a new screen in Main.storyboard for entering the user’s name and starting the game.
  • Create a new Swift file called BoardViewController.swift.
  • Create a new UIViewController class named BoardViewController.

Challenge 3: User Input Screen

  • 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 UITextField for the user to enter their name.
  • Add a UIButton labeled "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 ViewController class:
    • Create an @IBOutlet for the UITextField, e.g., @IBOutlet weak var nameTextField: UITextField!.
    • Create an @IBAction for the "Start Game" button.

Challenge 4: Programmatic Navigation

  • In the action method for the "Start Game" button, navigate to BoardViewController programmatically:

    @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.swift to receive the player's name:

    var playerName: String?

Challenge 5: Setting Up the Game Board

  • In BoardViewController.swift, create outlets for the 9 game board buttons (UIButton).
  • Add a UILabel to display the game status (e.g., "Player X's turn" or "Player wins!").
  • Connect these UI elements to the BoardViewController class.

Challenge 6: Game Logic Setup

  • Initialize a 2D array in BoardViewController.swift to 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
    }

Challenge 7: Handle Player Turns

  • 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()
        }
    }

Challenge 8: Computer Move Logic

  • 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"
            }
        }
    }

Challenge 9: Check for Winner

  • 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
    }

Challenge 10: Reset Game Functionality

  • 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)
            }
        }
    }

Challenge 11: Testing the App

  • 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.

Bonus Challenges

  • Implement score tracking for the player and computer.
  • Enhance the AI to make smarter moves.
  • Improve the UI with animations or sound effects.

@chaitanyaSoni96
Copy link
Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment