포커 페이스
소개
Leo는 포커 게임을 즐기지 만 Tech Inc.에서 일하는 것은 자신이 잘 플레이하는 방법을 배우기에는 너무나 까다 롭습니다. 컴퓨터 과학자 인 Leo는 낙담하지 않습니다. 그는 포커를 배우는 데 걸리는 시간보다 시간이 더 걸리고 포커 봇을 작성하여 더 나은 경기를 펼치기로 결정합니다. 그러나 이제 레오에게는 문제가 있습니다. 조금 더 잘 플레이하는 방법을 이해하기 위해 레오는 여러 "사람"의 여러 게임을 관찰해야하지만 "사람"은 게임의 품질과 현실을 향상시키기 위해 다른 플레이 스타일이 필요합니다.
도전
Leo는 실제로 프로그래밍 문제를 다루는 웹 사이트가 있다는 것을 기억하고 귀하의 도움을 모으고 있습니다! 당신의 임무는 "Pokerface"5 카드 포커의 수정 된 버전을 재생하는 프로그램을 작성하는 것입니다. 프로그램은 원하는 형식으로 5 장의 카드로 입력되며 그 후에 프로그램이 출력됩니다.
- 플레이어가 카드를 교환하려는 경우 정확히 (대소 문자 구분) "true" "1"또는 "t", 그렇지 않은 경우 비어 있지 않은 다른 출력.
- 참이면, 플레이어가 교환하고자하는 카드 및 / 또는 카드 이름의 색인 목록.
- 0에서 3 사이의 단일 숫자로, 플레이어가 원하는 추가 카드 수를 지정합니다.
- 플레이어가 사용하고자하는 손을 인쇄하십시오.
(아래 서식 참조)
포커 페이스 규칙
- pokerface는 텍스트 기반 어드벤처 게임이므로 카드를 일관된 방식으로 제시해야합니다. 카드는 두 개의 문자 코드로 표시되며 첫 번째 문자는 정장이고 두 번째 문자는 카드 이름입니다.
- 카드 :
- 2-9 = 2-9
- 10 = T
- 잭 = J
- 여왕 = Q
- 왕 = K
- 에이스 = A
- 양복들:
- 스페이드 = S
- 클럽 = C
- 하트 = H
- 다이아몬드 = D
- 카드 :
스페이드 에이스는 SA, 하트 10은 HT, 다이아몬드 4는 D4 등입니다.
- Pokerface의 단일 라운드는 4 단계로 구성됩니다 :
- 덱이 개편되고 각 플레이어는 5 장의 카드를받습니다.
- 각 플레이어는 원하는만큼 카드를 교환 할 수 있습니다.
- 각 플레이어는 최대 3 장의 카드를 더 얻을 수 있습니다.
- 각 플레이어는 최선의 핸드를 공개해야합니다.
- 최고의 핸드가 이기고 그 플레이어에게 점수를 얻습니다. 동점 일 경우 두 선수 모두 점수를받습니다.
- 한 번의 게임에서 10 라운드가 플레이되고 가장 많은 점수를 얻은 플레이어가 승리하고 하나의 "승점"을 얻습니다. 동점 일 경우 두 선수 모두 승점을 얻습니다.
- 레오는 실제로 많은 돈을 가지고 있지 않기 때문에 봇은 이것이 내기가없는 완벽한 세상이라고 가정 할 수 있습니다.
소유
입출력
- Leo는 Java 만 알고 있으므로 프로그램은 Process API (명령 줄) 를 통해 실행 가능해야하며 입력 및 출력에 각각 STDIN 및 STDOUT을 사용해야합니다.
- 위에서 설명한 각 입력 및 출력 단계마다 입력 및 출력이 각각 한 줄에 존재해야합니다.
- 최종 출력 후 하나 이상의 후행 줄이 있어야합니다. (이것은 STDIN에서 입력을 읽는 방식 때문입니다)
- 후행 및 선행 공간 이외의 외부 입출력은 허용되지 않습니다. 파서는 단순히 같은 것들을 이해하지 않습니다
final_hand=...
또는draw 0
. - 그림을 그릴 때, 출력은 단일 정수이고, 출력을 교환 할 때 아래에 정의 된 정수 및 / 또는 카드 목록이고, 원래 손을 처리 할 때 출력은 아래에 정의 된 카드 목록입니다.
- 모든 입력 / 출력 숫자는 10 진수의 양의 정수 여야합니다.
- 카드 입력 형식을 정의 할 수 있습니다 (아래 게시 형식 참조).
- True는 정확히 "true", "1"또는 "t"로 정의되며 false는 비어 있지 않은 다른 값입니다.
- 교환 단계 중 :
- 카드 인덱스가 그들 사이에 적어도 하나 개의 공간을 출력해야합니다 (예를 들어
3 4 0
) - 카드 이름은 그들 사이에 적어도 하나 개의 공간을 출력해야합니다 (예를 들어
H4 S8
) - 카드 이름과 인덱스가 출력에 혼합 될 수있다 (예를 들어
0 H7 3 D3
) - 후행 및 선행 공간이 허용됩니다.
- 위의 결과를 출력 한 플레이어의 결과는
bot.jlsc
요청한 순서대로 파일에 지정된 형식으로 지정됩니다.
- 카드 인덱스가 그들 사이에 적어도 하나 개의 공간을 출력해야합니다 (예를 들어
- 플레이어가 자신의 손에 추가하고자하는 카드의 수는 앞뒤 공백을 가질 수 있습니다.
- 손 사이에 최소한 하나의 공간 (예
H4 D5 CA
:)을 두고 출력해야하며 , 후행 공백과 선행 공백이 허용됩니다. - 손은 적절한 순서로 출력 할 필요 (예를하지 않는
H4 D4 C4 DA SA
및H4 DA D4 SA C4
모두 대표 4, 4, 4, 풀 하우스입니다 에이스, 에이스,). - 상대방의 손을 분석하여 전략을 세우려면
<botname>/data
디렉토리에 데이터를 저장할 수 있습니다 .- 경쟁하는 봇이 자신의 손을 표시 한 후에는 모든 봇 데이터 디렉토리에 hands.txt에 각 줄이 새 줄로 표시됩니다 (\ n으로 구분). 파일은 US_ASCII로 인코딩됩니다.
- 봇이 새 카드 또는 교환 카드를 요청하면
bot.jlsc
파일 에서 지정한 형식에 따라 카드가 입력 됩니다.
포스트 형식
- 모든 게시물에는 다음 두 가지가 포함되어야합니다.
- 봇의 소스 코드 또는 공개 저장소에 대한 링크입니다.
- 다음을 포함하는 zip 파일 :
- 봇의 컴파일 / 실행 가능한 버전 (파일이 .exe 또는 컴파일 할 수없는 기타 파일 인 경우 게시물에 컴파일 지침을 포함하십시오).
bot.jlsc
파일, 아래 (보조 노트를 다음 .jlsc 확장 단지 때문에 내 측면 프로젝트, 구성 형식입니다 일치 아래의 파일을 적절한 구문을, 너무 걱정하지 않습니다.)를 참조하십시오.
- .zip 파일의 이름은 봇과 동일해야합니다.
- Windows 또는 다른 압축 유틸리티에 액세스 할 수 없거나 어떤 이유로 든 .zip을 만들 수없는 경우 게시물에 bot.jlsc 파일의 텍스트를 포함하십시오.
bot.jlsc 파일 :
name= "Botty"
link= "example.com"
cmd= "java -jar Botty.jar"
input_hand= "${0} ${1} ${2} ${3} ${4}"
input_1= "${0}"
input_2= "${0} ${1}"
input_3= "${0} ${1} ${2}"
input_4= "${0} ${1} ${2} ${3}"
어디:
- "cmd"는 봇을 실행하기 위한 Windows 명령 행 명령입니다. 봇은 directory
<botname>
에 있으므로 명령을 적절히 조정하십시오. - "name"은 봇의 이름입니다.
- "link"는 귀하의 답변에 대한 링크입니다. 게시 후이를 수정해야합니다.
- "input_hand"은 원래 거래 형식을 지정하는 방법입니다 (카드 0-4를 나타내는 $ {#}).
- "input_1"은 하나의 추가 카드 입력 형식을 지정하는 방법입니다.
- "input_2"는 두 개의 추가 카드 입력을 포맷하는 방법입니다.
- "input_3"은 세 개의 추가 카드 입력을 포맷하는 방법입니다.
- "input_4"는 4 개의 추가 카드 입력을 포맷하는 방법입니다.
사양
- 이러한 허점은 허용되지 않습니다 ( '일반적인 함정'참조)
- 규칙 세트 내에서 항상 최상의 핸드를 출력하는 봇을 작성할 수는 없습니다. (즉, 오래 실행되는 무차별 봇은 없으며 LeoBot만큼 '좋은'것은 없어야합니다)
- 봇은 ~ 100ms 이하로 실행되어야합니다 (이 시점에서 최소, 최대 ~ 1 초).
- 선택한 핸드 이후 봇의 출력은 무시됩니다.
- 표준 허점은 허용되지 않습니다.
- 예, 리눅스가 더 낫다는 것을 알고 있지만 Windows PC가 있으므로 프로그램의 컴파일 / 실행 가능한 버전을 Windows 명령 줄에서 실행할 수 있는지 확인하십시오.
- 컴퓨터에 이미 python과 java가 설치되어 있지만 새 버전으로 업데이트하고 다른 환경을 설치하려고하므로 프로그램에 필요한 환경 유형을 지정하십시오.
- 모든 경우에 다른 봇과 동일한 기능을 수행하는 봇을 작성할 수는 없습니다. 스팸 봇은 허용되지만 사용하지 않는 것이 좋습니다.
- 봇은 가지고있는 카드 만 사용할 수 있습니다. 교환을 통해 잃어 버렸거나 시작하지 않은 카드는 최종 핸드에서 유효하지 않은 출력입니다.
- 입력 및 출력에는 ASCII 문자 만 포함될 수 있습니다.
토너먼트
- 시간이되면 토너먼트가 진행됩니다 (스케줄은 레오와 거의 비슷하기 때문에 조금 드문 일입니다. 불편을 끼쳐 드려 죄송합니다).
- 봇은 4 인 게임에서 서로에 맞서 싸울 것이며, 봇의 각 하위 세트 (즉, 많은 게임)에 대해 하나의 게임이있을 것입니다.
- 이 과정은 5 번 반복됩니다.
- 토너먼트 처리기가 봇 그룹을 만드는 방식으로 인해 최대 3 개의 필러 봇이 추가되어 봇 수를 4로 나눌 수 있습니다.이 봇은 원래 처리 된 핸드를 반환합니다.
- 모든 라운드와 게임이 실행 된 후, 봇의 점수는 그들이이긴 게임 수에 따라 계산됩니다.
- 여러 봇이 위치를 공유 할 수 있습니다 (처음 게시 된 첫 번째 원과의 관계).
- 토너먼트가 끝나면 점수가이 게시물의 하단에 추가됩니다.
채점
정상적인 KoTH 규칙. 가장 많은 게임에서이기는 봇이 도전에 이깁니다.
레오 봇
레오의 봇은 꽤 똑똑합니다. 그것은 어떤 카드도 교환하지 않고 너무 어렵지만 최대 수의 추가 카드를 요구하며 가능한 한 가장 좋은 핸드를 결정하고 그 핸드를 플레이합니다. leobot의 주요 논리는 다음과 같습니다.
package com.gmail.socraticphoenix.pokerface.leobot;
import com.gmail.socraticphoenix.pokerface.lib.card.Card;
import com.gmail.socraticphoenix.pokerface.lib.card.Deck;
import com.gmail.socraticphoenix.pokerface.lib.rule.HandRegistry;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class LeoBot {
public static void main(String[] args) {
List<Card> hand = new ArrayList<>();
Scanner scanner = new Scanner(System.in);
hand.addAll(Card.parseHand(scanner.nextLine()));
System.out.println(false);
System.out.println(3);
hand.addAll(Card.parseHand(scanner.nextLine()));
List<List<Card>> possibleHands = LeoBot.getSubsets(hand, 5);
System.out.println(Deck.toString(possibleHands.stream().sorted((a, b) -> HandRegistry.determineWinner(b, a).comparable()).findFirst().get()));
}
private static <T> void getSubsets(List<T> superSet, int k, int idx, List<T> current, List<List<T>> solution) {
if (current.size() == k) {
solution.add(new ArrayList<>(current));
return;
}
if (idx == superSet.size()) return;
T x = superSet.get(idx);
if (!current.contains(x)) {
current.add(x);
}
getSubsets(superSet, k, idx + 1, current, solution);
current.remove(x);
getSubsets(superSet, k, idx + 1, current, solution);
}
public static <T> List<List<T>> getSubsets(List<T> superSet, int k) {
List<List<T>> res = new ArrayList<>();
getSubsets(superSet, k, 0, new ArrayList<T>(), res);
return res;
}
}
LeoBot가 지속적으로 토너먼트에서 우승하고 참가 인원이 많으면 달리기를 중단합니다.
중요한 링크
기권
Leo and Tech Inc.는 스토리 요소 이며 실제 회사 나 사람들과의 유사성은 순전히 의도하지 않습니다. (그러나 레오의 '상황'은 질문에서 조건을 더하거나 빼면 실제로 질문의 일부입니다.)
"f"q+
은 최소 요구 사항을 충족합니다. 경쟁에 10 명이있는 경우, 이것은 아마도 벙어리가 아닌 모든 항목을 이길 것입니다. (먼저옵니다)). 따라서이 도전에서 codegolf를 제거해야합니다