https://en.wikipedia.org/wiki/Connect_Four
Кто-нибудь помнит, как 2 игрока соединяют 4? Для тех, кто этого не делал, это была доска 6х7, которая стоит вертикально на поверхности. Цель подключения 4 - хорошо подключить 4! Соединение считается, если оно горизонтальное, диагональное или вертикальное. Вы помещаете свои фигуры на доску, вставляя фигуру в верхнюю часть колонки, где она падает до нижней части этой колонки. Наши правила меняют 3 вещи в Connect 4.
- Изменение № 1 Победа определяется как игрок с наибольшим количеством очков. Вы получаете очки, подключив 4, как в правилах - подробнее об этом позже.
- Изменение # 2 У вас есть 3 игрока в каждом раунде.
- Изменение № 3 Размер доски 9x9.
Подсчет очков:
Оценка основана на том, сколько вы получаете подряд. Если у вас 4 группы подряд, вы получаете 1 очко. Если у вас есть 5 в группе подряд, вы получаете 2 очка, 6 в строке 3 и так далее.
Примеры:
Обратите внимание o
и x
заменены на #
и ~
соответственно для лучшей контрастности
Пример пустой доски: (все примеры - доска стандартного размера для 2 игроков)
a b c d e f g
6 | | | | | | | |
5 | | | | | | | |
4 | | | | | | | |
3 | | | | | | | |
2 | | | | | | | |
1 |_|_|_|_|_|_|_|
Если мы бросим кусок в столкновении d
, он приземлится на месте 1d
.
a b c d e f g
6 | | | | | | | |
5 | | | | | | | |
4 | | | | | | | |
3 | | | | | | | |
2 | | | | | | | |
1 |_|_|_|#|_|_|_|
Если мы d
снова бросим кусок в столкновении , он окажется на месте 2d
. Вот примеры положения 4 в ряд:
a b c d e f g
6 | | | | | | | |
5 | | | | | | | |
4 | | | |~| | | |
3 | | |~|#| | | |
2 | |~|#|~| |#| |
1 |~|#|~|#|_|#|_|
В этом случае x
получает 1 балл по диагонали ( 1a 2b 3c 4d
).
a b c d e f g
6 | | | | | | | |
5 | | | | | | | |
4 | | | |#| | | |
3 | | | |#| | | |
2 | | | |#| | | |
1 |_|~|_|#|~|_|~|
В этом случае o
получает 1 очко по вертикали ( 1d 2d 3d 4d
).
a b c d e f g
6 | | | | | | | |
5 | | | | | | | |
4 | | | | | | | |
3 | | | | | | | |
2 | | |#|#|#|#| |
1 |_|_|~|~|~|~|~|
В этом случае o
получает 2 точки по горизонтали ( 1c 1d 1e 1f 1g
) и x
получает 1 точку по горизонтали ( 2c 2d 2e 2f
).
a b c d e f g
6 | | |#| | | | |
5 | | |#| | | | |
4 | | |#| | | | |
3 | | |#| | |~| |
2 |~| |#| | |#|~|
1 |~|_|#|~| |~|~|
На этот раз x
3 очка за 6 подряд ( 1c 2c 3c 4c 5c 6c
).
Ввод, вывод
У вас будет доступ к плате через 2d массив. Каждое место будет представлено с int
представлением идентификатора игрока. Вам также будет передан ваш идентификатор игрока в вашу функцию. Вы делаете свой ход, возвращая коллизию, в которую хотите бросить свою фигуру. В каждом раунде будут выбраны 3 игрока. В конце игры все игроки сыграют в равное количество игр.
На данный момент будет запущено 100 000 раундов (обратите внимание, что это занимает много времени, вы можете уменьшить его для быстрого тестирования). В целом победителем становится игрок с наибольшим количеством побед.
Контроллер можно найти здесь: https://github.com/JJ-Atkinson/Connect-n/tree/master .
Написание бота:
Чтобы написать бота, вы должны расширить Player
класс. Player
является абстрактным и имеет один метод для реализации int makeMove(void)
. В makeMove
вас будет решать , какие Coll вы хотели бы бросить свой кусок в. Если вы выбрали неверный колл (например, колл не существует, колл уже заполнен), ваш ход будет пропущен . В Player
классе у вас есть много полезных вспомогательных методов. Ниже приводится список наиболее важных из них:
boolean ensureValidMove(int coll)
: Вернуть true, если колл на доске и колл еще не заполнен.int[] getBoardSize()
Возвращает массив типа int, где[0]
количество столбцов и[1]
количество строк.int[][] getBoard()
: Вернуть копию доски. Вы должны получить доступ к нему , как это:[coll number][row number from bottom]
.- Чтобы найти остальное, посмотрите на
Player
класс. EMPTY_CELL
: Значение пустой ячейки
Так как это будет многопоточным, я также включил random
функцию, если вам это нужно.
Отладка вашего бота:
Я включил некоторые вещи в контроллер, чтобы упростить отладку бота. Первый Runner#SHOW_STATISTICS
. Если это включено, вы увидите распечатку сыгранных групп игроков, включая количество выигрышей ботов. Пример:
OnePlayBot, PackingBot, BuggyBot,
OnePlayBot -> 6
PackingBot -> 5
BuggyBot -> 3
Draw -> 1
Вы также можете сделать пользовательскую игру с connectn.game.CustomGame
классом, вы можете увидеть результаты и победителя каждого раунда. Вы даже можете добавить себя в смесь с UserBot
.
Добавление вашего бота:
Чтобы добавить своего бота в линейку, перейдите в PlayerFactory
статический блок и добавьте следующую строку:
playerCreator.put(MyBot.class, MyBot::new);
Другие вещи, чтобы отметить:
- Симуляции многопоточные. Если вы хотите отключить это, перейдите
Runner#runGames()
и прокомментируйте эту строку (.parallel()
). - Чтобы изменить количество игр, установите
Runner#MINIMUM_NUMBER_OF_GAMES
по своему вкусу.
Добавлено позже:
- Общение между ботами запрещено.
Связанный: Play Connect 4!
================================
Табло: (100 000 игр)
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
================================
источник
Player
класс, чтобы увидеть все доступные методы.ensureValidMove
(если ваша стратегия, конечно, не пройти этот поворот).Ответы:
MaxGayne
Этот бот присваивает оценку каждой позиции, в основном на основе длины соединенных частей. Он просматривает 3 хода глубоко, просматривая 3 наиболее привлекательных хода на каждом этапе, и выбирает тот, который имеет максимальный ожидаемый результат.
источник
UserBot
вашим ботом, заключалось в том, что после некоторого моментаMaxGayne
он выбрасывает ходы (например, после 15 ходов он пропускает каждый ход, пока игра не закончится).javafx.util.Pair
не работает в Eclipse, потому что он не считается частью общедоступного API. И я понятия не имею, где искатьsun.plugin.dom.exception.InvalidStateException
. Вы, наверное, имели в видуjava.lang.IllegalStateException
.Pair
, это настолько близко, насколько я могу получить к типу данных, который я хочу, не катя свои собственные, поэтому, если затмение не скомпилируется, я думаю, что все в порядке. Что касается # 3, вы правы, мое автозаполнение в IntelliJ не всегда верно. (в большинстве случаев именно поэтому я и не проверял)Pair
проблема действительно мешает компиляции в Eclipse, если вы не знаете обходной путь .RowBot
Смотрит во всех направлениях и определяет оптимальный столбец. Пытается соединить свои фигуры, не позволяя противникам делать то же самое.
источник
OnePlayBot
У этого бота только одна игра - поместите его фигуру в крайнюю левую ячейку, которая действительна. Как ни странно, это довольно хорошо;)
источник
RandomBot
Просто поместите кусок в любое место, которое действительно.
источник
StraightForwardBot
Аналогичен OnePlayBot, но учитывает последний ход и воспроизводит следующий действительный столбец.
источник
JealousBot
Этот бот ненавидит другого игрока. И ему не нравится, что он бросает фигуры на доске. Поэтому он пытается быть последним, кто бросил кусок в столбце.
Я впервые на CodeGolf, поэтому я надеюсь, что этот ответ будет достаточно хорошим. Я еще не мог проверить это, поэтому, пожалуйста, извините, если есть какие-либо ошибки.
РЕДАКТИРОВАТЬ : Добавлена строка, чтобы разбить второй
for
.РЕДАКТИРОВАТЬ 2 : выяснил, почему это
while
было бесконечно. Теперь он завершен и может быть использован!источник
if(board[col][row]!=null && board[col][row]!=id)
должны быть изменены наif(board[col][row]!=-1....
. Проверьте game.Game.genBoard () в github ОП, если хотите быть уверенным. Я тоже не знаю, если выrandom()
будете делать то, что вы хотите, может быть, использовать(int)Math.random()*col
?random()
Метод вPlayer
классе! Поэтому я думаю, что это сработает =) Но да, я не был уверен в своих условиях. Я не нашел, как это определено в коде OP, но я проверю снова. Большое спасибо!public double random() {return ThreadLocalRandom.current().nextDouble();}
. Я не знаю точно, как это работает, но я предполагаю, что он возвращает значение от 0 до 1, поэтому, возможно, потребуется это сделать(int)random()*col
:)nextDouble
возвращает число между0
и1
. Я включил его, потому что симуляции выполняются параллельно иMath.random()
не являются потокобезопасными.BasicBlockBot
Простой (и наивный) блочный бот. Он не знает, что вы можете сделать 4 в ряд по горизонтали или по диагонали!
источник
прогрессирующий
Прогрессивный ... прогрессивный. Ему нравится смотреть на все , а некоторые! (Я не уверен в методологии этого. Однажды это сработало против друга.) И по какой-то причине работает прилично.
источник
FairDiceRoll
Всегда возвращает 4.
источник
BuggyBot
Пример бота для вас, чтобы победить (FYI: это не сложно;)
источник
PackingBot
Этот бот не стремится напрямую к очкам. Он пытается собрать максимум жетонов, пока доска не заполнится. Он понимал, что просто подниматься снова и снова глупо, поэтому он будет случайным образом размещать токены вокруг своего «домена».
Он должен быть в состоянии получить некоторые очки во всех направлениях, но не будет лучшим!
(Не проверено)
источник
Стив
источник
BasicBlockBot
.