XNA is een raamwerk voor het maken van hoge niveaus voor Microsoft-apparaten, waaronder Windows-pc's, Xbox 360 en het gloednieuwe Windows Phone 7-besturingssysteem. In een eerdere zelfstudie hebben we de basisprincipes van het XNA-framework besproken, inclusief de verwerking van invoer en het weergeven van sprites. In dit artikel leer je hoe je die vaardigheden combineert met een eigen spelidee om iets leuks te maken om te spelen en dat je het gemakkelijk kunt oppikken.
In deze zelfstudie maak je een eenvoudig Tic-Tac-Toe-spel dat je met vrienden kunt spelen. Tic-Tac-Toe is een eenvoudig spel waarbij twee spelers afwisselend beurten plaatsen door tekens op een drie bij drie rasters te plaatsen. De eerste speler gebruikt een O en de tweede speler gebruikt een X. Om het spel te winnen, moet een speler drie van zijn personages rangschikken in een rij, kolom of diagonaal.
Hoewel deze game eenvoudig is, zijn er een paar verschillende vaardigheden vereist om te bouwen. Ten eerste zul je XNA en zijn grafische mogelijkheden gebruiken om je spel te bouwen. Daarom moet je bekend zijn met het weergeven van sprites. Ten tweede moet u weten hoe u aanrakingen op het aanraakscherm van de telefoon kunt verwerken. Gelukkig biedt XNA een API op hoog niveau voor toegang tot deze aanrakingen. Ten slotte moet u een beetje programmeer- en logica-kennis toepassen om de winnaar te bepalen. Voor deze tutorial zal veel daarvan aan u worden gegeven. Bij het bouwen van games moet je in de toekomst met je eigen ideeën en logica komen.
Zorg er om te beginnen voor dat u de nieuwste ontwikkeltools voor Windows Phone 7 hebt geïnstalleerd. Als u uw hulpprogramma's sinds de laatste WP7-zelfstudie over MobileTuts niet hebt bijgewerkt, bezoekt u het Microsoft Downloadcentrum en haalt u de RTW-versie op. Deze nieuwste versie wordt geleverd met de laatste emulator die laat zien hoe uw apps zullen werken op de hardware van de release-dag.
Nadat u ervoor heeft gezorgd dat uw tools up-to-date zijn, opent u Visual Studio 2010 en klikt u op de link "Nieuw project ..." in de linkerzijbalk. In het dialoogvenster dat verschijnt, kiest u "XNA Game Studio 4" in de linkerkolom en zorgt u ervoor dat de sjabloon "Windows Phone Game (4.0)" aan de rechterkant is geselecteerd. Geef uw project een toepasselijke naam zoals "TicTacToe" en bevestig dat het selectievakje "Directory aanmaken voor oplossing" is geselecteerd. Als je dit allemaal goed hebt gedaan, zou je dialoogvenster moeten overeenkomen met de volgende afbeelding:
Klik op "OK" om uw nieuwe project aan te maken. Visual Studio 2010 genereert de benodigde bestanden in uw opgegeven map en opent Game1.cs
voor bewerking.
Aangezien u in dit project sprites gebruikt voor alle grafische afbeeldingen, moet u de vereiste items in uw project importeren. In de download bij deze zelfstudie vind je een Media
map met verschillende afbeeldingen. Zoek in de oplossingsverkenner aan de rechterkant van het scherm naar het inhoudsproject (TicTacToeContent genaamd) en klik er met de rechtermuisknop op. Selecteer "Toevoegen> Bestaand item ..." in het contextmenu. Wanneer het dialoogvenster opent, bladert u naar Media
map die u uit de tutorial download hebt uitgepakt en alle afbeeldingen erin selecteert. Je moet aan de afbeeldingsnamen precies kunnen zien wat elk item bevat.
Na het importeren van uw media, zou uw oplossingsverkenner op het volgende moeten lijken:
Nu uw media zijn geïmporteerd in het inhoudsproject dat aan uw oplossing is gekoppeld, moet u elke afbeelding als een afzonderlijke structuur laden. Omdat je deze texturen in je game zult gebruiken, ga je ze opslaan in velden in je gameklasse. Open het bestand Game1.cs en voeg de volgende velden toe aan de top van uw klassedeclaratie:
Texture2D gridTexture; Rechthoekraster Rechthoek; Texture2D resetButton; Rectangle resetButtonPosition; Texture2D oPiece; Texture2D xPiece; Texture2D oWinner; Texture2D xWinner; Texture2D noWinner; Texture2D oTurn; Texture2D xTurn;
U ziet dat elk van de afbeeldingen die u hebt geïmporteerd een veld heeft om een back-up van te maken. Bovendien hebben het hoofdspeelrooster en de textuur van de resetknop velden van het type Rechthoek
die worden gebruikt om die items te plaatsen. Deze worden als velden opgeslagen omdat ze tijdens het spel niet veranderen.
Nu u de juiste velden hebt aangemaakt, is het tijd om de Texture2D
en Rechthoek
objecten die aan de velden zijn toegewezen. Blader omlaag naar uw Game1.cs
bestand totdat je de LoadContent
methode. Voer binnen deze methode de volgende code in na de regel die luidt spriteBatch = nieuwe 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");
Na het laden van de sprites die door het spel worden gebruikt, moet je de workflow bedenken waarop het spel zal draaien. Voor de doeleinden van Tic-Tac-Toe is dit vrij eenvoudig en lijkt het op het volgende:
Zoals je waarschijnlijk wel zult merken, vallen deze stappen in een van de twee basiscategorieën, Draw of Update. Scannen door de Game1.cs
bestand zal je zien dat je twee methoden hebt, Trek
en Bijwerken
dat zijn de perfecte containers voor de code die nodig is om de workflow te beschrijven.
Als u naar de workflow kijkt, kunt u zien dat er vier verschillende items moeten worden bijgehouden om de spelstatus te beheren. Eerst moet je de status van elke rastervlek op het speelveld volgen. U doet dit met behulp van een aangepaste opsomming en een multidimensionale array. Vervolgens moet je bijhouden of de game is gewonnen en door wie. Ten derde moet u de wiens beurt het is volgen. Ten slotte moet je bijhouden of het spel te winnen is. Dit item is geïnitialiseerd als waar
en wordt herberekend nadat elke speler een beurt heeft. Wanneer alle rasterpunten zijn ingevuld, verandert dit in vals
.
U begint met het definiëren van de aangepaste opsomming die een speler beschrijft voor uw spel. Voeg de volgende code toe boven aan uw klassenbestand, boven uw klassenverklaring:
public enum TicTacToePlayer None, PlayerO, PlayerX
Deze opsomming geeft drie spelers weer (Geen, SpelerO en SpelerX) en wordt gebruikt om zowel de rasterstatus als de spelwinnaar te volgen. Voeg nu de instantievariabelen toe die u helpen de staat van het spel te volgen. Deze items moeten bovenaan je klassenverklaring worden toegevoegd:
bool winnable; TicTacToePlayer-winnaar; TicTacToePlayer current; TicTacToePlayer [,] raster;
Je slaat hier vier dingen op. Eerst geef je aan of de game nog steeds te winnen is. Ten tweede, verklaar je de winnaar. Als de winnaar Geen is, gaat het spel verder. Hierna slaat u de huidige speler op. Ten slotte slaat u de netstatus op. Op dit punt moet u elk van deze variabelen nog steeds initialiseren. Vooruitdenkend, u weet dat u ze opnieuw moet initialiseren wanneer iemand op de knop Reset klikt en daarom kunnen we een nieuwe methode maken die deze initialisatie afhandelt. Voeg de nieuwe methode toe aan uw klas onder de initialiseren
methode als volgt:
private void Reset () winnable = true; winner = TicTacToePlayer.Non; grid = nieuwe TicTacToePlayer [3, 3]; voor (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) grid[i, j] = TicTacToePlayer.None;
Noem deze nieuwe methode nu vanuit de initialiseren
methode door deze als volgt te lezen:
protected override void Initialize () Reset (); base.Initialize ();
Op dit punt slaat u alle gegevens op die u nodig hebt, dus het zou eenvoudig moeten zijn om de interface te tekenen.
Voordat u iets begint te tekenen, moet u de gewenste breedte en hoogte voor uw apparaat instellen. Je doet dit in de game1
constructeur. Wijzig het als volgt:
public Game1 () graphics = new GraphicsDeviceManager (this); Content.RootDirectory = "Inhoud"; graphics.PreferredBackBufferWidth = 480; graphics.PreferredBackBufferHeight = 800; // Beeldsnelheid is standaard 30 fps voor Windows Phone. TargetElapsedTime = TimeSpan.FromTicks (333333);
U hebt instructies toegevoegd waarin wordt verklaard dat u de breedte van de achtergrondbuffer 480 pixels en de hoogte 800 pixels wilt hebben. Dit vereenvoudigt het tekenen van de rest van de componenten voor het spel aanzienlijk.
Om dingen simpel te houden, ga je elke tekenstap uitvoeren binnen een aparte methode. Deze methoden worden dan vanuit de basis gebeld Trek
methode die al bestaat. Laten we beginnen met enkele goede namen te bedenken voor elk van de stappen in de spelworkflow, methoden voor die naam te creëren en oproepen aan die metho's toe te voegen Trek
. Naar mijn mening beschrijven de volgende methodamen voldoende zowel wat ze zullen doen als de workflow-stappen die worden behandeld:
Maak deze methoden nu door de volgende code onder je in te voegen Trek
methode:
private void DrawGrid () private void DrawPieces () private void DrawStatus () private void DrawResetButton ()
Je schrijft de code voor deze methoden in een oogwenk, maar voor nu moet je ze toevoegen aan je Trek
methode door deze als volgt te lezen:
beschermde override void Draw (GameTime gameTime) GraphicsDevice.Clear (Color.Black); spriteBatch.Begin (); DrawGrid (); DrawPieces (); DrawStatus (); DrawResetButton (); spriteBatch.End (); base.Draw (gametime);
U zult merken dat u de oproepen naar uw helpermethoden hebt omringd met oproepen naar de spriteBatch
voorwerpen Beginnen
en Einde
methoden. Je doet dit omdat je hulpmethoden allemaal sprites zullen tekenen en het is veel efficiënter om de Beginnen
en Einde
paar een keer binnen in Trek
in plaats van binnen elke helpermethode.
Laten we nu proberen het speelraster te laten verschijnen. Het spelraster is een 480 pixels breed bij 800 pixels lang beeld met een transparante achtergrond en een wit raster met vierkanten van 150 pixels breed in het midden. Je hebt het eerder geïmporteerd. Het kan niet eenvoudiger zijn om het naar het scherm van de telefoon te brengen. Je neemt de textuur die je hebt geladen en opgeslagen in de gridTexture
verander en teken het door het te positioneren met behulp van het prevoiusly instantiated gridRectangle
variabele, beide artikelen doorgeven aan de spriteBatch
voorwerpen Trek
methode. Verander jouw DrawGrid
methode om als volgt te lezen:
private void DrawGrid () spriteBatch.Draw (gridTexture, gridRectangle, Color.White);
Sla het bestand op waarin je werkt en druk op F5 om je project te compileren en uit te voeren. De Windows Phone 7-emulator verschijnt en geeft je Tic-Tac-Toe-raster weer op een zwarte achtergrond, net als in de volgende afbeelding:
Nu het raster op zijn plaats zit, laten we de speelstukken tekenen. Op dit punt kunnen we enkele eenvoudige logica toepassen om de stukjes te laten zien, maar niets zal worden weergegeven totdat we de code toevoegen om daadwerkelijk de aanrakingen te verwerken en het spel te spelen. Wijzig uw DrawPieces
methode als volgt:
private ongeldige 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);
Als je een scherp oog hebt (of, waarschijnlijker, Visual Studio je rode kronkelige lijnen laat zien) zul je zien dat het GetGridSpace
methode ontbreekt. GetGridSpace
is een gemakkelijke methode die helpt een beetje code uit de DrawPieces
methode en komt ook van pas bij het proberen om later aanraken te verwerken. Voeg het als volgt toe aan de onderkant van uw klassedeclaratie:
private Rectangle GetGridSpace (int-kolom, int-rij, int-width, int height) int centerX = spriteBatch.GraphicsDevice.Viewport.Width / 2; int centerY = spriteBatch.GraphicsDevice.Viewport.Height / 2; int x = centerX + ((kolom - 1) * 150) - (breedte / 2); int y = centerY + ((rij - 1) * 150) - (hoogte / 2); return new Rectangle (x, y, width, height);
Laten we nu kijken naar de rest DrawPieces
. Deze methode is een beetje ingewikkelder dan de DrawGrid
maar het moet nog steeds vrij gemakkelijk te begrijpen zijn. U itereert over elke rij en kolom van het speelveld, opgeslagen in de rooster
variabele en controleer om de status van die rasterruimte te zien. Als de rasterruimte een andere speler dan "Geen" bevat, teken dan de juiste textuur. U gebruikt de ternaire operator om de juiste textuur te verkrijgen op basis van de status van de rasterruimte en vervolgens te tekenen met de rechthoek die is verkregen uit GetGridSpace
.
Het volgende probleem om mee om te gaan is het tekenen van de huidige status. De status geeft aan wie aan de beurt is, wie de game heeft gewonnen of dat de game gelijkspel is. Vul de methode als volgt in:
private ongeldige DrawStatus () Texture2D texture; if (winner! = 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 (textuur, positie, Color.White);
Deze methode verschilt niet veel van de andere tekenmethoden die je tot nu toe hebt gemaakt. Je hebt een textuur en een positie en moet de textuur op het scherm tekenen. Het interessante deel van deze methode is het bepalen welke textuur moet worden getekend. Controleer eerst of er een winnaar is. Als dat het geval is, kies je de juiste winnaarstextuur en teken je dat. Vervolgens controleer je of alle rasterruimten bezet zijn en het spel niet langer te winnen is. Als dat het geval is, kies je de no-winner-structuur en tekent u die. Als geen van beide voorwaarden waar is, kijk dan welke speler aan de beurt is, kies de juiste bocht-structuur en teken die. Als u op dit punt uw project compileert en uitvoert (door op F5 te drukken), ziet u dat de interface aangeeft dat O aan de beurt is:
Ten slotte gaat u de code maken die de resetknop tekent. Dit is redelijk eenvoudig. Als er een winnaar is of als het spel niet meer te winnen is, teken je de textuur van de resetknop. Wijzig de DrawResetButton
methode zodat het als volgt luidt:
private void DrawResetButton () if (winner! = TicTacToePlayer.None ||! winnable) spriteBatch.Draw (resetButton, resetButtonPosition, Color.White);
Op dit punt hebt u alle code gemaakt die nodig is om uw interface en alle bijbehorende onderdelen te tekenen. Nu moet je gewoon je spel bijwerken op basis van de aanrakingen van de spelers.
Als u de laatste zelfstudie op XNA hebt gevolgd, ziet veel van de volgende code er bekend uit. Omgaan met aanrakingen op het scherm is iets dat vrij standaard is en het zit alleen in de aanraakverwerkingscode dat je je spellogica hebt. Laten we om te beginnen de eenvoudige code voor het afhandelen van aanraken in de Bijwerken
methode. Vind Bijwerken
in uw game1
klasse en wijzig deze om ze als volgt te lezen:
protected override void Update (GameTime gameTime) if (GamePad.GetState (PlayerIndex.One) .Buttons.Back == ButtonState.Pressed) this.Exit (); TouchCollection raakt = TouchPanel.GetState () aan; if (! touching && touches.Count> 0) touching = true; TouchLocation touch = raakt.Eerste (); HandleBoardTouch (touch); HandleResetTouch (touch); else if (touches.Count == 0) touching = false; base.Update (gameTime);
Er zijn een paar dingen in deze methode om op te letten. Eerst zul je een nieuwe opmerken aandoenlijk
variabele die niet bestaat. Deze variabele slaat op of de speler het bord van het vorige al dan niet aanraakte Bijwerken
bel en voorkomt dat een slepende vinger meerdere keren wordt afgespeeld zonder het scherm te verlaten. Toevoegen aandoenlijk
als een instantievariabele bovenaan uw klassenverklaring.
Bool raken;
Je zult ook merken dat je twee methodeaanroepen binnen de Bijwerken
methode voor methoden die nog niet bestaan. Voeg die methoden toe aan uw klassenverklaring direct onder de Bijwerken
methode:
private void HandleBoardTouch (TouchLocation touch) private ongeldige HandleResetTouch (TouchLocation touch)
Nu, wandelen door de Bijwerken
methode die u ziet dat u controleert op de huidige aanrakingen op het scherm. Als er aanrakingen zijn en de speler niet eerder het scherm heeft aangeraakt, dan pakt u de eerste aanraking en geeft u deze door aan de methoden die het aanraken van het bord en het opnieuw instellen van aanrakingen verzorgen. Als de speler het scherm niet aanraakt en deze eerder was, dan werkt u de aandoenlijk
veranderlijk in onwaar.
Laten we nu het volgende invullen HandleBoardTouch
en HandleResetTouch
methoden. Deze komen overeen met werkstroomstappen 5 en 6, respectievelijk.
Wanneer een gebruiker het scherm aanraakt, moet de game een paar dingen doen:
Werk het HandleBoardTouch
om als volgt te lezen, alle bovenstaande stappen afhandelen:
private void HandleBoardTouch (TouchLocation touch) if (winner == 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;
Zoals u kunt zien, volgt deze methode de bovenstaande basiscontour. Als er geen winnaar is, itereert deze over elke rasterruimte, controleert of de aanraking in die ruimte is, controleert of de spatie open is en plaatst een stuk daar. Het controleren op een winnaar en ervoor zorgen dat het spel nog steeds te winnen is, wordt op andere manieren afgehandeld. Laten we die methoden nu uitprinten. Onder de HandleBoardTouch
methode, voeg de volgende code toe:
private void CheckForWin (TicTacToePlayer player) private void CheckForWinnable ()
Laat deze methoden voorlopig leeg en compileer en voer je spel uit. Probeer het bord aan te raken door op de emulator te klikken en het statusbericht te bekijken en de speelstukken weer te geven. Je bent nu goed op weg naar een complete game!
Op dit punt kom je bij het echte vlees van het spel, de winnende logica. Zoals eerder besproken, vindt een winnende situatie plaats wanneer de stukken van een speler een van de rijen innemen, een van de kolommen of een van de twee diagonalen. Het spel wordt niet meer mogelijk als er geen winnaar wordt aangegeven en er zijn geen onbezette plekken meer over. Voor deze game gebruiken we een multidimensionale array om de status van het raster op te slaan en C # biedt geen methoden om rijen, kolommen of diagonalen te controleren. Gelukkig ondersteunt de taal een geweldige functie, uitbreidingsmethoden die je hier gebruikt om je code een beetje schoner te maken.
Als u de uitbreidingsmethoden wilt maken, moet u eerst een nieuwe klasse maken. Klik op de naam van uw project in de Solution Explorer en klik op "Toevoegen> Klasse ...". Noem uw klasse MultiDimensionalArrayExtensions en klik op "Toevoegen". Wanneer uw nieuwe bestand voor bewerking wordt geopend, wijzigt u het zodat uw klassenverklaring er als volgt uitziet:
openbare statische klasse MultiDimensionalArrayExtensions
Je zult zien dat je de modifiers hebt toegevoegd openbaar
en statisch
naar de klassenverklaring. Dit is nodig voor het maken van uitbreidingsmethoden. Nu gaan we een aantal methoden maken die we nodig hebben, die elk een IEnumerable
voor eenvoudig zoeken:
Wijzig uw klasse opnieuw door de methoden als volgt toe te voegen:
openbare statische klasse MultiDimensionalArrayExtensions public static IEnumerableRij (dit T [,] array, int rij) var columnLower = array.GetLowerBound (1); var columnUpper = array.GetUpperBound (1); voor (int i = columnLower; i <= columnUpper; i++) yield return array[row, i]; public static IEnumerable Kolom (deze T [,] array, int kolom) var rowLower = array.GetLowerBound (0); var rowUpper = array.GetUpperBound (0); voor (int i = rowLower; i <= rowUpper; i++) yield return array[i, column]; public static IEnumerable Diagonaal (dit T [,] array, DiagonalDirection richting) 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 Allemaal (dit T [,] array) var rowLower = array.GetLowerBound (0); var rowUpper = array.GetUpperBound (0); var columnLower = array.GetLowerBound (1); var columnUpper = array.GetUpperBound (1); voor (int rij = rowLower; rij <= rowUpper; row++) for (int column = columnLower; column <= columnUpper; column++) yield return array[row, column];
Je kunt zien dat er niet veel is aan deze methoden. Voor elk ervan wordt een bepaald deel van de multidimensionale array herhaald en wordt dat gedeelte van de array geretourneerd als onderdeel van een IEnumerable
. Het enige echt lastige deel is misschien het gebruik van de opbrengst
trefwoord. Een uitleg van het gedrag van dat zoekwoord valt buiten het bestek van dit artikel, maar de C # -referentie op MSDN voor het opbrengstsleutelwoord kan van pas komen als u meer wilt weten. Even terzijde, veel van het werk aan deze uitbreidingsmethoden is afkomstig van een gebruikersbijdrage op StackOverflow die u hier kunt vinden
Nu de noodzakelijke uitbreidingsmethoden zijn geïmplementeerd, zou het vrij eenvoudig moeten zijn om de win-logica te implementeren. Laten we teruggaan naar de CheckForWin
methode en implementeer het. Werk de methode bij om deze als volgt te lezen:
private void CheckForWin (TicTacToePlayer-speler) FunccheckWinner = b => b == speler; if (grid.Row (0). Allemaal (checkWinner) || grid.Row (1). Allemaal (checkWinner) || grid.Row (2). All (checkWinner) || grid.Column (0) .All ( checkWinner) || grid.Column (1). Allemaal (checkWinner) || grid.Column (2). Allemaal (checkWinner) || grid.Diagonal (MultiDimensionalArrayExtensions.DiagonalDirection.DownRight). All (checkWinner) || grid.Diagonal (MultiDimensionalArrayExtensions.DiagonalDirection.DownLeft). All (checkWinner)) winner = player;
Gezien wat u al weet van het maken van de uitbreidingsmethoden, moet dit vrij eenvoudig te ontcijferen zijn. Je maakt eerst een "Func": http: //msdn.microsoft.com/en-us/library/bb549151.aspx
object dat een afgevaardigde handelt en u toestaat om een lambda-statement te gebruiken (dat b => b == speler
deel) om een vraag te stellen IEnumerable
(zoals degenen die zijn teruggekeerd van de uitbreidingsmethode) en retourneert een bool
. U past dit vervolgens toe Func
object over elke rij, kolom en diagonaal met behulp van de IEnumerable.All
methode. Als een van die gevallen waar is, wijst u de winnaar
instantie variabele naar de speler
parameter. Als geen van deze gevallen waar is, gebeurt er niets.
Pas nu uw CheckForWinnable
methode:
private void CheckForWinnable () if (winner == TicTacToePlayer.None) FunccheckNone = b => b == TicTacToePlayer.None; if (! grid.All (). Any (checkNone)) winnable = false;
Deze methode lijkt veel op CheckForWin
. Eerst controleer je of de game een winnaar heeft. Als dat niet het geval is, maakt u een Func
object dat controleert of een item gelijk is aan de TicTacToePlayer
Geen
. U past dit vervolgens toe Func
tegen alle spaties in het raster, om te controleren of een van de spaties onbewoond is. Als dat niet het geval is, is het spel niet meer te winnen en kun je de instantievariabele wisselen verkiesbare
.
Op dit moment is je game klaar voor gebruik. Je kunt je project compileren en uitvoeren door op F5 te drukken en te beginnen met spelen (door jezelf of met een partner). Neem om beurten stukken op het bord, bekijk het statusbericht en zie wat er gebeurt als je wint. Zodra je wint of tekent, klik je op de resetknop en zie je het spel terugkeren naar de oorspronkelijke status.
Op dit punt zijn er een aantal verschillende dingen die je zou kunnen doen. Je zou een winnende telling kunnen uitvoeren die laat zien hoeveel verschillende tijden elke speler heeft gewonnen. U kunt de manier waarop stukken worden weergegeven wijzigen of een coole animatie toevoegen wanneer een winnaar wordt verklaard. Je zou het spel een beetje interessanter kunnen maken, misschien door de Rebel Alliance tegen het Galactische rijk te stoten?
Op dit moment is het aan jou om uit te breiden en te ontwikkelen wat je maar wilt. Ik hoop dat je deze tutorial net zo leuk vond als ik het leuk vond om het te schrijven en kijk uit naar je reacties.