2016-01-13 107 views
1

我有一个动态列表存储领域的协调和该领域的所有者如何使用动态列表在递归函数中的Prolog

这个名单的
:-dynamic 
    board/2. 

一个条目看起来像这样:

board(e4,[w]). 

还有22个看起来相似的板子位置。

我想实现一个AI的游戏董事会的目的。 我正在使用alpha测试版算法,因此必须创建新的“板子”来回避这种情况。

我原板的副本来工作,但现在有一个功能调节板当前的举动是这样的:

move(position,boardOld,boardNew) 

这是在第二个电话boardOld称为递归因此等于boardNew和boardNew是分析中下一步行动的老板。

我的想法是旧抄板在每次迭代,但我不知道如何做到这一点,因为这

copy_predicate_clauses(boardOld(A,B),boardNew(A,B)). 

将旧的董事会,因为名单已经存在添加到newBoard。

我使用以下算法(无法复制它,因为它是一个图像):

http://www.cuceinetwork.net/archivos/prolog/The_Art_of_Prolog.pdf

PDF页面445(书页407)。

该算法在初始化时将位置定义为'Board',我不知道如何使用我的列表执行此操作,此外,子句移动(Move,Position,Position1)返回当前移动的新Board。这被称为递归,我不知道如何为position1创建电路板而不覆盖之前的电路板。

编辑//

好的,我得到了问题。但是我在游戏中已经使用了这个谓词,并且不想全部改变。我这样做:

findall((X,Y),board(X,Y),CurrentBoard). 

CurrentBoard给了我这样的

[(e4,[w,w]),(g4,[s,w]),(b7,[r,w,s])] 

列表现在我不能用我的方法来确定可能的行动。

我有一个像

move(e4,d5). 
move(d5,e6). 

说明哪些举动事实(从,到)是可能的,现在我想这

findall((X,Y),listMoves(CurrentBoard,X,Y),possibleMoves). 

像这样的东西。在这一点上,我很困难。我如何生成可能的移动列表。我不知何故必须从currentBoard获取X坐标,检查来自该坐标的列表头(该坐标上的棋子)是否属于我,并检查Y坐标(to)是否空闲。

listMoves([Coordinate|[Head|Tail]], X, Y) :- 
    move(X,Y), 
    ownField(X,Coordinate,Head), 
+0

鉴于缺乏细节,这很难回答(如果不是不可能的话)。 –

+0

我将编辑问题并分享更多详细信息 – Sven182

+0

您的问题是您试图将动态存储作为列表处理(您自己这么说,但“board/2”是谓词,而不是列表),它不是列表真的不适合这个目的。你最好为你的棋盘状态制定明确的列表并传递给你,因为操纵实际列表比在动态存储中操纵事实要容易得多。 –

回答

1

如果从(打印)401页阅读,作者勾勒出基本的游戏算法:

play(Game) :- 
     initialize(Game, Position, Player), 
     display_game(Position, Player), 
     play(Position, Player, Result). 

节的其余部分使用的术语“位置”让我相信他们指的是游戏的整个状态。对于象棋这样的游戏,这将是棋盘本身的状态:棋子在哪里。

从那里,作者继续讨论move/2move/3,这些正是如此定义:

可以很方便地通过move/3

移动的选择由 choose_move/3从其分离执行

然后在403页上,

谓词如果Move是从当前位置可能的移动,则为10。

总之,这一切都表明,我认为他们期望Position是完整的国际象棋棋盘(我想你下棋,对吗?),并Move是一个合法的举动,为的目的定义move/2,然后move/3只是move/2,返回结果板。换言之,初始棋盘可能是这个样子:

starting_board([[b-r, b-b, b-n, b-q, b-k, b-n, b-b, b-r], 
       [b-p, b-p, b-p, b-p, b-p, b-p, b-p, b-p], 
       [nil, nil, nil, nil, nil, nil, nil, nil], 
       [nil, nil, nil, nil, nil, nil, nil, nil], 
       [nil, nil, nil, nil, nil, nil, nil, nil], 
       [nil, nil, nil, nil, nil, nil, nil, nil], 
       [w-p, w-p, w-p, w-p, w-p, w-p, w-p, w-p], 
       [w-r, w-b, w-n, w-q, w-k, w-n, w-b, w-r]]).  

这是怎么了,我可能将它设置;无疑可能有更高效或更明智的做法,但问题是,你的价值观应该总是像这样包含整个董事会的状态。事实上,它可能需要包括其他信息,比如谁的轮到它,或者如果你想记录每一个移动的日志,你也可以把它扔到那里。

从这里,你准备写move/2move/3。我会倾向于(为了教学目的)写move/3并使用它来构建move/2,但为了提高效率,您可能需要单独执行它们。我在国际象棋上已经够坏了,所以我要在这里停下来(我不相信你会下棋)。但基本上,你想看到move(StartPosition, Move, NewPosition),作为一个开始位置,将统一Move与某种简短的描述移动和NewPosition与整个董事会的状态后,这样做,所以你得到一个前 - 快照后。

一旦你建立了这些部分,我认为你可以主要使用书本原样。

我想你基本上有几个误区:

  1. 该主板不能与多个解决方案的断言。这是一个您创建的数据结构,代表了正在发生的事情的整个故事。
  2. 动态谓词不会形成一个列表。确实,您可以拥有多个解决方案并且他们有订单,但对于您需要执行的各种操作来说,这并不是一个方便的数据结构。
  3. 我真的不认为你想把这两个想法混合在一起,看看会发生什么。