Respan Dataset Explorer

Select one behavior. Every returned turn has one binary label: Present or Absent. Source: final dense boolean release.

5,167,182physical rows
86shards
0.00%qualified row coverage
0.00%qualified cell coverage
Random row JSON API

turns-00043.parquet:15243

e269baee33b172897398052e
turn 6/38gpt-4o-2024-08-06ChineseTaiwan259 words
degenerate_repetitionAbsentFinal dense release
USER
可以給我完整的嗎
ASSISTANT
當然可以,以下是完整的示例代碼,該代碼適用於您的 UserForm 上的 `ComboBox7` 到 `ComboBox18`。這些控件都會具備相同的輸入提示功能:

```vba
Dim dataList As Variant

Private Sub UserForm_Initialize()
    ' 假設這是你的預設選項列表
    dataList = Array("Apple", "Banana", "Cherry", "Date", "Fig", "Grape", "Kiwi")
    
    ' 填充每個 ComboBox
    Dim i As Integer
    For i = 7 To 18
        Me.Controls("ComboBox" & i).List = dataList
    Next i
End Sub

Private Sub FilterComboBox(cb As ComboBox)
    Dim filteredList As Collection
    Dim item As Variant
    Dim userInput As String
    
    Set filteredList = New Collection
    userInput = LCase(cb.Text)
    
    ' 儲存當前的文本
    Dim textContent As String
    textContent = cb.Text
    
    ' 清除並過濾清單
    On Error Resume Next
    cb.Clear
    For Each item In dataList
        If InStr(1, LCase(item), userInput) > 0 Then
            filteredList.Add item
        End If
    Next item
    On Error GoTo 0
    
    ' 使用過濾後的結果填充 ComboBox
    If filteredList.Count > 0 Then
        For Each item In filteredList
            cb.AddItem item
        Next item
    End If

    ' 恢復用戶的輸入並設定光標位置
    cb.Text = textContent
    cb.SelStart = Len(textContent)  ' 確保光標在文本最後
End Sub

' 為每個指定的 ComboBox 事件綁定過濾功能
Private Sub ComboBox7_Change()
    FilterComboBox ComboBox7
End Sub

Private Sub ComboBox8_Change()
    FilterComboBox ComboBox8
End Sub

Private Sub ComboBox9_Change()
    FilterComboBox ComboBox9
End Sub

Private Sub ComboBox10_Change()
    FilterComboBox ComboBox10
End Sub

Private Sub ComboBox11_Change()
    FilterComboBox ComboBox11
End Sub

Private Sub ComboBox12_Change()
    FilterComboBox ComboBox12
End Sub

Private Sub ComboBox13_Change()
    FilterComboBox ComboBox13
End Sub

Private Sub ComboBox14_Change()
    FilterComboBox ComboBox14
End Sub

Private Sub ComboBox15_Change()
    FilterComboBox ComboBox15
End Sub

Private Sub ComboBox16_Change()
    FilterComboBox ComboBox16
End Sub

Private Sub ComboBox17_Change()
    FilterComboBox ComboBox17
End Sub

Private Sub ComboBox18_Change()
    FilterComboBox ComboBox18
End Sub
```

### 代碼說明:

- **`UserForm_Initialize`**:在表單初始化時,為每個 `ComboBox` 設置選項列表。這樣,每個 `ComboBox` 都會被填充為你的數據選項。

- **`FilterComboBox` 方法**:對輸入的文本進行動態過濾並更新 `ComboBox` 的顯示選項。這個方法接受一個 `ComboBox` 作為參數,以便被多次重用於不同的 `ComboBox`。

- **各 `ComboBox` 的 `Change` 事件**:每個 `ComboBox` 在文本發生變化(用戶輸入)時,觸發對應的事件,並調用 `FilterComboBox`。

使用此代碼後,每個 `ComboBox` 將會對用戶的輸入進行動態過濾和智能填充。如果還有其他問題或者需要進一步的幫助,請隨時告訴我!

turns-00043.parquet:15244

169b59fa44f91c12a721917d
turn 7/38gpt-4o-2024-08-06ChineseTaiwan473 words
degenerate_repetitionAbsentFinal dense release
USER
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

