シガーボックスの色変えシミュレータ

シガーボックスの色変えシミュレータのexcelマクロです。ふんいきで遊んでね

派生→alternate版

導入

・下部にあるマクロのコードをシートモジュールに貼り付けてください。
VBE起動(Alt+F11)→sheet1をダブルクリック→貼り付け(すでになにか書いてある場合は消しておく)

・VBE起動参考:Excel VBA 起動と終了
標準モジュールにVBAのコードを貼り付けてマクロを使用するには - VBAの勉強を始めてみた

使い方

・まずA1セルをダブルクリックしてください。必要なセルが入力されます。

・実行と入力されたセルをダブルクリックすると始まります。コンベア色変えのシミュレーションが始まります。

・次は初期状態を変えてみましょう。順番・色のところを

1,2,3
0,0,0
2,3,1
0,0,1
から
1,2,3
0,1,0
2,3,1
1,0,1

にして実行してください。(色2か所変化)
周期の計算の意味がわかっていただけると思います。

・あとは雰囲気で遊んでください。なお想定外の操作に対してはガバガバなのであきらめて

・本質的には置換群と巡回群を組み合わせたものなので、色変えを例えば縦組み・横組みと読み替えたりもできます。

マクロのコード

以下の内容のテキストファイル(txt)
ーーーーーーーーーーーーーーーーー内容ーーーーーーーーーーーーーーーーー
''''''シガーボックスの色変えシミュレータ(エクセルマクロ)by森下''''''

''マクロが使える状態になったらまずA1セルをダブルクリックしてください

Option Explicit '変数を宣言して使用

''変えてもいい定数ここから
Const Max_Boxes As Long = 10 '箱数制限値
Const Max_Color As Long = 10 '色数制限値
Const Max_Trial As Long = 50 '回数制限値
Const Wait_Flag As Boolean = True '次シガーボックス生成のwaitあり・なし
Const Achieve_Flag As Boolean = True '終了メッセージあり・なし
''ここまで

Const iRow As Long = 10 '生成シガーボックス原点(Initial_Row)
Const iColumn As Long = 3

Sub Worksheet_Change(ByVal Target As Range)
'' 複数セルの場合処理なし
If Target.Count > 1 Then Exit Sub
'' 以下範囲の場合処理なし
If Target.Row >= 9 Then Exit Sub
If Target.Row <= 2 Then Exit Sub
If Target.Row = 4 Then Exit Sub
If Target.Row = 5 Then Exit Sub
If Target.Row = 7 Then Exit Sub
If Target.Column = 2 Then Exit Sub

If IsNumeric(Cells(3, 3).Value) = False Then 'シガーボックス数が不正の場合処理なし
    Call Total_Boxes_Maintain
    Exit Sub
ElseIf Cells(3, 3).Value < 1 Then
    Call Total_Boxes_Maintain
    Exit Sub
End If
Dim Total_Boxes As Long
Total_Boxes = Cells(3, 3).Value
If Target.Column >= Total_Boxes + 3 Then Exit Sub
'' 以上処理なし

If Target.Column >= 3 And Target.Column <= Total_Boxes + 2 Then
    If Target.Row = 6 Or Target.Row = 8 Then
        Call Set_Color(Target.Row, Target.Column)
    End If
End If

If Target.Row = 3 Then
    Select Case Target.Column
    Case 3
        Call Set_N_Boxes
    Case 4
        Call Set_N_Colors
    End Select
End If

If Target.Row = 8 And Target.Column = 1 Then
    Call Set_Total_Trial
End If
End Sub

Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)

'' 複数セルの場合処理なし
If Target.Count > 1 Then Exit Sub

'' 以下範囲の場合処理なし
If Target.Row >= 9 Then Exit Sub
If Target.Row = 4 Then Exit Sub
If Target.Row = 5 Then Exit Sub
If Target.Row = 7 Then Exit Sub
If Target.Column = 2 Then Exit Sub

Dim Total_Boxes As Long
Total_Boxes = Cells(3, 3).Value
If Target.Column >= Total_Boxes + 3 Then Exit Sub
'' 以上処理なし

If Target.Column = 1 Then
    Select Case Target.Row
    Case 2
        Call Execute_main_process
    Case 3
        Call Delete_boxes
    Case 6
        Call Change_endurance_type
    Case 1
        Call Initialize_sheet
    End Select
End If

