2016-01-12 3 views
-1

Эта ошибка появляется иногда только при вызове рекурсивной функции, одним из параметров которой является число: rand()%10. Как и в приведенном ниже кодексе:Как я могу обработать System.StackOverflowException?

private: System::Void AIrandomMove(int randomMove,String ^s) 
{ 
if (randomMove == 1) 
{ 
    if (Move(1)) // move number 1 had already been done 
     AIrandomMove(rand()%10,s); // here it appears the System.StackOverflowException 
    else 
     //do move number 1 
} 
//same goes for ==2 || ==3 || ... || ==10 
} 

Как я могу справиться с этим?

+0

Просто не полагайтесь на рекурсивный код с рекурсивным выбором случая, заданным случайным числом извлечения, поскольку это не имеет смысла. Преобразуйте алгоритм в итеративный. – Jack

+0

Почему это не имеет никакого смысла? Реализация выглядит примерно так: 'if (randomMove == 4) { if (этот шаг был сделан ранее) AIrandomMove (rand% 10, s); else // реализация } ' –

+1

это не имеет смысла, потому что вы явно разрешаете поведение без прерывания. Какой смысл использовать рекурсию? Я имею в виду, почему вам требуется рекурсия? – Jack

ответ

0

Надлежащий рекурсивный алгоритм работает в двух предположениях:

  • у вас есть базовый случай, прекратить рекурсию (поэтому функция не называют себя)
  • у вас есть рекурсивный случай, который вызывает функцию сам с различными аргументами, так что есть некоторая прогрессия участие

Это переводится в чем-то вроде:

void recursive(inArgs) { 
    if (condition) 
    return; 
    else 
    recursive(outArgs) 
} 

Понятно, что если condition является выражением true, тогда этот код никогда не заканчивается (следовательно, он в конечном итоге приведет к переполнению стека).

В вашей ситуации condition оценивается путем сравнения случайных значений. Предположим, что условие равно rand()%2 == 0. Поэтому в основном каждый раз, когда он оценивается, вы имеете 50% шанс быть true и 50% от false.

Это не гарантирует, что рекурсия закончится, поскольку существует оценка с оценкой n true (и вероятность ее может быть определена). Это проблема с вашим дизайном.

Если много ходов уже сделано (или, может быть, все они), то рекурсия не закончится.

Вам вообще не нужна рекурсия в вашем случае, так как вы можете хранить доступные ходы в наборе и удалять их, как только они больше не доступны (возможно, перетасовывая набор, а затем выбирайте случайным образом). Или даже более простое решение было бы что-то вроде:

int choosenMove = rand()%10; 

while (Move(choosenMove)) { 
    choosenMove = rand()%10; 
    // do move choosenMove 
} 

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

+0

Ох .. Хорошо. Теперь я наконец понял. Большое спасибо. В моей стране 3 часа ночи, и я определенно нуждаюсь в отдыхе. Тем не менее, я понял! Еще раз спасибо! знак равно –