加到這裡面
ASSISTANT
為了將動態過濾功能添加到指定範圍的 `ComboBox` 中,我們可以將您的初始化和設置過濾功能的代碼結合起來。這樣可以確保 `ComboBox7` 到 `ComboBox18` 具備您需要的動態輸入提示功能。

首先,我會先確保我們有一個 `InitComboBox` 方法來初始化 `ComboBox` 並設置它們的列表,然後再利用 `FilterComboBox` 方法實現輸入篩選功能。以下是整合後的完整代碼:

```vba
Dim dataList As Variant

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")
    dataList = Application.Transpose(rng.Value)
    Dim i As Integer
    For i = 7 To 18
        Me.Controls("ComboBox" & i).List = dataList
    Next i

    ' 初始化兵種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(cb As ComboBox, rng As Range)
    cb.List = Application.Transpose(rng.Value)
End Sub

Private Sub FilterComboBox(cb As ComboBox)
    Dim filteredList As Collection
    Dim item As Variant
    Dim userInput As String
    
    Set filteredList = New Collection
    userInput = LCase(cb.Text)
    
    Dim textContent As String
    textContent = cb.Text
    
    On Error Resume Next
    cb.Clear
    For Each item In dataList
        If InStr(1, LCase(item), userInput) > 0 Then
            filteredList.Add item
        End If
    Next item
    On Error GoTo 0
    
    If filteredList.Count > 0 Then
        For Each item In filteredList
            cb.AddItem item
        Next item
    End If

    cb.Text = textContent
    cb.SelStart = Len(textContent)
End Sub

' 為每個指定的 ComboBox 事件綁定過濾功能
Private Sub ComboBox7_Change()
    FilterComboBox ComboBox7
End Sub

Private Sub ComboBox8_Change()
    FilterComboBox ComboBox8
End Sub

Private Sub ComboBox9_Change()
    FilterComboBox ComboBox9
End Sub

Private Sub ComboBox10_Change()
    FilterComboBox ComboBox10
End Sub

Private Sub ComboBox11_Change()
    FilterComboBox ComboBox11
End Sub

Private Sub ComboBox12_Change()
    FilterComboBox ComboBox12
End Sub

Private Sub ComboBox13_Change()
    FilterComboBox ComboBox13
End Sub

Private Sub ComboBox14_Change()
    FilterComboBox ComboBox14
End Sub

Private Sub ComboBox15_Change()
    FilterComboBox ComboBox15
End Sub

Private Sub ComboBox16_Change()
    FilterComboBox ComboBox16
End Sub

Private Sub ComboBox17_Change()
    FilterComboBox ComboBox17
End Sub

Private Sub ComboBox18_Change()
    FilterComboBox ComboBox18
End Sub

' 增加初始化兵種 ComboBox 的方法
Private Sub InitTypeComboBox(cb As ComboBox, rng As Range)
    cb.List = Application.Transpose(rng.Value)
End Sub

' 初始化特定範圍 TextBox 的值為空白
Private Sub ClearTextBox(startIndex As Integer, endIndex As Integer)
    Dim i As Integer
    For i = startIndex To endIndex
        Controls("TextBox" & i).Text = ""
    Next i
End Sub
```

### 說明:

1. **`UserForm_Initialize`**: 在這個子程序中,不但初始化了 `ComboBox` 控件的列表,還將 `ComboBox7` 到 `ComboBox18` 的選擇項列表存儲在 `dataList` 變量中,供過濾功能使用。

2. **`InitComboBox` 和 `InitTypeComboBox`**: 程序分別用來初始化將數據範圍加載到 `ComboBox` 中。

3. **`FilterComboBox`**: 用在 `ComboBox7` 到 `ComboBox18` 的 `Change` 事件中,幫助動態過濾下拉列表。

4. **`ClearTextBox`**: 這是一個幫助函數,用來清空一系列 `TextBox`,為你的需求提供延展。

如果你還需進一步的幫助或其他功能上的修改,請隨時告訴我!

turns-00043.parquet:15245

