游戏开发论坛

 找回密码
 立即注册
搜索
查看: 3226|回复: 0

[分享] 学写 装备强化模拟器

[复制链接]

9

主题

55

帖子

296

积分

中级会员

Rank: 3Rank: 3

积分
296
发表于 2016-9-18 13:56:07 | 显示全部楼层 |阅读模式
看了  半不癫   发的帖子  [原创 [游戏策划] 马尔科夫链强化问题

很幸运他分享了源文件。学习后自己也照着写了一份,感谢
核心算法还是原来的 。我只是改了改界面,和优化了下性能。
觉得可能用起来会方便一点。

从分享中学习,当然也要回到分享。希望大家能指出其中的缺点和不足

装备强化模拟器.rar (40.33 KB, 下载次数: 219)

捕获6.PNG

  1. Option Explicit
  2. Option Base 0

  3. Public Tag_stop As Boolean '用来停止的开关变量

  4. 'GO 按钮直接调用此 sub
  5. Sub Button_Click()
  6.     '获取表单按钮上的文字,判断状态
  7.     If ActiveSheet.[go_btn].Caption = "G0" Then
  8.         Tag_stop = False
  9.         ActiveSheet.[go_btn].Caption = "快住手"
  10.         Call iTimer
  11.         ActiveSheet.[go_btn].Caption = "G0"
  12.     Else
  13.         ActiveSheet.[go_btn].Caption = "G0"
  14.         Tag_stop = True
  15.     End If

  16.    
  17. End Sub

  18. '显示测试所用时长
  19. Sub iTimer()
  20.     Dim T As Single
  21.     T = Timer
  22.     Call test_main '要计时的过程名称放这里
  23.     ActiveSheet.[Consuming_time] = Round(Timer - T, 5) & " 秒"
  24.    ' MsgBox Timer - t & " 秒"
  25. End Sub


  26. Sub test_main()

  27.     Dim currentLevel As Byte        '当前等级
  28.     Dim goalLevel As Byte         '目标等级
  29.     Dim total As Long             '强化测试样本次数
  30.     Dim table As Variant           '装备强化表

  31.     '-----------------------载入数据----------------------------------------------
  32.     '将 Sheet1 改为 ActiveSheet 也许能避免些麻烦
  33.     With ActiveSheet
  34.         table = .[Data].Resize(.[Data].End(xlDown).Row - 1, 4)
  35.         goalLevel = .[Goal_lvl]
  36.         total = .[Sample_size]
  37.         currentLevel = .[Current_Level]
  38.         
  39.         '表头
  40.         .[Avg_times].Offset(-1, 0) = "次数"
  41.         .[Avg_cost].Offset(-1, 0) = "花费"

  42.         '清空log
  43.         .[showLevel].Resize(.[showLevel].End(xlDown).Row - 1, 4).ClearContents

  44.     End With

  45.     '数据检查
  46.     If currentLevel <= 0 Or goalLevel <= currentLevel Or goalLevel > UBound(table) Or total <= 0 Then
  47.         MsgBox "初始等级必须大于等于 1。" & Chr(13) & "目标等级必须大于当前等级,小于配置表中的等级上限" & Chr(13) & "样本总数必须大于等于 1"
  48.         currentLevel = 1
  49.         Exit Sub
  50.     End If
  51.    
  52.     '----------------- 开始测试 -----------------
  53.     test_total currentLevel, goalLevel, total, table

  54. End Sub

  55. '强化到目标等级 goalLevel 测试 total 件, table 强化表数据
  56. Sub test_total(currentLevel As Byte, goalLevel As Byte, total As Long, table As Variant)

  57.     Dim i As Byte, jx As Byte, nextLevel As Byte
  58.     Dim showLevelRow As Integer, showLevelColumn As Integer
  59.     Dim j As Long, tt As Long
  60.     Dim my_mod As Single, lastTime As Single, tc As Single, timesTotal As Single

  61.     showLevelRow = ActiveSheet.[showLevel].Row '获取单位格行坐标
  62.     showLevelColumn = ActiveSheet.[showLevel].Column  '获取单位格列坐标

  63.     '---------------------------- 显示优化部分 ---------------------------
  64.     'WorksheetFunction.Log10(n) + 1 求一个数的位数
  65.     '用总数除以一个优化值,得到刷新UI的频率
  66.     my_mod = Application.Max(total / Round(-1.7 * (WorksheetFunction.Log10(total) + 0.5) + 15, 0), 1)
  67.    
  68.     '优化效率,先把字符串拆好
  69.     i = 0
  70.     For i = currentLevel To goalLevel
  71.         table(i, 3) = Split(table(i, 3), "+")
  72.         table(i, 4) = Split(table(i, 4), "+")
  73.         '安全检查
  74.         If UBound(table(i, 3)) <> UBound(table(i, 4)) Then
  75.             MsgBox "【等级范围】 与 【对应概率】字段的数据" & Chr(13) & " 必须一一对应!", , "数据有误!"
  76.             Exit Sub
  77.         End If
  78.     Next i

  79.     lastTime = Timer
  80.     '---------------------------------------------------------------------

  81.     i = tt = tc = 0
  82.     '当前到目标等级,每一级重复采样 total 次
  83.     For i = currentLevel To goalLevel - 1
  84.    
  85.         '---- 每当开始测试新等级前,先刷新和重置参数
  86.         timesTotal = 0
  87.         nextLevel = i + 1
  88.         jx = i - currentLevel
  89.         
  90. '        '----- 初始化显示 ----- 为了效率在循环中引用单元格时都用 cells(showLevelRow,showLevelColumn)
  91.         With ActiveSheet
  92.             .Cells(showLevelRow, showLevelColumn).Offset(jx, 0) = i & " -> " & i + 1     '从几级强化到几级
  93.             .Cells(showLevelRow, showLevelColumn + 1).Offset(jx, 0) = "计算中..."
  94.             .Cells(showLevelRow, showLevelColumn + 2).Offset(jx, 0) = "计算中..."
  95.             .Cells(showLevelRow, showLevelColumn + 3).Offset(jx, 0) = 0    '进度条初始刻度为 0
  96.         End With
  97.                
  98.         '----- 开始循环采样 -----
  99.         For j = 1 To total
  100.             '---- 中止开关 ------
  101.             If Tag_stop = True Then
  102.                 Exit Sub
  103.             End If
  104.         
  105.             '---- 从“当前等级”强化到“下一等级”所用的次数 ------
  106.             Do
  107.                 timesTotal = timesTotal + 1
  108.             Loop Until probatilisticChoice(table(i, 3), table(i, 4)) = nextLevel
  109.             
  110.             '----- 间隔刷新进度条 -----
  111.             If j Mod my_mod = 0 Or j = total Then
  112.                 ActiveSheet.Cells(showLevelRow, showLevelColumn + 3).Offset(jx, 0) = j / total    '更新进度条
  113.             End If

  114.             '---- 适当放手,避免假死 ------
  115.             If Timer - lastTime > 3 Then
  116.                 DoEvents
  117.                 lastTime = Timer
  118.             End If
  119.                         
  120.         Next j
  121.         '----- 刷新显示 -----
  122.         With ActiveSheet
  123.             .Cells(showLevelRow, showLevelColumn + 1).Offset(jx, 0) = total & "件 " & timesTotal & "次,平均:" & Round(timesTotal / total, 2) 'N 件装备强化到 X 的平均次数
  124.             .Cells(showLevelRow, showLevelColumn + 2).Offset(jx, 0) = total & "件,总花费" & timesTotal * table(i, 2) & " 平均:" & Round(timesTotal * table(i, 2) / total, 2) 'N 件装备强化到 X 的平均花费
  125.         End With

  126.         tt = tt + Round(timesTotal / total, 2)
  127.         tc = tc + Round(timesTotal * table(i, 2) / total, 2)
  128.     Next i
  129.    
  130.     '----- 汇总显示 -----
  131.     With ActiveSheet
  132.         .[Avg_times].Offset(-1, 0) = "平均次数: " & tt
  133.         .[Avg_cost].Offset(-1, 0) = "平均花费: " & tc
  134.     End With

  135. End Sub

  136. '按概率选择目标。按参数B中的概率,选择参数A中对应的目标
  137. '参数A = {鱼丸, 粗面, 叉烧, 牛肉}
  138. '参数B = {10%, 20%, 20%, 50%}
  139. Public Function probatilisticChoice(ByRef targetList As Variant, ByRef targetProbability As Variant) As Integer

  140.     Dim rnd_num As Integer        '随机数
  141.     Dim startPoint As Integer      '区间开始点,区间结束点就用 startPoint + targetProbability(i)

  142.     '------------ 初始化参数 ----------------
  143.     Randomize   '初始化随机种子
  144.     rnd_num = Int(Rnd() * 10000 + 1)    ' 随机区间  [1,10000]  这里因为是用的 万分比。
  145.     startPoint = 0
  146.     '------------ 遍历数组,选择目标 ----------------
  147.     Dim i As Byte
  148.     For i = 0 To UBound(targetProbability)
  149.         '定义区间范围: 开始点 = 结束点,结束点 = 自己 + 向右的偏移量
  150.         If rnd_num <= startPoint + targetProbability(i) Then
  151.             If rnd_num > startPoint Then
  152.                 probatilisticChoice = targetList(i)  '如果找到目标,直接返回值
  153.             End If
  154.         End If
  155.     Next i
  156. End Function
复制代码



您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-6-18 14:34

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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