2013-12-08 13 views
0

Я делаю небольшой проект по игре 4x4 tic-tac-toe. Я использую Alpha Beta Search для поиска следующего лучшего шага. В альфа-бета поиска, я использую функцию оценки обрезания, который вызывается в функции «полезности» следующего алгоритмаФункция не возвращает отрицательное значение

Alpha Beta Search

я реализовал все успешно, но проблема в том, функция полезности не вернуть отрицательное значение, и я действительно не знаю, почему! Ниже приводится функция

private static int utility(GameTreeNode gtn, bool isMin = false) 
{ 
    int nodeValue = 0; 
    switch (gtn.NodeBoard.getBoardStatus()) 
    { 
     case Status.Success: 
      nodeValue = 50; 
      if (isMin) nodeValue = -50; /// here 
      break; 
     case Status.Incomplete: 
      if (isMin) 
       nodeValue = gtn.evaluate(State.X); 
      else 
       nodeValue = gtn.evaluate(State.O); 
      break; 
    } 
    // case Status.Draw: 
    return nodeValue; 
} 

isMin установлена ​​истина, когда она вызывается из функции MinValue

isMin является ход O и движение ИИ является X. Если O выигрывает утилита должна возвращать -50. Но он возвращает только 0. Я отлаживал программу, и она фактически присваивает от -50 до nodeValue (nodeValue изменений в отладчике до -50), но когда я получаю в функции Min или Max, она равна нулю.

Примечание: весь int, используемый во всем проекте, составляет signed int. Нет unsigned не используется ключевое слово, если вы думаете, функция-абонент беззнаковое

Полный код альфа-бета поиска здесь: http://pastie.org/8538015

Пожалуйста, друзья, помочь как можно скорее.

+0

Я не вижу вызовы 'Utility' с' isMin', установленными в 'true' в псевдокоде ... – MiMo

+0

В моем коде он делает, чтобы дифференцировать вызов от MinValue и MaxValue (чтобы дифференцировать перемещение of O из X) –

ответ

1

Поскольку вы используете необязательный параметр в своей сигнатуре метода, я бы предостерег вас обратить внимание на то, что ваш код фактически работает при вводе вашей функции. Вы сказали, что отлаживали его, и значение присваивается, но мне не хватает контекста, чтобы узнать, происходит ли это только в одном из многих случаев или нет. Во всяком случае, будьте осторожны с этими!

Я хотел бы переписать функцию так:

private static int utility(GameTreeNode gtn, bool isMin) 
{ 
    switch (gtn.NodeBoard.getBoardStatus()) 
    { 
     case Status.Success: 
      return isMin 
       ? -50 
       : 50; 
     case Status.Incomplete: 
      return isMin 
       ? gtn.evaluate(State.X) 
       : gtn.evaluate(State.O); 
     default: 
      throw new NotImplementedException("The status is not implemented."); 
    } 
} 

Несколько улучшений, которые я вижу с этим подходом:

  • Вам не нужно хранить значение и вернуть его в конце. В вашем случае вы всегда сохраняете 50 в nodeValue, когда вы берете путь Status.Success, а затем иногда присваиваете ему -50. Если вы не будете уверены в одном возврате своей функции, я думаю, что этот подход более ясен. Мог бы просто быть моим мнением.
  • В директиве switch есть значение по умолчанию, чтобы вы явно выбрали исключение в случае, когда у вас есть статус, который не был реализован.
  • нет дополнительный параметр к вашей функции. Я не вижу возможности сделать этот параметр необязательным. На мой взгляд, это похоже только на то, что это добавляет комнату, чтобы усложнять процесс отладки.

EDIT:

на основе кода по адресу: http://pastie.org/8538015#33,43

Похоже только время вы можете когда-либо получить утилита для возвращения отрицательное значение, когда if (gtn.Nodes.Count == 0) return utility(gtn, true); ударил в private static int MinValue(GameTreeNode gtn, int alpha, int beta) функция. В противном случае, если нет еще какого-либо кода, который вы еще не отправили, ни один другой вызов функции утилиты не ударит по логическому пути, к которому вы собираетесь идти. Вы упомянули, когда вы входите туда, вы можете увидеть, что значение для nodeValue получает должным образом.

Я предлагаю вам изменить:

// if Terminal-test(state) then return utitly(state) 
if (gtn.Nodes.Count == 0) return utility(gtn, true); 
gtn.Value = Globals.MAXINT; 

Для

// if Terminal-test(state) then return utitly(state) 
if (gtn.Nodes.Count == 0) 
{ 
    int retVal = utility(gtn, true); 
    return retVal; 
} 

gtn.Value = Globals.MAXINT; 

По крайней мере, временно, а затем поставить точку останова на return retVal. Если ваша служебная функция равна, на самом деле вы устанавливаете значение, которое вы ожидаете, как вы говорите, нет способа, которым он мог бы волшебным образом уйти, когда он вернет его функции MinValue. Я чувствую, что происходит что-то подозрительное, и код на самом деле не выполняет путь, который вы ожидаете.

+0

Я знаю, что могу вернуть его напрямую, но в отладчике он не сохраняет значение при возврате напрямую, поэтому я использовал значение, чтобы я мог войти и посмотреть, выполнено ли это или нет. Кроме того, я мог бы сделать то же самое и в функции звонящего. Я также размещаю функции minmax. Пожалуйста, –

+0

Хорошо, справедливо :) Я вернусь, как только появится другой код. –

+0

Я разместил его - это находится в http://pastie.org/8538015 –

Смежные вопросы