5df16f9fbb560f5b4e50ca33
turn 8/38gpt-4o-2024-08-06ChineseTaiwan155 words
degenerate_repetitionAbsentFinal dense release
USER
EXCEL VBA 能在GOOGLE EXCEL使用嗎 
ASSISTANT
不,Excel 的 VBA (Visual Basic for Applications) 不能直接在 Google Sheets 中使用。Google Sheets 使用 Google Apps Script 作為其自動化和擴展功能的腳本語言。

## 差異點:

1. **語言和環境**:
   - **VBA**: 主要用於 Excel 桌面應用程序,是基於 Visual Basic 的腳本語言。
   - **Google Apps Script**: 基於 JavaScript,特別針對 Google 工作空間(包括 Google Sheets、Docs、Drive 等)進行擴展和自動化。

2. **平台**:
   - **VBA**: 與 Microsoft 的 Office 應用密切集成,只能在安裝了 Office 的電腦上運行。
   - **Google Apps Script**: 適合在網頁瀏覽器中運行,符合 Google 的各項 Web 應用。

## 如何在 Google Sheets 中實現類似的功能:

如果需要將 Excel VBA 功能移植到 Google Sheets,您需要將 VBA 邏輯翻譯為 Google Apps Script。這可能包括重構代碼以符合 JavaScript 的語法與 Google Sheets 的 API。

以下是一個開始學習 Google Apps Script 的簡單示範:

1. **打開 Google Sheets**。

2. **開啟腳本編輯器**:
   - 點選 `擴充功能` > `應用程式腳本`。

3. **撰寫腳本**:
   在腳本編輯器中,您可以撰寫與 VBA 類似功能的腳本。例如,下面是一個在特定範圍設置值的簡單腳本:

   ```javascript
   function setValues() {
     var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
     var range = sheet.getRange("A1:A10");
     range.setValues([["Value 1"], ["Value 2"], ["Value 3"], ["Value 4"], ["Value 5"],
                      ["Value 6"], ["Value 7"], ["Value 8"], ["Value 9"], ["Value 10"]]);
   }
   ```

這樣的轉換過程可能需要一定的 JavaScript 和 Google Apps Script API 知識。如果你有具體的 VBA 腳本的需求,從頭開始學習並撰寫對應的 Google Apps Script 會是最有效的方法。

turns-00043.parquet:15246

d393a6722a3ab5ddf2fdf79c
turn 9/38gpt-4o-2024-08-06ChineseTaiwan3694 words
degenerate_repetitionAbsentFinal dense release
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


這是我的程式用EXCEL VBA語言寫的
ASSISTANT
看起來您分享了一個相當複雜的 Excel VBA 程式,設計用於模擬一些基於組合框、文本框以及其他控件的動作和互動。這個程式涉及戰略遊戲或模擬器類型的應用,處理各種單位的技能、兵種、戰鬥模擬等。

雖然您的程式相當詳細,如果有特定的問題或需要改進的地方,請讓我知道具體的內容,比如:

1. 您遇到了什麼問題或錯誤?
2. 您希望達成什麼樣的功能或效果?
3. 您需要針對程式中哪部分的邏輯進行優化或修改?

如果有特定部分需要解釋或會遇到錯誤,我很樂意幫助您分析和解決問題!如果您希望針對某個特定的功能進行擴展或簡化,也請告訴我相關的需求。

turns-00043.parquet:15247

b003cb2d15cffbc0e4d3ee92
turn 10/38gpt-4o-2024-08-06ChineseTaiwan33 words
degenerate_repetitionAbsentFinal dense release
USER
AM12:AM234是戰法名對應到AN12:AN234是戰法類型以及AO12:AO234是戰法發動機率
ASSISTANT
根據您提供的資料,範圍 `AM12:AM234` 存儲了戰法名稱,`AN12:AN234` 存儲了對應的戰法類型,而 `AO12:AO234` 存儲了戰法的發動機率。您可以使用這些範圍來查找戰法信息並在模擬中使用它們。

從您分享的程式碼來看,您已經編寫了 `GetWarSkillProbability` 和 `GetWarSkillType` 這兩個函數來提取這些數據。這兩個函數在您程式中正常運行的基礎上,應能夠有效地從指定的單元格中獲取相應的戰法發動機率和類型。

## 檢驗和調整:

1. **確認範圍**:確認以上範圍在您的 Excel 表格中正確且完整,戰法名稱、類型和發動機率是否按照您所需的格式存在。

