われわれは3次元的な発想をしていないのではないか

私の経歴と算数・数学に関する考え(https://hoshikuzumath.com/profile/)に少し書いてあります通り、私は中高時代、4次元に興味があったわけです(律儀にお読みにならなくてもだいじょうぶですよ)。しかし、じつはわれわれは3次元もきちんと把握していない、すなわち、われわれは3次元的な発想をしていないのではないか、という話を今回は書きます。難しくは書かないように気を付けますので、どうぞよろしければお付き合いくださいませ。

小学校で、面積は「広さ」と習います。「広さ」は普通に使う言葉で、よくイメージできます。しかし、小学校で最初に体積(容積)を習うときには「かさ」という言葉で習います。いかがでしょうか。「かさ」って普通に使う言葉でしょうか。この時点で、これはわれわれがあまり3次元的な発想はしていないことのひとつの証拠である気がするのですがいかがでしょうか。

もののたとえで、「点と点で線になる」という言いかたをなさるかたがおられます。「出来事(点)と出来事(点)を因果関係(線)で結ぶ」という意味でお用いになるかたです。これでときどき「線と線で面になる」という言い方をなさるかたもおいでになります。しかし、ここで「面と面で体になる」とまでおっしゃるかたはほとんどおられないと思いませんか?だいたい、「体」という言葉を「たい」(立方体の「体」)と読ませて使う人があまりいませんし。大学で習う「体」(というものがあるのですが)とは別物であることは言わずもがなですが、それも含めて、やはりわれわれが3次元的な発想をしていないことの証拠のひとつである気がします。いかがでしょうか。

皆さんは、お引越しのご経験はおありでしょうか。おありのかたはご存知だろうと思うのですが、棚からものを出してみたら、ものすごくたくさん入っていた、という記憶はありませんか?やはり、3次元的にものが入る「棚」というものは、すごいわけです。これも、普段、われわれが3次元的な発想をしていないひとつの証拠かと。

小学生のころの私の話です。「1キロリットル」はとても多い気がしていたのです。1メートルより1キロメートルのほうがずっと長く、1グラムより1キログラムのほうがずっと重いです。ですから、1キロリットルって、プールの水くらいあるのではないかと思っていました。しかし、よく考えると、1キロリットルって、1メートル×1メートル×1メートルの、立方体なのですよね。思ったよりずっと「小さかった」。10センチ×10センチ×10センチが1リットルなので、1辺を10倍したら、体積はそれを3回かけているので、1,000倍になるわけです。考えてみますと、1リットルの牛乳パックで、10回くらい、お風呂に牛乳を入れても、ぜんぜんいっぱいにならないことは想像がつきますよね。

あとは、スマホやパソコンの画面も2次元ですよね。3次元のテトリスがあったら、果たしてわれわれはうまくプレイできるのか不明です(私はゲームに疎いですので、実際に世の中に「3次元テトリス」があったらごめんなさい)。

そんなわけで、われわれは3次元的な発想はしていないようなのです。いかがでしょうか。

それだけです。私の話にオチはなかったりしますので、これでおしまいです。つまらなかったらごめんなさいね。

最後に、私が今年の5月頭に、半日で書いてしまった、エクセルのマクロで走る「テトリス」のコードをさらして終わりにしますね。64ビット版のウィンドウズで動きます。なにかありましても自己責任でお願いしますね。ごめんなさい。往年のファミコンのようにスムーズに動きますよ。世の中にエクセルのテトリスのコードをさらしておられるかたはときどきおいでになりますが、おそらく私が最も短くシンプルに書いています。以下です。

Option Explicit

Declare PtrSafe Function GetAsyncKeyState Lib “User32.dll” (ByVal vKey As Long) As Integer

Sub テトリス()

   Dim shurui As Integer

   Dim ochigyou(1 To 4), ochiretu(1 To 4) As Integer

   Dim hayasa, hayaokuri, hayasas As Integer

   Dim tate, yoko As Integer

   Dim px As Double

   tate = 30

   yoko = 15

   Dim sude(1 To 100, 1 To 100, 1 To 3) As Integer

   Dim i, j, k, n, x, p, q As Integer

   Dim a(1 To 4), b(1 To 4) As Integer

   Dim iro(1 To 7, 1 To 3) As Integer

   Dim PressNumber(1 To 5) As Integer

   Dim narabi, kaisuu As Integer

   Dim tuyosa As Integer

   Dim tuyosastr As String

   Dim keshi, keshikazu As Integer

   ‘初期化

   ‘何回消したらクリアか

   keshikazu = 10

   ‘色を定める

   iro(1, 1) = 255

   iro(1, 2) = 0

   iro(1, 3) = 0

   iro(2, 1) = 0

   iro(2, 2) = 255

   iro(2, 3) = 0

   iro(3, 1) = 0

   iro(3, 2) = 0

   iro(3, 3) = 255

   iro(4, 1) = 255

   iro(4, 2) = 255

   iro(4, 3) = 0

   iro(5, 1) = 255

   iro(5, 2) = 0

   iro(5, 3) = 255

   iro(6, 1) = 0

   iro(6, 2) = 255

   iro(6, 3) = 255

   iro(7, 1) = 0

   iro(7, 2) = 0

   iro(7, 3) = 0

   ‘メッセージ

   MsgBox “「←」「→」のキーで左右に動きます。「z」「x」のキーで左右に回転します。「↓」で早送りできます。” & keshikazu & “回以上消したらクリアです。”

   tuyosastr = InputBox(“速さを選んでください。1.ゆっくり。2.ややゆっくり。3.普通。 4.やや速い。5.速い。 6.すごく速い。 “)

   tuyosa = Int(Val(tuyosastr))

   Select Case tuyosa

        Case 1

            hayasas = 60

        Case 2

            hayasas = 30

        Case 3

            hayasas = 20

        Case 4

            hayasas = 14

        Case 5

            hayasas = 10

        Case 6

            hayasas = 5

        Case Else

            hayasas = 20

    End Select

   ‘速さを定める

   hayaokuri = 3

   ‘セルを正方形にする

    px = 12 ‘正方形の一辺の長さ[px]

    ‘ セルの高さと幅を設定

    Cells.ColumnWidth = px * 0.118

    Cells.RowHeight = px * 0.75

    Cells.Clear

    Range(Cells(1, yoko + 1), Cells(2, yoko + 2)).MergeCells = True

    Cells(1, yoko + 1).Font.Size = 12

    Cells(1, yoko + 1).HorizontalAlignment = xlCenter

    Cells(1, yoko + 1).VerticalAlignment = xlCenter

    Cells(1, yoko + 1).Value = 0

   ‘本当のゲームスタート

   ‘すべて白

   For i = 1 To tate

        For j = 1 To yoko

            For k = 1 To 3

                sude(i, j, k) = 255

                Range(Cells(i, j), Cells(i, j)).Interior.Color = RGB(255, 255, 255)

            Next

        Next

   Next

   keshi = 0

   ‘ゲームスタート

   ‘上に発生する

L1:

   x = 0

   hayasa = hayasas

   shurui = Int(Rnd * 7) + 1

   Select Case shurui

        Case 1

            ochigyou(1) = 3

            ochiretu(1) = Int(yoko / 2)

            ochigyou(2) = 1

            ochigyou(3) = 2

            ochigyou(4) = 4

            For j = 1 To 3

                ochiretu(j + 1) = ochiretu(1)

            Next

        Case 2

            ochigyou(1) = 1

            ochiretu(1) = Int(yoko / 2)

            ochigyou(2) = 2

            ochiretu(2) = ochiretu(1)

            ochigyou(3) = 1

            ochiretu(3) = ochiretu(1) + 1

            ochigyou(4) = 2

            ochiretu(4) = ochiretu(1) + 1

        Case 3

            ochigyou(1) = 2

            ochiretu(1) = Int(yoko / 2)

            ochigyou(2) = 1

            ochiretu(2) = ochiretu(1)

            ochigyou(3) = 2

            ochiretu(3) = ochiretu(1) – 1

            ochigyou(4) = 2

            ochiretu(4) = ochiretu(1) + 1

        Case 4

            ochigyou(1) = 1

            ochiretu(1) = Int(yoko / 2)

            ochigyou(2) = 2

            ochiretu(2) = ochiretu(1)

            ochigyou(3) = 1

            ochiretu(3) = ochiretu(1) – 1

            ochigyou(4) = 1

            ochiretu(4) = ochiretu(1) – 2

        Case 5

            ochigyou(1) = 1

            ochiretu(1) = Int(yoko / 2)

            ochigyou(2) = 2

            ochiretu(2) = ochiretu(1)

            ochigyou(3) = 1

            ochiretu(3) = ochiretu(1) + 1

            ochigyou(4) = 1

            ochiretu(4) = ochiretu(1) + 2

        Case 6

            ochigyou(1) = 2

            ochiretu(1) = Int(yoko / 2)

            ochigyou(2) = 1

            ochiretu(2) = ochiretu(1)

            ochigyou(3) = 2

            ochiretu(3) = ochiretu(1) – 1

            ochigyou(4) = 1

            ochiretu(4) = ochiretu(1) + 1

        Case 7

            ochigyou(1) = 2

            ochiretu(1) = Int(yoko / 2)

            ochigyou(2) = 1

            ochiretu(2) = ochiretu(1)

            ochigyou(3) = 2

            ochiretu(3) = ochiretu(1) + 1

            ochigyou(4) = 1

            ochiretu(4) = ochiretu(1) – 1

    End Select

    For i = 1 To 4

        Range(Cells(ochigyou(i), ochiretu(i)), Cells(ochigyou(i), ochiretu(i))).Interior.Color = RGB(iro(shurui, 1), iro(shurui, 2), iro(shurui, 3))

    Next

    For k = 1 To 4

        If sude(ochigyou(k), ochiretu(k), 1) < 255 Or sude(ochigyou(k), ochiretu(k), 2) < 255 Or sude(ochigyou(k), ochiretu(k), 3) < 255 Then

            GoTo L3

        End If

    Next

‘待つ

L4:

   For i = 1 To hayasa

        Application.Wait [Now()] + 0.01 / 86400

        If PressLeft = True Then

            PressNumber(1) = 1

        End If

        If PressRight = True Then

            PressNumber(2) = 1

        End If

        If PressZ = True Then

            PressNumber(3) = 1

        End If

        If PressX = True Then

            PressNumber(4) = 1

        End If

        If PressDown = True Then

            PressNumber(5) = 1

        End If

        If PressNumber(1) = 1 Then

            For j = 1 To 4

                If ochiretu(j) = 1 Then

                    PressNumber(1) = 0

                ElseIf sude(ochigyou(j), ochiretu(j) – 1, 1) < 255 Or sude(ochigyou(j), ochiretu(j) – 1, 2) < 255 Or sude(ochigyou(j), ochiretu(j) – 1, 3) < 255 Then

                    PressNumber(1) = 0

                End If

            Next

            If PressNumber(1) = 1 Then

                For k = 1 To 4

                    Range(Cells(ochigyou(k), ochiretu(k)), Cells(ochigyou(k), ochiretu(k))).Interior.Color = RGB(255, 255, 255)

                Next

                For k = 1 To 4

                    ochiretu(k) = ochiretu(k) – 1

                Next

                For k = 1 To 4

                    Range(Cells(ochigyou(k), ochiretu(k)), Cells(ochigyou(k), ochiretu(k))).Interior.Color = RGB(iro(shurui, 1), iro(shurui, 2), iro(shurui, 3))

                Next

                PressNumber(1) = 0

            End If

        End If

        If PressNumber(2) = 1 Then

            For j = 1 To 4

                If ochiretu(j) = yoko Then

                 PressNumber(2) = 0

                ElseIf sude(ochigyou(j), ochiretu(j) + 1, 1) < 255 Or sude(ochigyou(j), ochiretu(j) + 1, 2) < 255 Or sude(ochigyou(j), ochiretu(j) + 1, 3) < 255 Then

                    PressNumber(2) = 0

                End If

            Next

            If PressNumber(2) = 1 Then

                For k = 1 To 4

                    Range(Cells(ochigyou(k), ochiretu(k)), Cells(ochigyou(k), ochiretu(k))).Interior.Color = RGB(255, 255, 255)

                Next

                For k = 1 To 4

                    ochiretu(k) = ochiretu(k) + 1

                Next

                For k = 1 To 4

                    Range(Cells(ochigyou(k), ochiretu(k)), Cells(ochigyou(k), ochiretu(k))).Interior.Color = RGB(iro(shurui, 1), iro(shurui, 2), iro(shurui, 3))

                Next

                PressNumber(2) = 0

            End If

        End If

        If PressNumber(3) = 1 Then

            Select Case shurui

                Case 1, 3, 4, 5, 6, 7

                    For k = 2 To 4

                        a(k) = ochigyou(1) + (ochiretu(1) – ochiretu(k))

                        b(k) = ochiretu(1) – (ochigyou(1) – ochigyou(k))

                        If a(k) > tate Or a(k) < 1 Or b(k) > yoko Or b(k) < 1 Then

                            PressNumber(3) = 0

                            If PressNumber(3) = 1 Then

                                If sude(a(k), b(k), 1) < 255 Or sude(a(k), b(k), 2) < 255 Or sude(a(k), b(k), 3) < 255 Then

                                    PressNumber(3) = 0

                                End If

                            End If

                        End If

                    Next

                    If PressNumber(3) = 1 Then

                        For k = 2 To 4

                            Range(Cells(ochigyou(k), ochiretu(k)), Cells(ochigyou(k), ochiretu(k))).Interior.Color = RGB(255, 255, 255)

                        Next

                        For k = 2 To 4

                            ochigyou(k) = a(k)

                            ochiretu(k) = b(k)

                            Next

                        For k = 2 To 4

                            Range(Cells(ochigyou(k), ochiretu(k)), Cells(ochigyou(k), ochiretu(k))).Interior.Color = RGB(iro(shurui, 1), iro(shurui, 2), iro(shurui, 3))

                        Next

                        PressNumber(3) = 0

                    End If

                Case 2

                    PressNumber(3) = 0

            End Select

        End If

        If PressNumber(4) = 1 Then

            Select Case shurui

                Case 1, 3, 4, 5, 6, 7

                    For k = 2 To 4

                        a(k) = ochigyou(1) – (ochiretu(1) – ochiretu(k))

                        b(k) = ochiretu(1) + (ochigyou(1) – ochigyou(k))

                        If a(k) > tate Or a(k) < 1 Or b(k) > yoko Or b(k) < 1 Then

                            PressNumber(4) = 0

                            If PressNumber(4) = 1 Then

                                If sude(a(k), b(k), 1) < 255 Or sude(a(k), b(k), 2) < 255 Or sude(a(k), b(k), 3) < 255 Then

                                    PressNumber(4) = 0

                                End If

                            End If

                        End If

                    Next

                    If PressNumber(4) = 1 Then

                        For k = 2 To 4

                            Range(Cells(ochigyou(k), ochiretu(k)), Cells(ochigyou(k), ochiretu(k))).Interior.Color = RGB(255, 255, 255)

                        Next

                        For k = 2 To 4

                            ochigyou(k) = a(k)

                            ochiretu(k) = b(k)

                        Next

                        For k = 2 To 4

                            Range(Cells(ochigyou(k), ochiretu(k)), Cells(ochigyou(k), ochiretu(k))).Interior.Color = RGB(iro(shurui, 1), iro(shurui, 2), iro(shurui, 3))

                        Next

                        PressNumber(4) = 0

                    End If

                Case 2

                    PressNumber(4) = 0

            End Select

        End If

        If PressNumber(5) = 1 Then

            hayasa = hayaokuri

            PressNumber(5) = 0

            Exit For

        End If

   Next

‘落ちる

    x = 0

    For k = 1 To 4

        If sude(ochigyou(k) + 1, ochiretu(k), 1) < 255 Or sude(ochigyou(k) + 1, ochiretu(k), 2) < 255 Or sude(ochigyou(k) + 1, ochiretu(k), 3) < 255 Or ochigyou(k) >= tate Then

            x = 1

        End If

    Next

    If x = 0 Then

        For j = 1 To 4

            Range(Cells(ochigyou(j), ochiretu(j)), Cells(ochigyou(j), ochiretu(j))).Interior.Color = RGB(255, 255, 255)

        Next

        For j = 1 To 4

            ochigyou(j) = ochigyou(j) + 1

        Next

        For j = 1 To 4

            Range(Cells(ochigyou(j), ochiretu(j)), Cells(ochigyou(j), ochiretu(j))).Interior.Color = RGB(iro(shurui, 1), iro(shurui, 2), iro(shurui, 3))

        Next

        GoTo L4

    Else

        For k = 1 To 4

            For i = 1 To 3

                sude(ochigyou(k), ochiretu(k), i) = iro(shurui, i)

            Next

        Next

        For kaisuu = 1 To 4

            For i = 1 To tate

                narabi = 0

                For j = 1 To yoko

                    If sude(i, j, 1) < 255 Or sude(i, j, 2) < 255 Or sude(i, j, 3) < 255 Then

                        narabi = narabi + 1

                    End If

                Next

                If narabi = yoko Then

                    keshi = keshi + 1

                    Cells(1, yoko + 1).Value = keshi

                    For k = 1 To i – 1

                        For p = 1 To yoko

                            For q = 1 To 3

                                sude(i + 1 – k, p, q) = sude(i – k, p, q)

                            Next

                        Next

                    Next

                End If

            Next

        Next

        For i = 1 To tate

            For j = 1 To yoko

                Range(Cells(i, j), Cells(i, j)).Interior.Color = RGB(sude(i, j, 1), sude(i, j, 2), sude(i, j, 3))

            Next

        Next

    End If

    If keshi >= keshikazu Then

        MsgBox “おめでとうございます”

        Exit Sub

    End If

GoTo L1

L3:

    MsgBox “ゲームオーバーです。”

End Sub

Function PressCtrl() As Boolean

    Const KEY_PRESSED = -32767

    PressCtrl = (GetAsyncKeyState(vbKeyControl) And KEY_PRESSED) = KEY_PRESSED

End Function

Function PressZ() As Boolean

    Const KEY_PRESSED = -32767

    PressZ = (GetAsyncKeyState(vbKeyZ) And KEY_PRESSED) = KEY_PRESSED

End Function

Function PressX() As Boolean

    Const KEY_PRESSED = -32767

    PressX = (GetAsyncKeyState(vbKeyX) And KEY_PRESSED) = KEY_PRESSED

End Function

Function PressC() As Boolean

    Const KEY_PRESSED = -32767

    PressC = (GetAsyncKeyState(vbKeyC) And KEY_PRESSED) = KEY_PRESSED

End Function

Function PressV() As Boolean

    Const KEY_PRESSED = -32767

    PressV = (GetAsyncKeyState(vbKeyV) And KEY_PRESSED) = KEY_PRESSED

End Function

Function PressLeft() As Boolean

    Const KEY_PRESSED = -32767

    PressLeft = (GetAsyncKeyState(vbKeyLeft) And KEY_PRESSED) = KEY_PRESSED

End Function

Function PressRight() As Boolean

    Const KEY_PRESSED = -32767

    PressRight = (GetAsyncKeyState(vbKeyRight) And KEY_PRESSED) = KEY_PRESSED

End Function

Function PressUp() As Boolean

    Const KEY_PRESSED = -32767

    PressUp = (GetAsyncKeyState(vbKeyUp) And KEY_PRESSED) = KEY_PRESSED

End Function

Function PressDown() As Boolean

    Const KEY_PRESSED = -32767

    PressDown = (GetAsyncKeyState(vbKeyDown) And KEY_PRESSED) = KEY_PRESSED

End Function

目次