You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

实现井字棋Minimax算法遇报错:NilClass未定义`<`方法求助

Fixing the undefined method '<' for nil:NilClass Error in Your Tic-Tac-Toe Minimax Implementation

Let's break down why you're hitting this error and how to fix it step by step.

The Root Cause

Your error stems from two critical issues in your code:

1. Inconsistent Return Values in Minimax

Your minimax function has a conflicting return type:

  • In terminal states (win/loss/tie), it returns a numerical score (-10, 10, 0).
  • In non-terminal states, it returns a move position (like an integer representing a board square).

When you recursively call minimax and assign the result to score, you're sometimes getting a position instead of a score. Worse, if your tie? function is broken, the function can return nil (when the board is full but tie? doesn't trigger), leading to the NoMethodError when you try to compare nil < best_score.

2. Potential Bug in the tie? Function

If your tie? function doesn't properly check for a full board plus no winner, it won't trigger the terminal state return of 0. This leaves the function to proceed to the end, where best_move stays nil (since there are no available squares to evaluate), and the function returns nil.

Step-by-Step Fix

First: Correct the tie? Function

Make sure it accurately identifies a full board with no winner:

def tie?(board)
  empty_squares(board).empty? && !user_won?(board) && !computer_won?(board)
end

Second: Split Minimax into Two Functions

To eliminate return value confusion, split the logic into two focused parts: one to calculate scores for recursive evaluation, and another to find the best move based on those scores.

1. Minimax Score Calculator (Recursive)

This function only returns numerical scores for internal recursive calls:

def minimax_score(current_board, current_player)
  # Terminal state checks
  if user_won?(current_board)
    return -10
  elsif computer_won?(current_board)
    return 10
  elsif tie?(current_board)
    return 0
  end

  available_squares = empty_squares(current_board)
  scores = []

  available_squares.each do |square|
    # Simulate the current player's move
    current_board[square] = current_player == 'computer' ? COMPUTER_MARKER : PLAYER_MARKER
    # Recursively get the opponent's best possible score
    scores << minimax_score(current_board, alternate_player(current_player))
    # Undo the move (backtracking)
    current_board[square] = INITIAL_MARKER
  end

  # Maximize score for computer, minimize for human player
  current_player == 'computer' ? scores.max : scores.min
end

2. Best Move Finder

This function uses the score calculator to evaluate all possible moves and select the optimal one:

def find_best_move(current_board)
  best_score = -Float::INFINITY
  best_move = nil

  available_squares = empty_squares(current_board)
  available_squares.each do |square|
    # Simulate the computer making this move
    current_board[square] = COMPUTER_MARKER
    # Calculate the best score the human player can achieve after this move
    current_score = minimax_score(current_board, 'player')
    # Undo the move
    current_board[square] = INITIAL_MARKER

    # Update best move if this option yields a better score
    if current_score > best_score
      best_score = current_score
      best_move = square
    end
  end

  best_move
end

Third: Update Your Code to Use find_best_move

Replace any calls to your original minimax function with find_best_move—this is the function you'll use to get the computer's next move.

Why This Works

  • Consistent Return Values: The recursive minimax_score always returns a number, so you'll never get nil (as long as tie? is correct) when comparing scores.
  • Clear Separation of Concerns: Splitting the logic makes debugging and maintenance easier—you no longer have to juggle returning scores and moves in the same function.

内容的提问来源于stack exchange,提问作者testing09

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:49:09