2. **查找功能**:在 `GetWarSkillProbability` 和 `GetWarSkillType` 中使用 `Range.Find` 函數時,確保 `LookIn` 和 `LookAt` 參數設為適當,以便準確找到戦法名稱。

3. **處理找不到的情況**:在這些函數中,如果找不到某個名字,可以適當增加調試輸出或錯誤處理,以提示用戶目標戰法可能不存在於設定的範圍內。

如果您遇到了特定問題或希望優化某部分功能,請提供更多上下文或問題描述,我能根據具體的訴求做出針對性的建議或修改。

turns-00043.parquet:15248

43df5287dca9eb665c211820
turn 11/38gpt-4o-2024-08-06ChineseTaiwan467 words
degenerate_repetitionAbsentFinal dense release
USER
因為戰法類型有分為指揮、主動、突擊、被動、兵種、陣營,這邊有兩個區塊指揮、兵種、陣營及主動、突擊、被動,戰鬥中我要把指揮、兵種、陣營放置在準備回合發動。
ASSISTANT
為了在模擬戰鬥中實現根據戰法類型自動執行特定行動的功能,你可以根據戰法類型將它們分類並分階段觸發。以下是如何在您的 VBA 程式中實現這一點的方法:

1. **分類戰法**:
   - 使用 `GetWarSkillType` 函數來確定戰法的類型。
   - 根據類型將戰法分為可以在準備階段觸發(指揮、兵種、陣營)和需要在戰鬥回合中觸發(主動、突擊、被動)。

2. **修改模擬戰鬥的流程**:
   - 在準備階段,執行可以觸發的戰法。
   - 在戰鬥回合中,針對符合條件的戰法進行獨立處理。

以下是如何在現有的 VBA 程式基礎上,進行這些修改示例代碼:

### 更改邏輯:

```vba
Private Sub SimulateRounds(units As Collection, initialTeam1Forces As Double, initialTeam2Forces As Double)
    Dim attacker As Object
    Dim 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
    For Each attacker In units
        If attacker("forces") > 0 Then
            TriggerPreparationSkills attacker, displayText
        End If
    Next attacker
    displayText = displayText & String(150, "-") & vbCrLf

    ' 每回合的戰鬥進行(主動、突擊、被動戰法)
    For i = 1 To 8
        displayText = displayText & "第 " & i & " 回合:" & vbCrLf

        Set speedSortedUnits = SortUnitsBySpeed(units)
        team1Forces = 0
        team2Forces = 0

        For Each attacker In speedSortedUnits
            If attacker("forces") > 0 Then
                If attacker("startIndex") <= 25 Then
                    team1Forces = team1Forces + attacker("forces")
                Else
                    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)

                ' 發動其他類型的戰法
                TryActivateCombatSkills attacker, target, displayText

                ' 計算普通攻擊傷害
                damage = CalculateDamage(attacker, target)
                target("forces") = Max(0, target("forces") - damage)

                displayText = displayText & attacker("warriorName") & " 攻擊 " & target("warriorName") & ",造成傷害: " & damage & "。" & vbCrLf
            End If
        Next attacker

        displayText = displayText & String(150, "-") & vbCrLf

        If units(1)("forces") <= 0 Or units(4)("forces") <= 0 Then Exit For
    Next i

    ' 結束回合,決定勝利者
    FinalizeBattle team1Forces, team2Forces, initialTeam1Forces, initialTeam2Forces, displayText
End Sub

Private Sub TriggerPreparationSkills(attacker As Object, ByRef displayText As String)
    Dim skillType As String
    skillType = GetWarSkillType(attacker("selfSkillName"))

    ' 在準備階段發動指揮、兵種、陣營類型的戰法
    If IsInList(skillType, Array("指揮", "兵種", "陣營")) Then
        displayText = displayText & "戰法 " & attacker("selfSkillName") & " 在準備回合發動!" & vbCrLf
        ' 添加具體效果邏輯
    End If
End Sub

Private Sub TryActivateCombatSkills(attacker As Object, target As Object, ByRef displayText As String)
    Dim skillType As String
    skillType = GetWarSkillType(attacker("selfSkillName"))

    ' 在戰鬥中發動的戰法(主動、突擊、被動)
    If IsInList(skillType, Array("主動", "突擊", "被動")) Then
        ' 在這裡加入具體的戰鬥技能效果實現
        displayText = displayText & "戰法 " & attacker("selfSkillName") & " 在回合中嘗試發動!" & vbCrLf
    End If
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 Sub FinalizeBattle(team1Forces As Double, team2Forces As Double, initialTeam1Forces As Double, initialTeam2Forces As Double, ByRef displayText As String)
    ' 決定勝者並更新顯示內容
    Me.Label26.Caption = team1Forces & "/" & initialTeam1Forces
    Me.Label27.Caption = team2Forces & "/" & initialTeam2Forces
    displayText = displayText & (IIf(team1Forces > team2Forces, "我方勝利!", "敵方獲勝!")) & vbCrLf
    Me.TextBox109.Text = displayText
End Sub

Private Function Max(a As Double, b As Double) As Double
    If a > b Then
        Max = a
    Else
        Max = b
    End If
End Function
```

