≡ Menu

Realizzazione di TicTacToe in SwiftUI

Il presente articolo fornisce una dettagliata panoramica della realizzazione di un gioco di Tic Tac Toe (o Tris) utilizzando SwiftUI, il potente framework UI di Apple. Esploreremo le funzionalità fondamentali di SwiftUI, come le proprietà @State, le View, e i Button, e come queste possano essere utilizzate per creare un’app di gioco semplice ma interattiva.

L’app del gioco che abbiamo progettato si compone principalmente di un tabellone di gioco 3×3, rappresentato da una matrice 2D (board). Questa matrice è inizializzata con zeri, con l’idea che 1 rappresenta un giocatore (X) e 2 l’altro (O). L’app tiene traccia del giocatore corrente (currentPlayer) e se il gioco è terminato (gameOver) o meno.

Per rappresentare visivamente il tabellone di gioco, abbiamo utilizzato un anello esterno di VStack che contiene tre HStack. Ogni HStack contiene a sua volta tre Button, creando così un tabellone 3×3. Ogni Button rappresenta una cella del tabellone di gioco.

Per creare la struttura del nostro gioco, abbiamo utilizzato una combinazione di VStack (Vertical Stack) e HStack (Horizontal Stack). Questi sono tipi speciali di View in SwiftUI che permettono di impilare altre View in senso verticale o orizzontale. Guardiamo un frammento di codice:

VStack {
    ForEach(0..<3) { i in
        HStack {
            ForEach(0..<3) { j in
                ...
            }
        }
    }
}

In questo codice, creiamo un VStack che contiene tre HStack. Ogni HStack, a sua volta, contiene tre Button, creando così un layout 3×3.

Per risolvere la sfida della gestione delle mosse dei giocatori, abbiamo utilizzato la potente proprietà @State di SwiftUI. Questa proprietà ci permette di monitorare le modifiche al suo valore, aggiornando automaticamente la UI quando il valore cambia. Quando un giocatore tocca una cella del tabellone, la cella viene assegnata al currentPlayer, e il currentPlayer viene quindi alternato.

Ogni Button è collegato a un’azione che si attiva quando viene premuto. L’azione controlla se la cella del tabellone può essere occupata dal giocatore corrente:

Button(action: {
    if self.board[i][j] == 0 && !self.gameOver {
        self.board[i][j] = self.currentPlayer
        self.winner = self.checkWin()
        if self.winner != 0 {
            self.gameOver = true
        } else {
            self.currentPlayer = 3 - self.currentPlayer
        }
    }
})

Nell’azione del Button, controlliamo se la cella corrente è vuota e se il gioco non è finito. Se entrambe le condizioni sono vere, la cella viene assegnata al currentPlayer e viene verificato se c’è un vincitore. Se c’è un vincitore, gameOver viene impostato su true; altrimenti, currentPlayer viene alternato.

Una caratteristica fondamentale del Tic Tac Toe è la determinazione del vincitore. Per farlo, abbiamo implementato la funzione checkWin(), che verifica le righe, le colonne e le diagonali per un tris. Se trova un tris, restituisce il numero del giocatore che ha vinto. Se tutte le celle sono occupate senza un tris, la funzione dichiara un pareggio restituendo -1.

Dopo ogni mossa, la funzione checkWin() viene chiamata per verificare se la partita è finita. Se un giocatore ha vinto o se la partita è finita in pareggio, viene visualizzato un messaggio appropriato. Inoltre, il conto delle vittorie di ciascun giocatore viene aggiornato di conseguenza.

La funzione checkWin() è fondamentale per determinare l’esito del gioco. Verifica le righe, le colonne e le diagonali per vedere se c’è un tris. Se c’è un tris, restituisce il numero del giocatore che ha vinto. Se tutte le celle sono occupate e non c’è un tris, dichiara un pareggio restituendo -1:

func checkWin() -> Int {
    // Verifica righe e colonne
    for i in 0..<3 {
        if board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != 0 {
            return board[i][0]
        }
        if board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != 0 {
            return board[0][i]
        }
    }
    // Verifica diagonali
    if board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != 0 {
        return board[0][0]
    }
    if board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[2][0] != 0 {
        return board[2][0]
    }
    // Verifica pareggio
    for i in 0..<3 {
        for j in 0..<3 {
            if board[i][j] == 0 {
                return 0
            }
        }
    }
    return -1  // Pareggio
}

Il codice, ancora, per ripristinare il gioco, resetGame(), viene chiamato alla fine di ogni partita, per riportare tutte le variabili allo stato iniziale e preparare il tabellone per una nuova partita.

Un’altra sfida da affrontare era rendere ogni cella del gioco interamente sensibile al tocco. Inizialmente, solo la parte centrale della cella (il punto in cui appare la X o la O) rispondeva al tocco. Per risolvere questo problema, abbiamo utilizzato .background(Color.white) per la View Text quando è vuota, fornendo così un’area sensibile al tocco in tutta la cella.

Infine, per garantire un’esperienza di gioco fluida, abbiamo aggiunto un Button per ripristinare la partita una volta terminata. Questo resetta il tabellone e assegna il turno al giocatore che inizia in maniera casuale, preparando tutto per una nuova partita.

In sintesi, l’utilizzo di SwiftUI ha reso relativamente semplice la realizzazione di un gioco di Tic Tac Toe funzionante. La sua reattività integrata e l’uso di proprietà @State, insieme alla struttura componibile delle view, rendono SwiftUI un ottimo strumento per creare interfacce utente dinamiche e interattive su piattaforme Apple.

{ 0 comments… add one }

Rispondi