废话少说。现在我把一年多前的在Excel环境下用vba实现的俄罗斯方块的代码提供给大家,算是对拓展office应用的一个总结。由于程序是在去年写的,现在看来思路都有点不记得了,而且语句都不太高效。但我又懒得修改了,毕竟这个是可以正确运行的。大家参考我另外两篇相关的文章,试着做吧。
还是新建一个宏,键入下面代码。
Public Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
Public Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long '首先是API函数调用的声明。
Type pos_
row As Long
col As Long
End Type
Type obj
pos As pos_
stat As Long
typ As Long
color As Long
End Type '基本对象数据结构的定义
Public cur_obj As obj
Public prv_obj As obj
Public nex_obj As obj
Public objs_array(27, 3) As pos_
Dim startpos As pos_
Dim nextpos As pos_
Global score As Long '分数
Public score_level As Long
Dim level As Long
Public gaming As Boolean
Public pulse As Boolean
Public interval As Long '定时器时间间隙
Public timerset As Long '定时器
Public top As Long '记录方块堆积的最高层所在行
Public Const mosttop As Long = 5 '游戏区域的顶,当方块堆积到这里游戏结束
Public Const left As Long = 5 '游戏区域左边界
Public Const right As Long = 22 '游戏区域左边界
Public Const middle As Long = (left + right) \ 2 '游戏区域中线,用以定位
Public Const bottom As Long = 25 '游戏区域底
Sub main()
gaming = False
If Worksheets.Count < 2 Then
ActiveWorkbook.Sheets.Add after:=Worksheets(Worksheets.Count)
Else
Worksheets(Worksheets.Count).Select
End If
Load UserForm1
UserForm1.Show
End Sub
Function game_initial()
'游戏初始化函数
startpos.row = mosttop
startpos.col = middle
nextpos.row = mosttop
nextpos.col = right + 8
top = bottom - 1
score = 0
Range(Cells(mosttop + 1, left), Cells(bottom - 1, left)).Interior.ColorIndex = 1
Range(Cells(mosttop + 1, right), Cells(bottom - 1, right)).Interior.ColorIndex = 1
Range(Cells(bottom, left), Cells(bottom, right)).Interior.ColorIndex = 1
Range(Cells(bottom, left), Cells(bottom, right)) = " "
If Not gaming Then
Cells.ColumnWidth = 1
Cells.RowHeight = 10
'初始化各形状的方块,我都忘了哪个对应哪种类型了
objs_array(0, 0).row = -1
objs_array(0, 0).col = -1
objs_array(0, 1).row = 0
objs_array(0, 1).col = -1
objs_array(0, 2).row = 0
objs_array(0, 2).col = 0
objs_array(0, 3).row = 1
objs_array(0, 3).col = 0
objs_array(1, 0).row = 0
objs_array(1, 0).col = 0
objs_array(1, 1).row = 0
objs_array(1, 1).col = 1
objs_array(1, 2).row = 1
objs_array(1, 2).col = 0
objs_array(1, 3).row = 1
objs_array(1, 3).col = -1
objs_array(2, 0).row = -1
objs_array(2, 0).col = -1
objs_array(2, 1).row = 0
objs_array(2, 1).col = -1
objs_array(2, 2).row = 0
objs_array(2, 2).col = 0
objs_array(2, 3).row = 1
objs_array(2, 3).col = 0
objs_array(3, 0).row = 0
objs_array(3, 0).col = 0
objs_array(3, 1).row = 0
objs_array(3, 1).col = 1
objs_array(3, 2).row = 1
objs_array(3, 2).col = 0
objs_array(3, 3).row = 1
objs_array(3, 3).col = -1
''type 2
objs_array(4, 0).row = -1
objs_array(4, 0).col = 0
objs_array(4, 1).row = 0
objs_array(4, 1).col = 0
objs_array(4, 2).row = 0
objs_array(4, 2).col = -1
objs_array(4, 3).row = 1
objs_array(4, 3).col = -1
objs_array(5, 0).row = 0
objs_array(5, 0).col = -1
objs_array(5, 1).row = 0
objs_array(5, 1).col = 0
objs_array(5, 2).row = 1
objs_array(5, 2).col = 0
objs_array(5, 3).row = 1
objs_array(5, 3).col = 1
objs_array(6, 0).row = -1
objs_array(6, 0).col = 0
objs_array(6, 1).row = 0
objs_array(6, 1).col = 0
objs_array(6, 2).row = 0
objs_array(6, 2).col = -1
objs_array(6, 3).row = 1
objs_array(6, 3).col = -1
objs_array(7, 0).row = 0
objs_array(7, 0).col = -1
objs_array(7, 1).row = 0
objs_array(7, 1).col = 0
objs_array(7, 2).row = 1
objs_array(7, 2).col = 0
objs_array(7, 3).row = 1
objs_array(7, 3).col = 1
''type 3
objs_array(8, 0).row = -1
objs_array(8, 0).col = 0
objs_array(8, 1).row = 0
objs_array(8, 1).col = 0
objs_array(8, 2).row = 0
objs_array(8, 2).col = 1
objs_array(8, 3).row = 1
objs_array(8, 3).col = 0
objs_array(9, 0).row = -1
objs_array(9, 0).col = 0
objs_array(9, 1).row = 0
objs_array(9, 1).col = 0
objs_array(9, 2).row = 0
objs_array(9, 2).col = -1
objs_array(9, 3).row = 0
objs_array(9, 3).col = 1
objs_array(10, 0).row = -1
objs_array(10, 0).col = 0
objs_array(10, 1).row = 0
objs_array(10, 1).col = 0
objs_array(10, 2).row = 0
objs_array(10, 2).col = -1
objs_array(10, 3).row = 1
objs_array(10, 3).col = 0
objs_array(11, 0).row = 0
objs_array(11, 0).col = -1
objs_array(11, 1).row = 0
objs_array(11, 1).col = 0
objs_array(11, 2).row = 0
objs_array(11, 2).col = 1
objs_array(11, 3).row = 1
objs_array(11, 3).col = 0
''type 4
objs_array(12, 0).row = 0
objs_array(12, 0).col = 0
objs_array(12, 1).row = 1
objs_array(12, 1).col = 0
objs_array(12, 2).row = 2
objs_array(12, 2).col = 0
objs_array(12, 3).row = 3
objs_array(12, 3).col = 0
objs_array(13, 0).row = 0
objs_array(13, 0).col = 0
objs_array(13, 1).row = 0
objs_array(13, 1).col = 1
objs_array(13, 2).row = 0
objs_array(13, 2).col = 2
objs_array(13, 3).row = 0
objs_array(13, 3).col = 3
objs_array(14, 0).row = 0
objs_array(14, 0).col = 0
objs_array(14, 1).row = 1
objs_array(14, 1).col = 0
objs_array(14, 2).row = 2
objs_array(14, 2).col = 0
objs_array(14, 3).row = 3
objs_array(14, 3).col = 0
objs_array(15, 0).row = 0
objs_array(15, 0).col = 0
objs_array(15, 1).row = 0
objs_array(15, 1).col = 1
objs_array(15, 2).row = 0
objs_array(15, 2).col = 2
objs_array(15, 3).row = 0
objs_array(15, 3).col = 3
''type 5
objs_array(16, 0).row = 0
objs_array(16, 0).col = 0
objs_array(16, 1).row = 0
objs_array(16, 1).col = 1
objs_array(16, 2).row = 1
objs_array(16, 2).col = 0
objs_array(16, 3).row = 1
objs_array(16, 3).col = 1
objs_array(17, 0).row = 0
objs_array(17, 0).col = 0
objs_array(17, 1).row = 0
objs_array(17, 1).col = 1
objs_array(17, 2).row = 1
objs_array(17, 2).col = 0
objs_array(17, 3).row = 1
objs_array(17, 3).col = 1
objs_array(18, 0).row = 0
objs_array(18, 0).col = 0
objs_array(18, 1).row = 0
objs_array(18, 1).col = 1
objs_array(18, 2).row = 1
objs_array(18, 2).col = 0
objs_array(18, 3).row = 1
objs_array(18, 3).col = 1
objs_array(19, 0).row = 0
objs_array(19, 0).col = 0
objs_array(19, 1).row = 0
objs_array(19, 1).col = 1
objs_array(19, 2).row = 1
objs_array(19, 2).col = 0
objs_array(19, 3).row = 1
objs_array(19, 3).col = 1
''type 6
objs_array(20, 0).row = -2
objs_array(20, 0).col = 0
objs_array(20, 1).row = -1
objs_array(20, 1).col = 0
objs_array(20, 2).row = 0
objs_array(20, 2).col = 0
objs_array(20, 3).row = 0
objs_array(20, 3).col = 1
objs_array(21, 0).row = -1
objs_array(21, 0).col = 0
objs_array(21, 1).row = 0
objs_array(21, 1).col = 0
objs_array(21, 2).row = 0
objs_array(21, 2).col = -1
objs_array(21, 3).row = 0
objs_array(21, 3).col = -2
objs_array(22, 0).row = 0
objs_array(22, 0).col = -1
objs_array(22, 1).row = 0
objs_array(22, 1).col = 0
objs_array(22, 2).row = 1
objs_array(22, 2).col = 0
objs_array(22, 3).row = 2
objs_array(22, 3).col = 0
objs_array(23, 0).row = 0
objs_array(23, 0).col = 0
objs_array(23, 1).row = 0
objs_array(23, 1).col = 1
objs_array(23, 2).row = 0
objs_array(23, 2).col = 2
objs_array(23, 3).row = 1
objs_array(23, 3).col = 0
''type 7
objs_array(24, 0).row = -2
objs_array(24, 0).col = 0
objs_array(24, 1).row = -1
objs_array(24, 1).col = 0
objs_array(24, 2).row = 0
objs_array(24, 2).col = 0
objs_array(24, 3).row = 0
objs_array(24, 3).col = -1
objs_array(25, 0).row = 0
objs_array(25, 0).col = -2
objs_array(25, 1).row = 0
objs_array(25, 1).col = -1
objs_array(25, 2).row = 0
objs_array(25, 2).col = 0
objs_array(25, 3).row = 1
objs_array(25, 3).col = 0
objs_array(26, 0).row = 0
objs_array(26, 0).col = 0
objs_array(26, 1).row = 0
objs_array(26, 1).col = 1
objs_array(26, 2).row = 1
objs_array(26, 2).col = 0
objs_array(26, 3).row = 2
objs_array(26, 3).col = 0
objs_array(27, 0).row = -1
objs_array(27, 0).col = 0
objs_array(27, 1).row = 0
objs_array(27, 1).col = 0
objs_array(27, 2).row = 0
objs_array(27, 2).col = 1
objs_array(27, 3).row = 0
objs_array(27, 3).col = 2
End If
Randomize
nex_obj.typ = Int(7 * Rnd)
nex_obj.stat = Int(4 * Rnd)
nex_obj.color = Int(8 * Rnd) + 3
nex_obj.pos = nextpos
cur_obj = nex_obj
prv_obj = cur_obj
Call obj_draw
Randomize
cur_obj.typ = Int(7 * Rnd)
cur_obj.stat = Int(4 * Rnd)
cur_obj.color = Int(8 * Rnd) + 3
cur_obj.pos = startpos
prv_obj = cur_obj
Call obj_draw
level = 1000
pulse = False
interval = 800
gaming = True
End Function
Public Function obj_left() '游戏对象向左移动,需判断是否超越左边界
Dim i As Long
Dim ii As Long
Dim nextcol As Long
Dim collide As Boolean
collide = False
nextcol = cur_obj.pos.col - 1
ii = cur_obj.typ * 4 + cur_obj.stat
For i = 0 To 3
If ((nextcol + objs_array(ii, i).col <= left) Or Cells(cur_obj.pos.row + objs_array(ii, i).row, nextcol + objs_array(ii, i).col) = " ") Then collide = True: Exit For
Next i
If (Not collide) Then
prv_obj = cur_obj
cur_obj.pos.col = nextcol
Call obj_draw
End If
End Function
Public Function obj_right() '游戏对象向右移动,需判断是否超越右边界
Dim i As Long
Dim ii As Long
Dim nextcol As Long
Dim collide As Boolean
collide = False
nextcol = cur_obj.pos.col + 1
ii = cur_obj.typ * 4 + cur_obj.stat
For i = 1 To 3
If ((nextcol + objs_array(ii, i).col >= right) Or Cells(cur_obj.pos.row + objs_array(ii, i).row, nextcol + objs_array(ii, i).col) = " ") Then collide = True: Exit For
Next i
If (Not collide) Then
prv_obj = cur_obj
cur_obj.pos.col = nextcol
Call obj_draw
End If
End Function
Public Function obj_change() '游戏对象下落形态的改变
Dim i As Long
Dim ii As Long
Dim iii As Long
Dim iiii As Long
Dim nextstat As Long
Dim nextcol As Long
Dim collide As Boolean
collide = False
nextstat = cur_obj.stat + 1
If (nextstat >= 4) Then
nextstat = nextstat Mod 4
End If
ii = cur_obj.typ * 4 + nextstat
nextcol = cur_obj.pos.col
If cur_obj.pos.col <= left + 3 Then
For i = 0 To 3
iii = left + 1 - cur_obj.pos.col - objs_array(ii, i).col
If (iii >= 0 And iii > iiii) Then iiii = iii
Next i
nextcol = nextcol + iiii
For i = 0 To 3
If Cells(cur_obj.pos.row + objs_array(ii, i).row, nextcol + objs_array(ii, i).col) = " " Then collide = True: Exit For
Next i
ElseIf cur_obj.pos.col >= right - 5 Then
For i = 0 To 3
iii = cur_obj.pos.col + objs_array(ii, i).col - right + 1
If (iii >= 0 And iii > iiii) Then iiii = iii
Next i
nextcol = nextcol - iiii
For i = 0 To 3
If Cells(cur_obj.pos.row + objs_array(ii, i).row, nextcol + objs_array(ii, i).col) = " " Then collide = True: Exit For
Next i
Else
For i = 0 To 3
If Cells(cur_obj.pos.row + objs_array(ii, i).row, nextcol + objs_array(ii, i).col) = " " Then collide = True: Exit For
Next i
End If
If Not collide Then
prv_obj = cur_obj
cur_obj.stat = nextstat
cur_obj.pos.col = nextcol
Call obj_draw
End If
End Function
Function obj_fall() '游戏对象下落
Dim i As Long
Dim ii As Long
Dim collide As Boolean
Dim j As Long
Dim k As Long
Dim nextrow As Long
collide = False
ii = cur_obj.typ * 4 + cur_obj.stat
nextrow = cur_obj.pos.row + 1
'判断是否下落到底
For i = 0 To 3
If (Cells(nextrow + objs_array(ii, i).row, cur_obj.pos.col + objs_array(ii, i).col) = " " Or nextrow + objs_array(ii, i).row >= bottom) Then collide = True: Exit For
Next i
If Not collide Then
prv_obj = cur_obj
cur_obj.pos.row = nextrow
Call obj_draw
Else
score = score + 10
score_level = 0
ii = cur_obj.typ * 4 + cur_obj.stat
For i = 0 To 3
Cells(cur_obj.pos.row + objs_array(ii, i).row, cur_obj.pos.col + objs_array(ii, i).col) = " "
Next i
If cur_obj.pos.row + objs_array(ii, 0).row < top Then
top = cur_obj.pos.row + objs_array(ii, 0).row
End If
'这里我偷懒用了一个不具通用性的方法判断每个方块像素所在行是否已满,若满后则消去这行
For i = 0 To 3
For j = left + 1 To right - 1
If Cells(cur_obj.pos.row + objs_array(ii, i).row, j) <> " " Then Exit For
Next j
If right - j <= 0 Then
Cells(cur_obj.pos.row + objs_array(ii, i).row, left + 1) = " "
score_level = score_level + 1
End If
Next i
If score_level > 0 Then
Dim l As Long
l = objs_array(ii, 3).row - objs_array(ii, 0).row
Dim tmp_array(3) As Long
For i = 0 To 3
tmp_array(i) = 0
Next i
'消去满的几行后把由消去的这几行以上到顶的所有像素向下移动
j = cur_obj.pos.row + objs_array(ii, 3).row
k = 0
For i = 0 To l
If Cells(j - i, left + 1) = " " Then
Range(Cells(j - i, left + 1), Cells(j - i, right - 1)).ClearContents
Range(Cells(j - i, left + 1), Cells(j - i, right - 1)).Interior.ColorIndex = 0
Else
Range(Cells(j - i, left + 1), Cells(j - i, right - 1)).Cut Destination:=Range(Cells(j - k, left + 1), Cells(j - k, right - 1))
k = k + 1
End If
Next i
l = cur_obj.pos.row + objs_array(ii, 0).row
If top < l Then
Range(Cells(top, left + 1), Cells(l - 1, right - 1)).Cut Destination:=Range(Cells(top + score_level, left + 1), Cells(l - 1 + score_level, right - 1))
End If
Range(Cells(top, left + 1), Cells(top + score_level - 1, right - 1)).ClearContents
Range(Cells(top, left + 1), Cells(top + score_level - 1, right - 1)).Interior.ColorIndex = 0
top = top + score_level
End If
score = score + 50 * score_level * (1 + score_level)
UserForm1.Label2.Caption = "Now you have the score of " + Str(score)
If score >= level Then
level = level + 800
interval = interval - 150
If interval < 50 Then
interval = 50
End If
If timerset <> 0 Then
timerset = KillTimer(0, timerset)
End If
pulse = False
End If
'判断方块是否堆积到顶,若未则生成下一方块,否则游戏结束
If top > mosttop Then
Call reinitial: Exit Function
Else: Call game_over: Exit Function
End If
End If
End Function
Function obj_draw()
Dim i As Long
Dim ii As Long
ii = prv_obj.typ * 4 + prv_obj.stat
For i = 0 To 3
Cells(prv_obj.pos.row + objs_array(ii, i).row, prv_obj.pos.col + objs_array(ii, i).col).Interior.ColorIndex = 0
Next i
ii = cur_obj.typ * 4 + cur_obj.stat
For i = 0 To 3
Cells(cur_obj.pos.row + objs_array(ii, i).row, cur_obj.pos.col + objs_array(ii, i).col).Interior.ColorIndex = cur_obj.color
Next i
End Function
Function reinitial()
If gaming Then
prv_obj = nex_obj
Randomize
nex_obj.typ = Int(7 * Rnd)
nex_obj.stat = Int(4 * Rnd)
nex_obj.color = Int(8 * Rnd) + 3
nex_obj.pos = nextpos
cur_obj = nex_obj
Call obj_draw
cur_obj = prv_obj
cur_obj.pos = startpos
prv_obj = cur_obj
Call obj_draw
End If
End Function
Function game_over()
If timerset <> 0 Then
timerset = KillTimer(0, timerset)
End If
If MsgBox("Try it again?", vbOKCancel, "Game over temporarily") = vbOK Then
Cells.ClearContents
Cells.Interior.ColorIndex = 0
Call game_initial
Else
Cells.ClearContents
Cells.Interior.ColorIndex = 0
gaming = False
SendKeys "%{F4}"
End If
End Function
Public Sub pulse_()
If gaming Then
Call obj_fall
End If
End Sub
以上是宏部分的代码,下面引入窗体后键入如下代码
Private Sub UserForm_Initialize()
Label1.Caption = "NO PLAY,NO GAME"
Call game_initial
If (gaming) Then
Label2.Caption = "Move and change by ARROW keys. Pause the game by P and end it by E"
Else
Label2.Caption = "Something happened. It needs to do something"
Call game_over
End If
End Sub
Private Sub UserForm_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If gaming Then
If Not pulse Then
pulse = True
timerset = SetTimer(0, 0, interval, AddressOf pulse_)
Label2.Caption = "Move and change by ARROW keys. Pause the game by P and end it by E"
End If
Select Case KeyCode
Case vbKeyLeft
Call obj_left
Case vbKeyRight
Call obj_right
Case vbKeyUp
Call obj_change
Case vbKeyDown
Call obj_fall
Case vbKeyP '销毁定时器,游戏暂停
If timerset <> 0 Then
timerset = KillTimer(0, timerset)
pulse = False
End If
Label2.Caption = "Game Paused.You can resume by ANY key"
Case vbKeyE
Call game_over
End Select
End If
End Sub
Private Sub UserForm_Terminate()
MsgBox ("You have complete the game with the score of " + Str(score))
Worksheets(1).Select
End Sub
有问题再发问吧,我都忘得七七八八了。