Автокликер Clickermann :: Форум
Основной раздел => Общие вопросы => Topic started by: NStra on April 01, 2015, 03:10:41 PM
-
Дано: 4 переменных, содержащих произвольные числа.
Переменные могут быть равными по значению.
Задача: Построить алгоритм, определяющий, какая переменная содержит наименьшее число.
Если таких переменных несколько, выбрать рандомом любую из них.
P.S. Прошу прощения, если задача окажется легкой...
-
Если без рандома, а первая попавшееся
$v1 = 300
$v2 = 400
$v3 = 100
$v4 = 200
$min = $v1
IF($v2 < $min)
$min = $v2
END_IF
IF($v3 < $min)
$min = $v3
END_IF
IF($v4 < $min)
$min = $v4
END_IF
Если таких переменных несколько, выбрать рандомом любую из них.
И что значит выбрать любую из них рандомом? Нужно знать какие именно это переменные?
Потому как выбирать рандомом значения не имеет смысла, они одинаковые.
-
Немного не то...
1. Нужно определить переменную, которая содержит минимальное число, а не ее значение.
2. Рандом обязателен, в случае, если минимальных переменных несколько...
-
Что-то это мне напоминает... Год назад вот так же пытали про три наименьших из n и требовали именно переменную.
Подход к реализации неправильный. Такие вопросы не должны возникать.
Ну вот ладно, определю я что наименьшее значение находится в переменной $v3. И что я буду с этим делать?
Запомню имя в другой переменной как "$v3"? И как потом это можно использовать?
Поподробней задачу опиши, пошире. Подскажем что переделать.
-
Да, это похоже работа со строками, возможно и с массивами...+ наверно нагромождение условий...
Пример работы программы:
Вход:
$Dir1=1
$Dir2=1
$Dir3=3
$Dir4=4
Выход:
Print("выбрано $Dir1")
или
Print("выбрано $Dir2")
-
$Dir1=1
$Dir2=1
$Dir3=3
$Dir4=4
$min = $Dir1
IF($Dir2 < $min)
$min = $Dir2
END_IF
IF($Dir3 < $min)
$min = $Dir3
END_IF
IF($Dir4 < $min)
$min = $Dir4
END_IF
IF($Dir1 = $min)
ARRPUSH($names, "$Dir1")
END_IF
IF($Dir2 = $min)
ARRPUSH($names, "$Dir2")
END_IF
IF($Dir3 = $min)
ARRPUSH($names, "$Dir3")
END_IF
IF($Dir4 = $min)
ARRPUSH($names, "$Dir4")
END_IF
$name = $names[RND(0,ARRSIZE($names)-1)]
Print("выбрано ", $name)
И всё равно это неверный подход. Если есть несколько однотипных переменных, лучше хранить их в массиве, а индекс массива как раз и будет индикатором какая это из переменных.
А то при любых подобных обработках невозможно применить циклы и приходится кучу кода писать и дублировать вручную.
$Dir[0.....]
-
Мой вариант, номер определяет но с рандомом нужно думать..
$c1=4000
$c2=2
$c3=2
$c4=9
STRSEPARATE(STRCONCAT($c1,":",$c2,":",$c3,":",$c4), ":", $analiz)
$num=9999999
FOR($a=0,$a<ARRSIZE($analiz))
$min = $analiz[$a]
IF($min < $num)
$c = $a+1
$num = $min
END_IF
END_CYC
LOGWRITE ("Номер = ",$c," Min = ",$num)
HALT
-
Ну вот через массивы.
$Dir1 = 1
$Dir2 = 1
$Dir3 = 3
$Dir4 = 4
STRSEPARATE(STRCONCAT($Dir1,":",$Dir2,":",$Dir3,":",$Dir4), ":", $analiz)
$min = 99999999999
FOR($a=0,$a < ARRSIZE($analiz))
IF($analiz[$a] < $min)
$min = $analiz[$a]
END_IF
END_CYC
FOR($a=0,$a < ARRSIZE($analiz))
IF($analiz[$a] = $min)
ARRPUSH($names, $a)
END_IF
END_CYC
$name = $names[RND(0,ARRSIZE($names)-1)]
Print("выбрано $Dir", $name+1)
HALT
-
Вот так даже красивее
$Dir1 = 1
$Dir2 = 1
$Dir3 = 3
$Dir4 = 4
STRSEPARATE(STRCONCAT($Dir1,":",$Dir2,":",$Dir3,":",$Dir4), ":", $analiz)
$min = 99999999999
FOR($a=0,$a < ARRSIZE($analiz))
IF($analiz[$a] < $min)
$min = $analiz[$a]
UNDEFINE($names)
ARRPUSH($names, $a)
ELSE
IF($analiz[$a] = $min)
ARRPUSH($names, $a)
END_IF
END_IF
END_CYC
$name = $names[RND(0,ARRSIZE($names)-1)]
Print("выбрано $Dir", $name+1)
HALT
-
Эта задача: кусок алгоритма A* http://www.policyalmanac.org/games/aStarTutorial_rus.htm (http://www.policyalmanac.org/games/aStarTutorial_rus.htm)
В данном случае 4-и переменных это значения H где:
$Dir1 - влево
$Dir2 - вверх
$Dir3 - вправо
$Dir4 - вниз
...
Задумка вот в чем:
Если кликер будет обходить один и тот же путь с рандомом, то в 50% случаев он выберет короткий, в остальных пойдет по длинному (например стена влево больше чем вправо).
Если кликер будет обходить один и тот же путь без рандома, то высока вероятность что он все время будет ходить по длинному пути...
В идеале я хочу сделать вот что:
Кликер должен не выбирать пути, а мысленно пройти оба и сравнить длину, после выбрать короткий путь.
-
Там сам бог велел массив использовать. А индексы как раз и будут обозначать направление.
0 - влево, 1 - вверх ... и т.д.
Только рандом там не нужен, ты неправильно понял. Мы должны брать минимальное, но не важно какое. Как раз пока стоимость не начнет уменьшатся мы будем по очереди проверять то с одной стороны стены, то с другой.
И если стоимость новой открытой клетки равна, то мы должны следующей проверять её. (этот момент в статье упущен)
Если начнёт уменьшаться, вторая ветвь отвалится сама собой.
И не нужно гадать 50/50
Кликер должен не выбирать пути, а мысленно пройти оба и сравнить длину, после выбрать короткий путь.
А если их будет не два, а 5 или 10 или 100? Алгоритм поиска пути как раз и позволяет не обходить их все. Иначе ресурсов и времени потребуется уйма
Ха! :D А я после того как дал ссылку, почти каждый день думаю об этом A*
Хочется реализовать, но самому лень начинать, т.к. нет практической задачи, только спортивный интерес.
Я уже думал клич кинуть на форум с кем скооперироваться для совместного создания. Всё ж веселее. Но так и не решился, подумал кому оно надо.
Я представляю себе, что если поле большое, реализация на кликере может быть медленная. Не знаю на сколько, правда.
Но уже подумывал и о питоне и о AutoIT. Можно там модуль сделать трудоёмкий.
И самое главное, я не знаю какой выбрать способ хранения начальных данных, чтобы была универсальность и скрипт можно было использовать и в других задачах.
-
Там кстати в конце есть ссылка на код на C++
Я язык не знаю, но там есть скомпилированный код. Очень забавно погонять его.
Там два: редактор с показом всех построений-вычислений
и большой лабиринт/редактор кде бегают чудики и как они хорошо находят путь.
-
Доброго времени суток.
Решил достать из долгого ящика скрипт поиска пути.
Оказалось, что мой код содержит ошибки...Которые я еще и не могу исправить. :'(
После запуска, переменные Dir работают странно...Определяют стены там, где их нет, и наоборот.
Либо вообще определяют, что стены везде...
Карту и идентификаторы в файлах я проверял, там ошибок нет.
#name "ALGORITM A"
// В данном алгоритме не предусмотрено движение по диагонали.
//==============================================================================
//1) Занести клетки в массив.
SUB(name1)
ARRPUSH($ARR,0)
FOR($A=1, $A<18) //Кол-во рядов.
FOR($B=1, $B<15) //Кол-во строк.
IF(STRCUT(TFREAD("system\Map\Map2.txt",$B),$A,1)>0)//Клетка.
INC($C,1)
$D=TFREAD("system\Map\Map1.txt",$C) //Идентификатор орентира.
ELSE
$D=0
END_IF
ARRPUSH($ARR,$D)
END_CYC
END_CYC
END_SUB
//==============================================================================
//3) Подсчет значения H для соседних клеток.
SUB(name3)
$C=($XT-1)*$YT
IF($ARR[$C]!0)
$Dir1=DIST($XT-1,$YT,$XK,$YK)
ELSE
$Dir1="Wall"
END_IF
$C=$XT*($YT+1)
IF($ARR[$C]!0)
$Dir2=DIST($XT,$YT-1,$XK,$YK)
ELSE
$Dir2="Wall"
END_IF
$C=($XT+1)*$YT
IF($ARR[$C]!0)
$Dir3=DIST($XT+1,$YT,$XK,$YK)
ELSE
$Dir3="Wall"
END_IF
$C=$XT*($YT-1)
IF($ARR[$C]!0)
$Dir4=DIST($XT,$YT+1,$XK,$YK)
ELSE
$Dir4="Wall"
END_IF
END_SUB
//==============================================================================
//4) Выбрать короткий путь.
SUB(name4)
UNDEFINE($analiz)
ARRPUSH ($analiz,$Dir1)
ARRPUSH ($analiz,$Dir2)
ARRPUSH ($analiz,$Dir3)
ARRPUSH ($analiz,$Dir4)
PRINT("analiz0=",$analiz[0])
PRINT("analiz1=",$analiz[1])
PRINT("analiz2=",$analiz[2])
PRINT("analiz3=",$analiz[3])
$min = 99999999999
FOR($a=0,$a < ARRSIZE($analiz))
IF(($analiz[$a]!"Wall")=1)
IF($analiz[$a] < $min)
$min = $analiz[$a]
UNDEFINE($names)
ARRPUSH($names, $a)
ELSE
IF($analiz[$a] = $min)
ARRPUSH($names, $a)
END_IF
END_IF
END_IF
END_CYC
$name = $names[RND(0,ARRSIZE($names)-1)]
SWITCH($name)
case(0)
LCLICK(170,300)
case(1)
LCLICK(511,25)
case(2)
LCLICK(850,300)
case(3)
LCLICK(511,485)
END_SWITCH
END_SUB
//==============================================================================
//2) Определить текущую клетку.
SUB(name2)
$A=PXLCRC(497,522,523,523)
IF($B!$A)
$B=$A
FOR($C=1,$C!ARRSIZE($ARR))
IF(($A=$ARR[$C])=1)
$XT=INT($C/14)-6
$YT=$C-(INT($C/14)*14)-4
PRINT("$XT=",$XT)
PRINT("$YT=",$YT)
END_IF
END_CYC
IF(($XT=$XK)&($YT=$YK))
HALT //<<-- HALT Надо будет заменить
GOTO(name0) //<<-- Это все же будет поток...
END_IF
name3()
name4()
END_IF
WAIT(8)
END_SUB
//==============================================================================
//Программа.
name0:
$XK=0
$YK=3
name1()
WHILE(1)
GETSCREEN
name2()
END_CYC
-
До алгоритма не дошёл. Остановился здесь
$XT = INT($C/14) - 6
$YT = $C - (INT($C/14) * 14) - 4
Непонятно, что мы так высчитываем. Почему делим на 14? что это даст?
$C у нас номер по порядку, идём по рядам. В конце первого ряда $C = 17, в конце второго 34...
почему мы делим на количество рядов? По идее мы должны делить на количество "В РЯДУ", т.е.17
И что такое -6 и -4 ?
Отступление. Зачем мы здесь сравниваем с 1?
IF(($A = $ARR[$C]) = 1)
результат ничем не отличается от
IF($A = $ARR[$C])
И скрины бы рабочие, где там что считаем.
-
$XT = INT($C/14) - 6
$YT = $C - (INT($C/14) * 14) - 4
Это текущие координаты...Кхм, этот кусочек работает правильно=\
-6 и -4 это отступы, так как координаты начинаются не с 0,0 а -6,-3
Скрин в студию...
-
И всё равно я не пойму. Почему делим на 14?
В переменной $C нет информации чтобы её делить на количество строк (14)
$C мы пробегаем поле так ?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
18 19 20 21 22 23 24 25 .....
Что здесь 14?
-
Забыл уточнить...Поле перебирается так:
1 5 9
2 6 10
3 7 11
4 8 12
То есть сверху вниз, слева направо.
-
Аааа
А вот здесь тогда
$C = ($XT-1) * $YT
IF($ARR[$C] ! 0)
...
Допустим у нас
$XT = -5
$YT = 3
Куда мы в этом случае будем обращаться в $ARR по отрицательному индексу?
-
Ещё вариант, если
$XT = любое
$YT = 0
при любом $XT будет обращаться к $ARR[0]
-
Спасибо, пойду исправлю...
-
Может не нужно было запутываться с отрицательным смещением. Брать поле 17х14
А уже при определении с экрана или при ответе переводить в -6/-3...10/10
-
Движение есть? А где сам алгоритм поиска пути? В выложенном куске его нет.
Там мы просто двигаемся на всё что ближе к финишу, без всяких поисков.