Programmazione di un gioco Tic Tac Toe

La programmazione di giochi per computer può essere il lavoro tecnicamente più impegnativo (e forse il miglior pagamento) che un programmatore possa svolgere. I giochi di livello superiore richiedono il meglio da programmatori e computer.

Visual Basic 6 è stato ora completamente ignorato come piattaforma per la programmazione di giochi. (Non è mai stato davvero uno. Anche nei "bei vecchi tempi", i programmatori di giochi seri non avrebbero mai usato un linguaggio di alto livello come VB 6 perché non riuscivi a ottenere le prestazioni all'avanguardia che la maggior parte dei giochi richiede.) il semplice gioco "Tic Tac Toe" è un'ottima introduzione alla programmazione che è un po 'più avanzata di "Hello World!"

Questa è una grande introduzione a molti dei concetti fondamentali della programmazione poiché combina tecniche tra cui:

  • L'uso di array. I segnalini X e O sono tenuti in matrici separate e le matrici intere vengono passate tra le funzioni per tenere traccia dell'avanzamento del gioco.
  • Utilizzo della grafica di livello VB 6: VB 6 non offre una grande capacità grafica, ma il gioco è una buona introduzione a ciò che è disponibile. Gran parte del resto di questa serie è un'esplorazione di come GDI +, la prossima generazione di grafica Microsoft, sostituisce la grafica di livello VB 6.
  • Utilizzo dei calcoli matematici per il controllo del programma: il programma utilizza i moduli intelligenti (Mod) e i calcoli della divisione dei numeri interi utilizzando gli array di marcatori a due giochi per determinare quando si è verificata una "vincita" di tre elementi.

La classe di programmazione in questo articolo è forse solo un po 'oltre il livello iniziale, ma dovrebbe essere buona per i programmatori "intermedi". Ma partiamo da un livello elementare per illustrare alcuni concetti e iniziare con la tua carriera di programmazione di giochi in Visual Basic. Anche gli studenti più avanzati di così possono trovare leggermente impegnativo ottenere gli oggetti nella forma giusta.

Come giocare a Tic Tac Toe

Se non hai mai giocato a Tic Tac Toe, ecco le regole. Due giocatori si alternano nel posizionare X e O in un campo di gioco 3 x 3.

Prima dell'inizio del gioco, entrambi i giocatori devono concordare chi andrà per primo e chi segnerà le sue mosse con quale simbolo. Dopo la prima mossa, i giocatori posizionano alternativamente i loro segni in qualsiasi cella vuota. L'obiettivo del gioco è quello di essere il primo giocatore con tre segni in una linea orizzontale, diagonale o verticale. Se non ci sono celle vuote e nessuno dei due giocatori ha una combinazione vincente, il gioco è un pareggio.

Avvio del programma

Prima di iniziare qualsiasi codifica effettiva, è sempre una buona idea cambiare i nomi di tutti i componenti che usi. Una volta avviata la codifica, il nome verrà utilizzato automaticamente da Visual Basic, quindi si desidera che sia il nome giusto. Useremo il nome del modulo frmTicTacToe e cambieremo anche la didascalia in "Informazioni su Tic Tac Toe".

Con il modulo stabilito, utilizzare il controllo casella degli strumenti linea per disegnare una griglia 3 x 3. Fai clic sullo strumento linea, quindi disegna una linea nel punto desiderato. Dovrai creare quattro linee in questo modo e regolarne la lunghezza e la posizione per farle sembrare giuste. Visual Basic ha anche alcuni utili strumenti nel menu Formato che ti aiuteranno. Questa è una grande opportunità per esercitarsi con loro.

Oltre alla griglia di gioco, avremo bisogno di alcuni oggetti per i simboli X e O che verranno posizionati sulla griglia. Poiché ci sono nove spazi nella griglia, creeremo un array di oggetti con nove spazi, chiamati elementi in Visual Basic.

Esistono diversi modi per eseguire qualsiasi operazione nell'ambiente di sviluppo di Visual Basic e la creazione di matrici di controllo non fa eccezione. Probabilmente il modo più semplice è quello di creare la prima etichetta (fare clic e disegnare proprio come lo strumento linea), denominarlo, impostare tutti gli attributi (come Font e ForeColor) e quindi fare copie di esso. VB 6 chiederà se si desidera creare un array di controllo. Usa il nome lblPlayGround per la prima etichetta.

Per creare gli altri otto elementi della griglia, selezionare il primo oggetto etichetta, impostare la proprietà Index su zero e premere CTRL + C (copia). Ora puoi premere CTRL + V (incolla) per creare un altro oggetto etichetta. Quando si copiano oggetti come questo, ogni copia erediterà tutte le proprietà tranne Index dalla prima. L'indice aumenterà di uno per ogni copia. Questo è un array di controllo perché hanno tutti lo stesso nome, ma valori di indice diversi.

Se si crea l'array in questo modo, tutte le copie verranno impilate l'una sull'altra nell'angolo in alto a sinistra del modulo. Trascina ogni etichetta in una delle posizioni della griglia di gioco. Assicurarsi che i valori dell'indice siano sequenziali nella griglia. La logica del programma dipende da questo. L'oggetto etichetta con valore di indice 0 dovrebbe essere nell'angolo in alto a sinistra e l'etichetta in basso a destra dovrebbe avere l'indice 8. Se le etichette coprono la griglia di riproduzione, selezionare ciascuna etichetta, fare clic con il tasto destro del mouse e selezionare Invia alla parte posteriore.

Dal momento che ci sono otto modi possibili per vincere la partita, avremo bisogno di otto linee diverse per mostrare la vittoria sulla griglia di gioco. Utilizzerai la stessa tecnica per creare un altro array di controllo. Innanzitutto, disegna la linea, chiamala linWin e imposta la proprietà Index su zero. Quindi utilizzare la tecnica copia-incolla per produrre altre sette righe. La seguente illustrazione mostra come impostare correttamente i numeri di indice.

Oltre all'etichetta e agli oggetti linea, sono necessari alcuni pulsanti di comando per giocare e più etichette per mantenere il punteggio. I passaggi per crearli non sono dettagliati qui, ma questi sono gli oggetti di cui hai bisogno.

Oggetti a due pulsanti:

  • cmdNewGame
  • cmdResetScore

Oggetto Frame fraPlayFirst contenente due pulsanti di opzione:

  • optXPlayer
  • optOPlayer

Oggetto Frame fraScoreBoard contenente sei etichette. Solo lblXScore e lblOScore vengono modificati nel codice del programma.

  • lblX
  • lblXScore
  • lblO
  • lblOScore
  • lblMinus
  • lblColon

Infine, è necessario anche l'oggetto etichetta lblStartMsg per "mascherare" il pulsante cmdNewGame quando non è necessario fare clic. Ciò non è visibile nell'illustrazione seguente perché occupa lo stesso spazio nel modulo del pulsante di comando. Potrebbe essere necessario spostare temporaneamente il pulsante di comando per disegnare questa etichetta sul modulo.

Finora, non è stata eseguita alcuna codifica VB, ma siamo finalmente pronti per farlo.

Inizializzazione

Ora puoi finalmente iniziare a programmare il programma. Se non l'hai già fatto, potresti voler scaricare il codice sorgente da seguire mentre viene spiegato il funzionamento del programma.

Una delle prime decisioni di progettazione da prendere è come tenere traccia dell'attuale "stato" del gioco. In altre parole, quali sono le X e gli OS attuali sulla griglia di gioco e chi si sposta dopo. Il concetto di "stato" è fondamentale in molta programmazione e, in particolare, è importante nella programmazione di ASP e ASP.NET per il web

Esistono diversi modi per farlo, quindi è un passaggio critico nell'analisi. Se stavi risolvendo questo problema da solo, potresti voler disegnare un diagramma di flusso e provare diverse opzioni con 'scratch paper' prima di iniziare qualsiasi codifica.

variabili

La nostra soluzione utilizza due "array bidimensionali" perché aiutano a tenere traccia dello "stato" semplicemente modificando gli indici dell'array nei cicli del programma. Lo stato dell'angolo in alto a sinistra sarà nell'elemento dell'array con indice (1, 1), l'angolo in alto a destra sarà in (1, 3), in basso a destra in (3,3) e così via . I due array che fanno questo sono:

iXPos (x, y)

e

iOPos (x, y)

Ci sono molti modi in cui questo può essere fatto e la soluzione VB.NET finale di questa serie ti mostra come farlo con un solo array unidimensionale.

La programmazione per tradurre queste matrici in decisioni di vincita del giocatore e visualizzazioni visibili nel modulo sono nella pagina successiva.

Sono inoltre necessarie alcune variabili globali come segue. Si noti che questi sono nel codice Generale e Dichiarazioni per il modulo. Questo li rende variabili "a livello di modulo" a cui è possibile fare riferimento in qualsiasi parte del codice per questo modulo. Per ulteriori informazioni, vedere Informazioni sull'ambito delle variabili nella Guida di Visual Basic.

Esistono due aree in cui le variabili sono inizializzate nel nostro programma. Innanzitutto, alcune variabili vengono inizializzate durante il caricamento del modulo frmTicTacToe.

Sottotitolo privato_Load ()

In secondo luogo, prima di ogni nuovo gioco, tutte le variabili che devono essere ripristinate ai valori iniziali vengono assegnate in una subroutine di inizializzazione.

Sub InitPlayGround ()

Si noti che l'inizializzazione del caricamento del modulo chiama anche l'inizializzazione del parco giochi.

Una delle abilità critiche di un programmatore è la capacità di utilizzare le funzionalità di debug per capire cosa sta facendo il codice. Puoi usare questo programma per provare:

  • Scorrere il codice con il tasto F8
  • Impostazione di un orologio su variabili chiave, come sPlaySign o iMove
    Impostazione di un punto di interruzione e interrogazione del valore delle variabili. Ad esempio, nel ciclo interno dell'inizializzazione:
lblPlayGround ((i - 1) * 3 + j - 1) .Caption = ""

Si noti che questo programma mostra chiaramente perché è una buona pratica di programmazione tenere i dati negli array quando possibile. Se non avessi array in questo programma, dovresti scrivere un codice simile a questo:

Line0.Visible = False
Line1.Visible = False
Line2.Visible = False
Line3.Visible = False
Line4.Visible = False
Line5.Visible = False
Line6.Visible = False
Line7.Visible = False

Invece di questo:

Per i = 0 a 7
linWin (i) .Visible = False
Successivamente io

Fare una mossa

Se una qualsiasi parte del sistema può essere pensata come "il cuore", è la subroutine lblPlayGround_Click. Questa subroutine viene chiamata ogni volta che un giocatore fa clic sulla griglia di gioco. (I clic devono trovarsi all'interno di uno dei nove elementi lblPlayGround.) Notare che questa subroutine ha un argomento: (Indice come intero). La maggior parte delle altre "subroutine di eventi", come cmdNewGame_Click () no. L'indice indica quale oggetto etichetta è stato cliccato. Ad esempio, l'indice conterrà il valore zero per l'angolo superiore sinistro della griglia e il valore otto per l'angolo inferiore destro.

Dopo che un giocatore ha fatto clic su un quadrato nella griglia del gioco, il pulsante di comando per avviare un altro gioco, cmdNewGame, viene "attivato" rendendolo visibile. Lo stato di questo pulsante di comando fa il doppio dovere perché viene utilizzato anche come variabile booleana di decisione in seguito nel programma. L'uso di un valore di proprietà come variabile di decisione è di solito sconsigliato perché se diventa mai necessario cambiare il programma (ad esempio, per rendere sempre visibile il pulsante di comando cmdNewGame), il programma fallirà inaspettatamente perché potresti non ricordare che è anche usato come parte della logica del programma. Per questo motivo, è sempre una buona idea cercare nel codice del programma e controllare l'uso di tutto ciò che cambi durante la manutenzione del programma, anche i valori delle proprietà. regola in parte per chiarire questo punto e in parte perché si tratta di un pezzo di codice relativamente semplice in cui è più facile vedere cosa viene fatto ed evitare problemi in seguito.

Una selezione del giocatore di una casella di gioco viene elaborata chiamando la subroutine GamePlay con Index come argomento.

Elaborazione della mossa

Innanzitutto, controlla se è stato fatto clic su un quadrato non occupato.

Se lblPlayGround (xo_Move) .Caption = "" Quindi

Una volta che siamo sicuri che si tratti di una mossa legittima, il contatore delle mosse (iMove) viene incrementato. Le due righe successive sono molto interessanti poiché traducono le coordinate dall'array del componente If lblPlayGround unidimensionale in indici bidimensionali che è possibile utilizzare in iXPos o iOPos. La divisione mod e integer (la "barra rovesciata") sono operazioni matematiche che non si usano tutti i giorni, ma ecco un ottimo esempio che mostra come possono essere molto utili.

 Se lblPlayGround (xo_Move) .Caption = "" Quindi
iMove = iMove + 1
x = Int (xo_Move / 3) + 1
y = (xo_Move Mod 3) + 1

Il valore xo_Move 0 verrà tradotto in (1, 1), 1 in (1, 2) ... 3 in (2, 1) ... 8 in (3, 3).

Il valore in sPlaySign, una variabile con ambito del modulo, tiene traccia di quale giocatore ha effettuato la mossa. Dopo aver aggiornato le mosse di spostamento, i componenti dell'etichetta nella griglia di gioco possono essere aggiornati con il segno appropriato.

Se sPlaySign = "O" Quindi
iOPos (x, y) = 1
iWin = CheckWin (iOPos ())
Altro
iXPos (x, y) = 1
iWin = CheckWin (iXPos ())
Finisci se
lblPlayGround (xo_Move) .Caption = sPlaySign

Ad esempio, quando il giocatore X fa clic sull'angolo in alto a sinistra della griglia, le variabili avranno i seguenti valori:

La schermata utente mostra solo una X nella casella in alto a sinistra, mentre iXPos ha 1 nella casella in alto a sinistra e 0 in tutti gli altri. L'iOPos ha 0 in ogni scatola.

I valori cambiano quando O player fa clic sul quadrato centrale della griglia. Ora iOPos mostra un 1 nella casella centrale mentre la schermata dell'utente mostra una X in alto a sinistra e una O nella casella centrale. IXPos mostra solo l'1 nell'angolo in alto a sinistra, con 0 in tutte le altre caselle.

Ora che sai dove un giocatore ha fatto clic e quale giocatore ha fatto il clic (usando il valore in sPlaySign), tutto ciò che devi fare è scoprire se qualcuno ha vinto una partita e capire come mostrarlo sul display.

Trovare un vincitore

Dopo ogni mossa, la funzione CheckWin verifica la combinazione vincente. CheckWin funziona aggiungendo verso il basso ogni riga, attraverso ogni colonna e attraverso ogni diagonale. Tracciare i passaggi attraverso CheckWin utilizzando la funzionalità Debug di Visual Basic può essere molto istruttivo. Trovare una vincita è innanzitutto una questione, verificando se sono stati trovati tre 1 in ciascuno dei singoli controlli nella variabile iScore e quindi restituendo un valore "firma" univoco in Checkwin che viene utilizzato come indice dell'array per modificare la proprietà Visible di un elemento nell'array del componente linWin. Se non c'è vincitore, CheckWin conterrà il valore -1. Se c'è un vincitore, il display viene aggiornato, il tabellone segnapunti viene modificato, viene visualizzato un messaggio di congratulazioni e il gioco viene riavviato.

Esaminiamo in dettaglio uno dei controlli per vedere come funziona. Gli altri sono simili.

'Controlla righe per 3
Per i = 1 a 3
iScore = 0
CheckWin = CheckWin + 1
Per j = 1 a 3
iScore = iScore + iPos (i, j)
Prossimo j
Se iScore = 3, allora
Esci dalla funzione
Finisci se
Successivamente io

La prima cosa da notare è che il primo contatore dell'indice i conta alla rovescia le righe mentre il secondo j conta attraverso le colonne. Il ciclo esterno, quindi, si sposta semplicemente da una riga alla successiva. Il ciclo interno conta gli 1 nella riga corrente. Se ce ne sono tre, allora hai un vincitore.

Si noti che si tiene anche traccia del numero totale di quadrati testati nella variabile CheckWin, che è il valore restituito al termine di questa funzione. Ogni combinazione vincente finirà con un valore univoco in CheckWin da 0 a 7 che viene utilizzato per selezionare uno degli elementi nell'array di componenti linWin (). Questo rende importante anche l'ordine del codice nella funzione CheckWin! Se hai spostato uno dei blocchi di codice loop (come quello sopra), quando qualcuno vince verrebbe tracciata una linea sbagliata sulla griglia di gioco. Provalo e vedi!

Dettagli di finitura

L'unico codice non ancora discusso è la subroutine per un nuovo gioco e la subroutine che ripristinerà il punteggio. Il resto della logica nel sistema rende la creazione abbastanza semplice. Per iniziare una nuova partita, devi solo chiamare la subroutine InitPlayGround. Per comodità dei giocatori poiché è possibile fare clic sul pulsante durante una partita, chiedete conferma prima di andare avanti. Chiedete anche conferma prima di riavviare il tabellone.