If Target.Column >= 3 And Target.Column <= Total_Boxes + 2 Then
    If Target.Row = 6 Or Target.Row = 8 Then
        Call Change_Color(Target.Row, Target.Column)
    End If
End If

Cancel = True 'デフォルトのイベントの実行をキャンセル
End Sub

''ここまでセル操作イベント指定、ここから各イベントの中身

Sub Set_Color(ByVal tRow As Long, ByVal tColumn As Long) 'シガーボックス色セット
Application.EnableEvents = False

Dim Set_color_Num As Long
If IsNumeric(Cells(tRow, tColumn).Value) = False Then
    MsgBox "色指定数エラー"
    Set_color_Num = 0
ElseIf Cells(tRow, tColumn).Value < 0 Or Cells(tRow, tColumn).Value >= Cells(3, 4).Value Then
    MsgBox "色指定数エラー"
    Set_color_Num = 0
Else
    Set_color_Num = Cells(tRow, tColumn).Value
End If
Cells(tRow, tColumn).Value = Set_color_Num

Cells(tRow - 1, tColumn).Interior.Color = Cells(3, 5 + Set_color_Num).Interior.Color

Application.EnableEvents = True
End Sub

'’シガーボックスの色指定はダブルクリックでもいじれます(裏技)
Sub Change_Color(ByVal tRow As Long, ByVal tColumn As Long)
Application.EnableEvents = False

Dim Total_Color As Long
Total_Color = Cells(3, 4).Value
Cells(tRow, tColumn).Value = (Cells(tRow, tColumn).Value + 1) Mod Total_Color
Dim Set_color_Num As Long
Set_color_Num = Cells(tRow, tColumn).Value
Cells(tRow - 1, tColumn).Interior.Color = Cells(3, 5 + Set_color_Num).Interior.Color

Application.EnableEvents = True
End Sub

Sub Total_Boxes_Maintain()
Application.EnableEvents = False

MsgBox "シガーボックス数エラー"
Dim Count_Boxes As Long
Dim i As Long
Count_Boxes = 0
For i = 0 To (Max_Boxes - 1)
    If Cells(5, 3 + i).Borders(xlEdgeRight).LineStyle = xlContinuous Then
       Count_Boxes = Count_Boxes + 1
    Else
       Exit For
    End If
Next i
If Count_Boxes = 0 Then
    MsgBox "シガーボックス数0エラー:初期化をおすすめします"
End If
Cells(3, 3).Value = Count_Boxes

Application.EnableEvents = True
End Sub

Sub Set_N_Boxes() '箱数セット
Application.EnableEvents = False

Dim Total_Boxes As Long
Total_Boxes = Cells(3, 3).Value
If Total_Boxes > Max_Boxes Then
    MsgBox "シガーボックスを" & Max_Boxes & "個にします"
    Total_Boxes = Max_Boxes
End If
Cells(3, 3).Value = Total_Boxes

'' 一旦すべての設定用シガーボックスを消す→再構成
Range(Cells(5, 3), Cells(8, 2 + Max_Boxes)).Clear
Range(Cells(5, 3), Cells(5, 2 + Total_Boxes)).Borders.LineStyle = True
Range(Cells(7, 3), Cells(7, 2 + Total_Boxes)).Borders.LineStyle = True

Dim temparray As Variant
ReDim temparray(1 To 4, 1 To Total_Boxes)
Dim i As Long
For i = 1 To Total_Boxes
    temparray(1, i) = i
    temparray(2, i) = 0
    temparray(3, i) = i + 1
    temparray(4, i) = 0
Next i
temparray(3, Total_Boxes) = 1
temparray(4, Total_Boxes) = 1
Range(Cells(5, 3), Cells(8, 2 + Total_Boxes)).Value = temparray

Range(Cells(5, 3), Cells(5, 2 + Total_Boxes)).Interior.Color = Cells(3, 5).Interior.Color
Range(Cells(7, 3), Cells(7, 2 + Total_Boxes)).Interior.Color = Cells(3, 5).Interior.Color
Cells(7, 2 + Total_Boxes).Interior.Color = Cells(3, 6).Interior.Color

Application.EnableEvents = True
End Sub

Sub Set_N_Colors() '色数セット
Application.EnableEvents = False

Dim Total_Color As Long

If IsNumeric(Cells(3, 4).Value) = False Then
    MsgBox "色数エラー"
    Total_Color = 2
ElseIf Cells(3, 4).Value < 1 Then
    MsgBox "色数エラー"
    Total_Color = 2
