Что нового

[Процессы] Помогите победить рекурсию

Notum

Новичок
Сообщения
71
Репутация
0
Вылетил скрипт с ошибкой ==> Recursion level has been exceeded - AutoIt will quit to prevent stack overflow.:
и указывает вот на строку FindComboHit(). Разве тут может быть рекурсия?
Код:
Func Fight_Check_new()
$mm = PixelGetColor (570, 498)
	if $mm = 15847510 then
		If $ComboCounter = $ComboCounterHit Then
			If $ComboCounterHit = 4 Then
				HitCombo4()
			Else
				HitCombo8()
			EndIf	
		Else
			If $RandomHit = True Then
				Call("Udar" & Random(1, 3, 1) )
			Else
				FindComboHit()
			EndIf	
		EndIf	
	Else
		Sleep (1000)
		Win_Check()
EndIf	
EndFunc

Func FindComboHit()
	$ForwardHit = PixelGetColor(859, 508)
	if $ForwardHit = 4791042 Then
		Udar3()
	Else
		$LeftHit = PixelGetColor(421, 508)
		If $LeftHit = 4791042 Then
			Udar1()
		Else
			Udar2()
		EndIf	
	EndIf	
EndFunc


Заранее спасибо.
 

SyDr

Сидра
Сообщения
651
Репутация
158
Re: Рекурсия

Если одна из функций
HitCombo4()
HitCombo8()
FindComboHit()
Win_Check()
Udar1()
Udar2()
Udar3()
вызывает функцию Fight_Check_new(), то да, эта самая настоящая рекурсия.
 
Автор
N

Notum

Новичок
Сообщения
71
Репутация
0
Re: Рекурсия

Да, вызывает. Огромное спасибо, буду переписывать!
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
Re: Рекурсия

{TopicNameWarn}
 
Автор
N

Notum

Новичок
Сообщения
71
Репутация
0
Re: Рекурсия

Kaster сказал(а):
[warn]За нарушение правил форума (пункт Б.5):
Имя темы должно нести смысловую нагрузку (отражать суть вопроса/проблемы)
Правильно сформулированное название темы привлекает больше внимания, и шансы получить конкретный ответ увеличиваются.


Как правильно называть темы

Переименуйте тему иначе она будет закрыта.

С уважением, Модератор раздела.[/warn]















Исправил.


Добавлено:
Сообщение автоматически объединено:

SyDr сказал(а):
Если одна из функций
HitCombo4()
HitCombo8()
FindComboHit()
Win_Check()
Udar1()
Udar2()
Udar3()
вызывает функцию Fight_Check_new(), то да, эта самая настоящая рекурсия.

Ещё раз спасибо за ответ, но у меня возник следующий вопрос - как тогда быть? Есть ли какие нибудь основы (законы) соблюдая которые можно избежать рекурсии?

У меня на ум приходит только одна идея - создание вспомогательной (второстепенной) функции, которая как бы будет промежуточной!

Заранее спасибо!
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
Re: Причина возникновения рекурсии

Notum [?]
Есть ли какие нибудь основы (законы) соблюдая которые можно избежать рекурсии?
да. рекурсия - очень удобный инструмент для сокращенной записи циклов, но имеющий ряд ограничений. к примеру, предел вложенности рекурсионных функций. рекурсию нецелесообразно использовать для циклов кол-во итераций в которых большой. в таких случаях следует использовать просто циклы. в AutoIt есть несколько равноправных способов организовать циклы, рекомендую использовать их
 

SyDr

Сидра
Сообщения
651
Репутация
158
Re: Причина возникновения рекурсии

Оставь в этой функции только проверку. Сделай, чтобы она возвращала значение. В цикле проверяй результат, и вызывай соответсвующие функции.

Код:
While 1
$Result = FightCheckNew()
Switch $Result
...
EndSwitch
If <условие выхода> Then ExitLoop
WEnd
 

Belfigor

Модератор
Локальный модератор
Сообщения
3,608
Репутация
941
Re: Причина возникновения рекурсии

