2017-02-11 4 views
2

현재 Python TicTacToe 게임용 AI를 구현하려고합니다. 하나의 상황을 제외하고 모든 것이 크게 수행됩니다. 내 현재 코드 :Python TicTacToe minimax가 잘못된 옵션을 선택했습니다.

def testLine(line): 
    ''' 
    ' :param line: Liste containing 3 ints 
    ' :return: 1, if all elements of the list == 1 
    '   -1, if all elements of the list == -1 
    '   0, otherwise 
    ''' 

    if line[0] == 1 and line[1] == 1 and line[2] == 1: 
     return 1 
    elif line[0] == -1 and line[1] == -1 and line[2] == -1: 
     return -1 
    return 0 


def getWinner(board): 
    # test columns 
    for idx in range(3): 
     line = [board[0][idx], board[1][idx], board[2][idx]] 
     if not testLine(line) == 0: 
      return line[0] 

    # test rows 
    for idx in range(3): 
     line = board[idx] 
     if not testLine(line) == 0: 
      return line[0] 

    # test diagonals 
    line = [board[0][0], board[1][1], board[2][2]] 
    if not testLine(line) == 0: 
     return line[0] 
    line = [board[0][2], board[1][1], board[2][0]] 
    if not testLine(line) == 0: 
     return line[0] 

    # no winner 
    return 0 

def count(board, obj): 
    c = 0 
    for r in range(len(board)): 
     for col in range(len(board[r])): # FIXED IT 
      if board[r][col] == obj: 
       c += 1 
    return c 

def nextMove(board, player): 

    if len(board[0]) + len(board[1]) + len(board[2]) == 1: return 0, 4 
    nextPlayer = player * (-1) 

    if not getWinner(board) == 0: 
     if player is 1: return -1, (-1, -1) 
     else: return 1, (-1, -1) 
    listOfResults = [] # empty array 

    if count(board, 0) == 0: # there is no empty field 
     return 0, (-1, -1) 

    _list = [] 
    for i in range(len(board)): 
     for j in range(len(board[i])): 
      if board[i][j] == 0: 
       _list.append((i, j)) 

    for (i, j) in _list: 
     board[i][j] = player 
     ret, move = nextMove(board, nextPlayer) 
     listOfResults.append(ret) 
     board[i][j] = 0 
    if player is 1: 
     maxPossibleValue = max(listOfResults) 
     return maxPossibleValue, _list[listOfResults.index(maxPossibleValue)] 
    else: 
     minPossibleValue = min(listOfResults) 
     return minPossibleValue, _list[listOfResults.index(minPossibleValue)] 



if __name__ == '__main__': 
    print(str(nextMove([[ 1, -1, 0], 
         [ -1, -1, 1], 
         [ 1, 1, 0]], 
         -1))) 

출력 : (0, (0, 2))

나는 확실히 그 count, getWinnertestLine 작업에 완벽을 말할 수있다. 그러나 코드 하단의 시나리오 출력은 으로 잘못되었습니다. (0, 2, 2)이어야합니다. 컴퓨터가 수익을 얻을 수있는 기회를 "차단"해야하기 때문입니다. 내 미니 맥스 알고리즘을 수정하는 방법에 대한 제안이 있으십니까?

편집 : 수정했습니다.count 메서드에서 오류가 발생했습니다. 그렇지 않으면 올바른 순서로 요소를 보관하지 않습니다 전체 방법은 거짓 값을 반환하기 때문에 당신은

for col in board[r] 

하지만

for col in range(len(board[r])) 

말을해서는 안된다.

+1

1) 각 방법에 대한 단위 테스트를 작성하십시오. 2) 해당 문제는 목록과 관련이있을 수 있습니다 (변경 가능하고 추가로 링크 된 사본을 수정하면 원본 목록도 수정 됨) – Sergius

+1

@ Ser 나는 성공적으로이 문제를 고쳐서이 질문을 편집했습니다. unittests에 대한 아이디어를 가져 주셔서 감사합니다. 그들은 제게 많은 도움을주었습니다. 나는 원래'count' 메소드에 에러가 없을 거라고 생각했기 때문에 실제로 테스트하지는 않았다. 당신은 저에 대해 생각하게했고, 나는 그 기능을 올바르게 할 수있었습니다. 정말 고맙습니다! – dv02

답변

1

해결했습니다. 카운트 방법에 오류가 있습니다. 그렇지 않으면 올바른 순서로 요소를 보관하지 않습니다 전체 방법은 거짓 값을 반환하기 때문에 당신은

for col in board[r] 

하지만

for col in range(len(board[r])) 

말을해서는 안된다.

0

첫 번째로 알아야 할 사항은 return a, breturn (a,b)과 비슷하다는 것입니다. 튜플을 정의 할 때 괄호가 필요하지 않으므로 (빈 튜플의 경우 제외).

그래서 당신은 쉽게 (0, (0, 2)) 대신 (0, 0, 2)를 반환 할 수 있습니다

return (maxPossibleValue,) + _list[listOfResults.index(maxPossibleValue)] 
# use (a,) for a tuple of len 1 

그러나 나는이 문제의 절반을 해결 알고 있어요.

+0

알아,하지만이 "반환 형식"을 사용하면 다른 값에 쉽게 액세스 할 수 있습니다. "하지만 문제의 절반 만 해결합니다." 정말로 문제를 해결하는 것은 아니지만 어쨌든 고맙습니다! :) – dv02

+0

당신이 "_it는 (0, 2, 2)'_"이어야한다고 말하기 때문에 혼란 스러웠습니다. 알고리즘 자체를 살펴 보겠습니다 ... – User9123

+0

젠장, 그건 바보 같았 어. 오류는'count' 메소드에 있습니다. 그렇지 않으면 옳은 순서로 유지하지 않기 때문에, 그것은 '보드에있는 콜용'이 아니라 '범위의 콜 (len (보드 [r]))'이어야합니다. 당신의 도움을 주셔서 감사합니다! – dv02