XNA è un framework di creazione di giochi di alto livello per dispositivi Microsoft, inclusi PC Windows, Xbox 360 e il nuovissimo sistema operativo Windows Phone 7. In un precedente tutorial, abbiamo trattato le basi del framework XNA, inclusa la gestione dell'input e la visualizzazione degli sprite. In questo articolo imparerai come combinare quelle abilità con un'idea di gioco per creare qualcosa di divertente da giocare e facile da imparare.
In questo tutorial, creerai un semplice gioco Tic-Tac-Toe giocabile con gli amici. Tic-Tac-Toe è un gioco semplice in cui due giocatori eseguono turni alternati mettendo i personaggi su una griglia tre per tre. Il primo giocatore usa una O e il secondo giocatore usa una X. Per vincere la partita, un giocatore deve organizzare tre dei suoi personaggi in una riga, colonna o diagonale.
Mentre questo gioco è semplice, richiede un paio di abilità diverse da costruire. In primo luogo, utilizzerai XNA e le sue capacità grafiche per creare il tuo gioco. In quanto tale, è necessario avere familiarità con la visualizzazione degli sprite. In secondo luogo, è necessario sapere come gestire i tocchi sul touchpanel del telefono. Fortunatamente, XNA fornisce un'API di alto livello per accedere a questi tocchi. Infine, è necessario applicare un po 'di programmazione e know-how logico per decidere il vincitore. Per questo tutorial, molto di questo ti sarà dato. Quando costruisci giochi in futuro dovrai inventare le tue idee e la tua logica.
Per iniziare, assicurati di aver installato gli ultimi strumenti di sviluppo di Windows Phone 7. Se non hai aggiornato gli strumenti dall'ultimo tutorial del WP7 su MobileTuts, visita l'Area download Microsoft e ottieni la versione RTW. Questa ultima versione include l'emulatore finale che dimostra come le tue app funzioneranno nell'hardware di rilascio.
Dopo aver verificato che i tuoi strumenti siano aggiornati, apri Visual Studio 2010 e fai clic sul link "Nuovo progetto ..." nella barra laterale sinistra. Nella finestra di dialogo che si apre, scegli "XNA Game Studio 4" nella colonna di sinistra e assicurati che il modello "Windows Phone Game (4.0)" sia selezionato sulla destra. Assegna al tuo progetto un nome appropriato come "TicTacToe" e conferma che la casella di controllo "Crea directory per soluzione" sia selezionata. Se hai fatto tutto correttamente, la finestra di dialogo dovrebbe corrispondere all'immagine seguente:
Fai clic su "OK" per creare il tuo nuovo progetto. Visual Studio 2010 genererà i file necessari nella directory specificata e verrà aperto Game1.cs
per la modifica.
Dato che in questo progetto utilizzerai gli sprite per tutta la grafica di gioco, devi importare gli elementi richiesti nel tuo progetto. Nel download che accompagna questo tutorial troverai a Media
directory contenente una varietà di immagini. Nell'explorer della soluzione sul lato destro dello schermo, individuare il progetto Contenuto (chiamato TicTacToeContent) e fare clic con il pulsante destro del mouse su di esso. Dal menu di scelta rapida, seleziona "Aggiungi> Elemento esistente ...". Quando si apre la finestra di dialogo, accedere a Media
cartella che hai decompresso dal download del tutorial e seleziona tutte le immagini contenute al suo interno. Dovresti essere in grado di distinguere dai nomi delle immagini esattamente cosa contiene ogni oggetto.
Dopo aver importato i file multimediali, il tuo solution explorer dovrebbe essere simile al seguente:
Ora che il tuo file multimediale è stato importato nel progetto Contenuto collegato alla tua soluzione, devi caricare ogni immagine come trama separata. Poiché utilizzerai queste trame nel corso del gioco, le imposterai nei campi all'interno della tua classe di gioco. Apri il file Game1.cs e aggiungi i seguenti campi all'inizio della dichiarazione della tua classe:
Texture2D gridTexture; Rectangle gridRectangle; Texture2D resetButton; Rectangle resetButtonPosition; Texture2D oPiece; Texture2D xPiece; Texture2D oWinner; Texture2D xWinner; Texture2D noWinner; Texture2D oTurn; Texture2D xTurn;
Vedi che ciascuna delle immagini che hai importato ha un campo per il backup. Inoltre, la griglia di riproduzione principale e la trama del pulsante di ripristino hanno campi di testo Rettangolo
che sarà usato per posizionare quegli oggetti. Questi sono memorizzati come campi perché non cambieranno nel corso del gioco.
Ora che hai creato i campi appropriati, è il momento di creare un'istanza di Texture2D
e Rettangolo
oggetti che sono assegnati ai campi. Scorri verso il basso fino al tuo Game1.cs
file fino a raggiungere il LoadContent
metodo. All'interno di questo metodo, inserire il seguente codice dopo la riga che legge spriteBatch = new SpriteBatch (GraphicsDevice);
:
gridTexture = Content.Load( "TicTacToe_Grid"); gridRectangle = new Rectangle (0, 0, spriteBatch.GraphicsDevice.Viewport.Width, spriteBatch.GraphicsDevice.Viewport.Height); oPiece = Content.Load ( "TicTacToe_O"); xPiece = Content.Load ( "TicTacToe_X"); resetButton = Content.Load ( "TicTacToe_Reset"); resetButtonPosition = new Rectangle (spriteBatch.GraphicsDevice.Viewport.Width / 2 - (resetButton.Width / 2), spriteBatch.GraphicsDevice.Viewport.Height - 95, resetButton.Width, resetButton.Height); oWinner = Content.Load ( "TicTacToe_O_Winner"); xWinner = Content.Load ( "TicTacToe_X_Winner"); noWinner = Content.Load ( "TicTacToe_Draw"); oTurn = Content.Load ( "TicTacToe_O_Turn"); xTurn = Content.Load ( "TicTacToe_X_Turn");
Dopo aver caricato gli sprite che verranno utilizzati dal gioco, è necessario trovare il flusso di lavoro su cui il gioco verrà eseguito. Ai fini di Tic-Tac-Toe, questo è abbastanza semplice e assomiglia al seguente:
Come probabilmente puoi dire, questi passaggi rientrano in una delle due categorie di base, Draw o Update. Scansione attraverso il Game1.cs
file vedrai che hai due metodi, Disegnare
e Aggiornare
sono i contenitori perfetti per il codice richiesto per descrivere il flusso di lavoro.
Osservando il flusso di lavoro, puoi discernere che ci sono quattro elementi diversi da tenere sotto controllo per gestire lo stato del gioco. Innanzitutto, devi tracciare lo stato di ogni punto della griglia sul campo di gioco. Lo farai utilizzando un'enumerazione personalizzata e un array multidimensionale. Successivamente, devi tenere traccia di se il gioco è stato vinto e da chi. In terzo luogo, è necessario tenere traccia di chi è il turno. Infine, è necessario verificare se il gioco è vincente. Questo elemento è inizializzato come vero
e viene ricalcolata dopo che ogni giocatore ha un turno. Quando tutti i punti della griglia sono compilati, questo cambia in falso
.
Inizierai definendo l'enumerazione personalizzata che descrive un giocatore per il tuo gioco. Nella parte superiore del tuo file di classe, sopra la tua dichiarazione di classe, aggiungi il seguente codice:
public enum TicTacToePlayer None, PlayerO, PlayerX
Questa enumerazione delinea tre giocatori (Nessuno, GiocatoreO e GiocatoreX) e sarà usato per tracciare sia lo stato della griglia che il vincitore del gioco. Ora aggiungi le variabili di istanza che ti aiuteranno a monitorare lo stato del gioco. Questi articoli dovrebbero essere aggiunti all'inizio della dichiarazione della classe:
bool vincente; Vincitore del TicTacToePlayer; TicTacToePlayer corrente; TicTacToePlayer [,] grid;
Stai memorizzando quattro cose qui. Innanzitutto, si definisce se il gioco è ancora vinabile. Secondo, dichiari il vincitore. Se il vincitore è Nessuno, la riproduzione continua. Dopodiché, memorizzi il giocatore corrente. Infine, si memorizza lo stato della griglia. A questo punto, devi ancora inizializzare ciascuna di queste variabili. Pensando al futuro, si sa che sarà necessario reinizializzarli ogni volta che qualcuno farà clic sul pulsante Ripristina e, in quanto tale, possiamo creare un nuovo metodo che gestisca tale inizializzazione. Aggiungi il nuovo metodo alla tua classe sotto il Inizializzare
metodo come segue:
private void Reset () winnable = true; winner = TicTacToePlayer.None; grid = new TicTacToePlayer [3, 3]; per (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) grid[i, j] = TicTacToePlayer.None;
Ora, chiama questo nuovo metodo dal Inizializzare
metodo modificandolo per leggere come segue:
protected override void Initialize () Reset (); base.Initialize ();
A questo punto stai memorizzando tutti i dati che ti servono, quindi dovrebbe essere semplice iniziare a disegnare l'interfaccia.
Prima di iniziare a disegnare qualsiasi cosa, devi impostare la larghezza e l'altezza preferite per il tuo dispositivo. Lo farai all'interno del Game1
costruttore. Cambiatelo per leggere come segue:
public Game1 () graphics = new GraphicsDeviceManager (this); Content.RootDirectory = "Contenuto"; graphics.PreferredBackBufferWidth = 480; graphics.PreferredBackBufferHeight = 800; // Il frame rate è 30 fps di default per Windows Phone. TargetElapsedTime = TimeSpan.FromTicks (333333);
Hai aggiunto dichiarazioni che dichiarano che vuoi che la larghezza del buffer posteriore sia di 480 pixel e l'altezza sia di 800 pixel. Questo semplifica enormemente il disegno del resto dei componenti per il gioco.
Per semplificare le cose, eseguirai ogni passaggio di disegno all'interno di un metodo separato. Questi metodi verranno quindi chiamati dalla base Disegnare
metodo che esiste già. Iniziamo pensando ad alcuni buoni nomi per ciascuna delle fasi del flusso di lavoro del gioco, creando metodi con quel nome e aggiungendo chiamate a quei methos da Disegnare
. A mio parere, i seguenti metodi di metodo descrivono adeguatamente sia ciò che faranno sia i passaggi del flusso di lavoro trattati:
Crea ora questi metodi inserendo il seguente codice sotto il tuo Disegnare
metodo:
private void DrawGrid () private void DrawPieces () private void DrawStatus () private void DrawResetButton ()
Scriverà il codice per questi metodi in un momento, ma per ora è necessario aggiungerli al tuo Disegnare
metodo modificandolo per leggere come segue:
protected override void Draw (GameTime gameTime) GraphicsDevice.Clear (Color.Black); spriteBatch.Begin (); DrawGrid (); DrawPieces (); DrawStatus (); DrawResetButton (); spriteBatch.End (); base.Draw (GameTime);
Noterai che hai circondato le chiamate ai tuoi metodi di supporto con le chiamate a SpriteBatch
oggetto di Inizio
e Fine
metodi. Lo fai perché i tuoi metodi di supporto attireranno tutti gli sprites ed è molto più efficiente chiamare il Inizio
e Fine
coppia una volta dentro Disegnare
piuttosto che all'interno di ciascun metodo di supporto.
Ora, lavoriamo per far apparire la griglia di gioco. La griglia di riproduzione è un'immagine di 480 pixel di larghezza per 800 pixel di altezza con uno sfondo trasparente e una griglia bianca di quadrati di 150 pixel di larghezza posizionata al centro. Lo hai importato prima. Disegnarlo sullo schermo del telefono non potrebbe essere più facile. Prendi la trama che hai caricato e immagazzinato nel gridTexture
variabile e disegnarla posizionandola usando l'istanza precedentemente creata gridRectangle
variabile, passando entrambi gli elementi al SpriteBatch
oggetto di Disegnare
metodo. Cambia il tuo DrawGrid
metodo da leggere come segue:
private void DrawGrid () spriteBatch.Draw (gridTexture, gridRectangle, Color.White);
Salva il file in cui stai lavorando e premi F5 per compilare ed eseguire il tuo progetto. L'emulatore di Windows Phone 7 dovrebbe apparire e visualizzare la griglia Tic-Tac-Toe su uno sfondo nero, proprio come l'immagine seguente:
Ora che la griglia è a posto, disegniamo i pezzi da giocare. A questo punto possiamo applicare alcune semplici logiche per mostrare i pezzi ma nulla verrà visualizzato fino a quando non aggiungeremo il codice per gestire effettivamente i tocchi e giocare. Modifica il tuo DrawPieces
metodo come segue:
private void DrawPieces () for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) if (grid[i, j] != TicTacToePlayer.None) Texture2D texture = grid[i, j] == TicTacToePlayer.PlayerO ? oPiece : xPiece; Rectangle position = GetGridSpace(i, j, texture.Width, texture.Height); spriteBatch.Draw(texture, position, Color.White);
Se hai un occhio acuto (o più probabilmente, Visual Studio ti mostra linee rosse ondulate) vedrai che il GetGridSpace
manca il metodo. GetGridSpace
è un metodo di convenienza che aiuta a mantenere un po 'di codice al di fuori DrawPieces
metodo e sarà anche utile quando si tenta di gestire i tocchi in seguito. Aggiungilo alla fine della dichiarazione della tua classe come segue:
Rettangolo privato GetGridSpace (int column, int row, int width, int height) int centerX = spriteBatch.GraphicsDevice.Viewport.Width / 2; int centerY = spriteBatch.GraphicsDevice.Viewport.Height / 2; int x = centerX + ((column - 1) * 150) - (width / 2); int y = centerY + ((row - 1) * 150) - (height / 2); restituisce il nuovo rettangolo (x, y, larghezza, altezza);
Ora, diamo un'occhiata al resto di DrawPieces
. Questo metodo è un po 'più complicato del DrawGrid
ma dovrebbe essere ancora abbastanza facile da capire. Si scorre su ogni riga e colonna del campo di gioco, memorizzato in griglia
variabile e controllare per vedere lo stato di quello spazio griglia. Se lo spazio della griglia contiene un giocatore diverso da "Nessuno", disegnare la trama appropriata. Si utilizza l'operatore ternario per acquisire la trama corretta in base allo stato dello spazio della griglia e quindi disegnarlo utilizzando il rettangolo ottenuto da GetGridSpace
.
Il prossimo problema da affrontare è il disegno dello stato attuale. Lo stato mostra di chi è il turno, chi ha vinto la partita o se il gioco è un pareggio. Compila il metodo come segue:
private void DrawStatus () Texture2D texture; if (vincitore! = TicTacToePlayer.None) texture = winner == TicTacToePlayer.PlayerO? oWinner: xWinner; else if (! winnable) texture = noWinner; else texture = current == TicTacToePlayer.PlayerO? oTurn: xTurn; Rectangle position = new Rectangle (spriteBatch.GraphicsDevice.Viewport.Width / 2 - (texture.Width / 2), 15, texture.Width, texture.Height); spriteBatch.Draw (texture, posizione, Color.White);
Questo metodo non differisce molto dagli altri metodi di disegno creati finora. Hai una trama e una posizione e devi disegnare la trama sullo schermo. La parte interessante di questo metodo è determinare quale trama disegnare. Per prima cosa controlla se c'è un vincitore. Se c'è, si sceglie la texture vincente corretta e si disegna. Quindi, controlli se tutti gli spazi della griglia sono stati occupati e il gioco non è più vincibile. Se questo è il caso, allora scegli la trama non vincente e disegna quella. Se nessuna di queste condizioni è vera, allora controlli quale è il turno di quel giocatore, scegli la trama di turno corretta e pescala. Se compilate ed eseguite il vostro progetto a questo punto (premendo F5), vedrete che l'interfaccia mostra che è il turno di O:
Infine, creerai il codice che disegna il pulsante di ripristino. Questo è abbastanza semplice. Se c'è un vincitore o il gioco non è più vincibile, si disegna la trama del pulsante di reset. Modifica il DrawResetButton
metodo in modo che legga come segue:
private void DrawResetButton () if (vincitore! = TicTacToePlayer.None ||! winnable) spriteBatch.Draw (resetButton, resetButtonPosition, Color.White);
A questo punto, hai creato tutto il codice necessario per disegnare la tua interfaccia e tutti i suoi componenti. Ora, devi solo gestire l'aggiornamento del gioco in base ai tocchi dei giocatori.
Se hai seguito l'ultimo tutorial su XNA, un sacco del seguente codice sembrerà familiare. La gestione dei tocchi sullo schermo è qualcosa di abbastanza standard ed è solo all'interno del codice di gestione del tocco che si avrà la logica di gioco. Per iniziare, inseriamo il codice di gestione del tocco di base in Aggiornare
metodo. Trova Aggiornare
nel tuo Game1
classificare e modificarlo come segue:
protetto override void Update (GameTime gameTime) if (GamePad.GetState (PlayerIndex.One) .Buttons.Back == ButtonState.Pressed) this.Exit (); TouchCollection tocca = TouchPanel.GetState (); se (! toccando && tocchi.Count> 0) toccando = vero; TouchLocation touch = touches.First (); HandleBoardTouch (touch); HandleResetTouch (touch); else if (tocca.Count == 0) toccando = falso; base.Update (gameTime);
Ci sono alcune cose in questo metodo a cui prestare attenzione. Innanzitutto, noterai un nuovo toccante
variabile che non esiste. Questa variabile memorizza se il giocatore sta toccando o meno il tabellone sul precedente Aggiornare
chiama e impedisce a un dito indugiato di suonare più volte senza rilasciare dallo schermo. Inserisci toccante
come variabile di istanza nella parte superiore della dichiarazione della classe.
bool toccando;
Noterai anche che stai effettuando due chiamate di metodo all'interno di Aggiornare
metodo a metodi che non esistono ancora. Aggiungi questi metodi alla tua dichiarazione di classe direttamente sotto Aggiornare
metodo:
private void HandleBoardTouch (TouchLocation touch) private void HandleResetTouch (TouchLocation touch)
Ora, camminando attraverso il Aggiornare
metodo si vede che controlli i tocchi correnti sullo schermo. Se ci sono dei tocchi e il giocatore non ha toccato lo schermo in precedenza, allora prendi il primo tocco e passalo ai metodi che gestiscono i tocchi della scheda e ripristini i tocchi. Se il giocatore non sta toccando lo schermo e lo erano in precedenza, allora aggiorni il toccante
variabile a falso.
A questo punto, inseriamo il HandleBoardTouch
e HandleResetTouch
metodi. Questi corrispondono ai passaggi 5 e 6 del flusso di lavoro, rispettivamente.
Quando un utente tocca lo schermo, il gioco deve fare alcune cose:
Aggiorna il HandleBoardTouch
leggere come segue, gestendo tutti i passaggi precedenti:
vuoto privato HandleBoardTouch (Touch Touch touch) if (vincitore == TicTacToePlayer.None) for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) Rectangle box = GetGridSpace(i, j, 150, 150); if (grid[i, j] == TicTacToePlayer.None && box.Contains((int)touch.Position.X, (int)touch.Position.Y)) grid[i, j] = current; CheckForWin(current); CheckForWinnable(); current = current == TicTacToePlayer.PlayerO ? TicTacToePlayer.PlayerX : TicTacToePlayer.PlayerO;
Come puoi vedere, questo metodo segue lo schema di base sopra. Se non c'è un vincitore, itera su ogni spazio della griglia, controlla se il tocco è in quello spazio, controlla se lo spazio è aperto, e quindi pone un pezzo lì. Controllare un vincitore e assicurarsi che il gioco sia ancora vincente viene gestito con altri metodi. Escludiamo quei metodi ora. Sotto il HandleBoardTouch
metodo, aggiungi il seguente codice:
private void CheckForWin (TicTacToePlayer player) private void CheckForWinnable ()
Per ora, lascia questi metodi vuoti e compilare ed eseguire il tuo gioco. Prova a toccare la scheda facendo clic sull'emulatore e guarda il messaggio di stato che cambia e vengono visualizzati i pezzi da giocare. Sei sulla buona strada per un gioco completo ora!
A questo punto si arriva alla vera carne del gioco, la logica vincente. Come discusso in precedenza, uno stato vincente si verifica quando i pezzi di un giocatore occupano una delle file, una delle colonne o una delle due diagonali. Il gioco diventa impossibile quando non è stato dichiarato il vincitore e non ci sono più posti non occupati. Per questo gioco, stiamo usando una matrice multidimensionale per memorizzare lo stato della griglia e fuori dalla scatola C # non fornisce metodi per controllare righe, colonne o diagonali. Fortunatamente, il linguaggio supporta una fantastica funzione chiamata metodi di estensione che userete qui per rendere il vostro codice un po 'più pulito.
Per creare i metodi di estensione, devi prima creare una nuova classe. Fare clic sul nome del progetto in Esplora soluzioni e fare clic su "Aggiungi> Classe ...". Assegna un nome alla classe MultiDimensionalArrayExtensions e fai clic su "Aggiungi". Quando il tuo nuovo file si apre per la modifica, modificalo in modo che la dichiarazione della tua classe sia simile alla seguente:
classe statica pubblica MultiDimensionalArrayExtensions
Vedrai che hai aggiunto i modificatori pubblico
e statico
alla dichiarazione di classe. Questo è necessario per la creazione di metodi di estensione. Ora, creeremo un paio di metodi di cui avremo bisogno, ognuno dei quali restituisce un IEnumerable
per una facile ricerca:
Modifica di nuovo la classe, aggiungendo i metodi come segue:
public static class MultiDimensionalArrayExtensions public static IEnumerableRiga (questo T [,] array, riga int) var columnLower = array.GetLowerBound (1); var columnUpper = array.GetUpperBound (1); per (int i = columnLower; i <= columnUpper; i++) yield return array[row, i]; public static IEnumerable Colonna (questo T [,] array, int column) var rowLower = array.GetLowerBound (0); var rowUpper = array.GetUpperBound (0); per (int i = rowLower; i <= rowUpper; i++) yield return array[i, column]; public static IEnumerable Diagonale (questo T [,] array, direzione DiagonalDirection) var rowLower = array.GetLowerBound (0); var rowUpper = array.GetUpperBound (0); var columnLower = array.GetLowerBound (1); var columnUpper = array.GetUpperBound (1); for (int row = rowLower, column = columnLower; row <= rowUpper && column <= columnUpper; row++, column++) int realColumn = column; if (direction == DiagonalDirection.DownLeft) realColumn = columnUpper - columnLower - column; yield return array[row, realColumn]; public enum DiagonalDirection DownRight, DownLeft public static IEnumerable Tutti (questo T [,] array) var rowLower = array.GetLowerBound (0); var rowUpper = array.GetUpperBound (0); var columnLower = array.GetLowerBound (1); var columnUpper = array.GetUpperBound (1); for (int row = rowLower; row <= rowUpper; row++) for (int column = columnLower; column <= columnUpper; column++) yield return array[row, column];
Puoi vedere che non c'è molto di questi metodi. Per ognuno di essi, una particolare parte dell'array multidimensionale viene ripetuta e quella parte dell'array viene restituita come parte di un IEnumerable
. L'unica parte davvero difficile potrebbe essere l'uso del dare la precedenza
parola chiave. Una spiegazione del comportamento di tale parola chiave esula dallo scopo di questo articolo, ma il riferimento C # su MSDN per la parola chiave yield può essere di aiuto se desideri saperne di più. Come nota a margine, gran parte del lavoro su questi metodi di estensione è preso da un contributo utente su StackOverflow che puoi trovare qui
Ora che sono implementati i necessari metodi di estensione, dovrebbe essere abbastanza semplice implementare la logica di vincita. Torniamo al CheckForWin
metodo e attuarlo. Aggiorna il metodo da leggere come segue:
privato vuoto CheckForWin (lettore TicTacToePlayer) FunccheckWinner = b => b == giocatore; if (grid.Row (0) .All (checkWinner) || grid.Row (1) .All (checkWinner) || grid.Row (2) .All (checkWinner) || grid.Column (0) .All ( checkWinner) || grid.Column (1) .All (checkWinner) || grid.Column (2) .All (checkWinner) || grid.Diagonal (MultiDimensionalArrayExtensions.DiagonalDirection.DownRight) .All (checkWinner) || grid.Diagonal (MultiDimensionalArrayExtensions.DiagonalDirection.DownLeft) .All (checkWinner)) winner = player;
Dato quello che sai già dalla creazione dei metodi di estensione, questo dovrebbe essere abbastanza semplice da decifrare. Per prima cosa crea un "Func": http: //msdn.microsoft.com/en-us/library/bb549151.aspx
oggetto che agisce come delegato e consente di utilizzare un'istruzione lambda (quella b => b == giocatore
parte) per interrogare un IEnumerable
(come quelli restituiti dal metodo di estensione) e restituiscono a bool
. Quindi applichi questo Func
oggetto attraverso ogni riga, colonna e diagonale usando il IEnumerable.All
metodo. Se uno di questi casi è vero, allora assegni il vincitore
variabile di istanza al giocatore
parametro. Se nessuno di questi casi è vero, non succede nulla.
Adesso modifica il tuo CheckForWinnable
metodo:
private void CheckForWinnable () if (vincitore == TicTacToePlayer.None) FunccheckNone = b => b == TicTacToePlayer.None; if (! grid.All (). Any (checkNone)) winnable = false;
Questo metodo è molto simile a CheckForWin
. Innanzitutto, controlli se il gioco ha un vincitore. In caso contrario, crei a Func
oggetto che controllerà se un oggetto è uguale al TicTacToePlayer
Nessuna
. Quindi applichi questo Func
contro tutti gli spazi della griglia, controllando se uno qualsiasi degli spazi non è occupato. Se nessuno lo è, il gioco non è più vinificabile e si alterna la variabile di istanza winnable
.
A questo punto il tuo gioco è pronto per partire. Puoi compilare ed eseguire il tuo progetto premendo F5 e iniziare a giocare (da solo o con un partner). A turno, posiziona i pezzi sulla scacchiera, guarda il messaggio di stato che cambia e vedi cosa succede quando vinci. Una volta che vinci o disegni, fai clic sul pulsante di ripristino e guarda il gioco tornare al suo stato originale.
A questo punto ci sono una varietà di cose diverse che potresti fare. Puoi implementare un conteggio vincente che mostra quante volte ogni giocatore ha vinto. Puoi cambiare il modo in cui i pezzi vengono visualizzati o aggiungere un'animazione interessante quando viene dichiarato un vincitore. Si potrebbe tematizzare il gioco per renderlo un po 'più interessante, magari mettendo l'Alleanza Ribelle contro l'Impero Galattico?
A questo punto, spetta a te espandere e sviluppare tutto ciò che desideri. Spero ti sia piaciuto seguire questo tutorial tanto quanto mi è piaciuto scriverlo e non vedo l'ora di sentire i tuoi commenti.