先生,我正在研究一个项目,我不时会在这里发布与此问题相关的问题。我已经创建了一个模拟场景,其中海龟(机器人)在空间中移动,并且每个机器人都跟踪其访问过的补丁。在patch-ahead 1
访问补丁的运动中,我需要将机器人向左转45度并再次检查patch-ahead
,直到它检查所有8个邻居,如果8个中的任何一个是UN访问的那么它应该转移到那个补丁并继续探索。但是如果所有8个都被访问过,那么它应该在检查所有8个邻居之后移动到当前标题前面的补丁,无论它是否被访问。
这是我正在使用的一段代码。
breed [robots robot ]
robots-own[ state memory ]
patches-own [ is-obstacle? ]
to setup
__clear-all-and-reset-ticks
create-robots num [
set memory (list patch-here)
]
draw-obstacles
ask patches [if pxcor = 0 and pycor = 0 [ set pcolor black ]]
end
to draw-obstacles
ask patches with [ pxcor mod 6 = 0 and pycor mod 6 = 0 ] [set pcolor red set is-obstacle? true]
; set pcolor red
ask patches [ ifelse pcolor = red [ set is-obstacle? true ][ set is-obstacle? false ] ]
ask patches with [ count neighbors != 8 ] [ set pcolor red set is-obstacle? true ]
end
to make-obstacle
if mouse-down?
[ ask-concurrent patches
[ if ((abs (pxcor - mouse-xcor)) < 1) and ((abs (pycor - mouse-ycor)) < 1)
[set pcolor red]]
]
end
to remove-obs
if mouse-down?
[ ask-concurrent patches
[ if ((abs (pxcor - mouse-xcor)) < 1) and ((abs (pycor - mouse-ycor)) < 1)
[set pcolor black]]
]
end
to go
ask patches [if ( pcolor = red )[set is-obstacle? true]]
ask patches [if ( pcolor = black )[set is-obstacle? false]]
ask-concurrent robots ; wanderers instructions
[
rt random-float rate-of-random-turn
lt (rate-of-random-turn / 2)
set-state
move-robots
]
tick
end
to move-robots ;;turtle proc
if (not member? state ["disperse" "explore"]) [
error "Unknown state"
]
if (state = "disperse") [
disperse
]
if (state = "explore") [
explore
]
end
to set-state ;;turtle proc
ifelse (any? other turtles in-radius 1) [
set state "disperse"
] [
set state "explore"
]
end
to disperse ;;turtle proc
avoid-obstacle
move1
; move-to one-of patch-set [neighbors] of neighbors
end
to explore
move
;search-open-room
avoid-obstacle
;move-to one-of neighbors
end
to move
fd speed
set memory lput patch-here memory
if ( (member? patch-ahead 1 memory) or ([is-obstacle?] of patch-ahead 1 ) )
[ lt random 45
]
end
to move1
fd speed
end
to avoid-obstacle
set memory lput patch-here memory
if ([is-obstacle?] of patch-ahead 1 )
[
ifelse [is-obstacle?] of patch-at-heading-and-distance (heading - 5) 1
[
ifelse [is-obstacle?] of patch-at-heading-and-distance (heading + 5) 1
[
ifelse random 1 = 0
[ rt 40 ]
[ lt 40 ]
]
[ rt 60 ]
]
[lt 60]
]
end
to search-open-room
ask robots[
ifelse ([is-obstacle?] of patches in-cone 2 150 )
[ rt 45 ] [ move ]
]
end
但在move
程序中我只能lt random 45
。如何根据上述场景进行更改。我用while
循环和repeat
语句尝试了很多但是代码似乎对我不起作用。
答案 0 :(得分:2)
您可以使用while
或repeat
执行此操作,但我认为这是recursion效果良好的情况。
我们的想法是让一个程序继续自我调用,直到达到所需的状态:
to turn-until-free [ n ]
let target ifelse-value (patch-ahead 1 = patch-here)
[ patch-ahead 2 ]
[ patch-ahead 1 ]
let seen? member? target memory
let obstacle? [ is-obstacle? ] of target
if-else n < 8
[ if seen? or obstacle? [ lt 45 turn-until-free n + 1 ] ]
[ if obstacle? [ lt 45 turn-until-free n + 1 ] ]
end
n
参数表示我们已对该过程进行的调用次数(或者,换句话说,我们到目前为止已检查过的邻居数)。当您第一次调用该过程时,请从n = 0
开始:
to move
turn-until-free 0
fd 1
set memory lput patch-here memory
ask patch-here [ set pcolor black + 2 ] ; just to show what's visited
end
一些不符合原始规范的事情:
可能会发生patch-ahead 1
与机器人已经在的补丁相同的补丁。贴片的边长为1,但其对角线稍长(√2)。因此,如果机器人位于左下角,并且面向右上方,patch-ahead 1 = patch-here
将为真。在这些情况下,我们会进一步了解并将目标设置为patch-ahead 2
。
在检查完所有8个邻居之后,你可能会遇到障碍。如果是这种情况,你需要继续转动直到你清除障碍物。事实上,这样做可以很好地避免障碍,并且您可以摆脱代码中的avoid-obstacle
过程。
修改强>
以下是完整工作示例所需的代码(除上述两个步骤外):
breed [ robots robot ]
robots-own [ memory ]
patches-own [ is-obstacle? ]
to setup
ca
ask patches [ set is-obstacle? false ]
ask patches with [ pxcor mod 6 = 0 and pycor mod 6 = 0 ] [
set is-obstacle? true
set pcolor red
]
ask n-of 5 patches with [ not is-obstacle? ] [
sprout-robots 1 [ set memory [] ]
]
reset-ticks
end
to go
ask robots [ move ]
tick
end
如果您遇到运行时错误或其他不需要的行为问题,我建议您从此开始,并一次性添加您在模拟中的任何其他内容。然后,您可以确切地看到问题的来源。
我还在上面的if-else n < 7
程序中更改了if-else n < 8
的{{1}}。这样,如果探索所有邻居而不是向右转,机器人会回到原来的标题。这可以避免在探索整个领土后进入圈内。