https://en.wikipedia.org/wiki/Connect_Four
Czy ktoś pamięta, że gra dla 2 graczy łączy 4? Dla tych, którzy tego nie zrobili, była to tablica 6x7, która stoi pionowo na powierzchni. Celem Connect 4 jest, dobrze połączyć 4! Połączenie jest liczone, jeśli jest poziome, ukośne lub pionowe. Umieszczasz swoje pionki na planszy, wstawiając pion na górze kolumny, gdzie spada na dół tej kolumny. Nasze zasady zmieniają 3 rzeczy w Connect 4.
- Zmiana nr 1 Wygrana jest definiowana jako gracz z największą liczbą punktów. Otrzymujesz punkty, łącząc 4 jak w regulaminie - więcej na ten temat później.
- Zmiana # 2 W każdej rundzie masz 3 graczy.
- Zmień nr 3 Rozmiar planszy to 9x9.
Punktacja:
Wynik opiera się na liczbie zdobytych z rzędu. Jeśli masz grupę 4 z rzędu, otrzymasz 1 punkt. Jeśli masz grupę 5 w rzędzie, dostajesz 2 punkty, 6 w rzędzie 3 i tak dalej.
Przykłady:
Uwaga o
i x
są zastępowane #
i ~
odpowiednio dla lepszego kontrastu
Przykład pustej planszy: (wszystkie przykłady to plansza o standardowym rozmiarze dla 2 graczy)
a b c d e f g
6 | | | | | | | |
5 | | | | | | | |
4 | | | | | | | |
3 | | | | | | | |
2 | | | | | | | |
1 |_|_|_|_|_|_|_|
Jeśli upuścimy kawałek w kol d
, wyląduje on na miejscu 1d
.
a b c d e f g
6 | | | | | | | |
5 | | | | | | | |
4 | | | | | | | |
3 | | | | | | | |
2 | | | | | | | |
1 |_|_|_|#|_|_|_|
Jeśli teraz upuścimy kawałek d
ponownie w kol , wyląduje on na miejscu 2d
. Oto przykłady 4 pozycji w rzędzie:
a b c d e f g
6 | | | | | | | |
5 | | | | | | | |
4 | | | |~| | | |
3 | | |~|#| | | |
2 | |~|#|~| |#| |
1 |~|#|~|#|_|#|_|
W tym przypadku x
dostaje 1 punkt po przekątnej ( 1a 2b 3c 4d
).
a b c d e f g
6 | | | | | | | |
5 | | | | | | | |
4 | | | |#| | | |
3 | | | |#| | | |
2 | | | |#| | | |
1 |_|~|_|#|~|_|~|
W takim przypadku o
dostaje 1 punkt w pionie ( 1d 2d 3d 4d
).
a b c d e f g
6 | | | | | | | |
5 | | | | | | | |
4 | | | | | | | |
3 | | | | | | | |
2 | | |#|#|#|#| |
1 |_|_|~|~|~|~|~|
W tym przypadku o
otrzymuje 2 punkty w poziomie ( 1c 1d 1e 1f 1g
) i x
otrzymuje 1 punkt w poziomie ( 2c 2d 2e 2f
).
a b c d e f g
6 | | |#| | | | |
5 | | |#| | | | |
4 | | |#| | | | |
3 | | |#| | |~| |
2 |~| |#| | |#|~|
1 |~|_|#|~| |~|~|
Tym razem x
dostaje 3 punkty za 6 z rzędu ( 1c 2c 3c 4c 5c 6c
).
Wejście wyjście
Będziesz miał dostęp do tablicy za pomocą tablicy 2d. Każda lokalizacja będzie int
reprezentowana przez identyfikator gracza. Będziesz także przekazywał swój identyfikator gracza do swojej funkcji. Poruszasz się, zwracając do której kolekcji chcesz wrzucić swój kawałek. W każdej rundzie do gry zostaną wybrani 3 gracze. Pod koniec gry wszyscy gracze rozegrają parzystą liczbę gier.
W tej chwili zostanie uruchomionych 100 000 rund (pamiętaj, że zajmuje to dużo czasu, możesz chcieć je zmniejszyć w celu szybkiego przetestowania). Ogólnie rzecz biorąc, zwycięzcą zostaje gracz z największą liczbą wygranych.
Kontroler można znaleźć tutaj: https://github.com/JJ-Atkinson/Connect-n/tree/master .
Pisanie bota:
Aby napisać bota, musisz rozszerzyć Player
klasę. Player
jest abstrakcyjna i ma jedną metodę wdrożenia, int makeMove(void)
. W makeMove
sam zdecydujesz, do której kolekcji chcesz wrzucić swój kawałek. Jeśli wybrałeś niepoprawne coll (np. Coll nie istnieje, coll jest już wypełniony), twoja kolej zostanie pominięta . W Player
klasie masz wiele przydatnych metod pomocniczych. Oto lista najważniejszych z nich:
boolean ensureValidMove(int coll)
: Zwraca true, jeśli coll jest na planszy, a coll nie jest jeszcze wypełniony.int[] getBoardSize()
: Zwraca tablicę int, gdzie[0]
jest liczba kolumn i[1]
liczba wierszy.int[][] getBoard()
: Zwróć kopię planszy. Należy do niego dostęp tak:[coll number][row number from bottom]
.- Aby znaleźć resztę, spójrz na
Player
klasę. EMPTY_CELL
: Wartość pustej komórki
Ponieważ będzie to wielowątkowe, dołączyłem również random
funkcję, jeśli jej potrzebujesz.
Debugowanie bota:
Dodałem kilka rzeczy do kontrolera, aby ułatwić debugowanie bota. Pierwszy to Runner#SHOW_STATISTICS
. Jeśli ta opcja jest włączona, zobaczysz wydruk grup graczy, w tym liczbę zwycięstw botów. Przykład:
OnePlayBot, PackingBot, BuggyBot,
OnePlayBot -> 6
PackingBot -> 5
BuggyBot -> 3
Draw -> 1
Możesz również stworzyć niestandardową grę z connectn.game.CustomGame
klasą, możesz zobaczyć wyniki i zwycięzcę każdej rundy. Możesz nawet dodać siebie do miksu za pomocą UserBot
.
Dodanie bota:
Aby dodać bota do składu, przejdź do PlayerFactory
bloku statycznego i dodaj następujący wiersz:
playerCreator.put(MyBot.class, MyBot::new);
Inne rzeczy do zapamiętania:
- Symulacje są wielowątkowe. Jeśli chcesz to wyłączyć, przejdź do
Runner#runGames()
i skomentuj ten wiersz (.parallel()
). - Aby zmienić liczbę gier, ustaw
Runner#MINIMUM_NUMBER_OF_GAMES
według własnych upodobań.
Dodano później:
- Komunikacja między botami jest niedozwolona.
Powiązane: Zagraj w Connect 4!
================================
Tablica wyników: (100 000 gier)
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
================================
źródło
Player
klasę, aby zobaczyć wszystkie dostępne metody.ensureValidMove
(chyba że twoją strategią jest oczywiście przejście tej kolejki).Odpowiedzi:
MaxGayne
Ten bot przypisuje ocenę do każdej pozycji, w oparciu głównie o długość połączonych części. Wygląda na 3 ruchy, sprawdzając 3 najlepiej wyglądające ruchy na każdym etapie i wybiera ten z maksymalnym oczekiwanym wynikiem.
źródło
UserBot
a twoim botem było to, że po pewnym czasieMaxGayne
wyrzuci tury (np. Po 15 ruchach przeskakuje co turę, aż do końca gry).javafx.util.Pair
nie działa w Eclipse, ponieważ nie jest uważany za część publicznego API. I nie mam pojęcia, gdzie szukaćsun.plugin.dom.exception.InvalidStateException
. Prawdopodobnie miałeś na myślijava.lang.IllegalStateException
.Pair
, to jest tak blisko, jak mogę dostać się do typu danych, który chcę, bez kręcenia własnym, więc jeśli zaćmienie się nie skompiluje, myślę, że jest OK. Jeśli chodzi o # 3, masz rację, moje autouzupełnianie w IntelliJ nie zawsze ma rację. (przez większość czasu tak nie sprawdzałem)Pair
problem naprawdę uniemożliwia kompilację w środowisku Eclipse, chyba że znasz obejście .RowBot
Patrzy we wszystkich kierunkach i określa optymalną kolumnę. Próbuje połączyć swoje pionki, nie pozwalając przeciwnikom robić tego samego.
źródło
OnePlayBot
Ten bot ma tylko jedną grę - umieść swój kawałek w poprawnej lewej komórce. Co dziwne, robi to całkiem dobrze;)
źródło
RandomBot
Po prostu umieść kawałek w dowolnym miejscu, które jest ważne.
źródło
StraightForwardBot
Podobne do OnePlayBot, ale uwzględnia ostatni ruch i odtwarza następną kolumnę, która jest poprawna.
źródło
JealousBot
Ten bot nienawidzi drugiego gracza. I nie podoba mu się to, że upuszcza kawałki na planszę. Więc stara się być ostatnim, który upuścił kawałek w kolumnie.
To mój pierwszy raz w CodeGolf, więc mam nadzieję, że ta odpowiedź będzie wystarczająco dobra. Nie mogłem tego jeszcze przetestować, więc przepraszam, jeśli są jakieś błędy.
EDYCJA : Dodano linię, aby przełamać sekundę
for
.EDYCJA 2 : Zrozumiałem, dlaczego
while
był nieskończony. Jest teraz kompletny i można go używać!źródło
if(board[col][row]!=null && board[col][row]!=id)
powinna zostać zmieniona naif(board[col][row]!=-1....
. Sprawdź game.Game.genBoard () w github OP, jeśli chcesz być pewien. Nie wiem też, czyrandom()
zrobisz, co chcesz, może wykorzystasz(int)Math.random()*col
?random()
Metoda jest wPlayer
klasie! Więc myślę, że to zadziała =) Ale tak, nie byłem pewien swoich warunków. Nie znalazłem, jak to jest zdefiniowane w kodzie OP, ale sprawdzę ponownie. Dziękuję Ci bardzo!public double random() {return ThreadLocalRandom.current().nextDouble();}
. Nie wiem dokładnie, jak to działa, ale zakładam, że zwraca wartość z zakresu od 0 do 1, więc może być konieczne(int)random()*col
:)nextDouble
zwraca liczbę pomiędzy0
a1
. Dołączyłem go, ponieważ symulacje są uruchamiane równolegle iMath.random()
nie są bezpieczne dla wątków.BasicBlockBot
Prosty (i naiwny) bot blokowy. Nie wie, że możesz zrobić 4 z rzędu poziomo lub ukośnie!
źródło
Progresywny
Postęp jest ... postępowy. Lubi patrzeć na wszystko i niektóre! (Nie jestem pewien tej metodologii. Raz działało to przeciwko przyjacielowi.) I z jakiegoś powodu działa przyzwoicie.
źródło
FairDiceRoll
Zawsze zwraca 4.
źródło
BuggyBot
Przykładowy bot do pokonania (FYI: to nie jest trudne;)
źródło
PackingBot
Ten bot nie celuje bezpośrednio w punkty. Próbuje spakować maksymalnie tokenów, dopóki plansza nie zostanie zapełniona. Zrozumiał, że po prostu ciągłe podnoszenie się jest głupie, więc losowo umieszcza tokeny wokół swojej „domeny”.
Powinien być w stanie zdobyć punkty we wszystkich kierunkach, ale nie będzie najlepszy!
(Nie testowany)
źródło
Steve
źródło
BasicBlockBot
.