Erstellen eines Tic-Tac-Toe-Spiels. Stufe: Überprüfen Sie, ob der Spieler gewonnen hat

Aufmerksamkeit! Hier ist eine Testversion der Lektion, deren Materialien möglicherweise nicht vollständig sind.

Melden Sie sich als Student an

Melden Sie sich als Schüler an, um auf Schulinhalte zuzugreifen

Erstellen von 1C-Konfigurationen: Schreiben von „Tic-tac-toe“ Teil 1/3

Wir werden beim Spielen lernen, und deshalb wird unser erstes Projekt das Erstellen sein
bekannt aus Kinderspiel - "Tic-tac-toe".

Was haben Spiele mit 1C, Buchhaltung und Handel zu tun, fragen Sie? Fast keiner. Aber wir müssen schrittweise beginnen, und mit der Zeit werden wir die Automatisierung von Lagern erreichen. Fangen wir erstmal klein an.

Bevor wir mit der Programmierung des Tic-Tac-Toe-Spiels beginnen, denken wir nach.

Wir wissen bereits, dass ein Formular Elemente hat, von denen eines ein Button ist. Schaltflächen können Befehle ausführen und haben gleichzeitig Eigenschaften, mit denen Sie ihre Anzeige auf dem Formular steuern können (z. B. den Titel).

Beispielsweise können Sie mit einer Schaltfläche ein Feld mit neun Hotspots erstellen (jene Zellen, auf die wir klicken und die Aktion beheben, während die Inschriften in Form von „O“ und „X“ angezeigt werden). Button uns dafür mehr als geeignet.

Was werden wir brauchen? Offensichtlich müssen wir uns an unseren Zug erinnern und uns an den Zug des Computers erinnern. Wir müssen auch die Schaltflächentitel ändern: Wenn wir klicken, ist der Schaltflächentitel immer "O", wenn sich der Computer bewegt - "X".

Und zuerst müssen wir eine neue Datenbank erstellen, in der wir unser Spiel erstellen werden. Lass es uns tun.

Schritt Nr. 1: Erstellen Sie eine leere Basis

Lassen Sie uns eine leere Tic-Tac-Toe-Datenbank erstellen.

Detaillierte Anleitung

Lass uns laufen 1C Verknüpfung zum Öffnen einer Liste der auf dem Computer verfügbaren Infobases. Sie lesen eine Testversion der Lektion, vollständige Lektionen befinden sich. Wir müssen eine neue Datenbank erstellen, also klicken Sie auf " Hinzufügen":

Es öffnet sich ein Fenster zum Hinzufügen einer Infobase, in dem Sie das erste Element auswählen müssen " Aufbau einer Informationsbasis und klicken Sie auf die Schaltfläche „Weiter“:

Wählen Sie im nächsten Fenster den zweiten Punkt " Eine Infobase ohne Konfiguration erstellen, um eine neue Konfiguration zu entwickeln... und klicken Sie erneut auf die Schaltfläche "Weiter":

Im nächsten Fenster werden wir aufgefordert, den Namen der neuen Basis einzugeben, unter dem sie in der Liste der Basis angezeigt wird. Lassen Sie uns eintreten " Tic-Tac-Toe und klicken Sie auf die Schaltfläche „Weiter“:

Im nächsten Fenster müssen Sie den Pfad zu einem leeren Ordner angeben, in dem unsere Datenbank gespeichert wird. In diesem Fall habe ich einen Ordner erstellt " Tic-Tac-Toe" im Ordner "Bases 1C" auf Laufwerk D:

Belassen Sie im nächsten Fenster alle Standardeinstellungen und klicken Sie auf " Bereit":

Nach einer kurzen Pause wird die Datenbank erstellt und der Liste hinzugefügt. Es gibt zwei Hauptbetriebsarten mit der Datenbank: 1C: Unternehmen und Konfigurator:

Im Konfigurator-Modus konfigurieren und programmieren wir die Basis, im 1C:Enterprise-Modus schauen wir uns an, was dabei herausgekommen ist.

Schritt 2: Öffnen Sie den Konfigurator

Drücken wir den Knopf " Konfigurator" um in den Konfigurationsmodus zu gelangen:

Schritt #3: Öffnen Sie den Konfigurationsbaum

Führen Sie den Menübefehl " Aufbau"->"Konfiguration öffnen":

Vor uns hat sich ein Konfigurationsbaum geöffnet, der verschiedene Abschnitte der Konfiguration enthält. Da wir noch nichts erstellt haben, sind diese Abschnitte bisher leer:

Schritt 4: Verarbeitung hinzufügen

Um die Logik unseres Spiels zu platzieren, verwenden wir den Abschnitt "Verarbeitung". Drücken wir Rechtsklick auf Abschnitt " wird bearbeitet und wählen Sie den Befehl "Hinzufügen":

Vor uns öffnete sich ein Fenster zum Erstellen einer neuen Verarbeitung. Geben Sie den Namen ein " Tic-Tac-Toe". Das Synonym wird durch sich selbst ersetzt. Dies reicht aus, um unsere Bearbeitung (noch leer) in der Datenbank zu speichern. Drücken Sie die Schaltfläche "Schließen":

Schritt #5: Zuerst das Programm debuggen

Sie können im Benutzermodus überprüfen, was passiert ist ( 1C: Unternehmen). Um direkt aus dem Konfigurator dorthin zu gelangen, führen Sie den Menübefehl " Debuggen"->"Starten Sie das Debuggen":

Da wir eine Änderung an der Datenbank vorgenommen haben, werden wir gefragt, ob wir dieser Änderung zustimmen. Diese Frage wird uns im Entwicklungsprozess ständig gestellt. Wir antworten mit Zustimmung (Schaltfläche " ja"):

Die Datenbank wurde im 1C:Enterprise-Modus gestartet. Sie lesen eine Testversion der Lektion, vollständige Lektionen befinden sich. Aber wie wir sehen, ist es immer noch schwierig, mit ihr zu arbeiten - es gibt einfach keine Auswahl. Es ist seltsam, weil wir die Verarbeitung bereits erstellt haben und sie theoretisch auf dem gelben Feld erscheinen sollte.

Wie man einen Bot schreibt, der beim Tic-Tac-Toe nicht zu schlagen ist, oder Einführung in die Minimax-Regel

Es ist möglich, dass Sie sich nach Hunderten von Tic-Tac-Toe-Spielen gefragt haben: Was ist der optimale Algorithmus? Aber wenn Sie hier sind, dann haben Sie wahrscheinlich auch versucht, eine Implementierung dieses Spiels zu schreiben. Wir gehen weiter und schreiben einen Bot, der in Tic-Tac-Toe nicht zu schlagen ist. Nachdem wir Ihre Frage „warum?“ vorweggenommen haben, werden wir antworten: dank des Algorithmus.

Wie ein professioneller Schachspieler berechnet dieser Algorithmus die Aktionen des Gegners für mehrere Züge voraus – bis zum Ende der Partie, egal ob Sieg, Niederlage oder Remis. In diesem Endzustand gibt sich die KI eine positive Punktzahl (+10 in unserem Fall) für einen Sieg, eine negative Punktzahl (-10) für eine Niederlage und eine neutrale Punktzahl (0) für ein Unentschieden.

Gleichzeitig führt der Algorithmus ähnliche Berechnungen für die Züge des Spielers durch. Es wählt den Zug mit der höchsten Punktzahl, wenn sich die KI bewegt, und den Zug mit der niedrigsten Punktzahl, wenn sich der Spieler bewegt. Mit dieser Strategie vermeidet Minimax eine Niederlage.

Versuchen Sie, dieses Spiel zu spielen.

Der Minimax-Algorithmus wird am einfachsten als eine rekursive Funktion beschrieben, die:

  1. gibt einen Wert zurück, wenn der Endzustand gefunden wird (+10, 0, -10),
  2. geht durch alle leeren Zellen auf dem Feld,
  3. ruft die Minimax-Funktion für jeden von ihnen auf (Rekursion),
  4. wertet die empfangenen Werte aus
  5. und gibt das Beste zurück.

Wenn Sie sich mit Rekursion nicht auskennen, dann sollten Sie sich diesen Vortrag aus dem Harvard CS50-Kurs ansehen:

Um zu verstehen, wie minimax funktioniert, schreiben wir seine Implementierung und modellieren sein Verhalten. Damit beschäftigen wir uns in den nächsten beiden Abschnitten.

Minimax-Implementierung

Wir werden die Situation betrachten, wenn das Spiel zu Ende geht (siehe Bild unten). Da Minimax alle möglichen Spielzustände durchläuft (und davon gibt es Hunderttausende), ist es sinnvoll, das Endspiel zu betrachten – so müssen wir weniger rekursive Funktionsaufrufe (insgesamt 9) im Auge behalten.

Lassen Sie die KI mit Kreuzen spielen, den Mann - mit Nullen.

Um die Arbeit mit dem Feld zu vereinfachen, deklarieren wir es als Array aus 9 Elementen mit Werten, die dem Inhalt der Zellen entsprechen. Füllen wir es mit Kreuzen und Nullen, wie im Bild oben, und nennen es origBoard .

Var origBoard = ["O",1,"X","X",4,"X",6,"O","O"];

