【问题标题】:Avoid visited patch netlogo避免访问补丁 netlogo
【发布时间】:2026-02-13 03:10:01
【问题描述】:

先生,我正在做一个项目,有时我会在这里发布与该问题相关的问题。我创建了一个模拟场景,其中海龟(机器人)在空间中四处移动,并且每个机器人都跟踪其访问过的补丁。在移动中,如果访问了patch-ahead 1 补丁,那么我需要将机器人向左转 45 度并再次检查patch-ahead,直到它检查所有 8 个邻居,如果这 8 个邻居中的任何一个未被访问,那么它应该移动到那个修补并继续探索。但是如果所有 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 语句尝试了很多,但代码似乎对我不起作用。

【问题讨论】:

  • 如何准确知道补丁是否被访问过?
  • David Merinos : 我正在使用一个名为“memory”的列表来存储访问过的位置。
  • 顺便说一句,您是否知道如果您一遍又一遍地向它添加已经访问过的补丁,memory 可能会永远增长?这可能不是问题,但如果成为问题,您可能需要考虑从列表切换到patch-set,或者至少偶尔在您的列表中调用remove-duplicates...

标签: netlogo


【解决方案1】:

您可以使用whilerepeat 来做到这一点,但我认为这是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

如果您遇到运行时错误或其他不需要的行为的问题,我建议您从这里开始,一次添加您在模拟中的任何其他内容。然后,您可以确切地看到问题出在哪里。

我还在上面的turn-until-free 过程中将if-else n &lt; 7 更改为if-else n &lt; 8。这样,如果所有邻居都被探索而不是向右转一点,机器人就会回到原来的航向。这样可以避免在探索完整个领土后陷入困境。

【讨论】:

  • 先生,我将这两个函数添加到我的代码中,但它会产生一些运行时错误并停止模拟。
  • 出现了我之前面临的同样问题。当所有 8 个邻居都被访问时,机器人开始在同一块旋转。
  • 就其本身而言,代码运行没有错误。问题可能在于您如何将其与其余部分集成以进行模拟。有关调试建议,请参见我上面的编辑。