ElseIf Cells(3, 4).Value > Max_Color Then
    MsgBox "色数を" & Max_Color & "にします"
    Total_Color = Max_Color
Else
    Total_Color = Cells(3, 4).Value
End If
Cells(3, 4).Value = Total_Color

Dim temparray As Variant
ReDim temparray(1 To 1, 1 To Total_Color)
Dim i As Long
For i = 1 To Total_Color
    temparray(1, i) = i - 1
Next i
Range(Cells(2, 5), Cells(2, 4 + Max_Color)).Clear
Range(Cells(2, 5), Cells(2, 4 + Total_Color)).Value = temparray

Application.EnableEvents = True
End Sub

Sub Set_Total_Trial() '回数セット
Application.EnableEvents = False

If IsNumeric(Cells(8, 1).Value) = False Then
    MsgBox "回数エラー"
    Cells(8, 1).Value = 8
ElseIf Cells(8, 1).Value < 1 Then
    MsgBox "回数エラー"
    Cells(8, 1).Value = 8
ElseIf Cells(8, 1).Value > Max_Trial Then
    MsgBox "試行回数を" & Max_Trial & "回にします。この制限は定数Max_Trialで決められています。"
    Cells(8, 1).Value = Max_Trial
End If
Cells(8, 1).Value = Int(Cells(8, 1).Value)

Application.EnableEvents = True
End Sub

Sub Delete_boxes() '生成したシガーボックスを消す
Application.EnableEvents = False

Cells(iRow, iColumn).Resize(Max_Trial * 2 + 1, Max_Boxes).Clear
Cells(10, 1).Value = 0
Cells(12, 1).Value = 0

Application.EnableEvents = True
End Sub

Sub Initialize_sheet() 'デフォルトにする
Application.EnableEvents = False
Application.ScreenUpdating = False

Cells.Clear 'シートをクリア(たぶん)
Range("A1") = "初期化"
Range("A2") = "実行"
Range("A3") = "箱消し"
Range("A5") = "何回する?"
Range("A6") = "上限固定"
Range("A7") = "上限回数"
Range("A8") = 8
Range("A9") = "区別なし周期"
Range("A10,A12") = 0
Range("A11") = "区別あり周期"
Range("B5,B7") = "順番"
Range("B6,B8") = "色"
Range("C1") = "A1~A3,A6:ダブルクリックしてください。5行~8行の(順番・色)より右:数入力で指定してください。C3・D3:数入力。E3・F3・以降右:カラーパレット。"
Range("C2") = "箱数"
Range("C3") = 3
Range("D2") = "色数"
Range("D3") = 2
Range("E3").Interior.Color = rgbYellow
Range("F3").Interior.Color = rgbRed
Range("A9:M9").Borders(xlEdgeTop).LineStyle = xlContinuous
Range("B5:B8").HorizontalAlignment = xlRight
Call Set_N_Colors
Call Set_N_Boxes

Application.ScreenUpdating = True
Application.EnableEvents = True

MsgBox "初期化完了"
End Sub

Sub Change_endurance_type() '試行の終わり方
Application.EnableEvents = False

If Cells(6, 1).Value = "上限固定" Then
    Cells(6, 1).Value = "区別あり周期"
ElseIf Cells(6, 1).Value = "区別あり周期" Then
    Cells(6, 1).Value = "区別なし周期"
Else
    Cells(6, 1).Value = "上限固定"
End If
Application.EnableEvents = True
End Sub

Sub Execute_main_process()
Application.EnableEvents = False
''準備
Call Delete_boxes
Dim Stop_Flag As Long
If Cells(6, 1).Value = "区別あり周期" Then
    Stop_Flag = 1
ElseIf Cells(6, 1).Value = "区別なし周期" Then
    Stop_Flag = 2
Else
    Cells(6, 1).Value = "上限固定"
    Stop_Flag = 0
End If

''置換を作成・検証
Dim Total_Boxes As Long
Total_Boxes = Cells(3, 3).Value
Dim permutation() As Long
ReDim permutation(Total_Boxes - 1)
Dim pmatrix() As Boolean
ReDim pmatrix(Total_Boxes - 1, Total_Boxes - 1)
Dim i As Long, j As Long
Dim icheck As Long, jcheck As Long
Dim pbefore As Variant, pafter As Variant
For i = 0 To (Total_Boxes - 1)
    permutation(i) = -1
    pbefore = Cells(5, 3 + i).Value
    icheck = 0
    For j = 0 To (Total_Boxes - 1)
        pmatrix(i, j) = False
        pafter = Cells(7, 3 + j).Value
        If pbefore = pafter Then
            pmatrix(i, j) = True
            permutation(i) = j
            icheck = icheck + 1
        End If
    Next j
    If icheck <> 1 Then
        MsgBox "シガーボックスの入れ替えが正しくありません"
        Exit Sub
    End If
