https://en.wikipedia.org/wiki/Connect_Four
Erinnert sich jemand an das 2-Spieler-Spiel Connect 4? Für diejenigen, die es nicht tun, war es ein 6x7-Brett, das vertikal auf einer Oberfläche steht. Das Ziel von connect 4 ist es, 4 gut zu verbinden! Die Verbindung wird gezählt, wenn sie horizontal, diagonal oder vertikal ist. Sie platzieren Ihre Spielsteine auf dem Brett, indem Sie einen Stein am oberen Rand einer Spalte einfügen, der am unteren Rand dieser Spalte liegt. Unsere Regeln ändern 3 Dinge in Connect 4.
- Änderung Nr. 1 Der Gewinn wird als der Spieler mit den meisten Punkten definiert. Sie erhalten Punkte, indem Sie 4 wie in den Regeln verbinden - dazu später mehr.
- Änderung Nr. 2 Sie haben 3 Spieler pro Runde.
- Änderung Nr. 3 Die Brettgröße ist 9x9.
Wertung:
Das Ergebnis basiert darauf, wie viele Sie in einer Reihe erhalten. Wenn Sie eine 4 in einer Zeilengruppe haben, erhalten Sie 1 Punkt. Wenn Sie eine 5 in einer Reihengruppe haben, erhalten Sie 2 Punkte, 6 in einer Reihe 3 und so weiter.
Beispiele:
Beachten Sie o
und x
werden mit #
und ~
ersetzt, um den Kontrast zu verbessern
Beispiel für ein leeres Brett: (Alle Beispiele sind Bretter in Standardgröße für 2 Spieler.)
a b c d e f g
6 | | | | | | | |
5 | | | | | | | |
4 | | | | | | | |
3 | | | | | | | |
2 | | | | | | | |
1 |_|_|_|_|_|_|_|
Wenn wir ein Stück in coll fallen lassen d
, wird es an Ort und Stelle landen 1d
.
a b c d e f g
6 | | | | | | | |
5 | | | | | | | |
4 | | | | | | | |
3 | | | | | | | |
2 | | | | | | | |
1 |_|_|_|#|_|_|_|
Wenn wir nun ein Stück wieder in coll ablegen d
, landet es an Ort und Stelle 2d
. Hier sind Beispiele für 4 in einer Reihe Positionen:
a b c d e f g
6 | | | | | | | |
5 | | | | | | | |
4 | | | |~| | | |
3 | | |~|#| | | |
2 | |~|#|~| |#| |
1 |~|#|~|#|_|#|_|
In diesem Fall x
erhält 1 Punkt diagonal ( 1a 2b 3c 4d
).
a b c d e f g
6 | | | | | | | |
5 | | | | | | | |
4 | | | |#| | | |
3 | | | |#| | | |
2 | | | |#| | | |
1 |_|~|_|#|~|_|~|
In diesem Fall o
erhält man 1 Punkt senkrecht ( 1d 2d 3d 4d
).
a b c d e f g
6 | | | | | | | |
5 | | | | | | | |
4 | | | | | | | |
3 | | | | | | | |
2 | | |#|#|#|#| |
1 |_|_|~|~|~|~|~|
In diesem Fall erhalten Sie o
2 Punkte horizontal ( 1c 1d 1e 1f 1g
) und x
1 Punkt horizontal ( 2c 2d 2e 2f
).
a b c d e f g
6 | | |#| | | | |
5 | | |#| | | | |
4 | | |#| | | | |
3 | | |#| | |~| |
2 |~| |#| | |#|~|
1 |~|_|#|~| |~|~|
Dieses Mal x
erhält 3 Punkte für eine 6 in einer Reihe ( 1c 2c 3c 4c 5c 6c
).
Input-Output
Sie haben über ein 2D-Array Zugriff auf die Karte. Jeder Ort wird mit einer int
Spielerkennung dargestellt. Sie werden auch Ihre Player-ID an Ihre Funktion übergeben. Sie machen Ihren Zug, indem Sie den Coll zurückgeben, in den Sie Ihr Stück fallen lassen möchten. In jeder Runde werden 3 Spieler ausgewählt. Am Ende des Spiels haben alle Spieler eine gerade Anzahl von Spielen gespielt.
Momentan werden 100.000 Runden ausgeführt (beachten Sie, dass dies sehr lange dauert. Möglicherweise möchten Sie es für schnelle Turnaround-Tests reduzieren). Insgesamt gewinnt der Spieler mit den meisten Siegen.
Den Controller finden Sie hier: https://github.com/JJ-Atkinson/Connect-n/tree/master .
Einen Bot schreiben:
Um einen Bot zu schreiben, müssen Sie die Player
Klasse erweitern. Player
ist abstrakt und ein Verfahren zu implementieren hat int makeMove(void)
. In makeMove
welcher Coll du dein Stück ablegen möchtest, entscheidest du. Wenn Sie ein ungültiges Coll gewählt haben (zB Coll existiert nicht, Coll ist bereits gefüllt), wird Ihr Zug übersprungen . In der Player
Klasse haben Sie viele nützliche Hilfsmethoden. Es folgt eine Auflistung der wichtigsten:
boolean ensureValidMove(int coll)
: Gib true zurück, wenn sich die Coll auf dem Board befindet und die Coll noch nicht gefüllt ist.int[] getBoardSize()
: Gibt ein int-Array zurück, in dem[0]
die Anzahl der Spalten und[1]
die Anzahl der Zeilen angegeben ist.int[][] getBoard()
: Gib eine Kopie der Tafel zurück. Sie sollten es so zugreifen:[coll number][row number from bottom]
.- Um den Rest zu finden, schauen Sie sich die
Player
Klasse an. EMPTY_CELL
: Der Wert einer leeren Zelle
Da es sich um eine Multithread- random
Funktion handelt , habe ich bei Bedarf auch eine Funktion hinzugefügt.
Debuggen Ihres Bots:
Ich habe einige Dinge in den Controller aufgenommen, um das Debuggen eines Bots zu vereinfachen. Der erste ist Runner#SHOW_STATISTICS
. Wenn dies aktiviert ist, sehen Sie einen Ausdruck der gespielten Spielergruppen, einschließlich der Anzahl der Bot-Gewinne. Beispiel:
OnePlayBot, PackingBot, BuggyBot,
OnePlayBot -> 6
PackingBot -> 5
BuggyBot -> 3
Draw -> 1
Sie können mit der connectn.game.CustomGame
Klasse auch ein benutzerdefiniertes Spiel erstellen. Sie können die Ergebnisse und Gewinner jeder Runde anzeigen. Sie können sich sogar dem Mix mit hinzufügen UserBot
.
Hinzufügen Ihres Bots:
Um Ihren Bot zur Aufstellung hinzuzufügen, gehen Sie zum PlayerFactory
statischen Block und fügen Sie die folgende Zeile hinzu:
playerCreator.put(MyBot.class, MyBot::new);
Andere Dinge zu beachten:
- Die Simulationen sind multithreaded. Wenn Sie das deaktivieren möchten, gehen Sie zu
Runner#runGames()
und kommentieren Sie diese Zeile (.parallel()
). - Um die Anzahl der Spiele zu ändern, stellen Sie sie
Runner#MINIMUM_NUMBER_OF_GAMES
nach Ihren Wünschen ein.
Später hinzugefügt:
- Kommunikation zwischen Bots ist nicht erlaubt.
Siehe auch: Play Connect 4!
===============================
Anzeigetafel: (100 000 Spiele)
MaxGayne -> 22662
RowBot -> 17884
OnePlayBot -> 10354
JealousBot -> 10140
Progressive -> 7965
Draw -> 7553
StraightForwardBot -> 7542
RandomBot -> 6700
PackingBot -> 5317
BasicBlockBot -> 1282
BuggyBot -> 1114
FairDiceRoll -> 853
Steve -> 634
===============================
quelle
Player
Klasse, um alle verfügbaren Methoden anzuzeigen.ensureValidMove
(es sei denn, Ihre Strategie besteht darin, diese Runde zu bestehen).Antworten:
MaxGayne
Dieser Bot weist jeder Position eine Punktzahl zu, die hauptsächlich auf der Länge der verbundenen Teile basiert. Es sieht so aus, als wären es 3 Züge in die Tiefe gegangen, wobei in jeder Phase 3 am besten aussehende Züge untersucht werden.
quelle
UserBot
und dein Bot war, dass er nach einem bestimmten ZeitpunktMaxGayne
Runden wegwirft (z. B. nach 15 Zügen wird jede Runde übersprungen, bis das Spiel endet).javafx.util.Pair
funktioniert in Eclipse nicht, da es nicht als Teil der öffentlichen API betrachtet wird. Und ich habe keine Ahnung, wo ich suchen sollsun.plugin.dom.exception.InvalidStateException
. Sie meinten wahrscheinlichjava.lang.IllegalStateException
.Pair
, das ist so nah wie möglich an den gewünschten Datentyp, ohne meinen eigenen zu rollen. Wenn Eclipse nicht kompiliert werden kann, denke ich, ist es in Ordnung. Was # 3 betrifft, haben Sie recht, meine automatische Vervollständigung in IntelliJ ist nicht immer richtig. (die meiste Zeit ist es, deshalb habe ich nicht überprüft)Pair
verhindert das Problem das Kompilieren in Eclipse, es sei denn, Sie kennen die Problemumgehung .RowBot
Schaut in alle Richtungen und ermittelt die optimale Säule. Versucht, seine Figuren zu verbinden, ohne dass seine Gegner dasselbe tun.
quelle
OnePlayBot
Dieser Bot hat nur ein Spiel - platziere seine Figur in der Zelle ganz links, die gültig ist. Seltsamerweise tut es ziemlich gut;)
quelle
RandomBot
Legen Sie einfach ein Stück an eine beliebige Stelle, die gültig ist.
quelle
StraightForwardBot
Ähnlich wie OnePlayBot, berücksichtigt jedoch den letzten Zug und spielt die nächste Spalte darüber ab, die gültig ist.
quelle
Eifersüchtiger Roboter
Dieser Bot hasst den anderen Spieler. Und er mag es nicht, dass er Steine auf das Brett fallen lässt. Also versucht er der letzte zu sein, der ein Stück in eine Spalte fallen lässt.
Es ist mein erstes Mal auf CodeGolf, also hoffe ich, dass diese Antwort gut genug ist. Ich konnte es noch nicht testen, bitte entschuldigen Sie, falls es Fehler gibt.
BEARBEITEN : Es wurde eine Zeile hinzugefügt, um die Sekunde zu unterbrechen
for
.EDIT 2 : Herausgefunden, warum das
while
unendlich war. Es ist jetzt komplett und kann verwendet werden!quelle
if(board[col][row]!=null && board[col][row]!=id)
sollte also auf geändert werdenif(board[col][row]!=-1....
. Check in game.Game.genBoard () im Github von OP, wenn du sicher sein willst. Ich weiß auch nicht, ob deinrandom()
Wille macht, was du willst, vielleicht benutzt(int)Math.random()*col
?random()
Methode ist in derPlayer
Klasse! Also denke ich, dass es funktionieren wird =) Aber ja, ich war nicht zuversichtlich in meinen Bedingungen. Ich habe nicht gefunden, wie es im OP-Code definiert ist, aber ich werde es noch einmal überprüfen. Vielen Dank!public double random() {return ThreadLocalRandom.current().nextDouble();}
. Ich weiß nicht genau, wie es funktioniert, aber ich gehe davon aus, dass es einen Wert zwischen 0 und 1 zurückgibt, also müsste ich es möglicherweise tun(int)random()*col
:)nextDouble
gibt eine Zahl zwischen0
und zurück1
. Ich habe es eingefügt, da die Simulationen parallel ausgeführt werden undMath.random()
nicht threadsicher sind.BasicBlockBot
Ein einfacher (und naiver) Blockbot. Er weiß nicht, dass Sie eine 4 in einer Reihe horizontal oder diagonal machen können!
quelle
Progressiv
Progressiv ist ... progressiv. Er mag es, alles und einige anzuschauen! (Ich bin nicht sicher, wie das funktioniert. Es hat einmal gegen einen Freund funktioniert.) Und aus irgendeinem Grund funktioniert es anständig.
quelle
FairDiceRoll
Gibt immer 4 zurück.
quelle
BuggyBot
Ein Sample-Bot, den du schlagen kannst (FYI: Es ist nicht schwer;)
quelle
PackingBot
Dieser Bot zielt nicht direkt auf Punkte. Er versucht, maximal Jetons zu packen, bis das Brett voll ist. Er verstand, dass es dumm ist, einfach immer wieder aufzusteigen, also wird er nach dem Zufallsprinzip Token um seine "Domain" legen.
Er sollte in der Lage sein, einige Punkte in alle Richtungen zu holen, wird aber nicht der Beste sein!
(Nicht getestet)
quelle
Steve
quelle
BasicBlockBot
.