Dann deklarieren wir die Variablen aiPlayer und huPlayer und weisen ihnen die Werte „X“ bzw. „O“ zu.

Außerdem brauchen wir eine Funktion, die nach Gewinnkombinationen sucht und wahr zurückgibt, wenn die Suche erfolgreich ist, und eine Funktion, die die Indizes der verfügbaren Zellen speichert.

/* Anfangszustand der Platine O | | X --------- X | | X --------- | O | O */ var origBoard = ["O",1 ,,X",",X",4 ,,X", 6 ,,O",,O"]; // Mensch var huPlayer = „O“; // AI var aiPlayer = "X"; // gibt eine Liste von Indizes leerer Zellen auf der Board-Funktion zurück emptyIndices(board)( return board.filter(s => s != "O" && s != "X"); ) // Gewinnkombinationen unter Berücksichtigung Kontoindizes Funktion winn(Brett, Spieler)( if((Brett == Spieler && Brett == Spieler && Brett == Spieler) || (Brett == Spieler && Brett == Spieler && Brett == Spieler) || (Brett == Spieler && Brett == Spieler && Brett == Spieler) || (Brett == Spieler && Brett == Spieler && Brett == Spieler) || (Brett == Spieler && Brett == Spieler && Brett == Spieler) || (Tafel == Spieler && Tafel == Spieler && Tafel == Spieler) || (Tafel == Spieler && Tafel == Spieler && Tafel == Spieler) || (Tafel == Spieler && Tafel == Spieler && Tafel == Spieler)) ( true zurückgeben; ) sonst ( false zurückgeben; ) )

Lassen Sie uns also eine Minimax-Funktion mit zwei Argumenten definieren: newBoard (neues Brett) und player (Spieler). Dann finden wir die Indizes der freien Zellen im Feld und übergeben sie an die VariableavailSpots.

// Minimax-Hauptfunktion function minimax(newBoard, player)( //verfügbare Zellen varavailSpots = emptyIndices(newBoard);

Außerdem müssen wir die Endzustände verfolgen und die entsprechenden Werte zurückgeben. Wenn die Null gewinnt, müssen Sie -10 zurückgeben, wenn das "Kreuz" - +10 . Wenn die Größe des ArraysavailSpots null ist, gibt es keine freien Zellen, das Spiel endet unentschieden und null sollte zurückgegeben werden.

// auf Endzustand prüfen (win/lose/draw) //und entsprechenden Wert zurückgeben if (winning(newBoard, huPlayer))( return (score:-10); ) else if (winning(newBoard, aiPlayer)) ( return (score:10); ) sonst wenn (availSpots.length === 0)( return (score:0); )

Danach müssen Sie Punkte aus jeder der leeren Zellen sammeln. Um dies zu tun, erstellen wir ein Array von Zügen und durchlaufen alle leeren Zellen, wobei wir die Indizes und Punktzahlen jeder Bewegung in das Bewegungsobjekt einfügen.

Dann setzen wir den Index der leeren Zelle, der als Zahl in origBoard gespeichert wurde, auf die Eigenschaft index des move-Objekts. Dann gehen wir für den aktuellen Spieler in eine leere Zelle des neuen Feldes newBoard und rufen die Minimax-Funktion eines anderen Spielers und das daraus resultierende Feld newBoard auf. Danach müssen wir die score-Eigenschaft des Objekts, das von der Minimax-Funktion zurückgegeben wird, in die score-Eigenschaft des move-Objekts einfügen.

Wenn Minimax keinen Endzustand findet, vertieft es sich rekursiv in das Spielgeschehen, bis es einen Endzustand erreicht. Danach passiert es die Punkte dieser "Ebene" der Rekursion eine Ebene höher.

Schließlich setzt die Funktion newBoard zurück und platziert das Move-Objekt im Moves-Array.

// Array zum Speichern aller Objekte var move = ; // verfügbare Zellen durchlaufen für (var i = 0; i< availSpots.length; i++){ //create an object for each and store the index of that spot var move = {}; move.index = newBoard]; // совершить ход за текущего игрока newBoard] = player; //получить очки, заработанные после вызова минимакса от противника текущего игрока if (player == aiPlayer){ var result = minimax(newBoard, huPlayer); move.score = result.score; } else{ var result = minimax(newBoard, aiPlayer); move.score = result.score; } // очистить клетку newBoard] = move.index; // положить объект в массив moves.push(move); }

Minimax muss dann den besten Zug aus der Reihe der Züge auswählen. Er braucht einen Zug mit der höchsten Punktzahl, wenn es der KI-Zug ist, und den kleinsten, wenn es ein menschlicher Zug ist. Wenn also der Wert von player aiPlayer ist, initialisiert der Algorithmus die bestScore -Variable auf eine sehr kleine Zahl und durchläuft das Moves-Array: Wenn der move move mehr Punkte erzielt als bestScore , merkt sich der Algorithmus diesen move . Bei Zügen mit gleichen Punkten merkt sich der Algorithmus den ersten.

Für den Fall, dass player gleich huPlayer ist, ist alles gleich – nur dass jetzt bestScore mit einer großen Zahl initialisiert wird und minimax nach dem Zug mit der geringsten Punktzahl sucht.

Schließlich gibt minimax das in bestMove gespeicherte Objekt zurück.

// wenn es ein KI-Zug ist, gehe durch die Züge und wähle den Zug mit der höchsten Punktzahl var bestMove; if(player === aiPlayer)( var bestScore = -10000; for(var i = 0; i< moves.length; i++){ if(moves[i].score >bestScore)( bestScore = Moves[i].score; bestMove = i; ) ) )else( // andernfalls Schleife durch die Züge und wähle den Zug mit der niedrigsten Punktzahl var bestScore = 10000; for(var i = 0; i< moves.length; i++){ if(moves[i].score < bestScore){ bestScore = moves[i].score; bestMove = i; } } } // вернуть выбранный ход (объект) из массива ходов return moves; }

Im nächsten Abschnitt werden wir unser Programm simulieren, um zu verstehen, wie es funktioniert.

MiniMax in Aktion

Anhand des folgenden Diagramms analysieren wir das Schritt-für-Schritt-Modell des Algorithmus.

Notiz: Im Diagramm geben große Zahlen die Ordnungszahl des Funktionsaufrufs an, und Ebenen geben an, wie viele Schritte der Algorithmus vorwärts gegangen ist.

  1. Der Algorithmus wird von origBoard und aiPlayer gefüttert. Es erstellt eine Liste der drei gefundenen leeren Zellen, prüft, ob der Zustand endlich ist, und durchläuft alle leeren Zellen. Der Algorithmus ändert dann newBoard, indem er aiPlayer in der ersten leeren Zelle platziert. Danach ruft es sich selbst von newBoard und huPlayer auf und wartet darauf, dass der zweite Aufruf einen Wert zurückgibt.
  2. Während der erste Funktionsaufruf noch läuft, läuft der zweite, erstellt eine Liste mit zwei leeren Zellen, prüft, ob der Zustand endlich ist, und durchläuft alle leeren Zellen. Der zweite Aufruf ändert dann newBoard, indem er huPlayer in die erste leere Zelle setzt. Danach ruft es sich selbst von newBoard und aiPlayer auf und wartet darauf, dass der dritte Aufruf einen Wert zurückgibt.

  3. Da der zweite Aufruf zwei leere Zellen gefunden hat, modifiziert minimax newBoard, indem es huPlayer in die zweite freie Zelle platziert. Es ruft sich dann von newBoard und aiPlayer auf.

  4. Der Algorithmus stellt eine Liste leerer Zellen zusammen und fixiert den Sieg des Spielers, nachdem er die Endlichkeit des Zustands überprüft hat. Daher gibt es ein Objekt mit einem Zählfeld gleich (-10) zurück.

    Im zweiten Funktionsaufruf erhält der Algorithmus die Werte, die der dritte und vierte Funktionsaufruf von der unteren Ebene zurückliefern. Da der huPlayer-Move diese beiden Ergebnisse erzeugt hat, wählt der Algorithmus das kleinste davon aus. Da sie gleich sind, wählt der Algorithmus die erste aus und übergibt sie an den ersten Funktionsaufruf.

    An diesem Punkt hat der erste Funktionsaufruf eine Schätzung der Bewegung von aiPlayer zur ersten leeren Zelle erhalten. Dann modifiziert es newBoard, indem es aiPlayer in die zweite leere Zelle platziert. Danach ruft es sich selbst von newBoard und huPlayer auf.

  5. Im fünften Funktionsaufruf stellt der Algorithmus eine Liste leerer Zellen zusammen und fixiert den KI-Sieg nach Prüfung der Endlichkeit des Zustands. Es gibt also ein Objekt mit einem Zählfeld von +10 zurück.

    Danach ändert der erste Aufruf newBoard, indem er aiPlayer in die dritte leere Zelle platziert. Es ruft sich dann von newBoard und huPlayer auf.

  6. Der sechste Aufruf erstellt eine Liste mit zwei leeren Zellen, prüft, ob der Zustand endlich ist, und durchläuft alle leeren Zellen. Dann modifiziert es newBoard, indem es huPlayer in die erste leere Zelle platziert. Dann ruft es sich selbst von newBoard und aiPlayer auf und wartet darauf, dass der siebte Aufruf einen Wert zurückgibt.
  7. Der neue Aufruf listet eine leere Zelle auf, prüft, ob der Zustand endlich ist, und modifiziert newBoard, indem er aiPlayer in der leeren Zelle platziert. Danach ruft es sich selbst von newBoard und huPlayer auf und wartet darauf, dass dieser Aufruf einen Wert zurückgibt.
  8. Der achte Aufruf erstellt eine leere Liste leerer Zellen und fixiert den Sieg von aiPlayer nach Überprüfung der Endlichkeit des Zustands. Daher gibt es beim siebten Aufruf ein Objekt mit einem Zählfeld gleich (+10), eine Ebene höher, zurück.

    Der siebte Anruf erhielt nur einen positiven Wert von den unteren Ebenen. Da dieser Wert im Verlauf von aiPlayer empfangen wurde, gibt der Algorithmus den größten der empfangenen Werte zurück. Es gibt also einen positiven Wert (+10) eine Ebene höher bis zum sechsten Anruf zurück.

    Da beim sechsten Aufruf zwei leere Zellen gefunden wurden, modifiziert minimax newBoard, indem es huPlayer in die zweite leere Zelle platziert. Es ruft sich dann von newBoard und aiPlayer auf.

  9. Danach stellt der Algorithmus eine Liste leerer Zellen zusammen und fixiert den Sieg von aiPlayer, nachdem er die Endlichkeit des Zustands überprüft hat. Daher wird ein Objekt mit einem Zählfeld gleich (+10) eine Ebene höher zurückgegeben.

    An diesem Punkt muss der sechste Anruf zwischen der Punktzahl (+10) des siebten Anrufs und der Punktzahl (-10) des neunten Anrufs wählen. Da der Zug von huPlayer diese beiden Ergebnisse lieferte, wählt der Algorithmus das kleinste von ihnen aus und gibt es als Objekt mit Punkte- und Indexfeldern auf die höhere Ebene zurück.

    Abschließend werden alle drei Zweige des ersten Anrufs ausgewertet (-10, +10, -10). Da der Zug von aiPlayer diese drei Ergebnisse lieferte, wählt der Algorithmus das Objekt mit der höchsten Punktzahl (+10) und seinem Index (4) aus.

