如何为战舰中的船只生成统计上可能的位置

时间:2013-07-29 00:28:06

标签: python algorithm math statistics

我制造了原始战舰,现在我正在寻求将我的AI从随机猜测升级为统计猜测位置。我无法在线查找算法,所以我的问题是这个应用程序已经存在哪种算法?我将如何实现一个?

船舶:5,4,3,3,2

字段:10X10

板:

OCEAN = "O"
FIRE = "X"
HIT = "*"
SIZE = 10
SEA = [] # Blank Board
for x in range(SIZE):
    SEA.append([OCEAN] * SIZE)

如果你想看到剩下的代码,我在这里发布:(https://github.com/Dbz/Battleship/blob/master/BattleShip.py);我不想用很多不相关的代码来混淆这个问题。

4 个答案:

答案 0 :(得分:5)

最终的天真解决方案是通过每一个可能的船只安置(合法的信息已知)并计算每个方格已满的次数。

显然,在一个相对空白的董事会中,这不会起作用,因为有太多的排列,但一个好的开始可能是:

对于船上的每个方格:浏览所有船只并计算它在该方格中适合的方式,即每个方格的船长检查它是否适合水平和垂直。

如果其他船舶可以合法放置,同时覆盖所有已知的“撞击”(已知包含船舶的地方),则可以对每个可能的船舶放置进行检查。

为了提高性能,如果只有一艘船可以放置在给定的位置,则不再需要在其他位置进行测试。此外,当有许多“命中”时,首先覆盖所有已知的“命中”可能会更快,并且每个可能的封面都可以通过其余部分。

编辑:您可能想要查看DFS。

编辑:在评论中详细说明OP的(@Dbz)建议: 持有一套被解雇的船只('被解雇')的船只(可以表示为字符串,比如说"4V5x3"表示长度为4的船只在5x3,5x4,5x5,5x6中),在猜测之后你添加所有的猜测放置的位置,然后对于每个方格保持一组与它相交的放置('placements [x,y]'),则概率为: 34-|intersection(placements[x,y], dissmissed)|/(3400-|dismissed|)

要添加到已被删除的列表:

  1. 如果猜测(X,Y)是未命中添加placements[x,y]
  2. 如果猜测(X,Y)是一个命中:
    • 添加相邻的展示位置(假设船只不能相邻放置),即添加:
      • <(2,3a,3b,4,5)>H<X+1>x<Y><(2,3a,3b,4,5)>V<X>x<Y+1>
      • <(2,3a,3b,4,5)>H<X-(2,3,3,4,5)>x<Y><(2,3a,3b,4,5)>V<X>x<Y-(2,3,3,4,5)>
      • 2H<X+-1>x<Y+(-2 to 1)>3aH<X+-1>x<Y+(-3 to 1)> ...
      • 2V<X+(-2 to 1)>x<Y+-1>3aV<X+(-3 to 1)>x<Y+-1> ...
    • 如果|intersection(placements[x,y], dissmissed)|==33,即只有一个展示位置可以添加(见下文)
  3. 检查是否有任何预览点击只剩下一个可能的位置,如果是,请添加船
  4. 检查是否有任何船只只有可能的位置,如果是,请添加船
  5. 添加船只:

    • 将该船的所有其他展示位置添加至已解散
    • 对于船舶展示位置的每个(x,y)添加placements[x,y]而不包含实际展示位置
    • 对于船舶放置标记的每个(x,y)作为命中猜测(如果尚未知道)运行阶段2
    • 对于每个(x,y)相邻的船舶放置标记作为未命中猜测(如果尚未知道)运行阶段1
    • 第3阶段和第4阶段。

    我可能已经过度复杂了,可能会有一些冗余的行动,但你明白了。

答案 1 :(得分:2)

很好的问题,我喜欢你对统计方法的想法。
我想我会尝试machine learning解决这个问题的方法如下:

首先将您的问题建模为classification problem
分类问题是:给定一个方格(x,y) - 你想知道在这个方格中有一艘船的可能性。让这个可能性为p

接下来,您需要开发一些功能&#39;。您可以将(x,y)的周围[因为您可能对其有部分了解]作为您的功能。

例如,以下迷你电路板中间的功能(+表示您想要确定是否有船的正方形):

OO*
O+*
?O?

可以是:

f1 = (0,0) = false
f2 = (0,1) = false
f3 = (0,2) = true
f4 = (1,0) = false
**note skipping (1,1)
f5 = (1,2) = true
f6 = (2,0) = unknown
f7 = (2,1) = false
f8 = (2,2) = unknown

我实现了相对于原点的功能(在这种情况下为(1,1)),而不是船上的绝对位置(因此(3,3)之前的正方形也将是f2)

现在,创建一个训练集。训练集是一个标记为&#39;一组功能 - 基于一些真正的主板。您可以手动创建它(创建大量的电路板),通过随机的放置生成器或您可以收集的其他数据自动创建。

将训练集提供给学习算法。该算法应该能够处理未知数&#39;并且能够给出&#34; true&#34;的概率。而且不仅仅是一个布尔答案。我认为Naive Bayes的变体可以很好地适应这里。

获得分类器后 - 将其与AI一起使用。
轮到你时,选择射击最大值为p的正方形。首先,镜头将是随机的 - 但是你射击更多的镜头,你将获得更多关于棋盘的信息,AI将利用它来进行更好的预测。


请注意,我根据大小为1的正方形提供了功能。您当然可以选择任何k并在这个更大的广场上查找功能 - 它会为您提供更多功能,但每个功能可能都不太准确。没有经验法则会更好 - 而且应该进行测试。

答案 2 :(得分:1)

主要问题是,您如何找到统计上可能的位置。他们已经知道了,或者你想弄明白吗? 无论哪种情况,我只是让网格称重。在您的情况下,每个插槽的初始权重为1.0 /(SIZE ^ 2)。权重之和必须等于1。 然后,您可以根据从N个最后一场比赛中收集的统计数据调整权重。 现在,当您的AI做出选择时,它会根据加权概率选择一个坐标。快速而简单的方法是:

  1. 在[0..1]

  2. 范围内生成随机数R.
  3. 从插槽(0,0)开始添加权重,即S = W(0,0)+ W(0,1)+ ....其中W(n,m)是权重相应的插槽。一旦S&gt; = R,你就得到了要点击的坐标。

  4. 这可以通过预先计算每一行的累积权重进行优化,玩得开心:)

答案 3 :(得分:1)

  • 找出哪些船还活着: alive = [2,2,3,4]#活船长度
  • 找出你没有拍摄的地方,例如使用numpy.where()
  • 环绕可以拍摄的地方。
  • 检查给定位置的两侧。左右走,有多少个空格?上下,有多少个空格?如果你可以在很多空间里安装一艘船,那么你可以安装任何较小的船,所以这个循环我是从最大的船向下进行的,而且我会在这个位置增加+1,因为船只较小比那个适合的。
  • 一旦完成了所有这些操作,具有更多分数的位置应该是最有可能攻击并击中的东西。

当然,它可以变得像你想要的那么复杂。你也可以问自己,而不是我的下一个命中,哪些命中组合将给我带来更少的命中数或任何其他组合/参数化问题的胜利。祝你好运!