ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 Excel Home精品图文教程库
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
300集Office 2010微视频教程 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 991|回复: 2

[原创] 和尚、妖怪过河VBA版(数据结构、递归)

[复制链接]

TA的精华主题

TA的得分主题

发表于 2019-12-23 16:10 | 显示全部楼层 |阅读模式
根据核心算法,用VBA实现了一下
  1. Option Explicit

  2. '状态
  3. Type ItemState
  4.     local_monster As Integer '本地妖怪数
  5.     local_monk   As Integer '本地和尚数
  6.     remote_monster  As Integer  '对岸妖怪数
  7.     remote_monk  As Integer  '对岸和尚数
  8.     BoatLocation As Boolean '船的位置 本地True,对岸 False
  9.     EffectName As String '动作名称
  10. End Type

  11. '动作
  12. Type ActionEffect
  13.     local_monster_move As Integer '本地妖怪移动数
  14.     local_monk_move  As Integer  '本地和尚移动数
  15.     remote_monster_move  As Integer  '对岸妖怪移动数
  16.     remote_monk_move  As Integer  '对岸和尚移动数
  17.     Boat_To As Boolean '船的移动方向 往本地True,往对岸 False
  18.     ActiveName As String '动作名称
  19. End Type

  20. '和尚、妖怪初始数
  21. Const MONK_COUNT As Long = 3
  22. Const MONSTER_COUNT As Long = 3

  23. '=========================================================
  24. '主过程
  25. Sub Main()
  26.     Dim myState(0) As ItemState
  27.     With myState(0)
  28.         .local_monk = MONK_COUNT
  29.         .local_monster = MONSTER_COUNT
  30.         .remote_monk = 0
  31.         .remote_monster = 0
  32.         .BoatLocation = True
  33.     End With
  34.    
  35.     ProcessState myState
  36.    
  37.     MsgBox "OK"
  38.     '【结果】
  39.     ',[3-3-0-0],TWO_MONSTER_GO[3-1-0-2],ONE_MONSTER_BACK[3-2-0-1],TWO_MONSTER_GO[3-0-0-3],ONE_MONSTER_BACK[3-1-0-2],TWO_MONK_GO[1-1-2-2],ONE_MONSTER_ONE_MONK_BACK[2-2-1-1],TWO_MONK_GO[0-2-3-1],ONE_MONSTER_BACK[0-3-3-0],TWO_MONSTER_GO[0-1-3-2],ONE_MONSTER_BACK[0-2-3-1],TWO_MONSTER_GO[0-0-3-3]
  40.     ',[3-3-0-0],TWO_MONSTER_GO[3-1-0-2],ONE_MONSTER_BACK[3-2-0-1],TWO_MONSTER_GO[3-0-0-3],ONE_MONSTER_BACK[3-1-0-2],TWO_MONK_GO[1-1-2-2],ONE_MONSTER_ONE_MONK_BACK[2-2-1-1],TWO_MONK_GO[0-2-3-1],ONE_MONSTER_BACK[0-3-3-0],TWO_MONSTER_GO[0-1-3-2],ONE_MONK_BACK[1-1-2-2],ONE_MONSTER_ONE_MONK_GO[0-0-3-3]
  41.     ',[3-3-0-0],ONE_MONSTER_ONE_MONK_GO[2-2-1-1],ONE_MONK_BACK[3-2-0-1],TWO_MONSTER_GO[3-0-0-3],ONE_MONSTER_BACK[3-1-0-2],TWO_MONK_GO[1-1-2-2],ONE_MONSTER_ONE_MONK_BACK[2-2-1-1],TWO_MONK_GO[0-2-3-1],ONE_MONSTER_BACK[0-3-3-0],TWO_MONSTER_GO[0-1-3-2],ONE_MONSTER_BACK[0-2-3-1],TWO_MONSTER_GO[0-0-3-3]
  42.     ',[3-3-0-0],ONE_MONSTER_ONE_MONK_GO[2-2-1-1],ONE_MONK_BACK[3-2-0-1],TWO_MONSTER_GO[3-0-0-3],ONE_MONSTER_BACK[3-1-0-2],TWO_MONK_GO[1-1-2-2],ONE_MONSTER_ONE_MONK_BACK[2-2-1-1],TWO_MONK_GO[0-2-3-1],ONE_MONSTER_BACK[0-3-3-0],TWO_MONSTER_GO[0-1-3-2],ONE_MONK_BACK[1-1-2-2],ONE_MONSTER_ONE_MONK_GO[0-0-3-3]

  43. End Sub

  44. '=========================================================
  45. '逐个动作判断、递归
  46. Function ProcessState(mState() As ItemState)
  47.     Dim ActionEffects() As ActionEffect
  48.     Dim CurState() As ItemState, lngID As Long
  49.    
  50.     CurState = mState
  51.     If IsFinalState(CurState) Then
  52.         Debug.Print PrintResult(CurState) '在立即窗口输出结果
  53.         Exit Function
  54.     End If
  55.    
  56.     ActionEffects = InicAE
  57.     For lngID = 0 To 9
  58.         ProcessStateOnNewAction CurState, ActionEffects(lngID)
  59.     Next
  60.    
  61. End Function

  62. '=========================================================
  63. '判断某个动作是否可行,并执行
  64. Function ProcessStateOnNewAction(mState() As ItemState, act As ActionEffect)
  65.     Dim CurState() As ItemState
  66.     CurState = mState
  67.     If CanTakeAction(CurState, act) Then
  68.         SetItemState CurState, act
  69.         ProcessState CurState
  70.     End If
  71. End Function

  72. '=========================================================
  73. '输出结果
  74. Function PrintResult(mState() As ItemState) As String
  75.     Dim strTemp As String, lngID As Long
  76.     For lngID = LBound(mState) To UBound(mState)
  77.         strTemp = strTemp & "," & mState(lngID).EffectName & "[" & mState(lngID).local_monk & "-" & mState(lngID).local_monster & "-" & mState(lngID).remote_monk & "-" & mState(lngID).remote_monster & "]"
  78.     Next
  79.     PrintResult = strTemp
  80. End Function

  81. '=========================================================
  82. ' 初始化动作
  83. Function InicAE() As ActionEffect()
  84.     Dim AE(9) As ActionEffect
  85.     AE(0) = InicActionEffect(-1, 0, 1, 0, False, "ONE_MONSTER_GO")
  86.     AE(1) = InicActionEffect(-2, 0, 2, 0, False, "TWO_MONSTER_GO")
  87.     AE(2) = InicActionEffect(0, -1, 0, 1, False, "ONE_MONK_GO")
  88.     AE(3) = InicActionEffect(0, -2, 0, 2, False, "TWO_MONK_GO")
  89.     AE(4) = InicActionEffect(-1, -1, 1, 1, False, "ONE_MONSTER_ONE_MONK_GO")
  90.     AE(5) = InicActionEffect(1, 0, -1, 0, True, "ONE_MONSTER_BACK")
  91.     AE(6) = InicActionEffect(2, 0, -2, 0, True, "TWO_MONSTER_BACK")
  92.     AE(7) = InicActionEffect(0, 1, 0, -1, True, "ONE_MONK_BACK")
  93.     AE(8) = InicActionEffect(0, 2, 0, -2, True, "TWO_MONK_BACK")
  94.     AE(9) = InicActionEffect(1, 1, -1, -1, True, "ONE_MONSTER_ONE_MONK_BACK")
  95.     InicAE = AE
  96. End Function
  97. Function InicActionEffect(local_monster_move As Integer, local_monk_move As Integer, remote_monster_move As Integer, remote_monk_move As Integer, Boat_To As Boolean, ActiveName As String) As ActionEffect
  98.     InicActionEffect.local_monster_move = local_monster_move
  99.     InicActionEffect.local_monk_move = local_monk_move
  100.     InicActionEffect.remote_monster_move = remote_monster_move
  101.     InicActionEffect.remote_monk_move = remote_monk_move
  102.     InicActionEffect.Boat_To = Boat_To
  103.     InicActionEffect.ActiveName = ActiveName
  104. End Function

  105. '=========================================================
  106. '设置状态
  107. Function SetItemState(ByRef mState() As ItemState, act As ActionEffect)
  108.     Dim lngLastID As Long, State As ItemState
  109.    
  110.     lngLastID = UBound(mState) + 1
  111.     ReDim Preserve mState(lngLastID)

  112.     State.local_monster = mState(lngLastID - 1).local_monster + act.local_monster_move
  113.     State.local_monk = mState(lngLastID - 1).local_monk + act.local_monk_move
  114.     State.remote_monster = mState(lngLastID - 1).remote_monster + act.remote_monster_move
  115.     State.remote_monk = mState(lngLastID - 1).remote_monk + act.remote_monk_move
  116.     State.BoatLocation = act.Boat_To
  117.     State.EffectName = act.ActiveName
  118.    
  119.     mState(lngLastID) = State
  120. End Function

  121. '=========================================================
  122. '是否成功
  123. Function IsFinalState(mState() As ItemState) As Boolean
  124.     Dim lngLastID As Long, State As ItemState
  125.     lngLastID = UBound(mState)
  126.     State = mState(lngLastID)
  127.    
  128.     If State.remote_monk = MONK_COUNT And State.remote_monster = MONSTER_COUNT Then
  129.         IsFinalState = True
  130.     Else
  131.         IsFinalState = False
  132.     End If
  133. End Function

  134. '=========================================================
  135. '是否可以移动
  136. Function CanTakeAction(mState() As ItemState, act As ActionEffect) As Boolean
  137.     Dim lngLastID As Long, State As ItemState, NextState As ItemState
  138.    
  139.     lngLastID = UBound(mState)
  140.     State = mState(lngLastID)
  141.    
  142.     If act.Boat_To = State.BoatLocation Then
  143.         CanTakeAction = False
  144.         Exit Function
  145.     End If
  146.    
  147.     With NextState
  148.         .local_monk = State.local_monk + act.local_monk_move
  149.         .local_monster = State.local_monster + act.local_monster_move
  150.         .remote_monk = State.remote_monk + act.remote_monk_move
  151.         .remote_monster = State.remote_monster + act.remote_monster_move
  152.         .BoatLocation = act.Boat_To
  153.     End With
  154.    
  155.     If NextState.local_monk < 0 Or NextState.local_monster < 0 Or NextState.remote_monk < 0 Or NextState.remote_monster < 0 Then
  156.         CanTakeAction = False
  157.         Exit Function
  158.     End If
  159.    
  160.     If ((NextState.local_monk < NextState.local_monster) And NextState.local_monk > 0) Or ((NextState.remote_monk < NextState.remote_monster) And NextState.remote_monk > 0) Then
  161.         CanTakeAction = False
  162.         Exit Function
  163.     End If
  164.    
  165.     For lngLastID = LBound(mState) To UBound(mState)
  166.         State = mState(lngLastID)
  167.         If State.BoatLocation = NextState.BoatLocation And _
  168.            State.local_monk = NextState.local_monk And _
  169.            State.local_monster = NextState.local_monster And _
  170.            State.remote_monk = NextState.remote_monk And _
  171.            State.remote_monster = NextState.remote_monster Then
  172.             CanTakeAction = False
  173.             Exit Function
  174.         End If
  175.     Next
  176.    
  177.     CanTakeAction = True
  178. End Function