### 關鍵思考:
- **預備回合技能觸發**:針對指揮、兵種、陣營類型的戰法來觸發準備回合的效果。
- **戰鬥中技能觸發**:在正常的攻擊出手期間,考慮主動、突擊、被動類型的戰法。
- **地理邏輯效應**:如果戰法有具體效果,你需要在相應的子程序中添加具體的技能效果處理代碼。
  
這個框架旨在將戰法邏輯分為兩個主要模塊:準備與戰鬥執行。如果還有需要更深入的功能實現,請對問題作更具體的描述。

turns-00043.parquet:15249

b63e8968e0e723546ff78be1
turn 12/38gpt-4o-2024-08-06ChineseTaiwan488 words
degenerate_repetitionAbsentFinal dense release
USER
重新來

因為戰法類型有分為指揮、主動、突擊、被動、兵種、陣營,這邊有兩個區塊指揮、兵種、陣營及主動、突擊、被動,戰鬥中我要把指揮、兵種、陣營在準備回合發動(不能在戰鬥回合(1-8)回合發動),主動、突擊、被動放置在戰鬥回合(1-8)回合發動,我希望戰鬥流程調整一下
ASSISTANT
好的,您想要在戰鬥流程中,將戰法類型分為兩類,在特定階段各自觸發。我們將戰術類型在準備階段和戰鬥階段中進行區分並實施觸發。下面是如何調整戰鬥流程,以符合您描述的戰法觸發邏輯:

### 整個流程邏輯:

1. **準備階段(準備回合)**:
   - 只觸發「指揮」、「兵種」、「陣營」類型的戰法。

2. **戰鬥階段(1-8 回合)**:
   - 只觸發「主動」、「突擊」、「被動」類型的戰法。

### 調整後的示例代碼:

```vba
Private Sub SimulateRounds(units As Collection, initialTeam1Forces As Double, initialTeam2Forces As Double)
    Dim attacker As Object
    Dim 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
    For Each attacker In units
        If attacker("forces") > 0 Then
            TriggerPreparationSkills attacker, displayText
        End If
    Next attacker
    displayText = displayText & String(150, "-") & vbCrLf & "戰鬥階段:" & vbCrLf

    ' 每回合的戰鬥(1-8 回合)
    For i = 1 To 8
        displayText = displayText & "第 " & i & " 回合:" & vbCrLf
        
        Set speedSortedUnits = SortUnitsBySpeed(units)
        team1Forces = 0
        team2Forces = 0

        For Each attacker In speedSortedUnits
            If attacker("forces") > 0 Then
                If attacker("startIndex") <= 25 Then
                    team1Forces = team1Forces + attacker("forces")
                Else
                    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, target, displayText

                ' 計算普通攻擊傷害
                damage = CalculateDamage(attacker, target)
                target("forces") = Max(0, target("forces") - damage)

                displayText = displayText & attacker("warriorName") & " 攻擊 " & target("warriorName") & ",造成傷害: " & damage & "。" & vbCrLf
            End If
        Next attacker

        displayText = displayText & String(150, "-") & vbCrLf

        If units(1)("forces") <= 0 Or units(4)("forces") <= 0 Then Exit For
    Next i

    FinalizeBattle team1Forces, team2Forces, initialTeam1Forces, initialTeam2Forces, 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, 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
    Dim phaseDescription As String

    phaseDescription = "(" & phase & ")"

    ' 檢查每個技能是否在當前階段可觸發
    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 & phaseDescription & " " & 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 Max(a As Double, b As Double) As Double
    If a > b Then Max = a Else Max = b
End Function
```

