我喜欢玩Ticket to Ride,所以我决定尝试在 Python 中实现部分游戏逻辑作为辅助编程项目。游戏板本质上是一个加权多重图,因此使用NetworkX复制游戏的基本结构是轻而易举的事。
我遇到麻烦的一个部分是分析在给定玩家拥有的火车卡清单的情况下是否有可能通过棋盘的特定路径。我认为这更像是一个数学问题,而不是编程问题本身,我可能可以拼凑出一种蛮力方法来解决问题,但认为必须有一种更有效的方法。
对于那些不了解游戏的人:在任何给定时间,每个玩家都有一些八种颜色中的一种的火车卡,以及一个特殊的“机车”类别,用作外卡。这些颜色与游戏板上的火车线颜色相对应(此处显示),除了灰色线,您可以使用任何颜色,只要该段中的所有汽车颜色相同即可。(有一些涉及隧道和渡轮的极端案例,但我们暂时将它们放在一边。)
使用现在的代码,我可以找到两个给定城市之间的所有路径,并返回需要多少每种颜色的火车卡才能走这条特定的路径,除非路径涉及灰色段。我先做非灰色部分,因为它们更简单——路径中的每个红色/绿色/蓝色部分都有足够的红色/绿色/蓝色卡片,或者你没有。使用灰色,因为您可以为每个部分选择任何颜色,它会涉及更多。
对于只有一个灰色段的路径,它仍然很容易——要么你有足够的任何一种颜色的卡片来填充它,要么没有。但是,对于多个灰色段,可能会遇到为第一段选择的颜色无法完成第二或第三段的情况。
举个例子,假设一个玩家的卡牌库存是 4 红色,2 绿色,3 蓝色,我们试图弄清楚他是否可以从巴黎到维也纳。看图板,很容易看出这张卡组合的唯一可能路线是去巴黎--(3灰色)-->苏黎世--(2绿色)-->威尼斯--(2灰色)-- > Zagrad --(2 灰色)--> 维也纳。我的算法从绿色部分开始,并在那里分配两张绿卡。然后它需要决定如何使用剩余的 4 张红卡和 3 张蓝卡来覆盖长度为 3、2 和 2 的灰色段。
答案当然是使用巴黎和苏黎世之间的 3 张蓝卡,威尼斯到萨格拉德和萨格拉德到维也纳各两张红卡。但是,对于涉及更多颜色和更多段的不太明显的情况,如何编写一个通用算法来解决这个问题呢?
我的代码现在看起来像这样:
def can_afford(path, cards):
grays = list()
for segment in path:
if segment.color == 'Gray':
grays.append(segment)
else:
if cards.get(segment.color, 0) >= segment.weight:
cards[segment.color] -= segment.weight
else:
return False
for gray in grays:
# Halp!
pass
return True
(“重量”是火车车厢中段的长度。)
我觉得这里潜伏着一个非常微不足道的解决方案,我无法指望。有任何想法吗?