复制代码


评分

4

查看全部评分

TA的精华主题

TA的得分主题

发表于 2019-12-23 16:19 | 显示全部楼层
虽然我看不懂,但觉得很高大上。
除了膜拜,暂时没有其他的应对方式。

TA的精华主题

TA的得分主题

 楼主| 发表于 2019-12-24 09:23 | 显示全部楼层
将动作枚举数组改为全局变量
  1. Option Explicit

  2. '状态
  3. Type ItemState
  4.     local_monster As Integer '本地妖怪数
  5.     local_monk   As Integer '本地和尚数
  6.     remote_monster  As Integer  '对岸妖怪数
  7.     remote_monk  As Integer  '对岸和尚数
  8.     BoatLocation As Boolean '船的位置 本地True,对岸 False
  9.     EffectName As String '动作名称
  10. End Type

  11. '动作
  12. Type ActionEffect
  13.     local_monster_move As Integer '本地妖怪移动数
  14.     local_monk_move  As Integer  '本地和尚移动数
  15.     remote_monster_move  As Integer  '对岸妖怪移动数
  16.     remote_monk_move  As Integer  '对岸和尚移动数
  17.     Boat_To As Boolean '船的移动方向 往本地True,往对岸 False
  18.     ActiveName As String '动作名称
  19. End Type

  20. '和尚、妖怪初始数
  21. Const MONK_COUNT As Long = 3
  22. Const MONSTER_COUNT As Long = 3

  23. '动作组,用于枚举
  24. Dim ActionEffects() As ActionEffect
  25. '记录有效的方法数
  26. Dim lngTotal As Long

  27. '=========================================================
  28. '主过程
  29. Sub Main()
  30.     Dim myState(0) As ItemState
  31.     '初始化状态
  32.     With myState(0)
  33.         .local_monk = MONK_COUNT
  34.         .local_monster = MONSTER_COUNT
  35.         .remote_monk = 0
  36.         .remote_monster = 0
  37.         .BoatLocation = True
  38.     End With
  39.     '初始化动作组
  40.     ActionEffects = InicAE
  41.    
  42.     lngTotal = 0
  43.     ProcessState myState
  44.    
  45.     MsgBox "路径计算完毕,共有【 " & lngTotal & " 】条"

  46. End Sub

  47. '=========================================================
  48. '逐个动作判断、递归
  49. Function ProcessState(mState() As ItemState)
  50.     Dim CurState() As ItemState, lngID As Long
  51.    
  52.     CurState = mState
  53.     If IsFinalState(CurState) Then
  54.         lngTotal = lngTotal + 1
  55.         Debug.Print PrintResult(CurState) '在立即窗口输出结果
  56.         Exit Function
  57.     End If

  58.     For lngID = 0 To 9
  59.         ProcessStateOnNewAction CurState, ActionEffects(lngID)
  60.     Next
  61.    
  62. End Function

  63. '=========================================================
  64. '判断某个动作是否可行,并执行
  65. Function ProcessStateOnNewAction(mState() As ItemState, act As ActionEffect)
  66.     Dim CurState() As ItemState
  67.     CurState = mState
  68.     If CanTakeAction(CurState, act) Then
  69.         SetItemState CurState, act
  70.         ProcessState CurState
  71.     End If
  72. End Function

  73. '=========================================================
  74. '输出结果
  75. Function PrintResult(mState() As ItemState) As String
  76.     Dim strTemp As String, lngID As Long
  77.     For lngID = LBound(mState) To UBound(mState)
  78.         strTemp = strTemp & "," & mState(lngID).EffectName & "[" & mState(lngID).local_monk & "-" & mState(lngID).local_monster & "-" & mState(lngID).remote_monk & "-" & mState(lngID).remote_monster & "]"
  79.     Next
  80.     PrintResult = strTemp
  81. End Function

  82. '=========================================================
  83. ' 初始化动作
  84. Function InicAE() As ActionEffect()
  85.     Dim AE(9) As ActionEffect
  86.     AE(0) = InicActionEffect(-1, 0, 1, 0, False, "ONE_MONSTER_GO")
  87.     AE(1) = InicActionEffect(-2, 0, 2, 0, False, "TWO_MONSTER_GO")
  88.     AE(2) = InicActionEffect(0, -1, 0, 1, False, "ONE_MONK_GO")
  89.     AE(3) = InicActionEffect(0, -2, 0, 2, False, "TWO_MONK_GO")
  90.     AE(4) = InicActionEffect(-1, -1, 1, 1, False, "ONE_MONSTER_ONE_MONK_GO")
  91.     AE(5) = InicActionEffect(1, 0, -1, 0, True, "ONE_MONSTER_BACK")
  92.     AE(6) = InicActionEffect(2, 0, -2, 0, True, "TWO_MONSTER_BACK")
  93.     AE(7) = InicActionEffect(0, 1, 0, -1, True, "ONE_MONK_BACK")
  94.     AE(8) = InicActionEffect(0, 2, 0, -2, True, "TWO_MONK_BACK")
  95.     AE(9) = InicActionEffect(1, 1, -1, -1, True, "ONE_MONSTER_ONE_MONK_BACK")
  96.     InicAE = AE
  97. End Function
  98. Function InicActionEffect(local_monster_move As Integer, local_monk_move As Integer, remote_monster_move As Integer, remote_monk_move As Integer, Boat_To As Boolean, ActiveName As String) As ActionEffect
  99.     InicActionEffect.local_monster_move = local_monster_move
  100.     InicActionEffect.local_monk_move = local_monk_move
  101.     InicActionEffect.remote_monster_move = remote_monster_move
  102.     InicActionEffect.remote_monk_move = remote_monk_move
  103.     InicActionEffect.Boat_To = Boat_To
  104.     InicActionEffect.ActiveName = ActiveName
  105. End Function

  106. '=========================================================
  107. '设置状态
  108. Function SetItemState(ByRef mState() As ItemState, act As ActionEffect)
  109.     Dim lngLastID As Long, State As ItemState
  110.    
  111.     lngLastID = UBound(mState) + 1
  112.     ReDim Preserve mState(lngLastID)

  113.     State.local_monster = mState(lngLastID - 1).local_monster + act.local_monster_move
  114.     State.local_monk = mState(lngLastID - 1).local_monk + act.local_monk_move
  115.     State.remote_monster = mState(lngLastID - 1).remote_monster + act.remote_monster_move
  116.     State.remote_monk = mState(lngLastID - 1).remote_monk + act.remote_monk_move
  117.     State.BoatLocation = act.Boat_To
  118.     State.EffectName = act.ActiveName
  119.    
  120.     mState(lngLastID) = State
  121. End Function

  122. '=========================================================
  123. '是否成功
  124. Function IsFinalState(mState() As ItemState) As Boolean
  125.     Dim lngLastID As Long, State As ItemState
  126.     lngLastID = UBound(mState)
  127.     State = mState(lngLastID)
  128.    
  129.     If State.remote_monk = MONK_COUNT And State.remote_monster = MONSTER_COUNT Then
  130.         IsFinalState = True
  131.     Else
  132.         IsFinalState = False
  133.     End If
  134. End Function

  135. '=========================================================
  136. '是否可以移动
  137. Function CanTakeAction(mState() As ItemState, act As ActionEffect) As Boolean
  138.     Dim lngLastID As Long, State As ItemState, NextState As ItemState
  139.    
  140.     lngLastID = UBound(mState)
  141.     State = mState(lngLastID)
  142.    
  143.     If act.Boat_To = State.BoatLocation Then
  144.         CanTakeAction = False
  145.         Exit Function
  146.     End If
  147.    
  148.     With NextState
  149.         .local_monk = State.local_monk + act.local_monk_move
  150.         .local_monster = State.local_monster + act.local_monster_move
  151.         .remote_monk = State.remote_monk + act.remote_monk_move
  152.         .remote_monster = State.remote_monster + act.remote_monster_move
  153.         .BoatLocation = act.Boat_To
  154.     End With
  155.    
  156.     If NextState.local_monk < 0 Or NextState.local_monster < 0 Or NextState.remote_monk < 0 Or NextState.remote_monster < 0 Then
  157.         CanTakeAction = False
  158.         Exit Function
  159.     End If
  160.    
  161.     If ((NextState.local_monk < NextState.local_monster) And NextState.local_monk > 0) Or ((NextState.remote_monk < NextState.remote_monster) And NextState.remote_monk > 0) Then
  162.         CanTakeAction = False
  163.         Exit Function
  164.     End If
  165.    
  166.     For lngLastID = LBound(mState) To UBound(mState)
  167.         State = mState(lngLastID)
  168.         If State.BoatLocation = NextState.BoatLocation And _
  169.            State.local_monk = NextState.local_monk And _
  170.            State.local_monster = NextState.local_monster And _
  171.            State.remote_monk = NextState.remote_monk And _
  172.            State.remote_monster = NextState.remote_monster Then
  173.             CanTakeAction = False
  174.             Exit Function
  175.         End If
  176.     Next
  177.    
  178.     CanTakeAction = True
  179. End Function


复制代码
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-5-1 02:33 , Processed in 0.041631 second(s), 11 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表