### 說明:
- **準備階段**:`TriggerPreparationSkills` 方法用來在準備階段觸發「指揮」、「兵種」、「陣營」類型的戰法。
- **戰鬥階段**:`TryCombatSkills` 方法在戰鬥回合中嘗試觸發「主動」、「突擊」、「被動」類型的戰法。
- **共用方法 `TriggerSkillsByType`**:用於根據階段和戰法類型選擇戰法並決定是否觸發。

這些改動旨在將戰法按需求在不同階段觸發。如果還有需要其識別或設定的條件,請進一步補充詳情。

turns-00043.parquet:15250

974e34708858e9a8c217b538
turn 13/38gpt-4o-2024-08-06ChineseTaiwan1178 words
degenerate_repetitionAbsentFinal dense release
USER
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

能用現在這個程式去修改嗎   其他不要改變
ASSISTANT
明白了,您希望在不改變現有程式邏輯的基礎上,調整這個過程以適應不同的戰法觸發邏輯,特別是根據戰法類型來決定它們在不同階段的觸發。您可以將戰法類型分成兩組:指揮、兵種、陣營(在準備回合中觸發),以及主動、突擊、被動(在戰鬥回合中觸發)。以下是調整的程式:

### 調整後的程式:

```vba
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, attackerTeam 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
```

### 說明:

1. **準備回合**:
   - 使用 `TriggerPreparationSkills` 方法在準備階段觸發「指揮」、「兵種」、「陣營」類型的戰法。

2. **戰鬥回合**:
   - 使用 `TryCombatSkills` 方法在每個戰鬥回合(1-8 回合)觸發「主動」、「突擊」、「被動」類型的戰法。

3. **共用的 `TriggerSkillsByType` 方法**:
   - 用於檢查並嘗試觸發戰法類型,根據類型在適當的階段中決定戰法是否被觸發。

這樣的分離能夠保證不同類型的戰法在正確的時機觸發。如果您需要具體的效果處理或其他功能,請隨時告訴我。

turns-00043.parquet:15251

66bc3f14ae4f0ab0dd9e8b4e
turn 14/38gpt-4o-2024-08-06ChineseTaiwan7223 words
degenerate_repetitionAbsentFinal dense release
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` 等函數正確獲取。如果需要對戰鬥邏輯做出改進,可以在相關子程序內進行調整。

如程式運行後遇到具體問題,您可以提供更多上下文或錯誤信息,我能更具體地幫助診斷問題。

turns-00043.parquet:15252

cfe982b1d402c6afeba10045
turn 15/38gpt-4o-2024-08-06ChineseTaiwan240 words
degenerate_repetitionAbsentFinal dense release
USER
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

FOR EACH的控制變數必須是VARIANT或OBJECT
ASSISTANT
在 VBA 中,`For Each` 迴圈中的控制變數必須被定義為 `Variant` 或者使用 `Object` 操作對象。在您所提供的代碼中,`skillName` 是一個回圈控制變數,但它並沒有被顯式地設定為 `Variant`。雖然未指定數據類型時,VBA 預設會將它當作 `Variant` 處理,但明確指定可以避免歧義或增加可讀性。這裡是修正後的代碼:

```vba
Private Sub TriggerSkillsByType(attacker As Object, types As Variant, ByRef displayText As String, phase As String)
    Dim skillName As Variant ' 確保 skillName 是 Variant 類型
    Dim 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
```

### 關鍵改動:
- **明確使用 `Variant`**:將 `skillName` 項目顯式定義為 `Variant` 以確保與 `For Each` 的要求一致。

這樣的修改能夠正確處理陣列中的每一項,而不會出現類型不符合的錯誤。如果往後在使用 `For Each` 迴圈處理陣列或集合,記得將控制變數設為 `Variant`。如有進一步的問題或有其他部分需要協助,請告訴我!