扑克脸
介绍
Leo喜欢玩扑克,但是他在Tech Inc.的工作要求他学习如何打法。不反对作为计算机科学家的Leo。他决定花更多的时间来学习扑克,并用它编写一个扑克机器人来帮助他玩得更好。但是现在,狮子座遇到了一个问题:为了了解如何更好地玩游戏,狮子座需要观察由多个“人物”组成的多个游戏,但是“人物”需要不同的游戏风格来提高游戏的质量和真实性。
挑战
Leo回忆说,实际上有一个致力于编程挑战的网站,正在寻求您的帮助!您的工作是编写一个程序,玩“ Pokerface”(五张扑克)的修改版。该程序将以您希望的任何格式将其输入为5张牌,然后程序将输出:
- 如果玩家希望交换纸牌,则完全(区分大小写)为“ true”,“ 1”或“ t”,否则为任何其他非空输出。
- 如果为true,则显示玩家希望交换的卡片索引列表和/或卡片名称。
- 0到3之间的一个数字,指定玩家需要多少张额外的纸牌。
- 打印出玩家希望使用的手。
(请参见下面的格式)
扑克规则
- 由于pokerface是基于文本的冒险游戏,因此必须以一致的方式提供卡片。卡用两个字符代码表示,第一个字符是西服,第二个字符是卡的名称。
- 牌:
- 2-9 = 2-9
- 10 = T
- 杰克= J
- 皇后= Q
- 国王= K
- ace = A
- 西装:
- 黑桃= S
- 球杆= C
- 心= H
- 钻石= D
- 牌:
所以黑桃的王牌是SA,红心的10是HT,钻石的第4是D4,依此类推。
- 一轮Pokerface包含四个步骤:
- 重新洗牌,向每位玩家发五张牌。
- 每个玩家都有机会交换任意数量的卡。
- 每个玩家都有机会再获得最多三张牌。
- 每个玩家都必须展现自己的最佳手牌。
- 最佳牌手获胜,并获得该玩家的积分。如果出现平局,两位选手都将获得积分。
- 在一个游戏中,进行了十轮比赛,得分最高的玩家获胜并获得一个“胜利点”。如果出现平局,则两个玩家都将赢得一个胜利点。
- Leo确实没有很多钱,因此您的机器人可以认为这是一个没有下注的完美世界。
手
- 手的长度正好是5张牌(初始输入和最终输出)。
- 双手的排名与此处所述规则一致。
输入输出
- 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,Ace,Ace,这是满屋子)。 - 如果您希望通过分析对手的手来制定策略,则可以将数据存储在
<botname>/data
目录中。- 竞争的机器人显示了其手之后,它们将被写入hands.txt中的每个bots数据目录,并且每只手都换行(由\ 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命令行命令。请注意,您的漫游器将位于目录中
<botname>
,因此请相应地调整命令。 - “名称”是您的机器人的名称。
- “链接”是您答案的链接,发布后您必须对其进行编辑。
- “ input_hand”是您希望格式化原始交易的方式($ {#}代表卡0-4)。
- “ input_1”是您希望格式化另一张卡的输入的方式。
- “ input_2”是您希望格式化另外两个卡的输入的方式。
- “ input_3”是您希望格式化三张附加卡的输入的方式。
- “ input_4”是您希望格式化四个附加卡的输入的方式。
细节
- 这些漏洞是不允许的(请参阅“常见陷阱”)
- 您可能没有写过机器人,它总是会在规则集中每次都输出最佳手牌。(即没有长期运行的暴力机器人,没有什么比LeoBot的“好”了)
- 您的漫游器应在〜100毫秒或更短的时间内运行(此时的延迟时间,最长为〜1秒)
- 机器人在其选择的手之后的任何输出都将被忽略。
- 不允许出现标准漏洞。
- 是的,我知道linux更好,但是我有Windows PC,因此请确保可以从Windows命令行运行程序的编译/可执行版本。
- 我已经在计算机上安装了python和java,但是我愿意更新到新版本并安装其他环境,因此请指定程序所需的环境类型。
- 您可能不会编写一个在任何情况下都与另一个机器人做相同事情的机器人。允许使用垃圾邮件漫游器,但不鼓励使用。
- 您的机器人只能使用其拥有的卡。通过交换丢失的卡或未开始处理的卡在最后一手无效输出。
- 输入和输出只能包含ASCII字符。
比赛
- 我会在有时间的时候进行比赛(我的日程安排几乎和Leo一样,所以我很少见。对于给您带来的不便,我们深表歉意。)
- 机器人将在4人游戏中互相对峙,每个可能的机器人子集(即很多游戏)都会有一个游戏。
- 此过程将重复五次。
- 由于锦标赛处理程序将机器人进行分组的方式,最多将添加三个加注机器人,以使机器人的数量被4整除。这些机器人将简单地返回最初处理的手。
- 每轮比赛结束后,将根据机器人赢得的比赛次数来计算机器人的得分。
- 多个机器人可以共享一个职位(按先发先赢的平局)。
- 比赛结束后,分数将附加到该帖子的底部。
计分
正常的KoTH规则。赢得最多游戏的机器人赢得了挑战。
狮子座
Leo的机器人非常聪明。它不交换任何卡,这太难了,但是它确实要求最大数量的附加卡,并且它决定了它可以做出的最佳手牌,并使用该手牌。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和Tech Inc.是故事元素,与现实生活中的公司或人员的任何相似之处纯属无意之举。(但是,当Leo的“情境”在问题中添加或减去条件时,这些实际上就是问题的一部分...)
"f"q+
满足了最低要求。如果比赛中有10个人,则这可能会击败所有非哑项(非哑项可能具有> 75个字符,5 * 10(哑机器人分数,倒数第二)= 50 <75(非常小的智能机器人分数) (先到))。因此,您可能应该从此挑战中删除代码高尔夫