In dem oben diskutierten Szenario entscheidet Minimax, dass es die beste Wahl ist, sich auf das zentrale Feld des Feldes zu bewegen.

Ende!

Inzwischen sollten Sie verstehen, wie der Minimax-Algorithmus funktioniert. Versuchen Sie, selbst eine Implementierung zu schreiben, oder sehen Sie sich ein Beispiel auf GitHub oder CodePen an und optimieren Sie es.

Wenn Sie sich für das Thema KI in Spielen interessieren, empfehlen wir Ihnen, unsere Materialien zu diesem Thema zu lesen.

SCHRITT 1. FORMULARPARAMETER EINSTELLEN1. Um das Formular anzupassen, legen Sie seine Größe fest
510 horizontale Punkte und 480 vertikale Punkte
vertikal. Maximum und Minimum
Geben Sie die Größe gleich den gleichen Werten an.
2. Benennen Sie die Form mit dem Wort „Tic Tac Toe“.
3. Verwenden Sie für den Hintergrund des Formulars die Datei aus dem Ordner
Bilder unter dem Namen background.png und platziere sie
in der Mitte des Formulars.
4. Für das Symbol in der Titelleiste
use Datei aus Ordner verwenden
Bilder mit dem Namen menu4.ico.
5. Die Hintergrundfarbe des Formulars muss eingestellt werden
MinzeCreme.

SCHRITT 2. HINZUFÜGEN EINES BUTTONS UND EINER KLASSE ZUM FORMULAR

1. Bei platzierten Elementen ändern
Schriftgröße auf 12 und Hintergrund festlegen
transparent.

1. Erstellen Sie eine Menüleiste mit Elementen darin
wie im Bild angegeben.

SCHRITT 3. HINZUFÜGEN DER MENÜLEISTE ZUM FORMULAR

1. Erstellen Sie im Menüpunkt Datei einen Befehl
Ausgang.
2. Für
Befehle
Ausgang
verschreiben
Programmcode ist derselbe wie in
vorherige Anwendung.

SCHRITT 3. HINZUFÜGEN DER MENÜLEISTE ZUM FORMULAR

1. Erstellen Sie im Menüpunkt Spiel ein Team
Neues Spiel.
2. Schreiben Sie für das New Game-Team
Programmcode in der Zukunft durch
ein paar Schritte.

SCHRITT 3. HINZUFÜGEN DER MENÜLEISTE ZUM FORMULAR

1. Erstellen Sie im Menüelement Hilfe einen Befehl
Über das Programm.
2. Erstellen Sie für den Befehl About einen neuen
Bilden und schreiben Sie den Programmcode
ähnlich wie im vorigen
Anwendung.

1. Durch Ziehen einer PictureBox auf das Formular
Ändern Sie die Größe auf 100 x 100.
2. Legen Sie einen transparenten Hintergrund fest.
3. Ordnen Sie die PictureBox wie in gezeigt an
Figur über der ersten Zelle des Spielfelds.

SCHRITT 4. FÜGEN SIE PICTUREBOX-OBJEKTE ZUM FORMULAR HINZU

1
2
3
4
5
6
7
8
9
1. Über den Rest der Zellen platzieren wir
PictureBox-Objekte, Kopien der ersten
Objekt, gemäß der Nummerierung auf angegeben
Bilder.

1. Bevor Sie Code schreiben
in einem Ordner benötigt
\Visual Studio
2010\Projekte\Tic Tac Toe \ Tic Tac Toe
zeros\bin\Debug\ muss umgeleitet werden
x.png-, 0.png-, none.png-Dateien aus dem Bilderordner.
2. Doppelklicken Sie mit der linken Maustaste auf das erste
Bilderkiste.

SCHRITT 5. CODE FÜR PICTUREBOX-OBJEKTE HINZUFÜGEN

1. Erstellen Sie ein zweidimensionales Array, auf das alle Elemente zugreifen können
in Form eines 3x3-Elements erstellt, das aus ganzen Zahlen besteht. Sofort
Wir füllen es beim Deklarieren mit Nullen auf. Für leere Zellen wir
Wir verwenden 0, für "Kreuze" - 1 und für "Nullen" - -1.

SCHRITT 5. CODE FÜR PICTUREBOX-OBJEKTE HINZUFÜGEN

In der Prozedur beim Klicken auf die erste
PictureBox, Hinzufügen eines Operators
Auswahl
welche die
Wille
eine Statusprüfung durchführen
Array-Zellen. Wenn der Wert
Array-Zelle wird 0 sein, was
Es bedeutet, dass es keine „Null“ gibt.
"Kreuz", dann in dieser Zelle
Das Array wird mit 1 und in geschrieben
PictureBox1
angezeigt
das Bild des "Kreuzes", und wenn
Array-Zellenwert wird sein
gleich 1, dann enthält es
"cross" und 0 wird hineingeschrieben, und
eine leere Zelle wird angezeigt.

SCHRITT 5. CODE FÜR PICTUREBOX-OBJEKTE HINZUFÜGEN

1
2
3
4
5
6
7
8
9



Fügen Sie für die restlichen Zellen des Felds den Code hinzu
genauso wie im ersten, nur wechselnd
PictureBox-Objektnummer und Zellenadresse
Reihe.
BEISPIEL für die zweite Zelle:

Zum Verfahren auf Schaltfläche klicken
hinzufügen
Operator
Kreislauf
wer prüft
alle Zellen von der ersten bis
das Vorhandensein leerer Zellen. Und wenn
Zelle ist leer
dann hinein
"Null" geschrieben wird, nämlich in
Array-Zelle wird mit -1 geschrieben.
Für die Bequemlichkeit bei der zukünftigen Arbeit
Variablen
ich
J
die
verwendet, um Schleifen zu iterieren
deklarieren Sie für das gesamte Formular.

SCHRITT 6. FÜGEN SIE DEN PROGRAMMCODE FÜR DIE GEHTASTE HINZU

Um Nullen anzuzeigen
Spielen
Bereich
notwendig
fügen Sie dem Körper Programmcode hinzu
Zyklus der Überprüfung der Zellen auf Leerheit.
Mit verschachteltem Operator
Verzweigung
Wille
stattfinden
Analyse der Array-Zellenadresse für
Nullausgabe in der richtigen
Bilderkiste.
Wir fügen auch eine break-Anweisung hinzu
zum vorzeitigen Ende
Schleife wenn leer
Zellen.

SCHRITT 6. FÜGEN SIE DEN PROGRAMMCODE FÜR DIE GEHTASTE HINZU

Um den Spielstatus anzuzeigen
Schnittstellenelement verwendet wird
Etikett1. Da bewegt sich der Spieler immer
Erste
dann
beim
Downloads
Anwendungen
notwendig
v
Element
Etikett1
notwendig
reflektieren
Sätze „dein
Bewegung."
Für
Dies
erstellen
Variable
Antworten
die
Nehmen wir diesen Satz. EIN
beim Laden der Formularvariablen
muss dem Element zugewiesen werden
Label1, um das Notwendige zu erstellen
Verfahren
notwendig
zuerst doppelklicken
informieren

SCHRITT 7. CODE FÜR DEN NEUEN SPIELMENÜEINTRAG HINZUFÜGEN

