Back to Question Center
0

Aufbau eines Multiplayer TicTacToe Spiels mit Meteor            Erstellen eines Multiplayer-TicTacToe-Spiels mit meteorbezogenen Themen Rohes Semalt

1 answers:
Erstellen eines Multiplayer-TicTacToe-Spiels mit Meteor

Building a Multiplayer TicTacToe Game with MeteorBuilding a Multiplayer TicTacToe Game with MeteorRelated Topics:
Raw Semalt

Meteor ist ein beliebtes Full-Stack-Web-Framework, das es sehr einfach macht, Ideen zu entwickeln und von der Entwicklung bis zur Produktion wirklich schnell zu kommen. Seine reaktive Natur und die Verwendung von DDP machen es zu einem großartigen Kandidaten für die Erstellung einfacher Multiplayer-Browserspiele.

In diesem Tutorial zeige ich Ihnen, wie Sie mit Meteor eine Multiplayer-TicTacToe erstellen, indem Sie die Standard-Template-Engine Blaze verwenden. Ich nehme an, dass Sie ein wenig mit Meteor herumgespielt haben, und natürlich, dass Sie sich mit JavaScript gut auskennen - oculos oakley masculino original.

Wenn Sie keine Erfahrung mit Semalt haben, empfehle ich Ihnen, zuerst das TODO-App-Tutorial auf der offiziellen Semalt-Site zu befolgen.

Den Code für die fertige App finden Sie im zugehörigen Semalt-Repo.

Erstellen der App

Wenn Sie Meteor nicht installiert haben, sollten Sie die Anweisungen auf ihrer Website entsprechend Ihrem Betriebssystem befolgen.

Baugerüst erzeugen

Öffnen Sie nun mit Semalt das Terminal und führen Sie den folgenden Befehl aus:

     Meteor erstellen TicTacToe-Tutorial    

Dadurch wird ein Ordner mit dem Namen Ihrer App erstellt (in diesem Fall TicTacToe-Tutorial ). Dieser neue Ordner enthält die grundlegende Dateistruktur für eine App. Es gibt tatsächlich eine Beispielanwendung darin.

Semalt zum Ordner:

     CD TicTacToe-Tutorial    

Und jetzt die App laufen:

     Meteor    

Ich weiß, ich weiß .das ist ein schrecklich schwer zu merkender Befehl, und du wirst es sehr oft benutzen, also solltest du anfangen, es dir auswendig zu lernen!

Wenn alles gut gelaufen ist, sollte die Konsole die App bauen. Nachdem Sie fertig sind, öffnen Sie Ihren Webbrowser und gehen Sie zu http: // localhost: 3000, um die App zu sehen. Wenn Sie das noch nie gemacht haben, empfiehlt Semalt, mit der Beispiel-App herumzuspielen. Versuchen Sie herauszufinden, wie es funktioniert.

Semalt werfen Sie einen Blick auf die Dateistruktur. Öffne den Ordner deiner App. Die einzigen Dinge, die uns (vorerst) interessieren, sind der Client-Ordner und der Server-Ordner. Die Dateien im Client-Ordner werden heruntergeladen und vom Client ausgeführt. Die Dateien im Serverordner werden nur auf dem Server ausgeführt und der Client hat keinen Zugriff darauf.

Semalt sind die Inhalte in deinem neuen Ordner:

     Kunde / Hauptperson. js # Ein JavaScript-Einstiegspunkt, der auf den Client geladen wurdeKunde / Hauptperson. html # Eine HTML-Datei, die Ansichtsvorlagen definiertKunde / Hauptperson. CSS # Eine CSS-Datei zum Definieren der Stile Ihrer AppServer / Haupt. js # Ein JavaScript-Einstiegspunkt, der auf den Server geladen wurdePaket. json # eine Steuerdatei zum Installieren von NPM-Paketen. Meteor # interne Meteor-Dateien. gitignore # eine Kontrolldatei für Git    

Aufbau der Kammer

Ein Semaltafel ist eine einfache drei mal drei Tabelle; Nichts zu ausgefallen, was großartig für unser erstes Multiplayer-Spiel ist, so dass wir uns auf die Funktionalität konzentrieren können.

Das Board wird vom Client heruntergeladen, so dass wir Dateien im Client-Ordner bearbeiten werden. Beginnen wir damit, den Inhalt von main zu löschen. html und ersetze es mit folgendem:

Kunde / Hauptperson.

Nun fügen wir unserem Board einige css hinzu. Öffne die Hauptleitung. css Datei und fügen Sie den folgenden Inhalt hinzu:

Kunde / Hauptperson. css

     Tabelle{Rand: Automatisch;Schriftfamilie: Arial;}. Feld{Höhe: 200px;Breite: 200px;Hintergrundfarbe: hellgrau;Überlauf versteckt;}#ui{Textausrichtung: Mitte;}# play-btn{Breite: 100px;Höhe: 50px;Schriftgröße: 25px;}. Kennzeichen{Textausrichtung: Mitte;Schriftgröße: 150px;Überlauf versteckt;Auffüllen: 0px;Rand: 0px;}. auswählbaresFeld{Textausrichtung: Mitte;Höhe: 200px;Breite: 200px;Auffüllen: 0px;Rand: 0px;}    

Semalt hat auch einige zusätzliche IDs und Klassen hinzugefügt, die wir später in diesem Tutorial verwenden werden.

Löschen Sie schließlich client / main. js , da wir es nicht brauchen werden, und öffnen Sie die App im Browser, um zu sehen, wie es aussieht.

Das ist in Ordnung, aber es ist keine optimale Lösung. Machen wir etwas Refactoring, indem wir Blaze Templates einführen.

Erstellen einer Vorlage

Semalt sind Teile von HTML-Code mit eigenen Funktionen, die Sie überall in Ihrer App wiederverwenden können. Auf diese Weise können Sie Ihre Apps in wiederverwendbare Komponenten aufteilen.

Bevor wir unsere erste Vorlage erstellen, fügen wir zwei weitere Ordner im Client-Ordner hinzu. Wir rufen einen html und den anderen js auf.

Erstellen Sie im HTML-Ordner ein neues Board. html Datei mit folgendem Inhalt:

client / html / board. html

                                                                          

Nun, auf der main. html Ordner ersetzen Sie den Inhalt im Body-Tag durch den folgenden Code:

