USER
Private isUpdating As Boolean
Private Sub UserForm_Initialize()
' 初始化隨機數生成器
Randomize
Dim rng As Range
' 初始化 ComboBox1 到 ComboBox6 的資料
Set rng = ThisWorkbook.Sheets("武將表").Range("F12:F121")
InitComboBox Me.ComboBox1, rng
InitComboBox Me.ComboBox2, rng
InitComboBox Me.ComboBox3, rng
InitComboBox Me.ComboBox4, rng
InitComboBox Me.ComboBox5, rng
InitComboBox Me.ComboBox6, rng
' 初始化 ComboBox7 到 ComboBox18 的資料
Set rng = ThisWorkbook.Sheets("武將表").Range("AM122:AM234")
InitComboBox Me.ComboBox7, rng
InitComboBox Me.ComboBox8, rng
InitComboBox Me.ComboBox9, rng
InitComboBox Me.ComboBox10, rng
InitComboBox Me.ComboBox11, rng
InitComboBox Me.ComboBox12, rng
InitComboBox Me.ComboBox13, rng
InitComboBox Me.ComboBox14, rng
InitComboBox Me.ComboBox15, rng
InitComboBox Me.ComboBox16, rng
InitComboBox Me.ComboBox17, rng
InitComboBox Me.ComboBox18, rng
' 初始化兵種ComboBox
InitTypeComboBox Me.ComboBox19, ThisWorkbook.Sheets("武將表").Range("M11:Q11")
InitTypeComboBox Me.ComboBox20, ThisWorkbook.Sheets("武將表").Range("M11:Q11")
' 初始化特定範圍 TextBox 的值為空白
ClearTextBox 7, 12
End Sub
Private Sub InitComboBox(cmb As MSForms.comboBox, rng As Range)
Dim cell As Range
cmb.Clear
For Each cell In rng
If Not IsEmpty(cell.value) Then
cmb.AddItem cell.value
End If
Next cell
End Sub
Private Sub InitTypeComboBox(cmb As MSForms.comboBox, rng As Range)
Dim cell As Range
cmb.Clear
For Each cell In rng
If Not IsEmpty(cell.value) Then
cmb.AddItem cell.value
End If
Next cell
End Sub
Private Sub ClearTextBox(startIndex As Integer, endIndex As Integer)
Dim i As Integer
For i = startIndex To endIndex
Me.Controls("TextBox" & i).value = ""
Next i
End Sub
Private Sub ComboBox7_Change()
UpdateComboBoxesForSubset Array(Me.ComboBox7, Me.ComboBox8, Me.ComboBox9, Me.ComboBox13, Me.ComboBox14, Me.ComboBox15)
End Sub
Private Sub ComboBox8_Change()
UpdateComboBoxesForSubset Array(Me.ComboBox7, Me.ComboBox8, Me.ComboBox9, Me.ComboBox13, Me.ComboBox14, Me.ComboBox15)
End Sub
Private Sub ComboBox9_Change()
UpdateComboBoxesForSubset Array(Me.ComboBox7, Me.ComboBox8, Me.ComboBox9, Me.ComboBox13, Me.ComboBox14, Me.ComboBox15)
End Sub
Private Sub ComboBox10_Change()
UpdateComboBoxesForSubset Array(Me.ComboBox10, Me.ComboBox11, Me.ComboBox12, Me.ComboBox16, Me.ComboBox17, Me.ComboBox18)
End Sub
Private Sub ComboBox11_Change()
UpdateComboBoxesForSubset Array(Me.ComboBox10, Me.ComboBox11, Me.ComboBox12, Me.ComboBox16, Me.ComboBox17, Me.ComboBox18)
End Sub
Private Sub ComboBox12_Change()
UpdateComboBoxesForSubset Array(Me.ComboBox10, Me.ComboBox11, Me.ComboBox12, Me.ComboBox16, Me.ComboBox17, Me.ComboBox18)
End Sub
Private Sub ComboBox13_Change()
UpdateComboBoxesForSubset Array(Me.ComboBox7, Me.ComboBox8, Me.ComboBox9, Me.ComboBox13, Me.ComboBox14, Me.ComboBox15)
End Sub
Private Sub ComboBox14_Change()
UpdateComboBoxesForSubset Array(Me.ComboBox7, Me.ComboBox8, Me.ComboBox9, Me.ComboBox13, Me.ComboBox14, Me.ComboBox15)
End Sub
Private Sub ComboBox15_Change()
UpdateComboBoxesForSubset Array(Me.ComboBox7, Me.ComboBox8, Me.ComboBox9, Me.ComboBox13, Me.ComboBox14, Me.ComboBox15)
End Sub
Private Sub ComboBox16_Change()
UpdateComboBoxesForSubset Array(Me.ComboBox10, Me.ComboBox11, Me.ComboBox12, Me.ComboBox16, Me.ComboBox17, Me.ComboBox18)
End Sub
Private Sub ComboBox17_Change()
UpdateComboBoxesForSubset Array(Me.ComboBox10, Me.ComboBox11, Me.ComboBox12, Me.ComboBox16, Me.ComboBox17, Me.ComboBox18)
End Sub
Private Sub ComboBox18_Change()
UpdateComboBoxesForSubset Array(Me.ComboBox10, Me.ComboBox11, Me.ComboBox12, Me.ComboBox16, Me.ComboBox17, Me.ComboBox18)
End Sub
Private Sub UpdateComboBoxesForSubset(comboBoxes As Variant)
If isUpdating Then Exit Sub
isUpdating = True
Dim i As Integer, j As Integer
Dim cmb As MSForms.comboBox
Dim currentValue As String
Dim selectedValues As New Collection
' 收集所有被選擇的值
On Error Resume Next
For i = LBound(comboBoxes) To UBound(comboBoxes)
Set cmb = comboBoxes(i)
If cmb.value <> "" Then
selectedValues.Add cmb.value, CStr(cmb.value)
End If
Next i
On Error GoTo 0
' 更新每個 ComboBox 列表, 移除已選擇的值
For i = LBound(comboBoxes) To UBound(comboBoxes)
Set cmb = comboBoxes(i)
currentValue = cmb.value
InitComboBox cmb, ThisWorkbook.Sheets("武將表").Range("AM122:AM234")
' 移除已選擇的值
For j = cmb.ListCount - 1 To 0 Step -1
If IsValueInCollection(selectedValues, cmb.List(j)) And cmb.List(j) <> currentValue Then
cmb.RemoveItem j
End If
Next j
cmb.value = currentValue
Next i
isUpdating = False
End Sub
Private Function IsValueInCollection(coll As Collection, value As String) As Boolean
Dim item As Variant
IsValueInCollection = False
On Error Resume Next
For Each item In coll
If item = value Then
IsValueInCollection = True
Exit Function
End If
Next item
On Error GoTo 0
End Function
Private Sub ComboBox_Change(comboBox As MSForms.comboBox, displayTextBox As MSForms.TextBox, associatedTextBoxStart As Integer, displayTextBox67 As MSForms.TextBox)
If Not isUpdating Then
UpdateComboBoxes (IIf(comboBox.name Like "ComboBox[1-3]", 1, 2))
UpdateTextBox comboBox, displayTextBox
UpdateTextBox67WithComboBox comboBox, displayTextBox67
UpdateAssociatedTextBoxes comboBox, associatedTextBoxStart
End If
Dim txtIndex As Integer: txtIndex = CInt(Mid(comboBox.name, Len(comboBox.name)))
Me.Controls("TextBox" & (txtIndex + 6)).value = IIf(comboBox.value = "", "", "10000")
End Sub
Private Sub ComboBox1_Change()
ComboBox_Change Me.ComboBox1, Me.TextBox1, 13, Me.TextBox67
End Sub
Private Sub ComboBox2_Change()
ComboBox_Change Me.ComboBox2, Me.TextBox2, 19, Me.TextBox68
End Sub
Private Sub ComboBox3_Change()
ComboBox_Change Me.ComboBox3, Me.TextBox3, 25, Me.TextBox69
End Sub
Private Sub ComboBox4_Change()
ComboBox_Change Me.ComboBox4, Me.TextBox4, 31, Me.TextBox70
End Sub
Private Sub ComboBox5_Change()
ComboBox_Change Me.ComboBox5, Me.TextBox5, 37, Me.TextBox71
End Sub
Private Sub ComboBox6_Change()
ComboBox_Change Me.ComboBox6, Me.TextBox6, 43, Me.TextBox72
End Sub
Private Sub UpdateComboBoxes(group As Integer)
Dim items As Collection
Set items = New Collection
Dim i As Integer, j As Integer, k As Integer
Dim combos(1 To 3) As MSForms.comboBox
Dim selectedValues As Collection
Dim currentValue As String
isUpdating = True
Set selectedValues = New Collection
For i = 1 To 3
Set combos(i) = Me.Controls("ComboBox" & ((group - 1) * 3 + i))
Next i
' 收集所有已選擇的值
For i = 1 To 3
If combos(i).value <> "" Then
On Error Resume Next
selectedValues.Add combos(i).value, CStr(combos(i).value)
On Error GoTo 0
End If
Next i
' 更新可選項
For i = 1 To 3
currentValue = combos(i).value
InitComboBox combos(i), ThisWorkbook.Sheets("武將表").Range("F12:F121")
' 移除已選擇的值
For j = 1 To selectedValues.Count
If CStr(selectedValues(j)) <> currentValue Then
For k = combos(i).ListCount - 1 To 0 Step -1
If combos(i).List(k) = selectedValues(j) Then
combos(i).RemoveItem k
End If
Next k
End If
Next j
combos(i).value = currentValue
Next i
isUpdating = False
End Sub
Private Sub UpdateTextBox(cmb As MSForms.comboBox, txt As MSForms.TextBox)
Dim ws As Worksheet
Dim found As Range
Dim r As Range
Set ws = ThisWorkbook.Sheets("武將表")
Set r = ws.Range("F12:F121")
Set found = r.Find(What:=cmb.value, LookIn:=xlValues, LookAt:=xlWhole)
If Not found Is Nothing Then
txt.value = ws.Cells(found.Row, "AM").value
Else
txt.value = "未找到對應的值"
End If
End Sub
Private Sub UpdateAssociatedTextBoxes(cmb As MSForms.comboBox, startTextBoxIndex As Integer)
Dim ws As Worksheet
Dim found As Range
Dim r As Range
Dim rowIndex As Long
Dim colIndex As Integer
Dim txt As MSForms.TextBox
Set ws = ThisWorkbook.Sheets("武將表")
Set r = ws.Range("F12:F121")
Set found = r.Find(What:=cmb.value, LookIn:=xlValues, LookAt:=xlWhole)
If Not found Is Nothing Then
rowIndex = found.Row
For colIndex = 0 To 5
Set txt = Me.Controls("TextBox" & startTextBoxIndex + colIndex)
txt.value = ws.Cells(rowIndex, 30 + colIndex).value
Next colIndex
Else
For colIndex = 0 To 5
Set txt = Me.Controls("TextBox" & startTextBoxIndex + colIndex)
txt.value = ""
Next colIndex
End If
End Sub
Private Sub UpdateTextBox67WithComboBox(cmb As MSForms.comboBox, txt As MSForms.TextBox)
Dim ws As Worksheet
Dim r As Range
Dim found As Range
Set ws = ThisWorkbook.Sheets("武將表")
Set r = ws.Range("F12:F121")
Set found = r.Find(What:=cmb.value, LookIn:=xlValues, LookAt:=xlWhole)
If Not found Is Nothing Then
txt.value = ws.Cells(found.Row, "G").value
Else
txt.value = "未找到對應值"
End If
End Sub
Private Sub ComboBox19_Change()
UpdateProficiencyTextBoxes Me.ComboBox19, Me.ComboBox1, Me.ComboBox2, Me.ComboBox3, Me.TextBox49, Me.TextBox50, Me.TextBox51
End Sub
Private Sub ComboBox20_Change()
UpdateProficiencyTextBoxes Me.ComboBox20, Me.ComboBox4, Me.ComboBox5, Me.ComboBox6, Me.TextBox52, Me.TextBox53, Me.TextBox54
End Sub
Private Sub UpdateProficiencyTextBoxes(typeCombo As MSForms.comboBox, warriorCombo1 As MSForms.comboBox, warriorCombo2 As MSForms.comboBox, warriorCombo3 As MSForms.comboBox, txt1 As MSForms.TextBox, txt2 As MSForms.TextBox, txt3 As MSForms.TextBox)
Dim ws As Worksheet
Dim colOffset As Integer
Set ws = ThisWorkbook.Sheets("武將表")
colOffset = Application.WorksheetFunction.Match(typeCombo.value, ws.Range("M11:Q11"), 0) - 1
UpdateTextBoxForWarrior ws, warriorCombo1, colOffset, txt1
UpdateTextBoxForWarrior ws, warriorCombo2, colOffset, txt2
UpdateTextBoxForWarrior ws, warriorCombo3, colOffset, txt3
End Sub
Private Sub UpdateTextBoxForWarrior(ws As Worksheet, warriorCombo As MSForms.comboBox, colOffset As Integer, txt As MSForms.TextBox)
Dim r As Range
Dim found As Range
Set r = ws.Range("F12:F121")
Set found = r.Find(What:=warriorCombo.value, LookIn:=xlValues, LookAt:=xlWhole)
If Not found Is Nothing Then
txt.value = ws.Cells(found.Row, "M").Offset(0, colOffset).value
Else
txt.value = ""
End If
End Sub
Private Sub LimitTextBoxValue(txt As MSForms.TextBox)
Dim inputValue As Integer
inputValue = Val(txt.value)
If inputValue > 5 Then
txt.value = "5"
End If
End Sub
Private Sub UpdateTextBox_55()
Me.TextBox55.value = GetTotal(Me.CheckBox1, Me.CheckBox7, Me.TextBox61)
End Sub
Private Sub UpdateTextBox_56()
Me.TextBox56.value = GetTotal(Me.CheckBox2, Me.CheckBox8, Me.TextBox62)
End Sub
Private Sub UpdateTextBox_57()
Me.TextBox57.value = GetTotal(Me.CheckBox3, Me.CheckBox9, Me.TextBox63)
End Sub
Private Sub UpdateTextBox_58()
Me.TextBox58.value = GetTotal(Me.CheckBox4, Me.CheckBox10, Me.TextBox64)
End Sub
Private Sub UpdateTextBox_59()
Me.TextBox59.value = GetTotal(Me.CheckBox5, Me.CheckBox11, Me.TextBox65)
End Sub
Private Sub UpdateTextBox_60()
Me.TextBox60.value = GetTotal(Me.CheckBox6, Me.CheckBox12, Me.TextBox66)
End Sub
Private Function GetTotal(chk1 As MSForms.CheckBox, chk2 As MSForms.CheckBox, txtSrc As MSForms.TextBox) As String
Dim total As Integer
total = 0
If chk1.value = True Then total = total + 10
If chk2.value = True Then total = total + 10
total = total + (Val(txtSrc.value) * 10)
GetTotal = CStr(total)
End Function
Private Sub TextBox61_Change()
LimitTextBoxValue Me.TextBox61
UpdateTextBox_55
End Sub
Private Sub CheckBox1_Click()
UpdateTextBox_55
End Sub
Private Sub CheckBox7_Click()
UpdateTextBox_55
End Sub
Private Sub TextBox62_Change()
LimitTextBoxValue Me.TextBox62
UpdateTextBox_56
End Sub
Private Sub CheckBox2_Click()
UpdateTextBox_56
End Sub
Private Sub CheckBox8_Click()
UpdateTextBox_56
End Sub
Private Sub TextBox63_Change()
LimitTextBoxValue Me.TextBox63
UpdateTextBox_57
End Sub
Private Sub CheckBox3_Click()
UpdateTextBox_57
End Sub
Private Sub CheckBox9_Click()
UpdateTextBox_57
End Sub
Private Sub TextBox64_Change()
LimitTextBoxValue Me.TextBox64
UpdateTextBox_58
End Sub
Private Sub CheckBox4_Click()
UpdateTextBox_58
End Sub
Private Sub CheckBox10_Click()
UpdateTextBox_58
End Sub
Private Sub TextBox65_Change()
LimitTextBoxValue Me.TextBox65
UpdateTextBox_59
End Sub
Private Sub CheckBox5_Click()
UpdateTextBox_59
End Sub
Private Sub CheckBox11_Click()
UpdateTextBox_59
End Sub
Private Sub TextBox66_Change()
LimitTextBoxValue Me.TextBox66
UpdateTextBox_60
End Sub
Private Sub CheckBox6_Click()
UpdateTextBox_60
End Sub
Private Sub CheckBox12_Click()
UpdateTextBox_60
End Sub
Private Sub CommandButton1_Click()
' 檢查 ComboBox19 和 ComboBox20 是否為空
If Me.ComboBox19.value = "" Then
MsgBox "兵種請勿空白(我方)", vbExclamation, "輸入錯誤"
Exit Sub
End If
If Me.ComboBox20.value = "" Then
MsgBox "兵種請勿空白(敵方)", vbExclamation, "輸入錯誤"
Exit Sub
End If
' 初始化我方和敵方武將的集合
Dim allUnits As Collection
Set allUnits = New Collection
' 初始化武將及其屬性,並從 TextBox 獲取兵力
AddUnit allUnits, "主將", ComboBox1, 13, TextBox7, TextBox49
AddUnit allUnits, "副將", ComboBox2, 19, TextBox8, TextBox50
AddUnit allUnits, "副將", ComboBox3, 25, TextBox9, TextBox51
AddUnit allUnits, "主將", ComboBox4, 31, TextBox10, TextBox52
AddUnit allUnits, "副將", ComboBox5, 37, TextBox11, TextBox53
AddUnit allUnits, "副將", ComboBox6, 43, TextBox12, TextBox54
' 計算初始兵力總和
Dim initialTeam1Forces As Double
Dim initialTeam2Forces As Double
initialTeam1Forces = Val(TextBox7.value) + Val(TextBox8.value) + Val(TextBox9.value)
initialTeam2Forces = Val(TextBox10.value) + Val(TextBox11.value) + Val(TextBox12.value)
' 開始模擬回合
SimulateRounds allUnits, initialTeam1Forces, initialTeam2Forces
End Sub
Private Sub CommandButton2_Click()
' 清除 TextBox109 的內容
Me.TextBox109.Text = ""
' 清除 Label26 和 Label27 的內容
Me.Label26.Caption = ""
Me.Label27.Caption = ""
End Sub
Private Function GetProficiencyFactor(proficiency As String) As Double
Select Case proficiency
Case "S"
GetProficiencyFactor = 1.2
Case "A"
GetProficiencyFactor = 1
Case "B"
GetProficiencyFactor = 0.85
Case "C"
GetProficiencyFactor = 0.7
Case Else
GetProficiencyFactor = 1
End Select
End Function
Private Sub AddUnit(units As Collection, name As String, cmb As MSForms.comboBox, startIndex As Integer, forceTextBox As MSForms.TextBox, proficiencyTextBox As MSForms.TextBox)
If cmb.value <> "" Then
Dim unit As Object
Dim proficiencyFactor As Double
Dim comboIndex As Integer
Set unit = CreateObject("Scripting.Dictionary")
' 設置兵種適性
unit.Add "proficiency", proficiencyTextBox.value
' 預先計算適性調整因子
Select Case proficiencyTextBox.value
Case "S"
proficiencyFactor = 1.2
Case "A"
proficiencyFactor = 1#
Case "B"
proficiencyFactor = 0.85
Case "C"
proficiencyFactor = 0.7
Case Else
proficiencyFactor = 1#
End Select
unit.Add "name", name
unit.Add "startIndex", startIndex
unit.Add "speed", Val(Me.Controls("TextBox" & startIndex + 3).value) * proficiencyFactor
unit.Add "force", Val(Me.Controls("TextBox" & startIndex).value) * proficiencyFactor
unit.Add "warriorName", cmb.value
unit.Add "forces", Val(forceTextBox.value)
' 根據 ComboBox 名稱判斷 index
comboIndex = CInt(Mid(cmb.name, Len("ComboBox") + 1))
' 添加兵種
If comboIndex >= 1 And comboIndex <= 3 Then
unit.Add "兵種", Me.Controls("ComboBox19").value
ElseIf comboIndex >= 4 And comboIndex <= 6 Then
unit.Add "兵種", Me.Controls("ComboBox20").value
End If
unit.Add "兵種適性", proficiencyTextBox.value
' 添加戰法信息
Dim selfSkillName As String
selfSkillName = Me.Controls("TextBox" & comboIndex).Text
unit.Add "selfSkillName", selfSkillName
unit.Add "selfSkillProbability", GetWarSkillProbability(selfSkillName)
unit.Add "selfSkillType", GetWarSkillType(selfSkillName)
' 添加額外戰法信息
Dim additionalSkillName As String
additionalSkillName = Me.Controls("ComboBox" & (comboIndex + 6)).value
unit.Add "additionalSkillName", additionalSkillName
unit.Add "additionalSkillProbability", GetWarSkillProbability(additionalSkillName)
unit.Add "additionalSkillType", GetWarSkillType(additionalSkillName)
' 為第三組 ComboBox 初始化額外額外戰法信息
Dim extraSkillName As String
extraSkillName = Me.Controls("ComboBox" & (comboIndex + 12)).value
unit.Add "extraSkillName", extraSkillName
unit.Add "extraSkillProbability", GetWarSkillProbability(extraSkillName)
unit.Add "extraSkillType", GetWarSkillType(extraSkillName)
' 添加單位到集合
units.Add unit
End If
End Sub
Private Function SortUnitsBySpeed(units As Collection) As Collection
Dim i As Integer, j As Integer
Dim unit As Object
Dim sortedUnits As New Collection
For i = 1 To units.Count
Set unit = units(i)
If sortedUnits.Count = 0 Then
sortedUnits.Add unit
Else
For j = 1 To sortedUnits.Count
If unit("speed") > sortedUnits(j)("speed") Then
sortedUnits.Add unit, , j
Exit For
End If
Next j
If j > sortedUnits.Count Then sortedUnits.Add unit
End If
Next i
Set SortUnitsBySpeed = sortedUnits
End Function
Private Sub SimulateRounds(units As Collection, initialTeam1Forces As Double, initialTeam2Forces As Double)
Dim attacker As Object, target As Object
Dim speedSortedUnits As Collection
Dim i As Integer
Dim damage As Double
Dim targetIndex As Integer
Dim team1Forces As Double, team2Forces As Double
Dim displayText As String
' 初始化顯示文本並重新排列顯示順序
displayText = "準備回合" & vbCrLf & vbCrLf & "雙方屬性數值:" & vbCrLf
For i = 1 To units.Count
Dim unit As Object
Set unit = units(i)
Dim proficiencyFactor As Double
proficiencyFactor = GetProficiencyFactor(unit("proficiency"))
displayText = displayText & unit("name") & " (" & unit("warriorName") & ") 的兵種適性為" & unit("proficiency") & ",調整後屬性:" & _
"武力: " & Format(Val(Me.Controls("TextBox" & unit("startIndex")).value) * proficiencyFactor, "0.0") & ", " & _
"智力: " & Format(Val(Me.Controls("TextBox" & (unit("startIndex") + 1)).value) * proficiencyFactor, "0.0") & ", " & _
"統率: " & Format(Val(Me.Controls("TextBox" & (unit("startIndex") + 2)).value) * proficiencyFactor, "0.0") & ", " & _
"速度: " & Format(Val(Me.Controls("TextBox" & (unit("startIndex") + 3)).value) * proficiencyFactor, "0.0") & ", " & _
"政治: " & Format(Val(Me.Controls("TextBox" & (unit("startIndex") + 4)).value) * proficiencyFactor, "0.0") & ", " & _
"魅力: " & Format(Val(Me.Controls("TextBox" & (unit("startIndex") + 5)).value) * proficiencyFactor, "0.0") & vbCrLf
Next i
' 開始模擬
For i = 1 To 8 ' 限制到最多八回合
displayText = displayText & vbCrLf & "第 " & i & " 回合:" & vbCrLf
' 按速度排序單元
Set speedSortedUnits = SortUnitsBySpeed(units)
' 初始化隊伍力量
team1Forces = 0
team2Forces = 0
For Each attacker In speedSortedUnits
' 忽略已陣亡的角色
If attacker("forces") > 0 Then
Dim attackerTeam As String
If attacker("startIndex") <= 25 Then
attackerTeam = "我方"
team1Forces = team1Forces + attacker("forces")
Else
attackerTeam = "敵方"
team2Forces = team2Forces + attacker("forces")
End If
' 試圖選擇一個有效的目標
Do
targetIndex = Application.WorksheetFunction.RandBetween(1, speedSortedUnits.Count)
Set target = speedSortedUnits(targetIndex)
Loop While (SameTeam(attacker("startIndex"), target("startIndex")) Or target("forces") <= 0)
' 進行戰法發動
TryActivateSkills attacker, attackerTeam, target, displayText
' 計算普通攻擊傷害
damage = CalculateDamage(attacker, target)
' 更新目標的剩餘兵力
Dim remainingForces As Double
remainingForces = target("forces") - damage
If remainingForces < 0 Then
remainingForces = 0
End If
' 更新字典中的兵力
target("forces") = remainingForces
' A 開始行動和攻擊描述
displayText = displayText & "(" & attackerTeam & ") " & attacker("warriorName") & " 對 " & target("warriorName") & " 發動普通攻擊," & _
target("warriorName") & " 損失了兵力 " & damage & ",剩餘 " & remainingForces & " 兵力。" & vbCrLf
End If
Next attacker
' 添加分隔線
displayText = displayText & String(150, "-") & vbCrLf
' 停止模擬,如果任一主將被擊敗
If units(1)("forces") <= 0 Or units(4)("forces") <= 0 Then
Exit For
End If
Next i
' 更新 Label26 和 Label27 來顯示剩餘/初始兵力
Me.Label26.Caption = team1Forces & "/" & initialTeam1Forces
Me.Label27.Caption = team2Forces & "/" & initialTeam2Forces
' 確定勝利者
If team1Forces > team2Forces Then
displayText = displayText & "我方取得勝利!" & vbCrLf
ElseIf team1Forces < team2Forces Then
displayText = displayText & "敵方取得勝利!" & vbCrLf
Else
displayText = displayText & "平局!" & vbCrLf
End If
' 在 TextBox109 中顯示累積的文本
Me.TextBox109.Text = displayText
End Sub
Private Sub TryActivateSkills(attacker As Object, team As String, target As Object, ByRef displayText As String)
Dim rng As Double
' Debug output to check if the skill names and probabilities are set correctly.
Debug.Print "Skill Name: " & attacker("selfSkillName")
Debug.Print "Skill Probability: " & attacker("selfSkillProbability")
' 發動自身戰法
rng = Rnd()
If rng <= attacker("selfSkillProbability") And target("forces") > 0 Then
displayText = displayText & "(" & team & ") " & attacker("warriorName") & " 嘗試對 " & target("warriorName") & " 發動 " & attacker("selfSkillName") & _
" (" & Format(attacker("selfSkillProbability") * 100, "0.0") & "%)!成功!" & vbCrLf
Else
displayText = displayText & "(" & team & ") " & attacker("warriorName") & " 嘗試對 " & target("warriorName") & " 發動 " & attacker("selfSkillName") & _
" (" & Format(attacker("selfSkillProbability") * 100, "0.0") & "%)!未發動。" & vbCrLf
End If
' 發動選擇戰法1 (來自 ComboBox[7-12])
rng = Rnd()
Debug.Print "Skill Name: " & attacker("additionalSkillName")
Debug.Print "Skill Probability: " & attacker("additionalSkillProbability")
If rng <= attacker("additionalSkillProbability") And target("forces") > 0 Then
displayText = displayText & "(" & team & ") " & attacker("warriorName") & " 嘗試對 " & target("warriorName") & " 發動 " & attacker("additionalSkillName") & _
" (" & Format(attacker("additionalSkillProbability") * 100, "0.0") & "%)!成功!" & vbCrLf
Else
displayText = displayText & "(" & team & ") " & attacker("warriorName") & " 嘗試對 " & target("warriorName") & " 發動 " & attacker("additionalSkillName") & _
" (" & Format(attacker("additionalSkillProbability") * 100, "0.0") & "%)!未發動。" & vbCrLf
End If
' 發動選擇戰法2 (來自 ComboBox[13-18])
rng = Rnd()
Debug.Print "Skill Name: " & attacker("extraSkillName")
Debug.Print "Skill Probability: " & attacker("extraSkillProbability")
If rng <= attacker("extraSkillProbability") And target("forces") > 0 Then
displayText = displayText & "(" & team & ") " & attacker("warriorName") & " 嘗試對 " & target("warriorName") & " 發動 " & attacker("extraSkillName") & _
" (" & Format(attacker("extraSkillProbability") * 100, "0.0") & "%)!成功!" & vbCrLf
Else
displayText = displayText & "(" & team & ") " & attacker("warriorName") & " 嘗試對 " & target("warriorName") & " 發動 " & attacker("extraSkillName") & _
" (" & Format(attacker("extraSkillProbability") * 100, "0.0") & "%)!未發動。" & vbCrLf
End If
' 進行普通攻擊
displayText = displayText & "(" & team & ") " & attacker("warriorName") & " 對 " & target("warriorName") & " 發動了普通攻擊!" & vbCrLf
End Sub
Private Function GetWarSkillProbability(skillName As String) As Double
Dim ws As Worksheet
Dim r As Range
Dim found As Range
Set ws = ThisWorkbook.Sheets("武將表")
Set r = ws.Range("AM12:AM234") ' 假設技能名稱信息位於這個範圍
Set found = r.Find(What:=Trim(skillName), LookIn:=xlValues, LookAt:=xlWhole)
If Not found Is Nothing Then
GetWarSkillProbability = ws.Cells(found.Row, "AO").value
Else
GetWarSkillProbability = 0
End If
End Function
Private Function GetWarSkillType(skillName As String) As String
Dim ws As Worksheet
Dim r As Range
Dim found As Range
Set ws = ThisWorkbook.Sheets("武將表")
Set r = ws.Range("AM12:AM234") ' 假設技能名稱信息位於這個範圍
Set found = r.Find(What:=Trim(skillName), LookIn:=xlValues, LookAt:=xlWhole)
If Not found Is Nothing Then
GetWarSkillType = ws.Cells(found.Row, "AN").value
Else
GetWarSkillType = ""
End If
End Function
Private Function CalculateDamage(attacker As Object, target As Object) As Double
Dim attack As Double
Dim defense As Double
Dim advantage As Double
Dim proficiencyFactor As Double
Dim Z As Double
Dim S As Double
Dim baseDamage As Double
Dim minimumDamage As Double
attack = attacker("force")
defense = target("force")
proficiencyFactor = GetProficiencyFactor(attacker("proficiency"))
advantage = 1
' 驗證兵種剋制
Select Case attacker("兵種")
Case "騎兵"
If target("兵種") = "盾兵" Or target("兵種") = "器械" Then
advantage = 1.15
End If
Case "盾兵"
If target("兵種") = "弓兵" Or target("兵種") = "器械" Then
advantage = 1.15
End If
Case "弓兵"
If target("兵種") = "槍兵" Or target("兵種") = "器械" Then
advantage = 1.15
End If
Case "槍兵"
If target("兵種") = "騎兵" Or target("兵種") = "器械" Then
advantage = 1.15
End If
End Select
' 計算 Z 和 S
Z = attack * proficiencyFactor * advantage
S = ((Z - defense) / 150 + 1) * (attacker("forces") / 20)
' 判斷是否需要使用傷害公式 2
If S <= 0 Then
baseDamage = GetBaseDamage(attacker("forces"))
minimumDamage = GetMinimumDamage(attacker("forces"))
S = baseDamage + (attack * 1.6 - defense * 1.6) * 0.9 + minimumDamage
If S < 0 Then S = 0 ' 防止負值
End If
' 無條件進位傷害至整數
CalculateDamage = Application.WorksheetFunction.RoundUp(S, 0)
End Function
Private Function GetBaseDamage(forces As Double) As Double
Select Case forces
Case Is <= 1000: GetBaseDamage = 88
Case Is <= 2000: GetBaseDamage = 176
Case Is <= 3000: GetBaseDamage = 232
Case Is <= 4000: GetBaseDamage = 276
Case Is <= 5000: GetBaseDamage = 314
Case Is <= 6000: GetBaseDamage = 334
Case Is <= 7000: GetBaseDamage = 350
Case Is <= 8000: GetBaseDamage = 364
Case Is <= 9000: GetBaseDamage = 376
Case Else: GetBaseDamage = 387
End Select
End Function
Private Function GetMinimumDamage(forces As Double) As Double
Select Case forces
Case Is <= 1000: GetMinimumDamage = 20
Case Is <= 2000: GetMinimumDamage = 40
Case Is <= 3000: GetMinimumDamage = 53
Case Is <= 4000: GetMinimumDamage = 64
Case Is <= 5000: GetMinimumDamage = 73
Case Is <= 6000: GetMinimumDamage = 77
Case Is <= 7000: GetMinimumDamage = 81
Case Is <= 8000: GetMinimumDamage = 84
Case Is <= 9000: GetMinimumDamage = 87
Case Else: GetMinimumDamage = 90
End Select
End Function
Private Function SameTeam(index1 As Integer, index2 As Integer) As Boolean
' 判斷兩個索引是否在相同隊伍
SameTeam = (index1 <= 25 And index2 <= 25) Or (index1 > 25 And index2 > 25)
End Function
' 第一組 CommandButton 和 TextBox 的事件處理
Private Sub CommandButton3_Click()
UpdateValues Me.TextBox55, Me.TextBox13, Me.TextBox73
End Sub
Private Sub CommandButton4_Click()
UpdateValues Me.TextBox55, Me.TextBox14, Me.TextBox74
End Sub
Private Sub CommandButton5_Click()
UpdateValues Me.TextBox55, Me.TextBox15, Me.TextBox75
End Sub
Private Sub CommandButton6_Click()
UpdateValues Me.TextBox55, Me.TextBox16, Me.TextBox76
End Sub
Private Sub CommandButton7_Click()
UpdateValues Me.TextBox55, Me.TextBox17, Me.TextBox77
End Sub
Private Sub CommandButton8_Click()
UpdateValues Me.TextBox55, Me.TextBox18, Me.TextBox78
End Sub
' 第二組 CommandButton 和 TextBox 的事件
Private Sub CommandButton9_Click()
UpdateValues Me.TextBox56, Me.TextBox19, Me.TextBox79
End Sub
Private Sub CommandButton10_Click()
UpdateValues Me.TextBox56, Me.TextBox20, Me.TextBox80
End Sub
Private Sub CommandButton11_Click()
UpdateValues Me.TextBox56, Me.TextBox21, Me.TextBox81
End Sub
Private Sub CommandButton12_Click()
UpdateValues Me.TextBox56, Me.TextBox22, Me.TextBox82
End Sub
Private Sub CommandButton13_Click()
UpdateValues Me.TextBox56, Me.TextBox23, Me.TextBox83
End Sub
Private Sub CommandButton14_Click()
UpdateValues Me.TextBox56, Me.TextBox24, Me.TextBox84
End Sub
' 第三組 CommandButton 和 TextBox 的事件
Private Sub CommandButton15_Click()
UpdateValues Me.TextBox57, Me.TextBox25, Me.TextBox85
End Sub
Private Sub CommandButton16_Click()
UpdateValues Me.TextBox57, Me.TextBox26, Me.TextBox86
End Sub
Private Sub CommandButton17_Click()
UpdateValues Me.TextBox57, Me.TextBox27, Me.TextBox87
End Sub
Private Sub CommandButton18_Click()
UpdateValues Me.TextBox57, Me.TextBox28, Me.TextBox88
End Sub
Private Sub CommandButton19_Click()
UpdateValues Me.TextBox57, Me.TextBox29, Me.TextBox89
End Sub
Private Sub CommandButton20_Click()
UpdateValues Me.TextBox57, Me.TextBox30, Me.TextBox90
End Sub
' 第四組 CommandButton 和 TextBox 的事件
Private Sub CommandButton21_Click()
UpdateValues Me.TextBox58, Me.TextBox31, Me.TextBox91
End Sub
Private Sub CommandButton22_Click()
UpdateValues Me.TextBox58, Me.TextBox32, Me.TextBox92
End Sub
Private Sub CommandButton23_Click()
UpdateValues Me.TextBox58, Me.TextBox33, Me.TextBox93
End Sub
Private Sub CommandButton24_Click()
UpdateValues Me.TextBox58, Me.TextBox34, Me.TextBox94
End Sub
Private Sub CommandButton25_Click()
UpdateValues Me.TextBox58, Me.TextBox35, Me.TextBox95
End Sub
Private Sub CommandButton26_Click()
UpdateValues Me.TextBox58, Me.TextBox36, Me.TextBox96
End Sub
' 第五組 CommandButton 和 TextBox 的事件
Private Sub CommandButton27_Click()
UpdateValues Me.TextBox59, Me.TextBox37, Me.TextBox97
End Sub
Private Sub CommandButton28_Click()
UpdateValues Me.TextBox59, Me.TextBox38, Me.TextBox98
End Sub
Private Sub CommandButton29_Click()
UpdateValues Me.TextBox59, Me.TextBox39, Me.TextBox99
End Sub
Private Sub CommandButton30_Click()
UpdateValues Me.TextBox59, Me.TextBox40, Me.TextBox100
End Sub
Private Sub CommandButton31_Click()
UpdateValues Me.TextBox59, Me.TextBox41, Me.TextBox101
End Sub
Private Sub CommandButton32_Click()
UpdateValues Me.TextBox59, Me.TextBox42, Me.TextBox102
End Sub
' 第六組 CommandButton 和 TextBox 的事件
Private Sub CommandButton33_Click()
UpdateValues Me.TextBox60, Me.TextBox43, Me.TextBox103
End Sub
Private Sub CommandButton34_Click()
UpdateValues Me.TextBox60, Me.TextBox44, Me.TextBox104
End Sub
Private Sub CommandButton35_Click()
UpdateValues Me.TextBox60, Me.TextBox45, Me.TextBox105
End Sub
Private Sub CommandButton36_Click()
UpdateValues Me.TextBox60, Me.TextBox46, Me.TextBox106
End Sub
Private Sub CommandButton37_Click()
UpdateValues Me.TextBox60, Me.TextBox47, Me.TextBox107
End Sub
Private Sub CommandButton38_Click()
UpdateValues Me.TextBox60, Me.TextBox48, Me.TextBox108
End Sub
' 更新邏輯的核心子程序
Private Sub UpdateValues(sourceTextBox As MSForms.TextBox, incrementTextBox As MSForms.TextBox, counterTextBox As MSForms.TextBox)
Dim currentValue As Integer
Dim currentIncrement As Double
Dim currentCount As Integer
' 確認數值有效
currentValue = SafeVal(sourceTextBox)
currentIncrement = SafeValDouble(incrementTextBox)
currentCount = SafeVal(counterTextBox)
' 確保 Textbox 值大於零才能操作
If currentValue > 0 Then
' 減少來源 TextBox 的值
sourceTextBox.value = currentValue - 1
' 增加到相應 TextBox 並保留一位小數
currentIncrement = currentIncrement + 1
incrementTextBox.value = Format(currentIncrement, "0.0")
' 增至計數 TextBox
counterTextBox.value = currentCount + 1
End If
End Sub
Private Function SafeVal(txt As MSForms.TextBox) As Integer
On Error Resume Next
SafeVal = Val(txt.value)
On Error GoTo 0
End Function
Private Function SafeValDouble(txt As MSForms.TextBox) As Double
On Error Resume Next
SafeValDouble = CDbl(txt.value)
On Error GoTo 0
End Function
抱歉請把程式加上來,順便檢查有沒有錯誤ASSISTANT
以上的程式碼相當複雜且功能多樣化,執行時涉及多個 ComboBox 和 TextBox 的初始化、更新,以及戰鬥模擬處理。根據之前的對話,我們已經為戰法的觸發進行了區分,下面是您需要的完整程式碼,帶有檢查和增加的說明:
```vba
Private isUpdating As Boolean
Private Sub UserForm_Initialize()
' 初始化隨機數生成器
Randomize
Dim rng As Range
' 初始化 ComboBox1 到 ComboBox6 的資料
Set rng = ThisWorkbook.Sheets("武將表").Range("F12:F121")
InitComboBox Me.ComboBox1, rng
InitComboBox Me.ComboBox2, rng
InitComboBox Me.ComboBox3, rng
InitComboBox Me.ComboBox4, rng
InitComboBox Me.ComboBox5, rng
InitComboBox Me.ComboBox6, rng
' 初始化 ComboBox7 到 ComboBox18 的資料
Set rng = ThisWorkbook.Sheets("武將表").Range("AM122:AM234")
InitComboBox Me.ComboBox7, rng
InitComboBox Me.ComboBox8, rng
InitComboBox Me.ComboBox9, rng
InitComboBox Me.ComboBox10, rng
InitComboBox Me.ComboBox11, rng
InitComboBox Me.ComboBox12, rng
InitComboBox Me.ComboBox13, rng
InitComboBox Me.ComboBox14, rng
InitComboBox Me.ComboBox15, rng
InitComboBox Me.ComboBox16, rng
InitComboBox Me.ComboBox17, rng
InitComboBox Me.ComboBox18, rng
' 初始化兵種ComboBox
InitTypeComboBox Me.ComboBox19, ThisWorkbook.Sheets("武將表").Range("M11:Q11")
InitTypeComboBox Me.ComboBox20, ThisWorkbook.Sheets("武將表").Range("M11:Q11")
' 初始化特定範圍 TextBox 的值為空白
ClearTextBox 7, 12
End Sub
Private Sub InitComboBox(cmb As MSForms.ComboBox, rng As Range)
Dim cell As Range
cmb.Clear
For Each cell In rng
If Not IsEmpty(cell.Value) Then
cmb.AddItem cell.Value
End If
Next cell
End Sub
Private Sub InitTypeComboBox(cmb As MSForms.ComboBox, rng As Range)
Dim cell As Range
cmb.Clear
For Each cell In rng
If Not IsEmpty(cell.Value) Then
cmb.AddItem cell.Value
End If
Next cell
End Sub
Private Sub ClearTextBox(startIndex As Integer, endIndex As Integer)
Dim i As Integer
For i = startIndex To endIndex
Me.Controls("TextBox" & i).Value = ""
Next i
End Sub
Private Sub ComboBox7_Change()
UpdateComboBoxesForSubset Array(Me.ComboBox7, Me.ComboBox8, Me.ComboBox9, Me.ComboBox13, Me.ComboBox14, Me.ComboBox15)
End Sub
Private Sub ComboBox8_Change()
UpdateComboBoxesForSubset Array(Me.ComboBox7, Me.ComboBox8, Me.ComboBox9, Me.ComboBox13, Me.ComboBox14, Me.ComboBox15)
End Sub
Private Sub ComboBox9_Change()
UpdateComboBoxesForSubset Array(Me.ComboBox7, Me.ComboBox8, Me.ComboBox9, Me.ComboBox13, Me.ComboBox14, Me.ComboBox15)
End Sub
Private Sub ComboBox10_Change()
UpdateComboBoxesForSubset Array(Me.ComboBox10, Me.ComboBox11, Me.ComboBox12, Me.ComboBox16, Me.ComboBox17, Me.ComboBox18)
End Sub
Private Sub ComboBox11_Change()
UpdateComboBoxesForSubset Array(Me.ComboBox10, Me.ComboBox11, Me.ComboBox12, Me.ComboBox16, Me.ComboBox17, Me.ComboBox18)
End Sub
Private Sub ComboBox12_Change()
UpdateComboBoxesForSubset Array(Me.ComboBox10, Me.ComboBox11, Me.ComboBox12, Me.ComboBox16, Me.ComboBox17, Me.ComboBox18)
End Sub
Private Sub ComboBox13_Change()
UpdateComboBoxesForSubset Array(Me.ComboBox7, Me.ComboBox8, Me.ComboBox9, Me.ComboBox13, Me.ComboBox14, Me.ComboBox15)
End Sub
Private Sub ComboBox14_Change()
UpdateComboBoxesForSubset Array(Me.ComboBox7, Me.ComboBox8, Me.ComboBox9, Me.ComboBox13, Me.ComboBox14, Me.ComboBox15)
End Sub
Private Sub ComboBox15_Change()
UpdateComboBoxesForSubset Array(Me.ComboBox7, Me.ComboBox8, Me.ComboBox9, Me.ComboBox13, Me.ComboBox14, Me.ComboBox15)
End Sub
Private Sub ComboBox16_Change()
UpdateComboBoxesForSubset Array(Me.ComboBox10, Me.ComboBox11, Me.ComboBox12, Me.ComboBox16, Me.ComboBox17, Me.ComboBox18)
End Sub
Private Sub ComboBox17_Change()
UpdateComboBoxesForSubset Array(Me.ComboBox10, Me.ComboBox11, Me.ComboBox12, Me.ComboBox16, Me.ComboBox17, Me.ComboBox18)
End Sub
Private Sub ComboBox18_Change()
UpdateComboBoxesForSubset Array(Me.ComboBox10, Me.ComboBox11, Me.ComboBox12, Me.ComboBox16, Me.ComboBox17, Me.ComboBox18)
End Sub
Private Sub UpdateComboBoxesForSubset(comboBoxes As Variant)
If isUpdating Then Exit Sub
isUpdating = True
Dim i As Integer, j As Integer
Dim cmb As MSForms.ComboBox
Dim currentValue As String
Dim selectedValues As New Collection
' 收集所有被選擇的值
On Error Resume Next
For i = LBound(comboBoxes) To UBound(comboBoxes)
Set cmb = comboBoxes(i)
If cmb.Value <> "" Then
selectedValues.Add cmb.Value, CStr(cmb.Value)
End If
Next i
On Error GoTo 0
' 更新每個 ComboBox 列表, 移除已選擇的值
For i = LBound(comboBoxes) To UBound(comboBoxes)
Set cmb = comboBoxes(i)
currentValue = cmb.Value
InitComboBox cmb, ThisWorkbook.Sheets("武將表").Range("AM122:AM234")
' 移除已選擇的值
For j = cmb.ListCount - 1 To 0 Step -1
If IsValueInCollection(selectedValues, cmb.List(j)) And cmb.List(j) <> currentValue Then
cmb.RemoveItem j
End If
Next j
cmb.Value = currentValue
Next i
isUpdating = False
End Sub
Private Function IsValueInCollection(coll As Collection, value As String) As Boolean
Dim item As Variant
IsValueInCollection = False
On Error Resume Next
For Each item In coll
If item = value Then
IsValueInCollection = True
Exit Function
End If
Next item
On Error GoTo 0
End Function
Private Sub ComboBox_Change(comboBox As MSForms.ComboBox, displayTextBox As MSForms.TextBox, associatedTextBoxStart As Integer, displayTextBox67 As MSForms.TextBox)
If Not isUpdating Then
UpdateComboBoxes (IIf(comboBox.Name Like "ComboBox[1-3]", 1, 2))
UpdateTextBox comboBox, displayTextBox
UpdateTextBox67WithComboBox comboBox, displayTextBox67
UpdateAssociatedTextBoxes comboBox, associatedTextBoxStart
End If
Dim txtIndex As Integer: txtIndex = CInt(Mid(comboBox.Name, Len(comboBox.Name)))
Me.Controls("TextBox" & (txtIndex + 6)).Value = IIf(comboBox.Value = "", "", "10000")
End Sub
Private Sub ComboBox1_Change()
ComboBox_Change Me.ComboBox1, Me.TextBox1, 13, Me.TextBox67
End Sub
Private Sub ComboBox2_Change()
ComboBox_Change Me.ComboBox2, Me.TextBox2, 19, Me.TextBox68
End Sub
Private Sub ComboBox3_Change()
ComboBox_Change Me.ComboBox3, Me.TextBox3, 25, Me.TextBox69
End Sub
Private Sub ComboBox4_Change()
ComboBox_Change Me.ComboBox4, Me.TextBox4, 31, Me.TextBox70
End Sub
Private Sub ComboBox5_Change()
ComboBox_Change Me.ComboBox5, Me.TextBox5, 37, Me.TextBox71
End Sub
Private Sub ComboBox6_Change()
ComboBox_Change Me.ComboBox6, Me.TextBox6, 43, Me.TextBox72
End Sub
Private Sub UpdateComboBoxes(group As Integer)
Dim items As Collection
Set items = New Collection
Dim i As Integer, j As Integer, k As Integer
Dim combos(1 To 3) As MSForms.ComboBox
Dim selectedValues As Collection
Dim currentValue As String
isUpdating = True
Set selectedValues = New Collection
For i = 1 To 3
Set combos(i) = Me.Controls("ComboBox" & ((group - 1) * 3 + i))
Next i
' 收集所有已選擇的值
For i = 1 To 3
If combos(i).Value <> "" Then
On Error Resume Next
selectedValues.Add combos(i).Value, CStr(combos(i).Value)
On Error GoTo 0
End If
Next i
' 更新可選項
For i = 1 To 3
currentValue = combos(i).Value
InitComboBox combos(i), ThisWorkbook.Sheets("武將表").Range("F12:F121")
' 移除已選擇的值
For j = 1 To selectedValues.Count
If CStr(selectedValues(j)) <> currentValue Then
For k = combos(i).ListCount - 1 To 0 Step -1
If combos(i).List(k) = selectedValues(j) Then
combos(i).RemoveItem k
End If
Next k
End If
Next j
combos(i).Value = currentValue
Next i
isUpdating = False
End Sub
Private Sub UpdateTextBox(cmb As MSForms.ComboBox, txt As MSForms.TextBox)
Dim ws As Worksheet
Dim found As Range
Dim r As Range
Set ws = ThisWorkbook.Sheets("武將表")
Set r = ws.Range("F12:F121")
Set found = r.Find(What:=cmb.Value, LookIn:=xlValues, LookAt:=xlWhole)
If Not found Is Nothing Then
txt.Value = ws.Cells(found.Row, "AM").Value
Else
txt.Value = "未找到對應的值"
End If
End Sub
Private Sub UpdateAssociatedTextBoxes(cmb As MSForms.ComboBox, startTextBoxIndex As Integer)
Dim ws As Worksheet
Dim found As Range
Dim r As Range
Dim rowIndex As Long
Dim colIndex As Integer
Dim txt As MSForms.TextBox
Set ws = ThisWorkbook.Sheets("武將表")
Set r = ws.Range("F12:F121")
Set found = r.Find(What:=cmb.Value, LookIn:=xlValues, LookAt:=xlWhole)
If Not found Is Nothing Then
rowIndex = found.Row
For colIndex = 0 To 5
Set txt = Me.Controls("TextBox" & startTextBoxIndex + colIndex)
txt.Value = ws.Cells(rowIndex, 30 + colIndex).Value
Next colIndex
Else
For colIndex = 0 To 5
Set txt = Me.Controls("TextBox" & startTextBoxIndex + colIndex)
txt.Value = ""
Next colIndex
End If
End Sub
Private Sub UpdateTextBox67WithComboBox(cmb As MSForms.ComboBox, txt As MSForms.TextBox)
Dim ws As Worksheet
Dim r As Range
Dim found As Range
Set ws = ThisWorkbook.Sheets("武將表")
Set r = ws.Range("F12:F121")
Set found = r.Find(What:=cmb.Value, LookIn:=xlValues, LookAt:=xlWhole)
If Not found Is Nothing Then
txt.Value = ws.Cells(found.Row, "G").Value
Else
txt.Value = "未找到對應值"
End If
End Sub
Private Sub ComboBox19_Change()
UpdateProficiencyTextBoxes Me.ComboBox19, Me.ComboBox1, Me.ComboBox2, Me.ComboBox3, Me.TextBox49, Me.TextBox50, Me.TextBox51
End Sub
Private Sub ComboBox20_Change()
UpdateProficiencyTextBoxes Me.ComboBox20, Me.ComboBox4, Me.ComboBox5, Me.ComboBox6, Me.TextBox52, Me.TextBox53, Me.TextBox54
End Sub
Private Sub UpdateProficiencyTextBoxes(typeCombo As MSForms.ComboBox, warriorCombo1 As MSForms.ComboBox, warriorCombo2 As MSForms.ComboBox, warriorCombo3 As MSForms.ComboBox, txt1 As MSForms.TextBox, txt2 As MSForms.TextBox, txt3 As MSForms.TextBox)
Dim ws As Worksheet
Dim colOffset As Integer
Set ws = ThisWorkbook.Sheets("武將表")
colOffset = Application.WorksheetFunction.Match(typeCombo.Value, ws.Range("M11:Q11"), 0) - 1
UpdateTextBoxForWarrior ws, warriorCombo1, colOffset, txt1
UpdateTextBoxForWarrior ws, warriorCombo2, colOffset, txt2
UpdateTextBoxForWarrior ws, warriorCombo3, colOffset, txt3
End Sub
Private Sub UpdateTextBoxForWarrior(ws As Worksheet, warriorCombo As MSForms.ComboBox, colOffset As Integer, txt As MSForms.TextBox)
Dim r As Range
Dim found As Range
Set r = ws.Range("F12:F121")
Set found = r.Find(What:=warriorCombo.Value, LookIn:=xlValues, LookAt:=xlWhole)
If Not found Is Nothing Then
txt.Value = ws.Cells(found.Row, "M").Offset(0, colOffset).Value
Else
txt.Value = ""
End If
End Sub
Private Sub LimitTextBoxValue(txt As MSForms.TextBox)
Dim inputValue As Integer
inputValue = Val(txt.Value)
If inputValue > 5 Then
txt.Value = "5"
End If
End Sub
Private Sub UpdateTextBox_55()
Me.TextBox55.Value = GetTotal(Me.CheckBox1, Me.CheckBox7, Me.TextBox61)
End Sub
Private Sub UpdateTextBox_56()
Me.TextBox56.Value = GetTotal(Me.CheckBox2, Me.CheckBox8, Me.TextBox62)
End Sub
Private Sub UpdateTextBox_57()
Me.TextBox57.Value = GetTotal(Me.CheckBox3, Me.CheckBox9, Me.TextBox63)
End Sub
Private Sub UpdateTextBox_58()
Me.TextBox58.Value = GetTotal(Me.CheckBox4, Me.CheckBox10, Me.TextBox64)
End Sub
Private Sub UpdateTextBox_59()
Me.TextBox59.Value = GetTotal(Me.CheckBox5, Me.CheckBox11, Me.TextBox65)
End Sub
Private Sub UpdateTextBox_60()
Me.TextBox60.Value = GetTotal(Me.CheckBox6, Me.CheckBox12, Me.TextBox66)
End Sub
Private Function GetTotal(chk1 As MSForms.CheckBox, chk2 As MSForms.CheckBox, txtSrc As MSForms.TextBox) As String
Dim total As Integer
total = 0
If chk1.Value = True Then total = total + 10
If chk2.Value = True Then total = total + 10
total = total + (Val(txtSrc.Value) * 10)
GetTotal = CStr(total)
End Function
Private Sub TextBox61_Change()
LimitTextBoxValue Me.TextBox61
UpdateTextBox_55
End Sub
Private Sub CheckBox1_Click()
UpdateTextBox_55
End Sub
Private Sub CheckBox7_Click()
UpdateTextBox_55
End Sub
Private Sub TextBox62_Change()
LimitTextBoxValue Me.TextBox62
UpdateTextBox_56
End Sub
Private Sub CheckBox2_Click()
UpdateTextBox_56
End Sub
Private Sub CheckBox8_Click()
UpdateTextBox_56
End Sub
Private Sub TextBox63_Change()
LimitTextBoxValue Me.TextBox63
UpdateTextBox_57
End Sub
Private Sub CheckBox3_Click()
UpdateTextBox_57
End Sub
Private Sub CheckBox9_Click()
UpdateTextBox_57
End Sub
Private Sub TextBox64_Change()
LimitTextBoxValue Me.TextBox64
UpdateTextBox_58
End Sub
Private Sub CheckBox4_Click()
UpdateTextBox_58
End Sub
Private Sub CheckBox10_Click()
UpdateTextBox_58
End Sub
Private Sub TextBox65_Change()
LimitTextBoxValue Me.TextBox65
UpdateTextBox_59
End Sub
Private Sub CheckBox5_Click()
UpdateTextBox_59
End Sub
Private Sub CheckBox11_Click()
UpdateTextBox_59
End Sub
Private Sub TextBox66_Change()
LimitTextBoxValue Me.TextBox66
UpdateTextBox_60
End Sub
Private Sub CheckBox6_Click()
UpdateTextBox_60
End Sub
Private Sub CheckBox12_Click()
UpdateTextBox_60
End Sub
Private Sub CommandButton1_Click()
' 檢查 ComboBox19 和 ComboBox20 是否為空
If Me.ComboBox19.Value = "" Then
MsgBox "兵種請勿空白(我方)", vbExclamation, "輸入錯誤"
Exit Sub
End If
If Me.ComboBox20.Value = "" Then
MsgBox "兵種請勿空白(敵方)", vbExclamation, "輸入錯誤"
Exit Sub
End If
' 初始化我方和敵方武將的集合
Dim allUnits As Collection
Set allUnits = New Collection
' 初始化武將及其屬性,並從 TextBox 獲取兵力
AddUnit allUnits, "主將", ComboBox1, 13, TextBox7, TextBox49
AddUnit allUnits, "副將", ComboBox2, 19, TextBox8, TextBox50
AddUnit allUnits, "副將", ComboBox3, 25, TextBox9, TextBox51
AddUnit allUnits, "主將", ComboBox4, 31, TextBox10, TextBox52
AddUnit allUnits, "副將", ComboBox5, 37, TextBox11, TextBox53
AddUnit allUnits, "副將", ComboBox6, 43, TextBox12, TextBox54
' 計算初始兵力總和
Dim initialTeam1Forces As Double
Dim initialTeam2Forces As Double
initialTeam1Forces = Val(TextBox7.Value) + Val(TextBox8.Value) + Val(TextBox9.Value)
initialTeam2Forces = Val(TextBox10.Value) + Val(TextBox11.Value) + Val(TextBox12.Value)
' 開始模擬回合
SimulateRounds allUnits, initialTeam1Forces, initialTeam2Forces
End Sub
Private Sub CommandButton2_Click()
' 清除 TextBox109 的內容
Me.TextBox109.Text = ""
' 清除 Label26 和 Label27 的內容
Me.Label26.Caption = ""
Me.Label27.Caption = ""
End Sub
Private Function GetProficiencyFactor(proficiency As String) As Double
Select Case proficiency
Case "S"
GetProficiencyFactor = 1.2
Case "A"
GetProficiencyFactor = 1
Case "B"
GetProficiencyFactor = 0.85
Case "C"
GetProficiencyFactor = 0.7
Case Else
GetProficiencyFactor = 1
End Select
End Function
Private Sub AddUnit(units As Collection, name As String, cmb As MSForms.ComboBox, startIndex As Integer, forceTextBox As MSForms.TextBox, proficiencyTextBox As MSForms.TextBox)
If cmb.Value <> "" Then
Dim unit As Object
Dim proficiencyFactor As Double
Dim comboIndex As Integer
Set unit = CreateObject("Scripting.Dictionary")
' 設置兵種適性
unit.Add "proficiency", proficiencyTextBox.Value
' 預先計算適性調整因子
Select Case proficiencyTextBox.Value
Case "S"
proficiencyFactor = 1.2
Case "A"
proficiencyFactor = 1#
Case "B"
proficiencyFactor = 0.85
Case "C"
proficiencyFactor = 0.7
Case Else
proficiencyFactor = 1#
End Select
unit.Add "name", name
unit.Add "startIndex", startIndex
unit.Add "speed", Val(Me.Controls("TextBox" & startIndex + 3).Value) * proficiencyFactor
unit.Add "force", Val(Me.Controls("TextBox" & startIndex).Value) * proficiencyFactor
unit.Add "warriorName", cmb.Value
unit.Add "forces", Val(forceTextBox.Value)
' 根據 ComboBox 名稱判斷 index
comboIndex = CInt(Mid(cmb.Name, Len("ComboBox") + 1))
' 添加兵種
If comboIndex >= 1 And comboIndex <= 3 Then
unit.Add "兵種", Me.Controls("ComboBox19").Value
ElseIf comboIndex >= 4 And comboIndex <= 6 Then
unit.Add "兵種", Me.Controls("ComboBox20").Value
End If
unit.Add "兵種適性", proficiencyTextBox.Value
' 添加戰法信息
Dim selfSkillName As String
selfSkillName = Me.Controls("TextBox" & comboIndex).Text
unit.Add "selfSkillName", selfSkillName
unit.Add "selfSkillProbability", GetWarSkillProbability(selfSkillName)
unit.Add "selfSkillType", GetWarSkillType(selfSkillName)
' 添加額外戰法信息
Dim additionalSkillName As String
additionalSkillName = Me.Controls("ComboBox" & (comboIndex + 6)).Value
unit.Add "additionalSkillName", additionalSkillName
unit.Add "additionalSkillProbability", GetWarSkillProbability(additionalSkillName)
unit.Add "additionalSkillType", GetWarSkillType(additionalSkillName)
' 為第三組 ComboBox 初始化額外額外戰法信息
Dim extraSkillName As String
extraSkillName = Me.Controls("ComboBox" & (comboIndex + 12)).Value
unit.Add "extraSkillName", extraSkillName
unit.Add "extraSkillProbability", GetWarSkillProbability(extraSkillName)
unit.Add "extraSkillType", GetWarSkillType(extraSkillName)
' 添加單位到集合
units.Add unit
End If
End Sub
Private Function SortUnitsBySpeed(units As Collection) As Collection
Dim i As Integer, j As Integer
Dim unit As Object
Dim sortedUnits As New Collection
For i = 1 To units.Count
Set unit = units(i)
If sortedUnits.Count = 0 Then
sortedUnits.Add unit
Else
For j = 1 To sortedUnits.Count
If unit("speed") > sortedUnits(j)("speed") Then
sortedUnits.Add unit, , j
Exit For
End If
Next j
If j > sortedUnits.Count Then sortedUnits.Add unit
End If
Next i
Set SortUnitsBySpeed = sortedUnits
End Function
Private Sub SimulateRounds(units As Collection, initialTeam1Forces As Double, initialTeam2Forces As Double)
Dim attacker As Object, target As Object
Dim speedSortedUnits As Collection
Dim i As Integer
Dim damage As Double
Dim targetIndex As Integer
Dim team1Forces As Double, team2Forces As Double
Dim displayText As String
' 初始化顯示文本並重新排列顯示順序
displayText = "準備回合" & vbCrLf & vbCrLf & "雙方屬性數值:" & vbCrLf
For i = 1 To units.Count
Dim unit As Object
Set unit = units(i)
Dim proficiencyFactor As Double
proficiencyFactor = GetProficiencyFactor(unit("proficiency"))
displayText = displayText & unit("name") & " (" & unit("warriorName") & ") 的兵種適性為" & unit("proficiency") & ",調整後屬性:" & _
"武力: " & Format(Val(Me.Controls("TextBox" & unit("startIndex")).Value) * proficiencyFactor, "0.0") & ", " & _
"智力: " & Format(Val(Me.Controls("TextBox" & (unit("startIndex") + 1)).Value) * proficiencyFactor, "0.0") & ", " & _
"統率: " & Format(Val(Me.Controls("TextBox" & (unit("startIndex") + 2)).Value) * proficiencyFactor, "0.0") & ", " & _
"速度: " & Format(Val(Me.Controls("TextBox" & (unit("startIndex") + 3)).Value) * proficiencyFactor, "0.0") & ", " & _
"政治: " & Format(Val(Me.Controls("TextBox" & (unit("startIndex") + 4)).Value) * proficiencyFactor, "0.0") & ", " & _
"魅力: " & Format(Val(Me.Controls("TextBox" & (unit("startIndex") + 5)).Value) * proficiencyFactor, "0.0") & vbCrLf
Next i
' 準備回合:觸發指揮、兵種、陣營類型的戰法
For Each attacker In units
If attacker("forces") > 0 Then
TriggerPreparationSkills attacker, displayText
End If
Next attacker
' 開始模擬
For i = 1 To 8 ' 限制到最多八回合
displayText = displayText & vbCrLf & "第 " & i & " 回合:" & vbCrLf
' 按速度排序單元
Set speedSortedUnits = SortUnitsBySpeed(units)
' 初始化隊伍力量
team1Forces = 0
team2Forces = 0
For Each attacker In speedSortedUnits
' 忽略已陣亡的角色
If attacker("forces") > 0 Then
Dim attackerTeam As String
If attacker("startIndex") <= 25 Then
attackerTeam = "我方"
team1Forces = team1Forces + attacker("forces")
Else
attackerTeam = "敵方"
team2Forces = team2Forces + attacker("forces")
End If
' 試圖選擇一個有效的目標
Do
targetIndex = Application.WorksheetFunction.RandBetween(1, speedSortedUnits.Count)
Set target = speedSortedUnits(targetIndex)
Loop While (SameTeam(attacker("startIndex"), target("startIndex")) Or target("forces") <= 0)
' 進行戰法發動
TryCombatSkills attacker, attackerTeam, target, displayText
' 計算普通攻擊傷害
damage = CalculateDamage(attacker, target)
' 更新目標的剩餘兵力
Dim remainingForces As Double
remainingForces = target("forces") - damage
If remainingForces < 0 Then
remainingForces = 0
End If
' 更新字典中的兵力
target("forces") = remainingForces
' A 開始行動和攻擊描述
displayText = displayText & "(" & attackerTeam & ") " & attacker("warriorName") & " 對 " & target("warriorName") & " 發動普通攻擊," & _
target("warriorName") & " 損失了兵力 " & damage & ",剩餘 " & remainingForces & " 兵力。" & vbCrLf
End If
Next attacker
' 添加分隔線
displayText = displayText & String(150, "-") & vbCrLf
' 停止模擬,如果任一主將被擊敗
If units(1)("forces") <= 0 Or units(4)("forces") <= 0 Then
Exit For
End If
Next i
' 更新 Label26 和 Label27 來顯示剩餘/初始兵力
Me.Label26.Caption = team1Forces & "/" & initialTeam1Forces
Me.Label27.Caption = team2Forces & "/" & initialTeam2Forces
' 確定勝利者
If team1Forces > team2Forces Then
displayText = displayText & "我方取得勝利!" & vbCrLf
ElseIf team1Forces < team2Forces Then
displayText = displayText & "敵方取得勝利!" & vbCrLf
Else
displayText = displayText & "平局!" & vbCrLf
End If
' 在 TextBox109 中顯示累積的文本
Me.TextBox109.Text = displayText
End Sub
Private Sub TriggerPreparationSkills(attacker As Object, ByRef displayText As String)
Dim skillTypes As Variant
skillTypes = Array("指揮", "兵種", "陣營")
TriggerSkillsByType attacker, skillTypes, displayText, "準備階段"
End Sub
Private Sub TryCombatSkills(attacker As Object, team As String, target As Object, ByRef displayText As String)
Dim skillTypes As Variant
skillTypes = Array("主動", "突擊", "被動")
TriggerSkillsByType attacker, skillTypes, displayText, "戰鬥回合"
End Sub
Private Sub TriggerSkillsByType(attacker As Object, types As Variant, ByRef displayText As String, phase As String)
Dim skillName As String, skillType As String
Dim rng As Double
Dim isTriggered As Boolean
' 檢查各自的技能是否在當前階段可觸發
For Each skillName In Array(attacker("selfSkillName"), attacker("additionalSkillName"), attacker("extraSkillName"))
skillType = GetWarSkillType(skillName)
If IsInList(skillType, types) Then
rng = Rnd()
isTriggered = rng <= GetWarSkillProbability(skillName)
displayText = displayText & "(" & phase & ") " & attacker("warriorName") & " 嘗試發動 " & skillName & " (" _
& Format(GetWarSkillProbability(skillName) * 100, "0.0") & "%) - " & IIf(isTriggered, "成功", "失敗") & "。" & vbCrLf
End If
Next skillName
End Sub
Private Function IsInList(value As String, list As Variant) As Boolean
Dim i As Integer
For i = LBound(list) To UBound(list)
If list(i) = value Then
IsInList = True
Exit Function
End If
Next i
IsInList = False
End Function
Private Function GetWarSkillProbability(skillName As String) As Double
Dim ws As Worksheet
Dim r As Range
Dim found As Range
Set ws = ThisWorkbook.Sheets("武將表")
Set r = ws.Range("AM12:AM234") ' 假設技能名稱信息位於這個範圍
Set found = r.Find(What:=Trim(skillName), LookIn:=xlValues, LookAt:=xlWhole)
If Not found Is Nothing Then
GetWarSkillProbability = ws.Cells(found.Row, "AO").Value
Else
GetWarSkillProbability = 0
End If
End Function
Private Function GetWarSkillType(skillName As String) As String
Dim ws As Worksheet
Dim r As Range
Dim found As Range
Set ws = ThisWorkbook.Sheets("武將表")
Set r = ws.Range("AM12:AM234") ' 假設技能名稱信息位於這個範圍
Set found = r.Find(What:=Trim(skillName), LookIn:=xlValues, LookAt:=xlWhole)
If Not found Is Nothing Then
GetWarSkillType = ws.Cells(found.Row, "AN").Value
Else
GetWarSkillType = ""
End If
End Function
Private Function CalculateDamage(attacker As Object, target As Object) As Double
Dim attack As Double
Dim defense As Double
Dim advantage As Double
Dim proficiencyFactor As Double
Dim Z As Double
Dim S As Double
Dim baseDamage As Double
Dim minimumDamage As Double
attack = attacker("force")
defense = target("force")
proficiencyFactor = GetProficiencyFactor(attacker("proficiency"))
advantage = 1
' 驗證兵種剋制
Select Case attacker("兵種")
Case "騎兵"
If target("兵種") = "盾兵" Or target("兵種") = "器械" Then
advantage = 1.15
End If
Case "盾兵"
If target("兵種") = "弓兵" Or target("兵種") = "器械" Then
advantage = 1.15
End If
Case "弓兵"
If target("兵種") = "槍兵" Or target("兵種") = "器械" Then
advantage = 1.15
End If
Case "槍兵"
If target("兵種") = "騎兵" Or target("兵種") = "器械" Then
advantage = 1.15
End If
End Select
' 計算 Z 和 S
Z = attack * proficiencyFactor * advantage
S = ((Z - defense) / 150 + 1) * (attacker("forces") / 20)
' 判斷是否需要使用傷害公式 2
If S <= 0 Then
baseDamage = GetBaseDamage(attacker("forces"))
minimumDamage = GetMinimumDamage(attacker("forces"))
S = baseDamage + (attack * 1.6 - defense * 1.6) * 0.9 + minimumDamage
If S < 0 Then S = 0 ' 防止負值
End If
' 無條件進位傷害至整數
CalculateDamage = Application.WorksheetFunction.RoundUp(S, 0)
End Function
Private Function GetBaseDamage(forces As Double) As Double
Select Case forces
Case Is <= 1000: GetBaseDamage = 88
Case Is <= 2000: GetBaseDamage = 176
Case Is <= 3000: GetBaseDamage = 232
Case Is <= 4000: GetBaseDamage = 276
Case Is <= 5000: GetBaseDamage = 314
Case Is <= 6000: GetBaseDamage = 334
Case Is <= 7000: GetBaseDamage = 350
Case Is <= 8000: GetBaseDamage = 364
Case Is <= 9000: GetBaseDamage = 376
Case Else: GetBaseDamage = 387
End Select
End Function
Private Function GetMinimumDamage(forces As Double) As Double
Select Case forces
Case Is <= 1000: GetMinimumDamage = 20
Case Is <= 2000: GetMinimumDamage = 40
Case Is <= 3000: GetMinimumDamage = 53
Case Is <= 4000: GetMinimumDamage = 64
Case Is <= 5000: GetMinimumDamage = 73
Case Is <= 6000: GetMinimumDamage = 77
Case Is <= 7000: GetMinimumDamage = 81
Case Is <= 8000: GetMinimumDamage = 84
Case Is <= 9000: GetMinimumDamage = 87
Case Else: GetMinimumDamage = 90
End Select
End Function
Private Function SameTeam(index1 As Integer, index2 As Integer) As Boolean
' 判斷兩個索引是否在相同隊伍
SameTeam = (index1 <= 25 And index2 <= 25) Or (index1 > 25 And index2 > 25)
End Function
' 第一組 CommandButton 和 TextBox 的事件處理
Private Sub CommandButton3_Click()
UpdateValues Me.TextBox55, Me.TextBox13, Me.TextBox73
End Sub
Private Sub CommandButton4_Click()
UpdateValues Me.TextBox55, Me.TextBox14, Me.TextBox74
End Sub
Private Sub CommandButton5_Click()
UpdateValues Me.TextBox55, Me.TextBox15, Me.TextBox75
End Sub
Private Sub CommandButton6_Click()
UpdateValues Me.TextBox55, Me.TextBox16, Me.TextBox76
End Sub
Private Sub CommandButton7_Click()
UpdateValues Me.TextBox55, Me.TextBox17, Me.TextBox77
End Sub
Private Sub CommandButton8_Click()
UpdateValues Me.TextBox55, Me.TextBox18, Me.TextBox78
End Sub
' 第二組 CommandButton 和 TextBox 的事件
Private Sub CommandButton9_Click()
UpdateValues Me.TextBox56, Me.TextBox19, Me.TextBox79
End Sub
Private Sub CommandButton10_Click()
UpdateValues Me.TextBox56, Me.TextBox20, Me.TextBox80
End Sub
Private Sub CommandButton11_Click()
UpdateValues Me.TextBox56, Me.TextBox21, Me.TextBox81
End Sub
Private Sub CommandButton12_Click()
UpdateValues Me.TextBox56, Me.TextBox22, Me.TextBox82
End Sub
Private Sub CommandButton13_Click()
UpdateValues Me.TextBox56, Me.TextBox23, Me.TextBox83
End Sub
Private Sub CommandButton14_Click()
UpdateValues Me.TextBox56, Me.TextBox24, Me.TextBox84
End Sub
' 第三組 CommandButton 和 TextBox 的事件
Private Sub CommandButton15_Click()
UpdateValues Me.TextBox57, Me.TextBox25, Me.TextBox85
End Sub
Private Sub CommandButton16_Click()
UpdateValues Me.TextBox57, Me.TextBox26, Me.TextBox86
End Sub
Private Sub CommandButton17_Click()
UpdateValues Me.TextBox57, Me.TextBox27, Me.TextBox87
End Sub
Private Sub CommandButton18_Click()
UpdateValues Me.TextBox57, Me.TextBox28, Me.TextBox88
End Sub
Private Sub CommandButton19_Click()
UpdateValues Me.TextBox57, Me.TextBox29, Me.TextBox89
End Sub
Private Sub CommandButton20_Click()
UpdateValues Me.TextBox57, Me.TextBox30, Me.TextBox90
End Sub
' 第四組 CommandButton 和 TextBox 的事件
Private Sub CommandButton21_Click()
UpdateValues Me.TextBox58, Me.TextBox31, Me.TextBox91
End Sub
Private Sub CommandButton22_Click()
UpdateValues Me.TextBox58, Me.TextBox32, Me.TextBox92
End Sub
Private Sub CommandButton23_Click()
UpdateValues Me.TextBox58, Me.TextBox33, Me.TextBox93
End Sub
Private Sub CommandButton24_Click()
UpdateValues Me.TextBox58, Me.TextBox34, Me.TextBox94
End Sub
Private Sub CommandButton25_Click()
UpdateValues Me.TextBox58, Me.TextBox35, Me.TextBox95
End Sub
Private Sub CommandButton26_Click()
UpdateValues Me.TextBox58, Me.TextBox36, Me.TextBox96
End Sub
' 第五組 CommandButton 和 TextBox 的事件
Private Sub CommandButton27_Click()
UpdateValues Me.TextBox59, Me.TextBox37, Me.TextBox97
End Sub
Private Sub CommandButton28_Click()
UpdateValues Me.TextBox59, Me.TextBox38, Me.TextBox98
End Sub
Private Sub CommandButton29_Click()
UpdateValues Me.TextBox59, Me.TextBox39, Me.TextBox99
End Sub
Private Sub CommandButton30_Click()
UpdateValues Me.TextBox59, Me.TextBox40, Me.TextBox100
End Sub
Private Sub CommandButton31_Click()
UpdateValues Me.TextBox59, Me.TextBox41, Me.TextBox101
End Sub
Private Sub CommandButton32_Click()
UpdateValues Me.TextBox59, Me.TextBox42, Me.TextBox102
End Sub
' 第六組 CommandButton 和 TextBox 的事件
Private Sub CommandButton33_Click()
UpdateValues Me.TextBox60, Me.TextBox43, Me.TextBox103
End Sub
Private Sub CommandButton34_Click()
UpdateValues Me.TextBox60, Me.TextBox44, Me.TextBox104
End Sub
Private Sub CommandButton35_Click()
UpdateValues Me.TextBox60, Me.TextBox45, Me.TextBox105
End Sub
Private Sub CommandButton36_Click()
UpdateValues Me.TextBox60, Me.TextBox46, Me.TextBox106
End Sub
Private Sub CommandButton37_Click()
UpdateValues Me.TextBox60, Me.TextBox47, Me.TextBox107
End Sub
Private Sub CommandButton38_Click()
UpdateValues Me.TextBox60, Me.TextBox48, Me.TextBox108
End Sub
' 更新邏輯的核心子程序
Private Sub UpdateValues(sourceTextBox As MSForms.TextBox, incrementTextBox As MSForms.TextBox, counterTextBox As MSForms.TextBox)
Dim currentValue As Integer
Dim currentIncrement As Double
Dim currentCount As Integer
' 確認數值有效
currentValue = SafeVal(sourceTextBox)
currentIncrement = SafeValDouble(incrementTextBox)
currentCount = SafeVal(counterTextBox)
' 確保 Textbox 值大於零才能操作
If currentValue > 0 Then
' 減少來源 TextBox 的值
sourceTextBox.Value = currentValue - 1
' 增加到相應 TextBox 並保留一位小數
currentIncrement = currentIncrement + 1
incrementTextBox.Value = Format(currentIncrement, "0.0")
' 增至計數 TextBox
counterTextBox.Value = currentCount + 1
End If
End Sub
Private Function SafeVal(txt As MSForms.TextBox) As Integer
On Error Resume Next
SafeVal = Val(txt.Value)
On Error GoTo 0
End Function
Private Function SafeValDouble(txt As MSForms.TextBox) As Double
On Error Resume Next
SafeValDouble = CDbl(txt.Value)
On Error GoTo 0
End Function
```
### 程式檢查和補充:
1. **變數和範圍確認**:檢查範圍(如 `"武將表"` 中的資料範圍)是否正確,以及所有控件名稱(`ComboBox` 和 `TextBox`)是否存在且正確連接。
2. **錯誤處理**:加上基本的錯誤處理來防止未能找到資料時的問題。
3. **邏輯檢查**:確認戰法的觸發機率和類型能夠通過如 `GetWarSkillProbability`、`GetWarSkillType` 等函數正確獲取。如果需要對戰鬥邏輯做出改進,可以在相關子程序內進行調整。
如程式運行後遇到具體問題,您可以提供更多上下文或錯誤信息,我能更具體地幫助診斷問題。