При этом, для возможности работы варианта что привел SyDr, функция FightCheckNew() должна иметь в себе какой-либо возврат, ибо вот так вот $Result будет равен 0 после отработки строки $Result = FightCheckNew()
Код:
$Result = FightCheckNew()
MsgBox(0,0,$Result) ; Ты увидишь 0
Func FightCheckNew()
    Sleep(100)
EndFunc

Вот так вот, ты увидишь в месседж боксе Hellow World!
Код:
$Result = FightCheckNew()
MsgBox(0,0,$Result) ; Ты увидишь Hellow World!
Func FightCheckNew()
    Return "Hellow World!" ;После отработки функции возвращаем какое-то значение.
EndFunc

В этом варианте, если $test = 1, скрипт сообщит тебе об этом, если же нет, то в $Result вернется другая строка.
Код:
Global $test = 1
$Result = FightCheckNew()
MsgBox(0,0,$Result) ; Ты увидишь равен $test единице или же нет
Func FightCheckNew()
    If $test = 1 Then
        Return "$test = 1"
    Else
        Return "$test <> 1"
    EndFunc
EndFunc
 
Автор
N

Notum

Новичок
Сообщения
71
Репутация
0
Привет.
Пишу кликкер для браузерной игры, написал 3 функции.

Функция выбора удара, комбо и проверка на смерть
Код:
Func Fight_Check_new() ;функция боя
$mm = PixelGetColor (570, 498) ; проверяем - появилось ли таблица с кнопкой ударов
	if $mm = 15847510 then ; таблица появилась
		If $ComboCounter = $ComboCounterHit Then
			If $ComboCounterHit = 4 Then
					Sleep(1000)
					MouseMove(604, 564, 0)
					Sleep(200)
					MouseClick("left")
					Sleep(4000)
					$ComboCounter = 0
					MouseMove (0, 0, 0)
					Sleep(5000)
					FightHPcheck()
			Else
					Sleep(1000)
					MouseMove(748, 564, 0)
					Sleep(200)
					MouseClick("left")
					Sleep(4000)
					$ComboCounter = 0
					Sleep(5000)
					FightHPcheck()
			EndIf	
		Else
			If $RandomHit = True Then
				Call("Udar" & Random(1, 3, 1) )
			Else
				FindComboHit()
			EndIf	
		EndIf	
	Else
		Sleep (1000)
		Win_Check() ;таблицы нет, ждём 1 сек и а не победили ли мы
EndIf	
EndFunc


Функция проверки HP, и если мало - выпить банку:
Код:
Func FightHPcheck()
	$low_hp = PixelGetColor($HPPixel,142) ;проверяем - сколько у нас хп
	if $low_hp = 16724794 Then
		Fight_Check_new()
	Else
		if $banka1 = False Then
			Send("{2}")
			$banka1 = True
			$bootlelatency = 6000
			Sleep(700)
			Fight_Check_new()
		Else
			If $banka2 = False Then
				Send("{3}") 
				$banka2 = True
				Sleep(700)
				Fight_Check_new()
			Else
				Send("{4}") 
				Sleep(700)
				$banka3 = True
				Fight_Check_new()
			EndIf
		EndIf	
	EndIf


Функция проверки победы:
Код:
Func Win_Check() ;функция проверки победы
	$win1 = PixelGetColor ( 614, 391) ;
	$win2 = PixelGetColor ( 667, 391) ;
	if $win1 = $win2 Then
		If $win1 = $checkwincolour1 or $win1 = $checkwincolour2 then
			MouseMove(639, 396, 0) 
			Sleep(700)
			MouseClick("left")
			Sleep(6000) 
			MouseMove(360, 110, 0)
			Sleep(200)
			MouseClick("left")
			Sleep(1000)
			DeathCheck()
		Else
		Sleep(4000)
			FightHPcheck()
		EndIf	
	Else
		Sleep(5000)
		FightHPcheck()
	EndIF
EndFunc


Опытный глаз программиста сразу увидит, что здесь имеется рекурсия и по истечению определённого кол-ва циклов - кликкер вылетает с ошибкой.

Буду признателен, ели кто то поможет мне решить проблему рекурсии.
Заранее спасибо.
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
А разве вот в этой теме, которая отмечена тобой как
topicsolved.gif
"Решенная", ты не решил проблему с рекурсией и заменой ее на циклы с пост- и препроверкой?
http://autoit-script.ru/index.php?topic=1849.msg13225#msg13225
 
