Python中连接四种可能移动生成的递归函数

Python中连接四种可能移动生成的递归函数,python,recursion,Python,Recursion,我正在为我的学校项目编程一个connect-four 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()

我正在为我的学校项目编程一个connect-four 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)
state0=[['','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','']
完整的集合=[]、[]、[]、[]、[]、[]、[]、[…]
导入副本
def playerplacetoken(周界、位置):
计数=0
对于范围(6)中的行:
如果周长[行][位置]=“X”或周长[行][位置]=“Y”:
计数+=1
周长[5计数][位置]='X'
def满(周界):
免费=[]
对于范围(7)中的列:
如果周长[0][列]='':
free.append(列)
免费返回
def标牌CPUTOKEN(周界、位置):
计数=0
对于范围(6)中的行:
如果周长[行][位置]=“X”或周长[行][位置]=“Y”:
计数+=1
周长[5-计数][位置]='Y'
def CheckP(周界):
changerow=[0,1,1]
changecolumn=[1,0,1]
Pwin=False
对于范围(7)中的列:
对于范围(6)中的行:
对于范围的变化(3):
尝试:
连续计数=0
对于范围(4)内的无变化:
如果周长[row+(changerow[change]*(nochange))][col+(changecolumn[change]*(nochange))]='X':
连续计数+=1
如果连续计数==4:
Pwin=True
除:
持续
返回Pwin
def CheckC(周界):
changerow=[0,1,1]
changecolumn=[1,0,1]
Cwin=False
对于范围(7)中的列:
对于范围(6)中的行:
对于范围的变化(3):
尝试:
连续计数=0
对于范围(4)内的无变化:
如果周长[row+(changerow[change]*(nochange))][col+(changecolumn[change]*(nochange))]='Y':
连续计数+=1
如果连续计数==4:
Cwin=True
除:
持续
返回Cwin
def recursive(state,move):#state:棋盘的状态,首先从一个空棋盘开始,随着函数循环,状态改变move:no of move of player and computer
对于处于完整(状态)的列:#full返回合法移动的列表,这意味着列未满
state1=copy.deepcopy(state)
playerplacetoken(州1,a)
完成集合[move]。追加(状态1)
如果Check p(state1):#Check p返回布尔值,检查玩家是否获胜
持续
对于b完整(状态1):
state2=copy.deepcopy(state1)
发布CPUTOKEN(州2,b)
完成集合[move+1]。追加(state2)
如果检查C(状态2):#检查C检查计算机是否获胜并返回布尔值
持续
移动时
  • 你做了一个状态的深度拷贝来计算进一步的移动
  • 您可以为每个递归调用创建一个新的
    完整集
  • 递归
    步骤中,您永远不会
    返回任何内容
因此,嵌套步骤中计算的信息无法流到调用步骤

更新:状态确实是通过递归步骤更新的:
complete\u set[…]。append(…)
会这样做,因为
complete\u set
是全局的

试着想想你要写的函数的类型

例如,它采用状态和整数深度级别。它返回一个可能移动的列表,如果深度太大,则该列表为空

实际上,您可能需要一个移动树,其中列表中的每个元素都是一对:
(move,[…])
。该列表包含相同类型的成对移动:移动后可能出现的移动子树,等等。叶子有一组空的可能移动

您可以考虑在构建节点时立即计算实用程序函数值。


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

请发布一个完整的源代码,足以重现问题。这是否意味着我不能使用递归函数生成所有可能的移动?@HiBye:当然可以!你只需要从递归步骤中返回一些东西。但我不是通过将新生成的状态附加到完整的_集来返回东西吗?@HiBye:可能是这样,但我没有注意到!改变全球状态很难追踪,我就是没能追踪到。我正在更新我的答案。您还可以调用一些没有提供源代码甚至描述的函数。如果不了解算法的作用,很难判断算法是否正确。@9000我刚刚编辑了问题,以便包含完整的代码