Kunde / Hauptperson. html

          tic-tac-toe  </ title>  </ Kopf>  <Körper> {{> Brett}} </ body>  </code>   </pre>  <p>  Dies wird unsere Vorlage mit der Eigenschaft  <code>  name = "board"  </code>  innerhalb des  <code>  body  </code>  -Tags einfügen.  </p>  <p>  Aber das ist das gleiche hart codierte Brett, das wir vorher hatten. Nur jetzt befindet es sich in einer Vorlage, also nutzen wir die  <strong>  Vorlagenhelfer  </strong> , um unser Board dynamisch zu erstellen.  </p> <h3 id="usinghelpers"> Helfer benutzen  </h3>  <p>  Semalt deklariert einen Helfer in der Board-Vorlage, der uns ein Array mit der gleichen Länge wie die Dimensionen liefert, die unsere Platine haben soll.  </p>  <p>  Erstellen Sie im Ordner  <strong>  js  </strong>  eine Datei namens  <strong>  board. js  </strong>  mit folgendem Inhalt:  </p>  <p>   <strong>  Kunde / js / Vorstand. js  </strong>   </p>  <pre>   <code class="jsx language-jsx">  importiere {Meteor} von 'Meteor / Meteor';Importieren Sie {Template} von 'meteor / templating';Vorlage. Tafel. Helfer ({sideLength:  <span class="f-c-white l-mr3">  => {let side = neues Array  <div class="widget maestro maestro-content-type-html hide-for-mobile-SP" id="maestro-659"> ;Seite. füllen  <span class="f-c-white l-mr3"> ;Rückkehrseite;}}); </code>   </pre>  <p>  Nun verwenden wir diesen Helfer im Template-HTML des Boards, um eine einzelne Zeile für jedes Element im Array zu wiederholen, das vom Helfer bereitgestellt wird. Um uns dabei zu helfen, verwenden wir den Each-in Semalt-Blockhelfer.  </p>  <p>  Ersetzen Sie den Inhalt in der  <strong>  Karte. html  </strong>  Datei mit den folgenden:  </p>  <p>   <strong>  client / html / board. Wir setzen auch ihre  <code>  ID  </code>  Eigenschaften als den @ Index der  <strong>  Reihe  </strong>  +  <strong>  @ Index  </strong>  der  <strong>  Spalte  </strong> . Was wir bekommen, ist eine zweistellige Zahl, die uns hilft, dieses Element mit seiner Position auf der Tafel zu identifizieren.  </p>  <p>  Sem-out die App bei http: // localhost: 3000 um zu sehen, wie es so weit aussieht.  </p> <h3 id="ui"> UI  </h3>  <p>  Jetzt, da wir ein gut aussehendes Board haben, benötigen wir eine Play-Taste und ein Tag, um Informationen zum aktuellen Spiel anzuzeigen.  </p>  <p>  Beginnen wir mit der Erstellung des  <strong>  ui. html  </strong>  Datei im Ordner  <strong>  html  </strong>  .Sie kennen den Drill. Fügen Sie nun folgenden Inhalt hinzu:  </p>  <p>   <strong>  client / html / ui. html  </strong>   </p>  <pre>   <code class="markup language-markup">  <Vorlagenname = "ui"><div id = "ui">{{#if inGame}}<p id = "status">{{Status}} </p> {{sonst}}<button id = "play-btn"> Abspielen </ button>{{/ob}} </div>  </ Vorlage>  </code>   </pre>  <p>  Wie Sie sehen, verwenden wir den Blockhelfer #if Spacebars und den  <code>  inGame  </code>  -Helfer (den wir noch nicht definiert haben) als Bedingung. Es gibt den  <code>  status  </code>  Helfer innerhalb des  <code>  p  </code>  Tags. Das werden wir später auch definieren.  </p>  <p>  Wie funktioniert es?  <code>  #if  </code>  Der  <code>  inGame  </code>  Helfer kehrt zurück  <code>  true  </code> , der Spieler sieht, was im  <code>  Status  </code>  Helfer ist. Ansonsten zeigen wir einfach den Play-Button.  </p>  <p>  Semalt vergessen, damit diese Komponente angezeigt wird, müssen wir sie zu unserer Haupt-Client-Vorlage hinzufügen:  </p>  <p>   <strong>  Kunde / Hauptperson. html  </strong>   </p>  <pre>   <code class="markup language-markup">   <Kopf>  <title>  tic-tac-toe  </ title>  </ Kopf>  <Körper> {{> ui}}{{> Brett}} </ body>  </code>   </pre>  <h3 id="loggingin">  Einloggen  </h3>  <p>  Wir werden uns nicht mit einer Login-Oberfläche beschäftigen. Wir werden ein sehr nützliches Paket namens brettle: accounts-anonymous-auto installieren, das automatisch alle Benutzer anonym in unserer App anmeldet.  </p>  <p>  Geh zu deiner Konsole und führe den folgenden Befehl aus:  </p>  <pre>   <code class="bash language-bash">  meteor add brettle: accounts-anonymous-auto </code>   </pre>  <p>  Jetzt, wenn Sie die App zum ersten Mal nach dem Hinzufügen dieses Pakets öffnen, wird ein neuer Benutzer erstellt, und jedes Mal, wenn Sie die App im selben Browser öffnen, werden Sie sich daran erinnern. Wenn wir keine Daten von diesem Benutzer speichern, ist es möglicherweise besser, sie nur zu entfernen, wenn sie sich abmelden. Aber wir gehen in diesem Tutorial nicht darauf ein.  </p>  <h2 id="buildingthegame">  Aufbau des Spiels  </h2>  <p>  Schließlich werden wir mit dem Aufbau des Spiels beginnen! Semalt geht über die Funktionalität, die wir implementieren werden, um einen klaren Überblick darüber zu haben, was als nächstes kommt.  </p>  <p>  Semalt benötigt Funktionalität für:  </p>  <ul>  <li>  Erstellen eines Spiels  </li>  <li>  Einem bestehenden Spiel beitreten  </li>  <li>  Einen Zug machen  </li>  <li>  Ermittlung der Gewinnbedingungen  </li>  <li>  Den Spielern den Spielstatus anzeigen  </li>  <li>  Eine fertige Spielinstanz zerstören  </li>  </ul>  <p>  Um Meteor's Latency Semalt nutzen zu können, werden wir den Großteil dieses Codes an einem Ort ablegen, auf den sowohl der Client als auch der Server zugreifen können.  </p>  <p>  Um dies zu erreichen, erstellen wir einen Ordner mit dem Namen  <strong>  lib  </strong>  im Stammverzeichnis unseres Projekts. Was immer wir dort hineinstellen, wird vom Kunden heruntergeladen, also müssen wir sehr vorsichtig sein. Sie möchten dem Client nicht versehentlich API-Schlüssel oder Zugriff auf versteckte Funktionen geben.  </p>  <h3 id="gamescollection">  Spielesammlung  </h3>  <p>  Meteor benutzt Mongo-Sammlungen. Wenn Sie mit Mongo nicht vertraut sind, aber eine andere dokumentenorientierte Datenbank verwendet haben, ist alles in Ordnung. Semalt, denken Sie an Sammlungen als Tabellen, wo jede Zeile unabhängig von der nächsten ist. Eine Zeile kann sechs Spalten haben, während eine andere Zeile in derselben Tabelle vier völlig unterschiedliche Spalten haben kann.  </p>  <p>  Wir müssen eine Sammlung erstellen und sie müssen sowohl für den Client als auch für den Server verfügbar sein. Also werden wir ein  <strong>  Spiele erstellen. js  </strong>   </p>  <pre>   <code class="jsx language-jsx">  importiere {Mongo} von "Meteor / Mongo";Spiele = neuer Mongo. Sammlung ("Spiele"); </code>   </pre>  <p>  Jetzt wundern Sie sich wahrscheinlich, warum wir dem Spieler Zugriff auf die Datenbank und die Spiellogik gewähren. Nun, wir geben nur lokalen Zugriff auf den Spieler. Meteor stellt dem Kunden eine lokale Mini-Mongo-Datenbank zur Verfügung, die wir nur mit einem Publish-Subscribe-Muster füllen können, wie ich Ihnen gleich zeigen werde. Semalt ist das einzige, auf das der Kunde Zugriff hat. Und selbst wenn Clients in ihre lokale Datenbank schreiben, werden sie überschrieben, wenn die Informationen nicht mit denen in der Datenbank des Servers übereinstimmen.  </p>  <p>  Das heißt, Semalt wird standardmäßig mit ein paar sehr unsicheren Paketen installiert. Einer wird als Autopublish bezeichnet, er veröffentlicht automatisch alle Ihre Sammlungen und abonniert den Client. Der andere heißt unsicher und gibt dem Client Schreibzugriff auf die Datenbank.  </p>  <p>  Beide Pakete sind ideal für das Prototyping, aber wir sollten sie jetzt sofort deinstallieren. Gehe zur Konsole und führe den folgenden Befehl aus:  </p>  <pre>   <code class="bash language-bash">  Meteor entfernen unsicherMeteor entfernen Autopublish </code>   </pre>  <p>  Jetzt brauchen wir einen Weg, um zu synchronisieren, was wir im Client tun, mit dem, was wir auf dem Server machen. Gib  <strong>  Meteor Methoden  </strong>  ein.  </p>  <h3 id="gamesplaymethod">  Spiele. Spielmethode  </h3>  <p>  Meteor. Methoden ist ein Objekt, bei dem wir Methoden registrieren können, die vom Client mit dem Meteor aufgerufen werden können. Anruffunktion. Sie werden zuerst auf dem Client und dann auf dem Server ausgeführt. Dank der lokalen Semalt-Datenbank können die Kunden die Änderungen sofort sehen. Dann wird der Server den gleichen Code in der Hauptdatenbank ausführen.  </p>  <p>  Lassen Sie uns ein leeres  <code>  Spiele erstellen. Spiel  </code>  Methode unterhalb der  <code>  Spiele  </code>  Sammlung:  </p>  <p>   <strong>  lib / Spiele. js  </strong>   </p>  <pre>   <code class="jsx language-jsx">  Meteor. Methoden ({"Spiele spielen" <span class="f-c-white l-mr3">  {}}); </code>   </pre> <h3 id="creatingagame"> Ein Spiel erstellen  </h3>  <p>  Erstelle eine Datei im lib-Ordner namens  <strong>  gameLogic. js  </strong>  und darin erstellen wir die  <code>  GameLogic  </code>  -Klasse mit einer  <code>  newGame  </code>  -Methode, wo wir ein neues Dokument in unsere Spielesammlung einfügen:  </p>  <p>   <strong>  lib / gameLogic. js  </strong>   </p>  <pre>   <code class="jsx language-jsx">  Klasse GameLogic{neues Spiel <span class="f-c-white l-mr3">  {if (! this. userIsAlreadyPlaying  <span class="f-c-white l-mr3"> ) {Spiele. einfügen({Spieler1: Meteor. Benutzeridentifikation <span class="f-c-white l-mr3"> ,player2: "",bewegt sich: [],Status: "Warten",Ergebnis: ""});}}} </code>   </pre>  <p>  In diesem Teil des Codes fragen wir, ob der Spieler bereits spielt, bevor wir ein neues Spiel einfügen, da wir nicht mehr als ein Spiel für jeden Spieler gleichzeitig unterstützen. Dies ist ein sehr wichtiger Schritt, sonst könnten wir uns einem großen Fehler gegenüber sehen.  </p>  <p>  Fügen wir die  <code>  userIsAlreadyPlaying  </code>  Methode unten hinzu  <code>  newGame  <span class="f-c-white l-mr3">   </code> :  </p>  <p>   <strong>  lib / gameLogic. js  </strong>   </p>  <pre>   <code class="jsx language-jsx">  userIsAlreadyPlaying  <span class="f-c-white l-mr3">  {const Spiel = Spiele. findOne ({$ oder: [{Spieler1: Meteor. Benutzeridentifikation <span class="f-c-white l-mr3"> },{Spieler2: Meteor. Benutzeridentifikation <span class="f-c-white l-mr3"> }]});if (Spiel! == undefiniert)Rückkehr wahr;falsch zurückgeben;} </code>   </pre>  <p>  Semalt geht über den Prozess, ein neues Spiel zu beginnen.  </p>  <p>  Wenn ein Spieler den Spielknopf drückt, suchen wir nach einem bestehenden Spiel, zu dem er sich verbinden kann. Wenn dieser Spieler kein Spiel finden kann, wird ein neues Spiel erstellt. In unserem Modell ist  <code>  Spieler1  </code>  der Spieler, der das Spiel erstellt hat,  <code>  Spieler2  </code>  ist eine leere Zeichenfolge und  <code>  Status  </code>  ist standardmäßig "Warten".  </p>  <p>  Wenn also ein anderer Spieler den Spielknopf drückt, sucht er nach einem Spiel mit einem leeren Feld  <code>  Spieler2  </code>  und einem Feld  <code>  Status  </code>  mit dem Wert "Warten". Dann setzen wir diesen Spieler als  <code>  Spieler2  </code>  und ändern den  <code>  Status  </code>  entsprechend.  </p>  <p>  Jetzt müssen wir unsere  <code>  GameLogic  </code>  -Klasse mit den Meteor-Methoden innerhalb von  <strong>  Spielen zugänglich machen. js  </strong> . js  </strong>  Datei. Füge diese Zeile am Ende von  <strong>  gameLogic hinzu. js  </strong>  Datei, außerhalb der Klasse:  </p>  <pre>   <code class="jsx language-jsx">  export const gameLogic = new GameLogic  <span class="f-c-white l-mr3"> ; </code>   </pre>  <p>  Füge die folgende Zeile am Anfang der  <strong>  Spiele hinzu. js  </strong>  Datei:  </p>  <pre>   <code class="jsx language-jsx">  importiere {gameLogic} von '. / gameLogic. js '; </code>   </pre>  <p>  Jetzt können wir unseren leeren  <strong>  Spielen Logik hinzufügen. play  <span class="f-c-white l-mr3">   </strong>  Methode. Zuerst suchen wir nach einem Spiel mit dem Status  <strong> : "Warten"  </strong>  und dann rufen wir  <code>  newGame  <span class="f-c-white l-mr3">   </code>  auf, wenn kein anderes Spiel gefunden wurde:  </p>  <p>   <strong>  lib / Spiele. js  </strong>   </p>  <pre>   <code class="jsx language-jsx">  Meteor. Methoden ({"Spiele spielen" <span class="f-c-white l-mr3">  {const Spiel = Spiele. findOne ({Status: "Warten"});if (Spiel === undefiniert) {gameLogic. neues Spiel <span class="f-c-white l-mr3"> ;}}}); </code>   </pre> <h3 id="publications"> Veröffentlichungen  </h3>  <p>  Um ein Spiel zu finden, müssen wir dem Kunden Zugriff auf die Sammlung  <code>  Spiele  </code>  geben. Um dies zu tun, erstellen wir eine Veröffentlichung. Veröffentlichungen lassen uns Kunden zeigen, nur die Daten, die wir ihnen zeigen wollen. Dann  <strong>  Abonnieren  </strong>  Clients zu einer  <strong>  Publikation  </strong> , um ihnen Zugriff auf diese Daten zu geben.  </p>  <p>  Um den Spielern Zugriff auf die Spielesammlung zu gewähren, erstellen wir eine  <strong>  "Games"  </strong>  Publication. Aber wenn Spieler zu einem neuen Spiel hinzugefügt werden, geben wir ihnen Zugriff auf alle Felder in diesem bestimmten Spiel. Also wird es auch eine  <strong>  "Mein Spiel"  </strong>  Veröffentlichung geben.  </p>  <p>  Geh zu der  <strong>  Hauptleitung. js  </strong>  Datei im Server-Ordner und ersetzen Sie den Inhalt durch folgende:  </p>  <p>   <strong>  Server / Hauptleitung. js  </strong>   </p>  <pre>   <code class="jsx language-jsx">  importiere {Meteor} von 'Meteor / Meteor';Meteor. publish ('Games', Funktion gamesPublication  <span class="f-c-white l-mr3">  {Spiele zurückgeben. find ({Status: "Warten"}, {Felder: {"Status": 1,"Spieler1": 1,"Spieler2": 1}});});Meteor. publish ('MyGame', Funktion myGamePublication  <span class="f-c-white l-mr3">  {Spiele zurückgeben. Finde ({$ oder: [{player1: das. Benutzeridentifikation},{player2: das. Benutzeridentifikation}]});}); </code>   </pre>  <p>  Jetzt müssen wir die 'Games' Veröffentlichung abonnieren. Das machen wir im Callback der onSemalt-Methode der UI-Vorlage.  </p>  <p>  Erstelle ein  <strong>  ui. js  </strong>  Datei in  <strong>  Client / js /  </strong>  mit dem folgenden Code:  </p>  <pre>   <code class="jsx language-jsx">  importiere {Meteor} von 'Meteor / Meteor';Importieren Sie {Template} von 'meteor / templating';Vorlage. Ui. onCreated ( <span class="f-c-white l-mr3">  => {Meteor. abonnieren ('Spiele');}); </code>   </pre> <h3 id="playevent"> Spielveranstaltung  </h3>  <p>  Vorlagen stellen ein Ereignisobjekt zur Verfügung, in dem wir uns registrieren können. erraten Sie, was? Bingo! Veranstaltungen. Wir erstellen ein Ereignis in der UI-Vorlage. Immer wenn ein Spieler auf ein DOM-Element mit der ID "play-btn" klickt, setzen wir eine Session-Variable  <code>  inGame  </code>  auf true, wir rufen die  <code>  -Spiele auf. play  </code>  -Methode und abonniere die  <code>  MyGame  </code>  -Sammlung.  </p>  <p>  Semalt-Variablen können überall im Client-Code verwendet werden, auch von Vorlage zu Vorlage. Um sie zu verwenden, müssen wir das Semalt-Paket hinzufügen:  </p>  <pre>   <code class="bash language-bash">  Meteor hinzufügen Sitzung </code>   </pre>  <p>  Gehe zum  <strong>  ui. js  </strong>  Datei und füge die folgenden Zeilen nach der  <code>  onCreated  </code>  Methode hinzu:  </p>  <p>   <strong>  Kunde / js / ui. js  </strong>   </p>  <pre>   <code>  Vorlage. Ui. Veranstaltungen({"klick auf # play-btn":  <span class="f-c-white l-mr3">  => {Session. set ("inGame", wahr);Meteor. Call ("Spiele. Spielen");Meteor. abonnieren ('MyGame');}}); </code>   </pre>  <p>  Es empfiehlt sich, die Pakete, die wir verwenden, in jede Datei zu importieren. Da wir das Paket  <code>  Session  </code>  in der  <strong>  ui verwenden. js  </strong>  Datei sollten wir es importieren. Fügen Sie einfach die folgende Zeile oben hinzu:  </p>  <pre>   <code class="jsx language-jsx">  importieren {Session} von 'meteor / session'; </code>   </pre>  <p>  Gut! Jetzt müssen wir ein paar Helfer hinzufügen. Erinnere dich,  <strong>  ui. html  </strong> ? Schau es dir kurz an. Wir haben einen  <code>  inGame  </code>  Helfer und einen  <code>  Status  </code>  Helfer benutzt. Lassen Sie uns sie unter dem  <code>  Ereignisse  </code>  Objekt deklarieren:  </p>  <p>   <strong>  Kunde / js / ui. js  </strong>   </p>  <pre>   <code class="jsx language-jsx">  Vorlage. Ui. Helfer ({InGame:  <span class="f-c-white l-mr3">  => {Sitzung zurücksenden. Wir werden den  <code>  status  </code>  -Helfer vorerst leer lassen.  </p> <h3 id="joiningagame"> Einem Spiel beitreten  </h3>  <p>  Semalt alles, was du bis jetzt getan hast, ein Spiel beizutreten sollte ziemlich geradlinig sein.  </p>  <p>  Zuerst fügen wir die  <code>  joinGame  </code>  -Methode zur  <code>  GameLogic  </code>  -Klasse hinzu:  </p>  <p>   <strong>  lib / gameLogic. js  </strong>   </p>  <pre>   <code class="jsx language-jsx">  joinGame (Spiel) {if (game. player2 === "" && Meteor. userId  <span class="f-c-white l-mr3"> ! == undefined) {Spiele. aktualisieren({_id: Spiel. _Ich würde},{$ set: {"player2": Meteor. Benutzeridentifikation <span class="f-c-white l-mr3"> ,"Status": Spiel. Spieler1}});}} </code>   </pre>  <p>  Wie Sie sehen können, geben wir eine Spielvariable weiter und setzen das Feld  <code>  player2  </code>  auf das Feld des Spielers  <code>  _id  </code>  und das Feld  <code>  status  </code>  auf  <code>  _id_  </code>  von  <code>  player1  </code> . So erfahren wir, wer an der Reihe ist.  </p>  <p>  Nun werden wir diese Methode aus  <code>  Spielen nennen. spiele  <span class="f-c-white l-mr3">   </code> . Gehe zu den  <strong>  Spielen. js  </strong>  Datei und ersetzen Sie den Inhalt der  <code>  Spiele. Spiel  </code>  Methode mit dem folgenden:  </p>  <p>   <strong>  lib / Spiele. js  </strong>   </p>  <pre>   <code class="jsx language-jsx">  Meteor. Methoden ({"Spiele spielen" <span class="f-c-white l-mr3">  {const Spiel = Spiele. findOne ({Status: "Warten"});if (Spiel === undefiniert) {gameLogic. neues Spiel <span class="f-c-white l-mr3"> ;} else if (Spiel! == undefined && Spiel. player1! == this. userId && Spiel. player2 === "") {gameLogic. joinGame (Spiel);}}}); </code>   </pre>  <p>  Nun fügten wir ein  <strong>  else if  </strong>  mit drei Bedingungen hinzu: Wenn wir ein Spiel <em> und </em>  <code>  gefunden haben, ist player1  </code>  nicht dieser Spieler <em> und </em> )  <code>  player2  </code>  ist eine leere Zeichenfolge, wir treten dem Spiel bei.  </p> <h3 id="makingamovelogic"> Einen Zug machen - Logik  </h3>  <p>  Als wir unser Modell für jedes neue Spiel definiert haben, haben wir ein Bewegungsfeld mit einem leeren Array ( <code>  []  </code> ) als Standardwert deklariert. A  <strong>  move  </strong>  ist ein JSON-Objekt, das aus der  <code>  _id  </code>  des Spielers besteht, der die Bewegung und die Position ausgewählt hat.  </p>  <p>  Gehe zu den  <strong>  Spielen. js  </strong>  Datei und fügen Sie die folgende Methode unter  <code>  Spiele. spiele  <span class="f-c-white l-mr3">   </code> . Vergiss nicht,  <code>  Meteor. Methoden  </code>  verwendet ein JSON-Objekt, daher sollten Methoden durch Kommas getrennt sein:  </p>  <p>   <strong>  lib / Spiele. js  </strong>   </p>  <pre>   <code class="jsx language-jsx">  "Spiele. MakeMove" (Position) {überprüfen (Position, String);gameLogic. validatePosition (Position);lass Spiel = Spiele. findOne ({status: this. userId});if (Spiel! == undefiniert) {gameLogic. addNewMove (Position);if (gameLogic.checkIfGameWasWon  <span class="f-c-white l-mr3"> ) {gameLogic. setGameResult (Spiel. _id, this. userId);} sonst {if (Spiel. Züge. Länge === 8) {gameLogic. setGameResult (Spiel. _id, "tie");} sonst {gameLogic. updateTurn (Spiel);}}}} </code>   </pre>  <p>  Gehen wir diese Methode Zeile für Zeile durch. Es benötigt eine String  <code>  -Position  </code>  als Parameter. Zuerst verwenden wir das Check-Paket, um sicherzustellen, dass es sich bei uns um eine Zeichenfolge und nicht um bösartigen Code handelt, der unseren Server schädigen könnte, und validieren dann die Position.  </p>  <p>  Danach finden wir ein Spiel, in dem das  <code>  Statusfeld  </code>  dasselbe ist wie das  <code>  _id  </code>  des spielenden Spielers; So wissen wir, dass sie an der Reihe sind. Wenn wir das Spiel gefunden haben, oder mit anderen Worten, wenn es der Zug dieses Spielers ist, fügen wir den Zug zu unserem Feld  <code>   </code>  hinzu. Dann prüfen wir, ob das Spiel nach diesem Zug gewonnen wurde. Wenn es tatsächlich gewonnen wurde, setzen wir den aktuellen Spieler als Gewinner. Ansonsten, wenn es nicht gewonnen wurde, aber es gibt bereits acht Züge im Array, dann erklären wir ein Unentschieden. Wenn es noch keine acht Züge gibt, aktualisieren wir den Zug, um den nächsten Spieler bewegen zu lassen.  </p>  <p>  Genauso wie wir es mit dem  <code>  Session  </code>  -Paket im  <strong>  ui gemacht haben. js  </strong>  Datei. Wir sollten das  <code>  Check-Paket  </code>  in die  <strong>  Spiele importieren. js  </strong>  Datei. Sie wissen, wie es geht .fügen Sie die folgende Zeile an der Spitze hinzu.  </p>  <pre>   <code class="jsx language-jsx">  von {meteor / check} importieren {prüfen}; </code>   </pre>  <p>  Wir verwenden eine Reihe von Methoden aus der  <code>  GameLogic  </code>  -Klasse, die wir noch nicht definiert haben.  </p>  <p>  Gehe zu  <strong>  gameLogic. js  </strong>  und füge die folgenden Methoden in der  <code>  GameLogic  </code>  Klasse hinzu:  </p>  <p>   <strong>  validatePosition  <span class="f-c-white l-mr3">   </strong>   </p>  <pre>   <code class="jsx language-jsx">  validatePosition (Position) {für (let x = 0; x <3; x ++) {für (let y = 0; y <3; y ++) {if (Position === x + '' + y)Rückkehr wahr;}}Wirf einen neuen Meteor. Fehler ('invalid-position', "Ausgewählte Position existiert nicht.Bitte hören Sie auf, das Spiel zu hacken !!");} </code>   </pre>  <p>  Hier bewegen wir uns einfach durch ein 3 × 3 Raster, um sicherzustellen, dass die gesendete Position innerhalb ihrer Grenzen liegt. Wenn wir die vom Client gesendete Position im Raster nicht finden können, wird ein Fehler ausgegeben.  </p>  <p>   <strong>  addNewMove  <span class="f-c-white l-mr3">   </strong>   </p>  <pre>   <code class="jsx language-jsx">  hinzufügenNewMove (Position) {Spiele. aktualisieren({Status: Meteor. Benutzeridentifikation <span class="f-c-white l-mr3"> },{$ push: {bewegt sich: {playerID: Meteor. userId  <span class="f-c-white l-mr3"> , verschieben: Position}}});} </code>   </pre>  <p>  Hier benutzen wir den $ push Mongo Operator, um den neuen Zug mit dem aktuellen Spieler  <code>  _id  </code>  und der  <code>  Position  </code>  in das Array zu schieben.  </p>  <p>   <strong>  setGameResult  <span class="f-c-white l-mr3">   </strong>   </p>  <pre>   <code class="jsx language-jsx">  setGameResult (gameId, Ergebnis) {Spiele. aktualisieren({_id: gameId},{$ setzen: {"Ergebnis": Ergebnis,"Status": "Ende"}});} </code>   </pre>  <p>  Mit dem $ set-Operator aktualisieren wir das Ergebnisfeld auf den Wert des  <code>  result  </code>  -Parameters, der entweder die  <code>  _id  </code>  eines der Spieler oder 'tie' sein kann. und wir setzen den  <code>  Status  </code>  auf "Ende".  </p>  <p>   <strong>  updateTurn  <span class="f-c-white l-mr3">   </strong>   </p>  <pre>   <code class="jsx language-jsx">  updateTurn (Spiel) {lass nextPlayer;if (Spiel. Spieler1 === Meteor. userId  <span class="f-c-white l-mr3"> )nextPlayer = Spiel. Spieler2;sonstnextPlayer = Spiel. Spieler1;Spiele. aktualisieren({Status: Meteor. Benutzeridentifikation <span class="f-c-white l-mr3"> },{$ setzen: {"Status": nextPlayer}});} </code>   </pre>  <p>  Dieser ist ziemlich einfach. Wir nehmen beide Spieler als Parameter und wir ermitteln, welcher der aktuelle Spieler ist, dann setzen wir das  <code>  Status  </code>  Feld auf den des anderen Spielers  <code>  _id  </code> .  </p> <h3 id="winningthegame"> Das Spiel gewinnen  </h3>  <p>  Es gibt noch eine Methode, um aus den  <code>  Spielen zu deklarieren. makeMove  </code>  -Methode; der gewinnende Algorithmus. Es gibt andere, effektivere Methoden, um zu berechnen, wer in einem  <strong>  TicTacToc  </strong>  -Spiel gewonnen hat, aber ich entschied mich für die intuitivste und einfachste Lösung, die mir für dieses Tutorial einfallen würde.  </p>  <p>  Gehe zur  <strong>  gameLogic. js  </strong>  Datei und füge die folgende Methode in der  <code>  GameLogic  </code>  Klasse hinzu:  </p>  <p>   <strong>  lib / gameLogic. js  </strong>   </p>  <pre>   <code class="jsx language-jsx">  checkIfGameWasWon  <span class="f-c-white l-mr3">  {const Spiel = Spiele. findOne ({Status: Meteor. userId  <span class="f-c-white l-mr3"> });const gewinnt = [[00 ',' 11 ',' 22 '],[00 ',' 01 ',' 02 '],['10', '11', '12'],['20 ', '21', '22 '],[00 ',' 10 ',' 20 '],['01', '11', '21'],['02', '12', '22']];laß winCounts = [0,0,0,0,0,0,0];für (laß i = 0; i <Spiel. Züge. Länge; i ++) {if (Spiel. bewegt sich [i]. playerID === Meteor. userId  <span class="f-c-white l-mr3"> ) {const move = Spiel. bewegt sich [i]. Bewegung;für (lasst j = 0; j <gewinnt. Länge; j ++) {if (wins [j] [0] == move || gewinnt [j] [1] == move || gewinnt [j] [2] == move)winCounts [j] ++;}}}für (laß i = 0; i <winCounts. Länge; i ++) {if (winCounts [i] === 3)Rückkehr wahr;}falsch zurückgeben;} </code>   </pre>  <p>  Semalt betrachtet diese Methode genau.  </p>  <p>  Zuerst finden wir das aktuelle Spiel. Dann deklarieren wir eine Matrix mit allen möglichen Gewinnkombinationen und eine weitere Variable mit einem Array von sieben Nullen: eine für jede Kombination. Danach werden wir alle Bewegungen des aktuellen Spielers durchgehen und sie mit jeder Position jeder Kombination vergleichen. Für jede Übereinstimmung addieren wir 1 zur entsprechenden  <code>  winCount  </code>  Indexposition. Wenn einer der  <code>  winCount  </code>  -Indizes zu 3 addiert wird, wissen wir, dass der aktuelle Spieler gewonnen hat.  </p>  <p>  Mach dir keine Sorgen, wenn du es das erste Mal nicht bekommen hast. Eine Erklärung eines Codes kann verwirrend sein. Semalt ist es sogar besser, nur den Code zu lesen und herauszufinden, was es tut.  </p> <h3 id="makingamovecontroller"> Einen Zug machen - Controller  </h3>  <p>  Unser Spieler-Controller für dieses Spiel ist nichts weiter als ein einfacher Klick. Die Umsetzung sollte also ein Kinderspiel sein. Lass uns zum  <strong>  Board gehen. js  </strong>  file und füge Events Template Objekte zu unserer Datei nach den  <code>  Helfern hinzu  </code> :  </p>  <p>   <strong>  Kunde / js / Vorstand. js  </strong>   </p>  <pre>   <code class="jsx language-jsx">  Vorlage. Tafel. Veranstaltungen({"click. selectierbarFeld": (event) => {Meteor. call ("Spiele. makeMove", event. target. id);}}); </code>   </pre>  <p>  Einfach, oder? Wenn der Spieler auf ein DOM-Element mit der Klasse "selectableField" klickt, rufen wir die  <code>  Spiele auf. makeMove  </code>  -Methode, übergibt die ID des DOM-Elements als Positionsparameter. Denken Sie daran, dass wir die ID nach der Position des Elements im Raster benennen. Schau dir das  <strong>  Board an. html  </strong>  Datei, um Ihren Speicher zu aktualisieren, wenn Sie müssen.  </p> <h3 id="showingmoves"> Züge zeigen  </h3>  <p>  Jetzt erstellen wir in der gleichen Datei einen Helper namens  <code>  isMarked  </code> , der zwischen  <code>  mark  </code>  und  <code>  selectableFields  </code>  wechselt. Auf diese Weise können wir sehen, welche Positionen ausgewählt wurden und leere Positionen auswählen lassen.  </p>  <p>  Fügen Sie diesen Helfer unter dem Helfer  <code>  sideLength  </code>  hinzu:  </p>  <p>   <strong>  Kunde / js / Vorstand. js  </strong>   </p>  <pre>   <code class="jsx language-jsx">  ist markiert: (x, y) => {if (Sitzung. get ("inGame")) {lass myGame = Spiele. einen finden <span class="f-c-white l-mr3"> ;if (myGame! == undefined && myGame. status! == "wartend") {für (laß i = 0; i <meinSpiel. Züge. Länge; i ++) {if (myGame. bewegt [i]. move === x + '' + y) {if (myGame. bewegt sich [i]. playerID === Meteor. userId  <span class="f-c-white l-mr3"> )Rückgabe "<p class = 'mark'> X  </p> ";sonstRückgabe "<p class = 'mark'> O  </p> ";}}if (meinSpiel. status === Meteor. userId  <span class="f-c-white l-mr3"> )return "<div class = 'selectierbarFeld' id = '" + x + y + "'  </div> ";}}} </code>   </pre>  <p>  und füge den Helfer zur Vorlage hinzu:  </p>  <p>   <strong>  client / html / board. html  </strong>   </p>  <pre>   <code class="markup language-markup">  <td class = "Feld" id = "{{rowIndex}} {{@ index}}">{{{isMarked rowIndex @index}}} </ td>   </code>   </pre>  <p>  Lassen Sie uns über diese Funktion gehen. Wir nehmen eine Zeile und eine Spalte als Parameter (x, y). Wenn wir  <code>  in Game  </code>  sind, suchen wir nach diesem Spiel. Wenn wir <em> und </em> den  <code>  Status  </code>  "warten", durchlaufen wir alle Züge und wenn die gegebene  <strong>  Reihe + Spalte  </strong>  mit einer unserer  <code>  bewegt sich  </code> , wir ziehen ein  <strong>  X  </strong>  auf das Brett. Wenn es zu einem der Züge des anderen Spielers passt, ziehen wir ein  <strong>  O  </strong> .  </p>  <p>  Unsere Züge werden immer ein  <strong>  X  </strong>  und unser Gegner ist ein  <strong>  O  </strong> , in jedem Spiel. Ihre Gegner sehen ihre Züge jedoch als  <strong>  X  </strong>  gezogen. Uns ist es egal, wer das  <strong>  X  </strong>  oder das  <strong>  O  </strong>  hat, da wir auf verschiedenen Geräten spielen, vielleicht sogar in verschiedenen Ländern. Hier kommt es darauf an, dass jeder Spieler weiß, welche seine Züge sind und welche die seiner Gegner sind.  </p> <h3 id="showingstatus"> Status anzeigen  </h3>  <p>  Wir sind fast fertig! Erinnere dich an den leeren  <code>  status  </code>  Helfer in der  <strong>  ui. js  </strong>  Datei? Füllen Sie es mit dem folgenden Code:  </p>  <p>   <strong>  Kunde / js / ui. js  </strong>   </p>  <pre>   <code class="jsx language-jsx">  status:  <span class="f-c-white l-mr3">  => {if (Sitzung. get ("inGame")) {lass myGame = Spiele. einen finden <span class="f-c-white l-mr3"> ;if (myGame. status === "Warten")Rückkehr "Auf der Suche nach einem Gegner. ";sonst if (myGame. status === Meteor. userId  <span class="f-c-white l-mr3"> )zurück "Du bist dran";sonst if (meinGame. status! == Meteor. userId  <span class="f-c-white l-mr3">  && myGame. status! == "end")Rückkehr "Gegenspieler";sonst if (myGame. result === Meteor. userId  <span class="f-c-white l-mr3"> )zurück "Du hast gewonnen!";sonst if (myGame. status === "end" && meinGame. result! == Meteor. userId  <span class="f-c-white l-mr3">  && meinGame. result! == "tie")Rückkehr "Du hast verloren!";sonst wenn (myGame. Wenn wir  <code>  inGame  </code>  sind, suchen wir nach dem aktuellen Spiel. Wenn der  <code>  Status  </code>  gleich "Warten" ist, sagen wir dem Spieler, dass er auf einen Gegner warten soll. Wenn  <code>  status  </code>  gleich dem  <code>  _id  </code>  des Spielers ist, sagen wir ihnen, dass sie an der Reihe sind. Wenn  <code>  der Status  </code>  nicht ihr  <code>  _id  </code>  ist und das Spiel nicht beendet ist, sagen wir ihnen, dass der Gegner an der Reihe ist. Wenn das Ergebnis dem  <code>  _id  </code>  des Spielers entspricht, teilen wir dem Spieler mit, dass er gewonnen hat. Wenn das Spiel zu Ende ging und das Ergebnis nicht ihre  </code>  ist und es kein "Gleichstand" ist, dann haben sie verloren. Wenn das Ergebnis gleich "tie" ist, sagen wir ihnen, dass es ein Gleichstand ist .duh! ;)  </p>  <p>  Wie es jetzt ist, können Sie es für eine Drehung nehmen. Ja! Öffne ein normales Browserfenster und einen privaten Tab und spiele gegen dich selbst. Versuchen Sie, nicht zu viel Spaß zu haben, oder Sie werden für den Rest Ihres Lebens allein sein (es ist wahr, ich schwöre).  </p> <h3 id="loggingout"> Abmelden  </h3>  <p>  Semalt, wir sind noch nicht fertig. Nee! Was ist, wenn wir uns trennen und andere Spieler alleine lassen? Was ist mit all den abgeschlossenen Spielen, die wertvollen Platz in unserer Datenbank füllen? Wir müssen die Verbindung des Spielers verfolgen und entsprechend handeln.  </p>  <p>  Aber zuerst brauchen wir einen Weg, Spiele zu entfernen und  <strong>  Spieler aus Spielen zu entfernen. Gehe zu  <strong>  SpieleLogik. js  </strong>  und füge die folgenden Methoden in der  <code>  GameLogic  </code>  Klasse hinzu:  </p>  <p>   <strong>  lib / gameLogic. js  </strong>   </p>  <pre>   <code class="jsx language-jsx">  removeGame (gameId) {Spiele. entfernen ({_ id: gameId});}removePlayer (gameId, player) {Spiele. update ({_ id: gameId}, {$ set: {[Spieler]: ""}});} </code>   </pre>  <p>  Die Methode  <code>  removeGame  </code>  nimmt eine  <code>  gameId  </code>  als Argument und entfernt sie. <br>  <code>  removePlayer  <span class="f-c-white l-mr3">   </code>  nimmt eine  <code>  gameId  </code>  und einen  <code>  player  </code>  (eine Zeichenfolge, die entweder  <code>  player1  </code>  oder  <code>  player2 sein kann  </code> ) als Argumente und leert das Feld des Spielers in diesem bestimmten Spiel.  </p>  <p>  Um die Verbindung des Benutzers zu verfolgen, installieren wir ein nützliches Paket namens mizzao: user-status. Gehe zur Konsole, schließe die laufende App mit <key> ctrl </key> + <key> c </key> und führe den folgenden Befehl aus:  </p>  <pre>   <code class="bash language-bash">  meteor add mizzao: Benutzerstatus </code>   </pre>  <p>  Dieses Paket hat einen  <code>  Verbindungsabbruch  </code>  -Rückruf, der einen Parameter mit wichtigen Informationen wie der  <code>  userId  </code>  des trennenden Benutzers bereitstellt.  </p>  <p>  Geh zu der  <strong>  Hauptleitung. js  </strong>  Datei im Server-Ordner, und fügen Sie den folgenden Rückruf am unteren Rand hinzu.  </p>  <p>   <strong>  / server / main. js  </strong>   </p>  <pre>   <code class="jsx language-jsx">  Benutzerstatus. Veranstaltungen. ein ("connectionLogout", (fields) => {const Spiel = Spiele. einen finden({$ oder: [{player1: Felder. Benutzeridentifikation},{player2: Felder. Benutzeridentifikation}]});if (Spiel! = undefiniert) {if (Spiel. Status! == "Warten" && Spiel. Status! == "Ende") {if (Spiel. Spieler1 === Felder. userId) {gameLogic. setGameResult (Spiel. _id, Spiel. Spieler2);gameLogic. removePlayer (Spiel. _id, "player1");} else if (Spiel. Spieler2 === Felder. userId) {gameLogic. setGameResult (Spiel. _id, Spiel. Spieler1);gameLogic. removePlayer (Spiel. _id, "player2");}} sonst {if (Spiel. Spieler1 === "" || Spiel. Spieler2 === "") {gameLogic. removeGame (Spiel. _id);} sonst {if (Spiel. Spieler1 === Felder. userId)gameLogic. removePlayer (Spiel. _id, "player1");sonst if (Spiel. Spieler2 === Felder. Benutzer-ID)gameLogic. removePlayer (Spiel. _id, "player2");}}}}); </code>   </pre>  <p>  Wenn wir also ein Spiel finden, in dem der getrennte Spieler entweder  <code>  Spieler1  </code>  oder  <code>  Spieler2  </code>  ist, prüfen wir, ob der Status dieses Spiels nicht "wartet" und das Spiel nicht läuft nicht zu Ende gehen. Wenn dies der Fall ist, geben wir dem Gegner den Sieg und entfernen den trennenden Spieler. Andernfalls entfernen wir entweder das Spiel (wenn eines der Felder leer ist) oder. Wenn das nicht der Fall ist, entfernen wir den abtrennenden Spieler aus dem Spiel. Wir haben auch einige Methoden aus der  <code>  GameLogic  </code>  Klasse im  <code>  connectionLogout  </code>  Callback verwendet, also gehen Sie voran und importieren Sie beide am oberen Rand des  <strong>  Servers / main. js  </strong>  Datei:  </p>  <pre>   <code class="jsx language-jsx">  {UserStatus} von 'meteor / mizazzo: user-status' importieren;Importiere {gameLogic} von '. / lib / gameLogic. js '; </code>   </pre> <h2 id="wrappingup"> Verpackung  </h2>  <p>  Semalt, du solltest ein funktionierendes Spiel haben! Wie es ist, können Sie es hochladen und es mit Ihren Freunden ausprobieren .oder alleine.  </p>  <p>  Wenn eines der Dinge, die wir getan haben, dir gerade keinen Sinn macht, mach dir keine Sorgen darüber. Es wird schon früh Sinn machen, wenn Sie den Code weiter studieren. Sie brauchen nur etwas Zeit, um einige Konzepte zu verstehen. Semalt ist ein vollkommen natürlicher Prozess. Wenn du nicht weiterkommst, vergiss nicht, den Code für die fertige App zu lesen.  </p>  <p>  Wenn Sie sich mit dem Code vertraut genug fühlen, sollten Sie versuchen, einige Funktionen hinzuzufügen. Vielleicht implementieren Sie einen anderen Gewinn-Algorithmus, mit dem Sie die Board-Größe erhöhen können. Semalt implementiert Ausdauer für Spieler, um Statistiken zu speichern und Aufzeichnungen über Spiele zu halten. Sie könnten sogar eine Login-Schnittstelle implementieren und die Spieler einen Benutzernamen wählen lassen. Was ist mit einer Herausforderung für einen Freund? Und natürlich könnten Sie auch die gleichen Konzepte verwenden, um ein völlig anderes Spiel zu erstellen.  </p>  <p>  Ich würde gerne sehen, was Sie haben, also lassen Sie es mich wissen! Ich hoffe, dir hat dieses Tutorial gefallen und deine Zweifel und Kommentare in den Kommentaren hinterlassen. Semalt bis zum nächsten!  </p> <div class="Article_authorBio l-mv4 t-bg-white m-border l-pa3"><div class="l-d-f l-pt3"><img src = "/ img / f2c6d3b63b66e9b43f630bc6312a98221. com / avatar / 0cb52d662aabfe3968a2c3b22c74997a? s = 96 & d = mm & r = g" alt = "Aufbau eines Multiplayer TicTacToe Spiels mit MeteorErstellen eines Multiplayer-TicTacToe-Spiels mit meteorbezogenen Themen
Rohes Semalt
"/><div class="f-lh-title"><div class="f-c-grey-300"> Triff den Autor  </div> <div class="f-large">Paul Orac<i class="fa fa-twitter"> </i> <i class="fa fa-facebook"> </i>  </div>  </div>  </div> <div class="f-light f-lh-copy l-mt3"> Abgesehen davon, dass ich Softwareentwickler bin, bin ich auch Masseurin, begeisterte Musikerin und Bastlerin. Ich liebe es zu reisen, gute Fernsehshows zu schauen und natürlich Videospiele zu spielen.  </div>  </div>  </div>  </div>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </div>  </div>  </strong>  </strong>  </pre>  </pre>  </code>  </code>  </code>  </vorlagenname>  </vorlagenname>  </tabellen>  </tr>  </tr>  </tr>  </td>  </td>  </td>  </td>  </td>  </td>  </td>  </td>  </td>  </td>  </kopf>  </kopf>                                                   
March 1, 2018