用于在Python中连接四个可能的移动生成的递归函数

时间:2017-06-13 19:05:40

标签: python recursion

我正在为我的学校项目编写一个连接四个AI。但首先,我要在编写minimax算法之前模拟6(行)* 7(列)上的每个可能的移动,以便为每个阶段的板完成最佳移动。 而不是使用

for a in range(7):
   place_player_disk()
   complete_set.append
   if check_win():
      continue
   for b in legal_move():
       place_AI_disk()
       complete_set.append
       if check_win()
          continue
       .... #repeat the nested for loop 42 times

我想用更简洁的方式来做这件事

state0=[['','','','','','',''],['','','','','','',''],['','','','','','',''],['','','','','','',''],['','','','','','',''],['','','','','','',''],['','','','','','','']]
complete_set=[[],[],[],[],[],[]...]
import copy
def playerplacetoken(perimeter,location):
      count=0
      for row in range(6):
          if perimeter[row][location]=='X' or perimeter[row][location]=='Y':
              count+=1
      perimeter[5-count][location]='X'
def full(perimeter):
    free = []
    for column in range(7):
    if perimeter[0][column] == '':
            free.append(column)
    return free
def PlacingCPUToken(perimeter,location):
    count=0
    for row in range (6):
      if perimeter[row][location]=='X' or perimeter[row][location]=='Y':
              count+=1
    perimeter[5-count][location]='Y'
def CheckP(perimeter):
    changerow=[0,1,1]
    changecolumn=[1,0,1]
    Pwin=False
        for col in range(7):
          for row in range (6):
            for change in range (3):
                try:
                    consecutivecount=0
                    for nochange in range(4):
                        if perimeter[row+(changerow[change]*(nochange))]     [col+(changecolumn[change]*(nochange))]=='X':
                            consecutivecount+=1
                        if consecutivecount==4:
                            Pwin=True
                except:
                    continue
    return Pwin
def CheckC(perimeter):
    changerow=[0,1,1]
    changecolumn=[1,0,1]
    Cwin=False
    for col in range(7):
        for row in range (6):
            for change in range (3):
                try:
                    consecutivecount=0
                    for nochange in range(4):
                        if perimeter[row+(changerow[change]*(nochange))][col+(changecolumn[change]*(nochange))]=='Y':
                            consecutivecount+=1
                        if consecutivecount==4:
                            Cwin=True
                except:
                    continue
    return Cwin
def recursive(state,move): #state: the state of board, first starts with an empty board and as the function loops, the state changes Move: no of moves taken by both the player and the computer

 for a in full(state):  #full returns a list of legal moves, which means columns that are not full
    state1= copy.deepcopy(state)
    playerplacetoken(state1, a)
    complete_set[move].append(state1)
    if CheckP(state1): #Check p returns boolean, checking if the player has won
        continue
    for b in full(state1):
        state2= copy.deepcopy(state1)
        PlacingCPUToken(state2, b)
        complete_set[move+1].append(state2)
        if CheckC(state2): #Check C checks if the computer wins and return a boolean
            continue
        while move<44:
            move+=2
            recursive(state2,move)
recursive(state0,0)

但这不能正常工作(我的意思是它没有错误,但结果不正确) 我真的不知道如何使用递归函数。请帮忙!

1 个答案:

答案 0 :(得分:0)

  • 您会对状态执行深层复制以计算进一步的移动。
  • 您为每个递归调用创建一个新的complete_set
  • 您永远不会return步骤recursive中的任何内容。

正因为如此,在嵌套步骤中计算出的信息无法进入调用步骤。

更新:状态确实是通过递归步骤更新的:complete_set[...].append(...)这样做,因为complete_set是全局的。

尝试考虑您尝试编写的函数的类型。

E.g。它需要一个状态和一个整数深度级别。它返回一个可能的移动列表,如果深度太大,则为空。

您可能真正想要的是移动的,其中列表的每个元素都是一对:(move, [...])。该列表包含相同类型的对:具有可移动子树的移动,等等。叶子有一组空的可能移动。

您可能会考虑在构建节点时正确计算即时效用函数值。

如果你使计算变得懒惰(使用yield和生成器),alpha-beta修剪也将变得易于实现。