Как создать минимаксный алгоритм сравнения массивов - PullRequest
0 голосов
/ 03 июля 2019

Я пытаюсь кодировать «минимаксный» алгоритм для Tic Tac Toe.

Каждый узел дерева имеет форму [nil/Int, String], где последний элемент представляет собой строку из девяти символов, описывающую доску,и первым является Integer, ранжирующий узел, или nil по умолчанию.

Если значение равно nil, оно пытается унаследовать соответствующее значение от дочерних узлов.

Здесь я получаюОшибка при сравнении массива с массивом.

class Scene_TicTacToe #Script 2/2

  def initialize
    #Boardstate as a str from top left corner to bottom right corner.
    @boardstate = "---------"
    #1 = player, -1 = comp
    @active_player = 1
  end

  def wincheck(boardstate=@boardstate)
    #should return -1 for loss, 0 for draw, 1 for win
    ["OOO","XXX"].each do |f|
      for i in 0..2
        if (boardstate[i]+boardstate[i+3]+boardstate[i+6]).chr == f || boardstate[(3*i)..(3*i)+2] == f
          return f == "OOO" ? 1 : -1
        end
      end
      if (boardstate[0]+boardstate[4]+boardstate[8]).chr == f || (boardstate[2]+boardstate[4]+boardstate[6]).chr == f
        return f == "OOO" ? 1 : -1
      end
    end
    return 0
  end

  def computer_play
    #Sets depth,and alpha/beta for pruning, so far so good
    depth = 3
    alpha = -100
    beta = 100
    #@boardstate starts as "---------"
    #@active_player: 1=player, -1=computer
    play(minimax(@boardstate, depth, alpha, beta, @active_player))
  end

  def play(array)
    #Check actual boardside with parameter boardside to see what move has been
    #selected and plays that move
    for i in 0...array[1].length
      if @boardstate[i] != array[1][i]
        #color = array[1][i].chr == "X" ? @ai : @player
        #@cursor.y = (i / 3) * @side
        #@cursor.x = (i % 3) * @side
        #@board.bitmap.fill_rect(@cursor.x,@cursor.y,@side,@side,color)
        @boardstate = array[1].dup
      end
    end
  end

  def minimax(boardstate, depth, alpha, beta, active_player)
    #If bottom node reached, returns [boardstate_score, boardstate]
    #wincheck returns 1 if player wins, -1 if computer wins, and 0 otherwise
    if depth == 0 or wincheck(boardstate) != 0 or (/-/ =~ boardstate) == nil
      return [wincheck(boardstate),boardstate]
    end

    if active_player == 1 #if player's turn
      #Gets an array of all the next possible boardstates and return the one with
      #the best eval.
      child = generate_child(boardstate, active_player)
      child.each do |f| #f = [Int/nil, String]
        if f[0] == nil
          #This should turn all the nil wincheck values to the best value of children nodes
          f[0] = minimax(f[1], depth-1, alpha, beta, -active_player).last[0]
        end
        alpha = [f[0], alpha].max
        if beta <= alpha
          break
        end
      end
      return child.sort_by{|c| c[0]}
    end

    if active_player == -1 #if computer's turn
      #Same as above but with worst eval.
      child = generate_child(boardstate, active_player)
      child.each do |f|
        if f[0] == nil
          f[0] = minimax(f[1], depth-1, alpha, beta, -active_player).first[0]
        end
        beta = [f[0], beta].min
        if beta <= alpha
          break
        end
      end
      #Following line raises "comparison of array with array failed" error :
      return child.sort_by{|c| c[0]}
    end

  end

  def generate_child(boardstate, active_player)
    #returns boardstate string with one X or O more than current boardstate
    #and sets nil as a default wincheck value
    c = active_player == 1 ? "O" : "X"
    a = []
    for i in 0...boardstate.length
      if boardstate[i].chr == "-"
        s = boardstate.dup
        s[i]= c
        a << [nil, s]
      end
    end
    return a
  end

end

Ошибка: сравнение массива с массивом

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...