Next i
For j = 0 To (Total_Boxes - 1)
    jcheck = 0
    For i = 0 To (Total_Boxes - 1)
        If pmatrix(i, j) Then
            jcheck = jcheck + 1
        End If
    Next i
    If jcheck <> 1 Then
        MsgBox "シガーボックスの入れ替えが正しくありません"
        Exit Sub
    End If
Next j

''色遷移を作成
Dim Total_Color As Long
Total_Color = Cells(3, 4).Value
Dim Color_Change() As Long
ReDim Color_Change(Total_Boxes - 1)
For i = 0 To (Total_Boxes - 1)
    Color_Change(i) = (Cells(8, 3 + permutation(i)).Value - Cells(6, 3 + i).Value + Total_Color) Mod Total_Color
Next i

Dim nowColor_Array() As Long
ReDim nowColor_Array(Total_Boxes - 1)
Dim nextColor_Array() As Long
ReDim nextColor_Array(Total_Boxes - 1)
Dim primColor_Array() As Long
ReDim primColor_Array(Total_Boxes - 1)
For i = 0 To (Total_Boxes - 1)
    nowColor_Array(i) = Cells(6, 3 + i).Value
    primColor_Array(i) = nowColor_Array(i)
Next i

''1つ目の試行を作成
Cells(iRow, iColumn).Resize(1, Total_Boxes).Borders.LineStyle = True
Cells(iRow, iColumn).Resize(1, Total_Boxes).Value = Cells(5, 3).Resize(1, Total_Boxes).Value
For i = 0 To (Total_Boxes - 1)
    Cells(iRow, iColumn + i).Interior.Color = Cells(5, 3 + i).Interior.Color
Next i

''前試行から次の試行を作成
Dim k As Long
Dim Total_Trial As Long
Total_Trial = Cells(8, 1).Value
Dim Return_Flag As Boolean
Dim period1 As Long
Dim period2 As Long

For k = 1 To Total_Trial
    If Wait_Flag Then
        Application.Wait [Now() + "0:00:00.5"] '0.5秒wait
    End If
    ''シガーボックス生成
    Cells(iRow + k * 2, iColumn).Resize(1, Total_Boxes).Borders.LineStyle = True
    For i = 0 To (Total_Boxes - 1)
        Cells(iRow + k * 2, iColumn + permutation(i)).Value = Cells(iRow + k * 2 - 2, iColumn + i).Value
        nextColor_Array(permutation(i)) = (nowColor_Array(i) + Color_Change(i)) Mod Total_Color
        Cells(iRow + k * 2, iColumn + permutation(i)).Interior.Color = Cells(3, 5 + nextColor_Array(permutation(i))).Interior.Color
    Next i
    For i = 0 To (Total_Boxes - 1)
        nowColor_Array(i) = nextColor_Array(i)
    Next i
    ''周期判定
    If period2 = 0 Then
        If period1 = 0 Then ''区別なし周期
            Return_Flag = True
            For i = 0 To (Total_Boxes - 1)
                If nowColor_Array(i) <> primColor_Array(i) Then
                    Return_Flag = False
                End If
            Next i
            If Return_Flag = True Then
                period1 = k
                Cells(10, 1).Value = period1
            End If
        End If
        If period1 <> 0 Then ''区別あり周期
            If k Mod period1 = 0 Then
                Return_Flag = True
                For i = 0 To (Total_Boxes - 1)
                    If Cells(iRow + k * 2, iColumn + i).Value <> Cells(iRow, iColumn + i).Value Then
                        Return_Flag = False
                    End If
                Next i
                If Return_Flag = True Then
                    period2 = k
                    Cells(12, 1).Value = period2
                End If
                If Stop_Flag = 2 Then ''離脱
                    Exit For
                ElseIf Stop_Flag = 1 And period2 > 0 Then
                    Exit For
                End If
            End If
        End If
    End If
Next k

If Achieve_Flag Then
    MsgBox "終了"
End If

Application.EnableEvents = True
End Sub










inserted by FC2 system