https://en.wikipedia.org/wiki/Connect_Four
Quelqu'un se souvient-il du jeu à 2 joueurs Connect 4? Pour ceux qui ne l'ont pas, c'était une planche 6x7 qui se tient verticale sur une surface. L'objectif de Connect 4 est de bien connecter 4! La connexion est comptée si elle est horizontale, diagonale ou verticale. Vous placez vos pièces sur le plateau en insérant une pièce en haut d'une colonne où elle tombe au bas de cette colonne. Nos règles changent 3 choses dans connect 4.
- Changement # 1 Gagner est défini comme le joueur avec le plus de points. Vous obtenez des points en connectant 4 comme dans les règles - plus à ce sujet plus tard.
- Changement # 2 Vous avez 3 joueurs à chaque tour.
- Changement n ° 3 La taille du tableau est 9x9.
Notation:
Le score est basé sur le nombre que vous obtenez consécutivement. Si vous avez un groupe de 4 dans une rangée, vous obtenez 1 point. Si vous avez un groupe de 5 dans une rangée, vous obtenez 2 points, 6 dans une rangée 3 et ainsi de suite.
Exemples:
Notez o
et x
sont remplacés par #
et ~
respectivement, pour un meilleur contraste
Exemple de plateau vide: (tous les exemples sont des plateaux de taille standard pour 2 joueurs)
a b c d e f g
6 | | | | | | | |
5 | | | | | | | |
4 | | | | | | | |
3 | | | | | | | |
2 | | | | | | | |
1 |_|_|_|_|_|_|_|
Si nous déposons un morceau en coll d
, il atterrira à l'emplacement 1d
.
a b c d e f g
6 | | | | | | | |
5 | | | | | | | |
4 | | | | | | | |
3 | | | | | | | |
2 | | | | | | | |
1 |_|_|_|#|_|_|_|
Si nous déposons à d
nouveau un morceau en coll , il atterrira à l'emplacement 2d
. Voici des exemples de 4 positions consécutives:
a b c d e f g
6 | | | | | | | |
5 | | | | | | | |
4 | | | |~| | | |
3 | | |~|#| | | |
2 | |~|#|~| |#| |
1 |~|#|~|#|_|#|_|
Dans ce cas, x
obtient 1 point en diagonale ( 1a 2b 3c 4d
).
a b c d e f g
6 | | | | | | | |
5 | | | | | | | |
4 | | | |#| | | |
3 | | | |#| | | |
2 | | | |#| | | |
1 |_|~|_|#|~|_|~|
Dans ce cas, o
obtient 1 point verticalement ( 1d 2d 3d 4d
).
a b c d e f g
6 | | | | | | | |
5 | | | | | | | |
4 | | | | | | | |
3 | | | | | | | |
2 | | |#|#|#|#| |
1 |_|_|~|~|~|~|~|
Dans ce cas, o
obtient 2 points horizontalement ( 1c 1d 1e 1f 1g
) et x
obtient 1 point horizontalement ( 2c 2d 2e 2f
).
a b c d e f g
6 | | |#| | | | |
5 | | |#| | | | |
4 | | |#| | | | |
3 | | |#| | |~| |
2 |~| |#| | |#|~|
1 |~|_|#|~| |~|~|
Cette fois x
obtient 3 points pour un 6 d'affilée ( 1c 2c 3c 4c 5c 6c
).
Entrée sortie
Vous aurez accès à la carte via un tableau 2D. Chaque emplacement sera représenté par un int
identifiant représentant un joueur. Vous aurez également votre identifiant de joueur transmis à votre fonction. Vous vous déplacez en retournant dans quel coll dans lequel vous voulez déposer votre pièce. Chaque tour 3 joueurs seront choisis pour jouer. À la fin de la partie, tous les joueurs auront joué une quantité égale de parties.
Pour le moment, des tours de 100k seront exécutés (notez que cela prend beaucoup de temps, vous voudrez peut-être le réduire pour un test de rotation rapide). Dans l'ensemble, le gagnant est le joueur qui a le plus de victoires.
Le contrôleur peut être trouvé ici: https://github.com/JJ-Atkinson/Connect-n/tree/master .
Écrire un bot:
Pour écrire un bot, vous devez étendre la Player
classe. Player
est abstraite et a une méthode pour mettre en œuvre, int makeMove(void)
. Dans, makeMove
vous déciderez dans quel coll vous souhaitez déposer votre pièce. Si vous avez choisi un coll invalide (par exemple coll n'existe pas, le coll est déjà rempli), votre tour sera ignoré . Dans la Player
classe, vous disposez de nombreuses méthodes d'aide utiles. Une liste des plus importants suit:
boolean ensureValidMove(int coll)
: Retourne vrai si le coll est sur le plateau et qu'il n'est pas encore rempli.int[] getBoardSize()
: Renvoie un tableau int où[0]
est le nombre de colonnes et[1]
le nombre de lignes.int[][] getBoard()
: Retournez une copie du tableau. Vous devriez y accéder comme ceci:[coll number][row number from bottom]
.- Pour trouver le reste, regardez la
Player
classe. EMPTY_CELL
: La valeur d'une cellule vide
Puisque ce sera multi-thread, j'ai également inclus une random
fonction si vous en avez besoin.
Débogage de votre bot:
J'ai inclus certaines choses dans le contrôleur pour simplifier le débogage d'un bot. Le premier est Runner#SHOW_STATISTICS
. Si cette option est activée, vous verrez une impression des groupes de joueurs joués, y compris le nombre de victoires du bot. Exemple:
OnePlayBot, PackingBot, BuggyBot,
OnePlayBot -> 6
PackingBot -> 5
BuggyBot -> 3
Draw -> 1
Vous pouvez également faire un jeu personnalisé avec la connectn.game.CustomGame
classe, vous pouvez voir les scores et le gagnant de chaque tour. Vous pouvez même vous ajouter au mélange avec UserBot
.
Ajout de votre bot:
Pour ajouter votre bot à la programmation, accédez au PlayerFactory
bloc statique et ajoutez la ligne suivante:
playerCreator.put(MyBot.class, MyBot::new);
Autres choses à noter:
- Les simulations sont multi-thread. Si vous souhaitez désactiver cela, allez sur
Runner#runGames()
et commentez cette ligne (.parallel()
). - Pour modifier le nombre de jeux, définissez-le
Runner#MINIMUM_NUMBER_OF_GAMES
à votre guise.
Ajouté plus tard:
- La communication entre les robots est interdite.
Connexes: jouez à Connect 4!
================================
Tableau de bord: (100 000 jeux)
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
================================
la source
Player
classe pour voir toutes les méthodes disponibles.ensureValidMove
(sauf si votre stratégie est de passer ce tour bien sûr).Réponses:
MaxGayne
Ce bot attribue un score à chaque position, basé principalement sur la longueur des parties connectées. Il regarde en profondeur 3 mouvements en inspectant les 3 mouvements les plus beaux à chaque étape, et choisit celui avec le score maximum attendu.
la source
UserBot
et votre bot était qu'après un certain point,MaxGayne
il perdrait des tours (par exemple, après 15 mouvements, il saute chaque tour jusqu'à la fin du jeu).javafx.util.Pair
ne fonctionne pas dans Eclipse car il n'est pas considéré comme faisant partie de l'API publique. Et je ne sais pas où cherchersun.plugin.dom.exception.InvalidStateException
. Vous vouliez probablement direjava.lang.IllegalStateException
.Pair
, c'est aussi proche que possible du type de données que je veux sans rouler le mien, donc à moins que l'éclipse ne compile pas, je pense que c'est OK. Quant au numéro 3, vous avez raison, ma saisie semi-automatique dans IntelliJ n'est pas toujours correcte. (la plupart du temps, c'est pourquoi je n'ai pas vérifié)Pair
problème empêche vraiment la compilation dans Eclipse, sauf si vous connaissez la solution de contournement .RowBot
Regarde dans toutes les directions et détermine la colonne optimale. Tente de relier ses pièces, tout en ne laissant pas ses adversaires faire de même.
la source
OnePlayBot
Ce bot n'a qu'un jeu - placez sa pièce dans la cellule la plus à gauche qui est valide. Assez curieusement, cela fait assez bien;)
la source
RandomBot
Il suffit de mettre un morceau n'importe où qui soit valide.
la source
StraightForwardBot
Semblable à OnePlayBot mais prend en compte le dernier mouvement et lit la colonne suivante sur celle qui est valide.
la source
JealousBot
Ce bot déteste l'autre joueur. Et il n'aime pas qu'il laisse tomber des morceaux sur la planche. Il essaie donc d'être le dernier à avoir déposé un morceau dans une colonne.
C'est ma première fois sur CodeGolf, donc j'espère que cette réponse sera assez bonne. Je n'ai pas encore pu le tester, alors veuillez m'excuser s'il y a des erreurs.
EDIT : Ajout d'une ligne pour briser la seconde
for
.EDIT 2 : Compris pourquoi l'
while
infini était. Il est maintenant terminé et peut être utilisé!la source
if(board[col][row]!=null && board[col][row]!=id)
devrait être changé enif(board[col][row]!=-1....
. Vérifiez game.Game.genBoard () dans le github d'OP si vous voulez en être sûr. Je ne sais pas non plus si turandom()
feras ce que tu veux, peut-être utiliser(int)Math.random()*col
?random()
méthode est enPlayer
classe! Je pense donc que cela fonctionnera =) Mais oui, je n'étais pas confiant dans mes conditions. Je n'ai pas trouvé comment il est défini dans le code OP, mais je vais vérifier à nouveau. Merci beaucoup!public double random() {return ThreadLocalRandom.current().nextDouble();}
. Je ne sais pas exactement comment cela fonctionne, mais je suppose qu'il renvoie une valeur comprise entre 0 et 1, il faudrait donc peut-être le faire(int)random()*col
:)nextDouble
renvoie un nombre entre0
et1
. Je l'ai inclus car les simulations sont exécutées en parallèle etMath.random()
ne sont pas thread-safe.BasicBlockBot
Un bot de bloc simple (et naïf). Il ne sait pas que vous pouvez faire un 4 de suite horizontalement ou en diagonale!
la source
Progressive
Progressive est ... progressive. Il aime regarder tout , et quelques - uns! (Je ne suis pas sûr de la méthodologie de cela. Cela a fonctionné contre un ami, une fois.) Et, pour une raison quelconque, cela fonctionne décemment.
la source
FairDiceRoll
Renvoie toujours 4.
la source
BuggyBot
Un échantillon de bot à battre (pour info: ce n'est pas difficile;)
la source
PackingBot
Ce bot ne vise pas directement des points. Il essaie d'emballer un maximum de jetons jusqu'à ce que le plateau soit rempli. Il a compris que monter et recommencer est stupide, alors il mettra au hasard des jetons autour de son "domaine".
Il devrait pouvoir obtenir des points dans toutes les directions, mais ce ne sera pas le meilleur!
(Pas testé)
la source
Steve
la source
BasicBlockBot
.