私の経歴と算数・数学に関する考え(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