Wenn Sie auf den Befehl neu klicken
Das Spiel wird zurückgesetzt
alle Zellen im Array, alle ersetzen
"Kreuze" und "Nullen" an
leere Zellen. Auch Ausgabe
Schriftzug "Dein Umzug"

SCHRITT 8. SPIELERGEBNISSE ANZEIGEN

Um die Ergebnisse von Zügen zu überprüfen
notwendig
analysieren
Inhalt von Zeilen, Spalten u
Diagonalen. Wenn alle drei Elemente
gleich 1 sind, dann ist dies ein Sieg für den Spieler, und
wenn drei -1 dann ist das eine Niederlage
Spieler.
Eine Siegesprüfung ist erforderlich
Benehmen
Vorderseite
Bewegung
Computer,
ein
Überprüfung
Niederlage danach.
Der letzte Befehl der Prozedur
zeigt die Ergebnisse an
Bewegung.

SCHRITT 8. SPIELERGEBNISSE ANZEIGEN

Programmcode zum Überprüfen des Benutzergewinns:
if (znacheniyeYacheyki == 1 && znacheniyeYacheyki == 1 && znacheniyeYacheyki == 1) otvet = "Du hast gewonnen";
if (znacheniyeYacheyki == 1 && znacheniyeYacheyki == 1 && znacheniyeYacheyki == 1) otvet = "Du hast gewonnen";
if (znacheniyeYacheyki == 1 && znacheniyeYacheyki == 1 && znacheniyeYacheyki == 1) otvet = "Du hast gewonnen";
if (znacheniyeYacheyki == 1 && znacheniyeYacheyki == 1 && znacheniyeYacheyki == 1) otvet = "Du hast gewonnen";
if (znacheniyeYacheyki == 1 && znacheniyeYacheyki == 1 && znacheniyeYacheyki == 1) otvet = "Du hast gewonnen";
if (znacheniyeYacheyki == 1 && znacheniyeYacheyki == 1 && znacheniyeYacheyki == 1) otvet = "Du hast gewonnen";
if (znacheniyeYacheyki == 1 && znacheniyeYacheyki == 1 && znacheniyeYacheyki == 1) otvet = "Du hast gewonnen";
if (znacheniyeYacheyki == 1 && znacheniyeYacheyki == 1 && znacheniyeYacheyki == 1) otvet = "Du hast gewonnen";
Programmcode zum Überprüfen des Benutzergewinns:
if (znacheniyeYacheyki == -1 & znacheniyeYacheyki == -1 & znacheniyeYacheyki == -1) otvet = "Du hast verloren";
if (znacheniyeYacheyki == -1 & znacheniyeYacheyki == -1 & znacheniyeYacheyki == -1) otvet = "Du hast verloren";
if (znacheniyeYacheyki == -1 & znacheniyeYacheyki == -1 & znacheniyeYacheyki == -1) otvet = "Du hast verloren";
if (znacheniyeYacheyki == -1 & znacheniyeYacheyki == -1 & znacheniyeYacheyki == -1) otvet = "Du hast verloren";
if (znacheniyeYacheyki == -1 & znacheniyeYacheyki == -1 & znacheniyeYacheyki == -1) otvet = "Du hast verloren";
if (znacheniyeYacheyki == -1 & znacheniyeYacheyki == -1 & znacheniyeYacheyki == -1) otvet = "Du hast verloren";
label1.text = Antwort;

SCHRITT 9 „SPIELBARKEIT“ VERBESSERN

Um die Spielbarkeit zu verbessern
statt serieller Ausgabe
im ersten leer
Zellen von "Nullen", implementieren wir
Ausgabe per Zufallsgenerator
Zahlen.
Dazu müssen Sie hinzufügen
eine boolesche Variable
uslovie und ändern Sie den Schleifentyp von For
auf While, weil wir es nicht wissen
die genaue Anzahl der Wiederholungen
Zufallszahlengenerator
es wird nicht in eine leere Zelle fallen.

MINISTERIUM FÜR BILDUNG UND WISSENSCHAFT RUSSLANDS

bundesstaatliche haushaltsbildende Bildungseinrichtung der Höheren Berufsbildung

„Staatliche Universität Wologda“

Institut für Automatisierung und Technische Informatik

Erläuterung zum Studiengangsprojekt zum Fach

Programmierung und die Grundlagen der Algorithmisierung

"Tic-Tac-Toe"

Erfüllt Schüler der Gruppe EM-21

Butorova L. Yu.

akzeptiert Rscheutskaja S. Ju.

EINLEITUNG

1. ANALYSE DES PROBLEMS UND BESTIMMUNG DER ANFORDERUNGEN AN DAS ENTWICKELTE PROGRAMM

1 Der Zweck des Programms, seine Benutzer, die Hauptfunktionen und Ziele, die während der Entwicklung verfolgt werden

2 Übersicht über bekannte Programme, die ähnliche Funktionen ausführen

3 Theoretische Grundlagen der Entwicklung

4 Auswahl an Entwicklungstools

DESIGN TEIL DER ENTWICKLUNG

1 Gestaltung der Benutzeroberfläche

2.2 Entwicklung von Datenstrukturen (in Extern und RAM)

2.3 Entwicklung und Analyse von Algorithmen

PROGRAMMIMPLEMENTIERUNG IN C++

1 Programmarchitektur

2 Auswahl von standardmäßigen visuellen und nicht-visuellen Komponenten

TESTERGEBNISSE

FAZIT

Literaturverzeichnis

Anwendungen

EINLEITUNG

Tic-Tac-Toe – ein logisches Spiel zwischen zwei Gegnern auf einem quadratischen Feld von 3 mal 3 Zellen oder größer (bis zum „endlosen Feld“). Einer der Spieler spielt mit "Kreuzen", der zweite - mit "Nein". Dieses Spiel wurde lange vor dem Aufkommen von Computern populär, nur früher wurde es mit einem einfachen Blatt Papier und einem Stift gespielt. Das traditionelle chinesische Spiel verwendet schwarze und weiße Steine.

Bei dieser Kursarbeit bleiben die Grundregeln und die Standardgröße des Spielfeldes (3x3 Felder) erhalten. Zur Vereinfachung des Spiels bleibt das Recht des ersten Zuges dem Benutzer überlassen, dh "Kreuze".

Tic-Tac-Toe ist ein Programm, das entwickelt wurde, um den Benutzer zu unterhalten, daher ist seine Benutzeroberfläche in dieser Kursarbeit in einem Spielstil mit einer Kombination positiver Farben gestaltet, die den emotionalen Teil des Spiels verstärken.

Es gibt drei Arten im Spiel: X gegen 0 - Benutzer gegen Benutzer, "1 Level mit einem Computer" - für diejenigen, die gerade die Grundlagen des Weltspiels lernen, und Level "2 Level mit einem Computer" - für diejenigen, die es tun sind sich ihres Sieges absolut sicher. Auf Level 1 und 2 sind drei Ergebnisse möglich: „Gewinn“, „Verlieren“ und „Unentschieden“. Der Gewinn steht fest, wenn die Vertikale, Horizontale oder Diagonale vollständig mit Kreuzen oder Nullen gefüllt ist.

Wenn die freien Felder des Feldes vorbei sind, aber niemand gewonnen hat, wird davon ausgegangen, dass das Spiel mit einem „Unentschieden“ endete.

1. ANALYSE DES PROBLEMS UND BESTIMMUNG DER ANFORDERUNGEN AN DAS ENTWICKELTE PROGRAMM

Programmübergreifende Schnittstelle

1.1 Zweck des Programms, seine Benutzer, Hauptfunktionen und während der Entwicklung verfolgte Ziele

Der Zweck dieses Programms besteht in erster Linie darin, die Benutzer zu unterhalten, um die Wartezeit einer Person zu verschönern, denn jede Arbeit braucht Ruhe, und dieses einfache Spiel hilft Ihnen, sich zu entspannen und vom Alltag abzulenken. Außerdem gehört „Tic-Tac-Toe“ zur Klasse der intellektuellen und logischen Spiele, die darauf ausgelegt sind, das logische Denken zu trainieren, die Konzentration zu fördern und das Gedächtnis zu entwickeln.

Die Zielgruppe der Nutzer sind Kinder und Jugendliche sowie Erwachsene. Die Hauptkriterien für die Verwendung des Produkts sind die Fähigkeit, den im Programm geschriebenen Text zu lesen und die erforderliche Aufgabe für den Computer mithilfe der Schaltflächen auszuwählen.

Daraus können wir schließen, dass die Hauptaufgaben sind: die Aufgabe der Unterhaltung und die Aufgabe, das logische Potenzial einer Person zu entwickeln.

1.2 Übersicht über bekannte Programme, die ähnliche Funktionen ausführen

Im Internet finden Sie eine große Anzahl von Werken, die dieses Spiel implementieren. Derzeit gibt es viele Analoga dieses Spiels, die von den ursprünglichen Standards abgewichen sind. Beispiele für solche Programme sind Tic-Tac-Toe on an Infinite Field und Tic-Tac-Toe 3D. Außerdem werden in vielen Spielen "Kreuze" und "Zehen" durch andere Symbole wie beispielsweise "Steine" ersetzt.