Автор
N

Notum

Новичок
Сообщения
71
Репутация
0
Увы, нет!
Убрать - Решено и написать туда?
 

AZJIO

Меценат
Меценат
Сообщения
2,874
Репутация
1,194
Notum
Логика проста, если в первой функции есть вызов второй функции, то проверяем есть ли вызов первой функции из второй. Если есть и условия вызова не препятствуют какими либо внутренними условиями функции, то функция рекурсивная, так как она может многократно генерировать вхождения одной в другую без возвращения.
А вылет наверно зависит от того присутствует ли условия выхода из многократного вызова или процес запущен на самотёк (накопления вхождений), покуда не зависнет.
Во всех рекурсивных скриптах, что приходилось мне использовать был выход к началу, а глубина рекурсии зависела от глубины субдиректорий и субветок, примерно не более 50.
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
AZJIO
в том-то и дело, что у Notum нет необходимости делать рекурсию. И в прошлых темах, мне казалось, что это было четко доведено до сведения. Рекурсия - всего лишь удобная запись цикла и имеет ряд ограничений. Если есть хоть какой-то риск эти ограничения достигнуть, лучше использовать циклы.

Notum
просто в той теме тебе была предложена концепция использования циклов взамен рекурсий. Следуя той концепции тебе нужно перестроить всю логику твоих скриптов. У меня например нет времени делать это за тебя.


Добавлено:
Сообщение автоматически объединено:

Notum [?]
Убрать - Решено...?
Если не сложно
 
Автор
N

Notum

Новичок
Сообщения
71
Репутация
0
Все принципы и методы решения проблем с рекурсией мне понятны, но я не могу применить их в моём примере.
 

Belfigor

Модератор
Локальный модератор
Сообщения
3,608
Репутация
941
Почему же о_О? Твой пример чем-то уникален?


Добавлено:
Сообщение автоматически объединено:

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

Notum

Новичок
Сообщения
71
Репутация
0
Belfigor сказал(а):
Почему же о_О? Твой пример чем-то уникален?


Добавлено:
Сообщение автоматически объединено:

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



Видимо не уникальна, раз вы так пишите. :-[ Остальной код нету смысла выкладывать, т.к. он не относиться к функции боя. В любом случае - был бы признателен, если мне покажут как работает Func.. Return... именно на моём примере. Заранее спасибо!
 

Belfigor

Модератор
Локальный модератор
Сообщения
3,608
Репутация
941
Дак выложи исходник, я могу перекроить твой код этой ночью, заняться все равно нечем, суть в том что эти 3 функции, ты уже в них используешь ссылки на другие функции которые ты не показываешь, и из этих функций должны быть какие-то возвраты. Кстати если ты за оптимизацию этого скрипта предлагал финансовое вознаграждение то я готов за это взяться :smile:. Все равно сегодня в еве патч, и ночью с работы залезть на сервер игры мне таки не удастся :(. Только решай скорее, пока у меня игра "Мор. Утопия" на нетбук не закачалась :smile:. Если таки решишь, скидывай аську мне в приват
91.gif
 
Автор
N

Notum

Новичок
Сообщения
71
Репутация
0
Belfigor сказал(а):
Дак выложи исходник, я могу перекроить твой код этой ночью, заняться все равно нечем, суть в том что эти 3 функции, ты уже в них используешь ссылки на другие функции которые ты не показываешь, и из этих функций должны быть какие-то возвраты. Кстати если ты за оптимизацию этого скрипта предлагал финансовое вознаграждение то я готов за это взяться :smile:. Все равно сегодня в еве патч, и ночью с работы залезть на сервер игры мне таки не удастся :(. Только решай скорее, пока у меня игра "Мор. Утопия" на нетбук не закачалась :smile:. Если таки решишь, скидывай аську мне в приват
91.gif
Напишите пожалуйста свой ник в скайпе мне в ЛС или аська, или как с вами связаться.
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
Так. я чего то не понял. мне опять переносить тему? на этот раз в стол заказов? :-X
 
Верх