Mein Kursprojekt ist eine PC-Anwendung. Das Spiel ist sowohl für einen Benutzer, dessen Gegner künstliche Intelligenz (oder Computer) ist, als auch für zwei Benutzer konzipiert. Es wird auf dem klassischen 3x3-Feld präsentiert.

Das interessanteste und ungewöhnlichste war meiner Meinung nach das Spiel "Tic Tac Toe 3D". Deshalb habe ich es zum Vergleich gewählt.

Dreidimensionales Tic-Tac-Toe ist viel interessanter als auf Papier oder auf einem normalen Feld. Hier gibt es mehr Chancen zu gewinnen und zu verlieren, und Unentschieden sind seltener. Sie können alleine - gegen den Computer - oder zusammen mit einem Freund spielen. Und das Ungewöhnlichste hier ist, dass Sie, um zu gewinnen, eine Kombination aus drei Kugeln Ihrer Farbe (schwarz oder weiß) nicht nur auf einer Ebene, sondern auch entlang der Ebene der Wände und sogar entlang der Diagonalen des Ganzen bilden können Feld (Abb. 1.1).

Reis. 1.1

Unter der Vielzahl von Spielen mit ähnlichem Thema kann man in jedem Werk eine einzigartige Umsetzung des Plans unterscheiden. Jedes Projekt unterscheidet sich von anderen durch seine Individualität.

1.3 Theoretische Grundlagen der Entwicklung

Analyse

Für jede der Parteien sind Algorithmen bekannt, die in jedem Spiel des Gegners ein Unentschieden garantieren, und wenn er einen Fehler macht, Sie gewinnen lassen. Das Spiel ist also im Stand "Niemands Tod"<#"877528.files/image002.gif">

Abb.1.2. Baum der Spielsituationen

Ein Teilbaum von Spielsituationen ist in Abb. 1.2 für das Spiel Tic-Tac-Toe dargestellt. Der Baum der Spielsituationen für das Tic-Tac-Toe-Spiel, bei dem der Spieler für „Tic-Tac-Toe“ zuerst geht und gemäß dem obigen Algorithmus handelt, und der Spieler für „Tac-Toe“ tun kann, was er will (außerdem ist für eine rationale und für eine irrationale Handlung ein Knoten angegeben, also jeder andere), besteht aus 50 Knoten.

1.4 Wahl der Entwicklungstools

Zur Umsetzung unserer Aufgaben wird eine integrierte Anwendungsentwicklungsumgebung benötigt. Daher wurde das Projekt in der Programmierumgebung Microsoft Visual Studio 2008 entwickelt.

Microsoft Visual Studio – Produktlinie von Microsoft , einschließlich einer integrierten Entwicklungsumgebung Software und eine Reihe anderer Tools. Mit diesen Produkten können Sie als Konsole entwickeln Anwendungen sowie GUI-Anwendungen , einschließlich Unterstützung für die Windows Forms-Technologie sowie Webseiten , Internetdienste wie in nativ , und in der kontrollierten Codes für alle von Windows unterstützten Plattformen Windows Mobil , Windows CE .NET-Framework , Xbox , Windows Phone .NET Compact-Framework und Silberlicht .

2. DESIGN TEIL DER ENTWICKLUNG

2.1 Gestaltung der Benutzeroberfläche

Bei der Erstellung einer Spielanwendung muss eine der Hauptkomponenten für den Erfolg des Produkts berücksichtigt werden - dies ist die Benutzeroberfläche. Die Benutzeroberfläche des Programms sollte vor allem verständlich und ansprechend für den Benutzer sein. Sie müssen versuchen, alle Momente zu entfernen, die den Benutzer ablenken oder ihm Unbehagen bereiten. Die gesamte Oberfläche des Programms kann in zwei Komponenten unterteilt werden.

) Hauptmenü des Programms

Reis. 2.1 - Hauptmenü des Programms

Das Hauptmenü ist so gestaltet, dass der Benutzer in die Spielatmosphäre eintauchen kann, daher ist die Benutzeroberfläche in bunten, verspielten Farben gehalten. Über das Menü können Sie zum Spielfeld gehen, die Spielregeln einsehen oder das Spiel verlassen.

) Spielfeld

Abb. 2.2 - Spielfeld

Das Spielfeld enthält den unmittelbaren Bereich für das Spiel, wo der Spieler und der Computer ihre Symbole platzieren. Vor dem Start des Spiels muss der Benutzer einen Spieltyp wie "X vs. 0", "1 Level mit Computer" oder "2 Level mit Computer" auswählen, andernfalls zeigt das Programm eine Meldung an, die Ihnen mitteilt, was zu tun ist. Eine Schaltfläche, die dem Spieler hilft, zum Hauptmenü zurückzukehren. Am Ende erscheinen weitere Fenster, die den Teilnehmer über die Ergebnisse des Duells informieren.

Reis. 2.3 - Zusätzliche Spielergebnisfenster

2.2 Entwicklung von Datenstrukturen (in Extern und RAM)

RAM wird für ein eindimensionales Array verwendet, das aus 9 Elementen besteht, die die Zustände des Spielfelds speichern, wobei jede Zelle des Arrays einer Zelle auf dem Spielfeld entspricht. Speicher wird auch für statische Variablen ausgegeben: Levelnummer, Zugreihenfolge.

Für die Ausführung sind 803 KB freier Speicher erforderlich.

.3 Entwicklung und Analyse von Algorithmen

Um den Game-Thinking-Algorithmus zu implementieren, müssen Sie das statische Array gcnew-Array angeben (9); in dem die Zustände des Spielfelds gespeichert werden, wobei jede Zelle des Arrays einer Zelle entspricht. "0" - entspricht einer leeren Zelle, wenn der Spieler in die Zelle gegangen ist, dh "X", wird der Wert "1" aufgezeichnet und wenn der Computer den Zug gemacht hat, ist der Wert "O". "2". Zu Beginn sind alle Elemente des Arrays gleich "0". Sie müssen die statische Variable lvl setzen, die die Leveldaten speichert. Insgesamt gibt es in diesem Spiel 3 Level: lvl nimmt den Wert „1“ an, wenn der Benutzer die Spielart „X vs. O“ gewählt hat, den Wert „2“, wenn „1 Level mit dem Computer“, und den Wert „ 3" wenn "2 Ebene mit dem Computer". Die Variable player - speichert die Zugreihenfolge ("true" - der Zug des Spielers, "false" - der Zug des Computers). Da dem Benutzer das Recht auf den ersten Zug eingeräumt wird, gilt zu Beginn des Spiels player = true. Die statische Variable flag speichert Informationen darüber, ob es leere Zellen auf dem Spielfeld gibt oder nicht: wenn flag = wahr – also falsch – gibt es keine leeren Zellen. Der Verifikationsalgorithmus muss die Aufzählung der Parameter des Arrays x enthalten und eine eigene Lösung vorschlagen, die für das weitere Spiel optimal ist. Dieses Programm präsentiert 2 Ebenen des Spiels mit dem Computer. In Level 1 besteht die Aufgabe des Computers nicht darin, den Gegner zu schlagen. Daher gibt diese Funktion einen zufälligen Wert der Zelle zurück, in die der Computer gehen wird. Der Code dieses Algorithmus ist in [Anhang 1] dargestellt. Abbildung 2.4 zeigt ein Blockdiagramm der Codeimplementierung.

Der erfolgreichste Zug zu Beginn des Spiels ist der Zug in die Mitte des Feldes. In der Funktion dif_level() wird zu Beginn die Bedingung überprüft: Wenn der Spieler nicht zum zentralen Feld gegangen ist, geht der Computer dorthin. Andernfalls, wenn der Spieler in die Mitte gegangen ist, wird die Funktion check(2) aufgerufen, um die Kombination des Computers zu überprüfen und, wenn es möglich ist, die Zellennummer zurückzugeben, wenn es möglich ist zu gewinnen. Wenn der Computer beim nächsten Zug nicht gewinnen kann, wird die Funktion check(1) aufgerufen: Überprüfung der Kombination des Spielers. Die Nummer der Zelle wird zurückgegeben, wobei gewettet wird, dass der Spieler gewinnen würde. Wenn es keine solche Kombination gibt, wird die Funktion low_level() aufgerufen.

Abb.2.4. - Flussdiagramm

Abb.2.5. - Flussdiagramm

3. IMPLEMENTIERUNG DES PROGRAMMS IN C++

.1 Programmarchitektur

Dieses Programm implementiert 3 Formulare: das Hauptmenü (Abb.2.1.), das Spielfeld (Abb.2.2) und das Hilfefeld (Spielregeln); 12 Tafeln, davon 9 Haupttafeln. Außerdem erscheint am Ende des Spiels eine PictureBox mit dem Ergebnis, es gibt insgesamt 5 (Abbildung 2.3).

Als Basis kann man Panel Click Handler nehmen, von denen es genau 9 auf dem Spielfeld gibt. Jeder Handler ruft mehrere Funktionen auf. Zu Beginn gibt es eine Bedingung, wenn der Nutzer die Spielart „X gegen 0“ auswählt, werden nur die Zellen mit den Werten 1 oder 2 (Kreuz oder Null) gefüllt. Als nächstes kommen die Funktionen: Anzeige des Zugs (CrossZero()), der das Kreuz auf Null ändert und umgekehrt, Blockieren von besetzten Zellen durch checkArray(), Finden des Gewinners winner(). In der Funktion winner() werden alle möglichen Gewinnoptionen berücksichtigt, wenn also einer der Spieler 3 seiner Figuren (Kreuz oder Null) vertikal, horizontal oder diagonal in einer Reihe aufstellt, gewinnt er. Andernfalls, wenn das Feld gefüllt ist, aber keiner der Spieler angetreten ist, wird die Funktion (_friend()) aufgerufen - auf Unentschieden prüfen, die prüft, ob es freie Felder auf dem Feld gibt oder nicht. Wenn fr = wahr, dann gibt es keine freien Zellen auf dem Feld. Wenn sich der Wert geändert hat, dann gibt es eine freie Zelle auf dem Feld.

Die zweite Bedingung funktioniert, wenn der zweite oder dritte Spieltyp ausgewählt ist. Dann wird die Funktion aufgerufen, in der die Bewegung des Computers move(int n) ausgeführt wird. Es erhält die Nummer der Zelle, auf die der Spieler geklickt hat. Als nächstes kommen die Funktionen: Fortschrittsanzeige (CrossZero()), Blockieren belegter Zellen durch checkArray(). Anschließend wird die Funktion winner() aufgerufen, die prüft, ob der Spieler diesen Zug gewonnen hat oder nicht. Wenn nicht, wird das Vorhandensein freier Zellen überprüft. Wenn es freie Zellen gibt, bewegt sich der Computer. Außerdem werden je nachdem, welches Level der Spieler "1" oder "2" gewählt hat, die folgenden Funktionen jeweils aufgerufen: low_level(), dif_level(). Die Funktion low_level() wählt zufällig aus, wo die Null gesetzt werden soll, und die Funktion dif_level() stellt einen speziellen Algorithmus bereit, mit dem der Computer gewinnt. Als nächstes kommen die Funktionen: Fortschrittsanzeige (CrossZero()), Blockieren belegter Zellen durch checkArray(). Anschließend wird die Funktion winner() aufgerufen, die prüft, ob der Computer diesen Zug gewonnen hat oder nicht. Wenn nicht, wird das Vorhandensein freier Zellen überprüft. Wenn es freie Zellen gibt, bewegt sich der Spieler.

.2 Auswahl von standardmäßigen visuellen und nicht-visuellen Komponenten

Für die Umsetzung dieser Arbeit wurden folgende Komponenten ausgewählt:

1) Form1, mit den gegebenen Parametern Text=Tic-Tac-Toe, ControlBox=False

2) f2, mit eingestellter Hintergrundfarbe, Text=Spiel

) comboBox1 mit den angegebenen Items-Optionen:

X gegen 0

1. Ebene mit Computer

2. Ebene mit Computer

4) Bedienfeld mit den angegebenen BackColor-Parametern und unterschiedlichen Werten der Visible- und Enabled-Parameter. Für einige Panels wurden Events wie Click geschrieben.

5) Schaltfläche, mit den angegebenen Parametern Font, Fore Color, BackColor, Text, für alle Schaltflächen wurden solche Ereignisse wie Click geschrieben.

6) Label, mit den gegebenen Parametern BackColor , Font, Fore Color, Text.

) pictureBox, mit eingestellten Bildparametern, SizeMode= StretchImage.

) textBox, mit den gegebenen Parametern BackColor, Font, Fore Color, Text=" ".

4. TESTERGEBNISSE

Lassen Sie uns das Programm testen, indem wir 3 Arten von Spielen durchgehen.

Lassen Sie uns die Aktionen der Hauptmenü-Schaltflächen ausprobieren. Die Tasten funktionieren einwandfrei. Versuchen wir, das Spiel zu starten, ohne einen Spieltyp auszuwählen. Das Programm zeigt eine Fehlermeldung an und fordert Sie auf, die Spielart auszuwählen (Abb.4.1).

Abb.4.1.

Wählen wir 1 Spielart - "X gegen 0", d.h. Benutzer gegen Benutzer. In dieser Phase des Spiels kann der Benutzer auch mit sich selbst spielen. (Abb.4.2)

Abb.4.2.

Beim Spiel „1 Level mit dem Computer“ setzt sich der Computer nicht das Ziel, den Teilnehmer zu gewinnen. Er setzt einfach Nullen an die freien Stellen des Feldes. In diesem Stadium kann der Benutzer den Computer leicht schlagen. Obwohl auf dieser Ebene andere Szenarien möglich sind.

Abb.4.3.

Spielart "Level 2 mit Computer". In dieser Phase analysiert das Spiel alle Züge und versucht, den optimalsten Zug auszuwählen. Alle drei Varianten der Ereignisentwicklung sind auch hier möglich, da Der Computer macht seinen ersten Zug zu einer freien Zelle. Meistens endet das Spiel unentschieden.

Abb.4.4.

Das Programm läuft auf allen Testvarianten erfolgreich, ohne Fehler.

FAZIT

Man kann mit Sicherheit sagen, dass die zu Beginn der Arbeit gestellte Aufgabe abgeschlossen ist. Im Zuge der Entwicklung wurde ein Remix-Projekt des berühmten Tic-Tac-Toe-Spiels geplant und entwickelt. Das Spiel erfüllt die angegebenen Anforderungen und erfüllt seine Funktionen. In der Arbeit sind verschiedene Spielarten und Schwierigkeitsgrade implementiert.

Im Zuge der Arbeit wurden neue Methoden der Programmierung in der integrierten Entwicklungsumgebung beherrscht. Altes Wissen im Umgang mit der Sprache C++ wird gefestigt. In Vorbereitung auf die Kursarbeit wurden verschiedene Methoden und Algorithmen zur Umsetzung dieses Spiels analysiert.

Trotz der scheinbaren Einfachheit dieses Programms ist es mit einer Reihe von Schwierigkeiten behaftet, die mit allen grundlegenden Techniken von Visual C++ implementiert werden.

Die Merkmale dieses Programms sind:

Klar aufgebauter Algorithmus;

Intuitive Schnittstelle;

Benutzerfreundlichkeit;

Völlig übersichtliche Bedienungsanleitung;

Keine Extras.

LITERATURVERZEICHNIS

1. http://www.pravilaigr.ru/xo.php

2. http://2igroka.com/stuff/sportivnye/krestiki_noliki_3d/15-1-0-14

3. https://www.draw.io/

Http://pol-video.ru/QPW9QHEO2GU/uroki_s_krestiki-noliki_ch1.html

ANHANG 1

private: int low_level()(// Prozedur für einen niedrigen Gegner;::Random^ rand = gcnew System::Random();(= rand->Next(0,8);

) während (x[r] != 0);r;

ANLAGE 2

private: bool check(int n)(k = -1;// überprüft alle Kombinationen und gibt korrekten move(x == n) (((x == n)&&(x == 0)) k =2; ( (x == n)&&(x == 0)) k =1;((x == n)&&(x == 0)) k =6;((x == n)&&(x == 0 )) k =3;((x == n)&&(x == 0)) k =8;((x == n)&&(x == 0)) k =4;

)(x == n) (((x == n)&&(x == 0)) k =0;((x == n)&&(x == 0)) k =7;((x = = n)&&(x == 0)) k =4;

)(x == n) (((x == n)&&(x == 0)) k =4;((x == n)&&(x == 0)) k =6;((x = = n)&&(x == 0)) k =8;((x == n)&&(x == 0)) k =5;

)(x == n) (((x == n)&&(x == 0)) k =0;((x == n)&&(x == 0)) k =5;((x = = n)&&(x == 0)) k =4;

)(x == n) (((x == n)&&(x == 0)) k =0;((x == n)&&(x == 0)) k =3;((x = = n)&&(x == 0)) k =1;((x == n)&&(x == 0)) k =2;

)(x == n) (((x == n)&&(x == 0)) k =2;

)(x == n) (((x == n)&&(x == 0)) k =8;((x == n)&&(x == 0)) k =7;

)(x == n) (((x == n)&&(x == 0)) k =6;

)(k!=-1) gebe wahr zurück, sonst gebe falsch zurück;

ANHANG 3

private: int dif_level()(//schwieriger Gegner

//return check(2);(x == 0) return (4);(check(2)) return k; sonst (check(1)) return k; sonst low_level();

ANHANG 4

private: void CrossZero()(// ändert das Kreuz auf Null (Fortschrittsanzeige)(player) (->Visible = true;->Visible = false;

) sonst (->Sichtbar = wahr;->Sichtbar = falsch;

): void checkArray()(// Funktion um zu prüfen ob etwas in der Zelle ist, wenn ja dann kannst du nicht mehr auf diese Zelle klicken. >Enabled = false;)(x == 2) (panel1-> BackgroundImage = panel10->BackgroundImage;panel1->Enabled = false;)(x == 1) (panel2->BackgroundImage = panel11->BackgroundImage;panel2- >Enabled = false;)(x == 2) (panel2-> BackgroundImage = panel10->BackgroundImage;panel2->Enabled = false;)(x == 1) (panel3->BackgroundImage = panel11->BackgroundImage;panel3- >Enabled = false;)(x == 2) (panel3-> BackgroundImage = panel10->BackgroundImage;panel3->Enabled = false;)(x == 1) (panel4->BackgroundImage = panel11->BackgroundImage;panel4- >Enabled = false;)(x == 2) (panel4-> BackgroundImage = panel10->BackgroundImage;panel4->Enabled = false;)(x == 1) (panel5->BackgroundImage = panel11->BackgroundImage;panel5- >Enabled = false;)(x == 2) (panel5-> BackgroundImage = panel10->BackgroundImage;panel5->Enabled = false;)(x == 1) (panel6->B ackgroundImage = panel11->BackgroundImage;panel6->Enabled = false;)(x == 2) (panel6->BackgroundImage = panel10->BackgroundImage;panel6->Enabled = false;)(x == 1) (panel7-> BackgroundImage = panel11->BackgroundImage;panel7->Enabled = false;)(x == 2) (panel7->BackgroundImage = panel10->BackgroundImage;panel7->Enabled = false;)(x == 1) (panel8-> BackgroundImage = panel11->BackgroundImage;panel8->Enabled = false;)(x == 2) (panel8->BackgroundImage = panel10->BackgroundImage;panel8->Enabled = false;)(x == 1) (panel9-> BackgroundImage = panel11->BackgroundImage;panel9->Enabled = false;)(x == 2) (panel9->BackgroundImage = panel10->BackgroundImage;panel9->Enabled = false;)

): bool winner()(// Prüfe den Gewinner und blockiere alle verbleibenden Zellen.

//bool flag = false;(((x == x)&&(x == x)&&(x == 2)) || ((x == x)&&(x == x)&&(x = = 2)) || ((x == x)&&(x == x)&&(x == 2)) || ((x == x)&&(x == x)&&(x == 2 )) || ((x == x)&&(x == x)&&(x == 2)) || ((x == x)&&(x == x)&&(x == 2)) || ((x == x)&&(x == x)&&(x == 2)) || ((x == x)&&(x == x)&&(x == 2)))( (lvl==1) ( picturePo->Visible = true;)(picturePr->Visible = true;)->Enabled = false;->Enabled = false;->Enabled = false;->Enabled = false;-> Aktiviert = falsch;->Aktiviert = falsch;->Aktiviert = falsch;->Aktiviert = falsch;->Aktiviert = falsch;wahr;

)(((x == x)&&(x == x)&&(x == 1)) || ((x == x)&&(x == x)&&(x == 1)) || ((x == x)&&(x == x)&&(x == 1)) || ((x == x)&&(x == x)&&(x == 1)) || (( x == x)&&(x == x)&&(x == 1)) || ((x == x)&&(x == x)&&(x == 1)) || ((x = = = x)&&(x == x)&&(x == 1)) || ((x == x)&&(x == x)&&(x == 1)))((lvl==1 ) ( picturePx->Visible = true;)(picturePobeda->Visible = true;)->Enabled = false;->Enabled = false;->Enabled = false;->Enabled = false;->Enabled = false;- > Aktiviert = falsch;->Aktiviert = falsch;->Aktiviert = falsch;->Aktiviert = falsch;wahr;

): void _friend()(fr = true;(int i = 0; i< 9; i++) if (x[i] == 0) {fr = false; break;}(fr) { pictureN->sichtbar=wahr;)

): void move(int n)(// computer move function= false;[n] = 1;= !player;();();(winner()) () ((int i = 0; i< 9; i++) if (x[i] == 0) flag = true;(flag){(lvl == 2) = 2; = 2;= !player;();();();

): System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) (// neues Spiel>Visible = false;>Visible = false;>Visible = false; >Visible = false; >Visible = false; = comboBox1->Text;(typeGame == "")(::Show("Zuerst Spieltyp auswählen!");

) else ((typeGame == "X vs 0") lvl = 1;(typeGame == "Computer level 1") lvl = 2;(typeGame == "Computer level 2") lvl = 3;(); = true ;(int i = 0; ich< 9; i++) x[i] = 0;->BackgroundImage = Panel12->BackgroundImage;->BackgroundImage = Panel12->BackgroundImage;->BackgroundImage = Panel12->BackgroundImage;->BackgroundImage = Panel12->BackgroundImage;->BackgroundImage = Panel12->BackgroundImage;->BackgroundImage = Panel12-> BackgroundImage;->BackgroundImage = panel12->BackgroundImage;->BackgroundImage = panel12->BackgroundImage;->BackgroundImage = panel12->BackgroundImage;->Enabled = true;->Enabled = true;->Enabled = true;->Enabled = true;->Enabled = true;->Enabled = true;->Enabled = true;->Enabled = true;->Enabled = true;

): System::Void panel1_MouseClick(System::Object^ sender, System::Windows::Forms::MouseEventArgs^ e) (n = 0;(lvl == 1)((player)( = 1;

)= !Spieler;();();();

): System::Void panel2_MouseClick(System::Object^ sender, System::Windows::Forms::MouseEventArgs^ e) (n = 1;(lvl == 1)((player)( = 1;

)= !Spieler;();();();

) else if ((lvl == 2)||(lvl == 3))((n);

): System::Void panel3_MouseClick(System::Object^ sender, System::Windows::Forms::MouseEventArgs^ e) (n = 2;(lvl == 1)((player)( = 1;

)= !Spieler;();();();

) else if ((lvl == 2)||(lvl == 3))((n);

): System::Void panel4_MouseClick(System::Object^ sender, System::Windows::Forms::MouseEventArgs^ e) (n = 3;(lvl == 1)((player)( = 1;

)= !Spieler;();();();

) else if ((lvl == 2)||(lvl == 3))((n);

): System::Void panel5_MouseClick(System::Object^ sender, System::Windows::Forms::MouseEventArgs^ e) (n = 4;(lvl == 1)((player)( = 1;

)= !Spieler;();();();

) else if ((lvl == 2)||(lvl == 3))((n);

): System::Void panel6_MouseClick(System::Object^ sender, System::Windows::Forms::MouseEventArgs^ e) (n = 5;(lvl == 1) ((player)( = 1;

)= !Spieler;();();();

) else if ((lvl == 2)||(lvl == 3))((n);

): System::Void panel7_MouseClick(System::Object^ sender, System::Windows::Forms::MouseEventArgs^ e) (n = 6;(lvl == 1) ((player)( = 1;

)= !Spieler;();();();

) else if ((lvl == 2)||(lvl == 3))((n);

): System::Void panel8_MouseClick(System::Object^ sender, System::Windows::Forms::MouseEventArgs^ e) (n = 7;(lvl == 1) ((player)( = 1;

)= !Spieler;();();();

) else if ((lvl == 2)||(lvl == 3))((n);

): System::Void panel9_MouseClick(System::Object^ sender, System::Windows::Forms::MouseEventArgs^ e) (n = 8;(lvl == 1) ((player)( = 1;

)= !Spieler;();();();

) else if ((lvl == 2)||(lvl == 3))((n);

): System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) (();

): System::Void picturePx_Click(System::Object^ sender, System::EventArgs^ e) (>Visible = false;

): System::Void picturePo_Click(System::Object^ sender, System::EventArgs^ e) (>Visible = false;

): System::Void picturePobeda_Click(System::Object^ sender, System::EventArgs^ e) (>Visible = false;

): System::Void picturePr_Click(System::Object^ sender, System::EventArgs^ e) (>Visible = false;

): System::Void pictureN_Click(System::Object^ sender, System::EventArgs^ e) (>Visible = false;

Grüße liebe Freunde! In diesem Tutorial zeige ich Ihnen, wie Sie ein Browserspiel erstellen können - Tic-Tac-Toe, in Javascript! Sie alle wissen, was dieses Spiel ist und wie man es spielt, aber lassen Sie mich Sie noch einmal daran erinnern:

Tic-Tac-Toe ist ein Logikspiel zwischen zwei Spielern auf einem 3 x 3 quadratischen Feld (möglicherweise größer). Einer spielt mit "Kreuzen" und der zweite - mit "Tac-Toes".

P.S. Wie in allen ähnlichen Javascript-Tutorials können Sie am Ende des Artikels die Quelldatei herunterladen und das Ergebnis der Arbeit am Demo-Beispiel sehen!

Beschreibung des Spiels, das erstellt wird

Werfen wir einen Blick auf die Features des Spiels:

  • das Spiel beginnt sofort nach dem Laden der Seite;
  • das Recht, sich zuerst zu bewegen, wird zufällig gewählt (entweder Sie beginnen zu laufen oder der Computer);
  • das Zeichen, das Sie setzen werden, wird zufällig gewählt (Kreuz oder Null);
  • Wenn der Spieler gewinnt, werden die Gewinnsymbole (ein Streifen aus Kreuzen oder Nullen) grün hervorgehoben;
  • wenn der Spieler gegen den Computer verliert, wird der Balken rot hervorgehoben;
  • Über dem Feld befindet sich eine Informationszeile, in der das Ergebnis (Sieg oder Niederlage) angezeigt wird.

Logik

Ich habe keine komplexen (universellen) Algorithmen für das Spielfeld 3 mal 3 Zellen entwickelt, ich bin den anderen Weg gegangen - Brute Force! (dazu später mehr). Ich habe drei aufeinanderfolgende Hauptstufen identifiziert, auf denen die gesamte Logik beruht:

Stufe 1: Check – hat der Spieler gewonnen?

In diesem Stadium prüfen wir, ob es 3 Zellen (in derselben Zeile) gibt, die mit denselben Spielersymbolen (Kreuze oder Nullen) gefüllt sind. Jene. Egal, was dieser Zug ist (auch der erste), wir prüfen immer zuerst, ob der Spieler gewonnen hat. So sieht der Sieg aus:

Phase 2: Check – kann der Computer beim nächsten Zug gewinnen?

In diesem Stadium suchen wir nach einer Reihe, in der zwei mit einem Computer gefüllte Zellen und eine leere Zelle vorhanden sind - das heißt, wir versuchen, aufgrund der Unaufmerksamkeit des Spielers zu gewinnen. So sieht eine Niederlage aus (d.h. Computersieg):

Stufe 3: Lass uns nicht gewinnen!

Hier suchen wir die gleiche Zeile wie in der zweiten Stufe, nur 2 Zellen müssen mit den Spielzeichen des Spielers gefüllt werden, das heißt, wir lassen den Computer in dieser Stufe nicht verlieren, indem wir ein Zeichen in eine leere Zelle setzen. Jede der Stufen ist eine unabhängige Funktion - Sie können dies im js-Code unten sehen.

Implementierung

Das Layout des Spielfelds ist sehr einfach - der Hauptblock enthält eine Informationszeile (Klasse - Ergebnis) und 9 Blöcke, die Zellen sind (Klasse - Block) HTML-Markup von Zellen:

Du bist dran!

Die Zellhilfsklasse wird benötigt, um die gewünschte Zelle auf dem Spielfeld genau zu identifizieren. CSS-Stile für das Spielfeld:

Krestiki_noliki (Breite: 306 Pixel; Rand: 0 Auto; ) .krestiki_noliki .block (Breite: 100 Pixel; Höhe: 100 Pixel; Rand: 1 Pixel solide #ccc; Cursor: Zeiger; Float: links; Textausrichtung: Mitte; Schriftgröße: 100px; Zeilenhöhe: 94px; )

Schauen wir uns nun den gesamten JS-Code an, danach werde ich auf die wichtigsten Punkte eingehen:

$(document).ready(function()( var znak_user = "O"; var znak_comp = "X"; var rand_num = Math.round((Math.random() * (9 - 1) + 1)); if (rand_num > 3)( var znak_comp = "O"; var znak_user = "X"; $(".cell"+rand_num).text(znak_comp); ) var exit_flag = false; var win_user_array = ["123"," 456","789","147","258","369","159","357"]; //Ermittle die Siegfunktion des Spielers check_3_user(znak)( for (var i = 0; i< 8; i++) { var first = "cell" + win_user_array[i].substr(0,1); var second = "cell" + win_user_array[i].substr(1,1); var third = "cell" + win_user_array[i].substr(2,1); if($("."+first).text() == znak && $("."+second).text() == znak && $("."+third).text() == znak){ $("."+first+",."+second+",."+third).css("background-color", "#83e2c3"); $(".result").text("Вы выиграли!"); $(".krestiki_noliki .block").unbind("click"); exit_flag = true; } } } //Определяем возможность победы компьютера function check_2_comp(znak){ for (var i = 0; i < 8; i++) { var first = "cell" + win_user_array[i].substr(0,1); var second = "cell" + win_user_array[i].substr(1,1); var third = "cell" + win_user_array[i].substr(2,1); if($("."+first).text() == znak && $("."+second).text() == znak && $("."+third).text() == "" && exit_flag == false){ $("."+third).text(znak); $("."+first+",."+second+",."+third).css("background-color", "#EF7C7C"); $(".result").text("Вы проиграли!"); $(".krestiki_noliki .block").unbind("click"); exit_flag = true; } if($("."+first).text() == znak && $("."+second).text() == "" && $("."+third).text() == znak && exit_flag == false){ $("."+second).text(znak); $("."+first+",."+second+",."+third).css("background-color", "#EF7C7C"); $(".result").text("Вы проиграли!"); $(".krestiki_noliki .block").unbind("click"); exit_flag = true; } if($("."+first).text() == "" && $("."+second).text() == znak && $("."+third).text() == znak && exit_flag == false){ $("."+first).text(znak); $("."+first+",."+second+",."+third).css("background-color", "#EF7C7C"); $(".result").text("Вы проиграли!"); $(".krestiki_noliki .block").unbind("click"); exit_flag = true; } } } //Определяем ход компьютера function check_2_user(znak){ for (var i = 0; i < 8; i++) { var first = "cell" + win_user_array[i].substr(0,1); var second = "cell" + win_user_array[i].substr(1,1); var third = "cell" + win_user_array[i].substr(2,1); if(exit_flag == false){ if($("."+first).text() == znak && $("."+second).text() == znak && $("."+third).text() == ""){ $("."+third).text(znak_comp); exit_flag = true; } } if(exit_flag == false){ if($("."+first).text() == znak && $("."+second).text() == "" && $("."+third).text() == znak){ $("."+second).text(znak_comp); exit_flag = true; } } if($("."+first).text() == "" && $("."+second).text() == znak && $("."+third).text() == znak){ $("."+first).text(znak_comp); exit_flag = true; } if(exit_flag) break; } } $(".krestiki_noliki .block").click(function(){ //Если клетка пустая if($(this).text() == ""){ $(this).text(znak_user); check_3_user(znak_user); check_2_comp(znak_comp); check_2_user(znak_user); if(exit_flag == false){ for (var i = 1; i < 10; i++) { if($(".cell"+i).text() == ""){ $(".cell"+i).text(znak_comp); break; } } }else exit_flag = false; } }); });

Zuerst deklarieren wir Variablen: znak_user – in dieser Variable speichern wir das Zeichen, dass der Benutzer spielen wird (standardmäßig wird dort eine Null gespeichert – das ist das englische Booth „O“). znak_comp - in dieser Variablen speichern wir das Zeichen, dass der Computer spielen wird (standardmäßig ist dort ein Kreuz gespeichert - dies ist der englische Stand "x").

Die Logik ist folgende: Wenn die Zufallszahl größer als 3 ist, dann spielt der Computer mit Nullen und er (der Computer) macht den ersten Zug.

Sie können diese Logik nach Belieben ändern, zum Beispiel können Sie einige Zufallszahlen erstellen, um mehr Optionen dafür zu haben, wer mindestens der erste und welche Charaktere sein wird. exit_flag - Dieses Flag (Variable) ist für das Verlassen der Funktion verantwortlich, dh wenn der Computer beispielsweise bereits seinen Zug ausgeführt hat und Sie die Funktion beenden und den Zug an den Spieler übertragen müssen. win_user_array – Dieses Array speichert alle Gewinnoptionen zum Füllen von Zellen. Schauen wir uns zur Verdeutlichung dieses Bild an:

Jedes Element des Arrays ist eine dreistellige Zeichenfolge, was eine Gewinnkombination darstellt, dh wenn Sie beispielsweise die Zellen unter den Zahlen 1, 2 und 3 ausfüllen, kommt es zum Sieg (oder zur Niederlage). Wie Sie sehen können, gibt es insgesamt 8 Gewinnoptionen, unsere Aufgabe ist es, alle diese Optionen zu sortieren. Es folgen 3 Funktionen:

  1. check_3_user();
  2. check_2_comp();
  3. check_2_user();

Der Zweck dieser Funktionen wird (in drei Schritten) im Abschnitt „Logik“ (oben) beschrieben. Diese Funktionen werden aufgerufen, indem Sie auf eine der Zellen des Felds klicken. Der Parameter (znak) wird an jede der Funktionen übergeben - dies ist das Zeichen des Spielers oder des Computers (Kreuz oder Null). In der Funktion, die den Sieg des Spielers bestimmt (check_3_user), übergeben wir beispielsweise das Zeichen des Spielers, um 3 identische Zeichen auf derselben Linie zu finden.

Nach drei Funktionen (wenn der Computer noch keinen Zug gemacht hat) füllt der Computer eines der freien Felder. Hier können Sie das Spiel verkomplizieren, indem Sie es zum Beispiel so machen, dass wenn die mittlere Zelle frei ist (Zelle Nummer 5), dann zuerst darauf wetten, wenn sie besetzt ist, dann auf eine der freien Ecken setzen (diese sind Zellen Nr. 1, 3, 7 und 9) und so weiter - im Allgemeinen liegt es hier an Ihnen.

Das ist im Prinzip alles, was erforderlich ist, um ein solches Spiel zu erstellen.

Jetzt können Sie sich das Spiel in einer Demo ansehen und die Quelldatei herunterladen (nur 1 Datei).

08.06.2018 - Danke für die Aufmerksamkeit an den Autor des Briefes: Patvakan Baghdasaryan, ein Fehler wurde behoben, als der Computer mehrere mögliche Siegoptionen hatte und alle seine Gewinnzüge übermalt wurden (von 4 auf 6 Zellen, statt 3 ).

Das ist alles für mich, ich hoffe, dieses Tutorial war nützlich für Sie, ich wünsche Ihnen viel Glück, tschüss!

Fortsetzung des Themas:
Internet

Eine Halbleiterdiode ist gegenüber ausreichend schnellen Strom- oder Spannungsänderungen inert, da sich nicht sofort eine neue Ladungsträgerverteilung einstellt. Wie...