程序设计报告
--28号:贪吃蛇游戏
1 程序介绍
“贪吃蛇”是一种很流行的电子游戏。游戏方法如下 :一条蛇在棋盘上爬行,由键盘控制其转弯;棋盘上随机地出现5个数字(1~5),当蛇的头部碰到数字时(吃数字),蛇的身体会变长。当蛇的头部撞到棋盘边界或碰到自己身体时,游戏结束。游戏结束时,蛇身体越长得分越高。
2 具体设计
⑴程序启动时界面上棋盘由25*25个方格构成。开始时,蛇静止不动,位于窗口的左上角,头向右。身体由一串共10个圆圈表示,代表头部的圆圈为红色。
⑵按回车键开始游戏,蛇自动在棋盘上向前爬行,用户可以使用“←↑↓→”4个方向键控制其拐弯。蛇只能向左右转90º的弯,不能后退。蛇吃掉一个数字后,身体伸长的幅度与数字的大小有关。例如,吃掉“3”后,蛇身体伸长3个圆圈;吃掉“5”后身体伸长5个圆圈。
⑶5个数字(1~5)的位置是随机的,并且互不重叠,且只出现在未被蛇盖住的格子中。当蛇吃掉一个数字时,同样的数字随机地出现在其他位置上,即棋盘上总保持有“1~5”5个数字。
⑷使用回车键可以暂停或继续游戏。游戏进行时,窗口标题栏上显示出已使用的时间和得分,得分是当前蛇身体的长度。
⑸蛇在爬行时,如果其头部碰到墙壁或自己的身体,则被“撞死”,游戏结束。程序回到游戏开始状态,用户可以重新开始玩。
三,设计过程中遇到的问题和解决方法
四,小结
通过这个程序,使我对本书的部分内容有了一定的了解,能更加熟练地运用一些定义和控件……
五,附件
'定义变量,确定方向,圆圈的总数,暂停与否
Private num As Integer
Dim up As Boolean, down As Boolean, zuo As Boolean, you As Boolean
Dim pause As Boolean, fei As Boolean
Private Sub pro(ByVal n As Integer, ByVal m As Integer)
Randomize ' 开始时和中间时产生数字标签的调用过程
If m = 5 And fei = True Then '开始时产生数字标签
For i = 1 To m
Load bq(i)
bq(i).Visible = True
t1: With bq(i)
.BackColor = RGB(i + i * 50, 255 - i * 50, 50 + i * 20) '确定数字标签的状态
.Width = 1
.Height = 1
.Caption = i
.Left = CInt(Rnd * 24)
.Top = Int(Rnd * 24)
For k = 1 To n '判断数字标签产生时是否与圆圈重合,如果是则重新产生
If Abs(bq(i).Left - Shape1(k).Left) < 1 And Abs(bq(i).Top - Shape1(k).Top) < 1 Then
GoTo t1
End If
Next k
End With
Next i
Else '中间时产生数字标签
Load bq(m)
bq(m).Visible = True
t3: With bq(m)
.BackColor = RGB(m + m * 50, 255 - m * 50, 50 + m * 20)
.Width = 1
.Height = 1
.Caption = m
.Left = (Rnd * 24) \ 1
.Top = (Rnd * 24) \ 1
For k = 1 To n
If bq(m).Left = Shape1(k).Left And bq(m).Top = Shape1(k).Top Then
GoTo t3
End If
Next k
End With
End If
End Sub
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
Select Case KeyCode
Case 13
pause = Not pause '开始游戏
If pause = False Then
Timer1.Enabled = True
Timer2.Enabled = True
Else '游戏暂停
Timer1.Enabled = False
Timer2.Enabled = False
Form1.Caption = "虫子吃数字(暂停)"
End If
'判断方向,设置变量值
Case 37
If you = True Then Exit Sub
zuo = True
you = False
down = False
up = False
Case 38
If down = True Then Exit Sub
zuo = False
you = False
down = False
up = True
Case 39
If zuo = True Then Exit Sub
zuo = False
you = True
down = False
up = False
Case 40
If up = True Then Exit Sub
zuo = False
you = False
down = True
up = False
End Select
End Sub
Private Sub Form_Load() '初始化变量值
fei = True
pause = True
Timer1.Enabled = False
Timer2.Enabled = False
up = False
down = False
zuo = False
you = True
Form1.Scale (0, 0)-(25, 25) '给窗体定坐标
For i = 1 To 25 '画方格
Load Line1(i)
Line1(i).Visible = True
Load Line2(i)
Line2(i).Visible = True
With Line1(i)
.X1 = 0
.Y1 = i
.X2 = 25
.Y2 = i
End With
With Line2(i)
.X1 = i
.Y1 = 0
.X2 = i
.Y2 = 25
End With
Next
For i = 1 To 10 '开始时产生圆圈
Load Shape1(i)
Shape1(i).Visible = True
With Shape1(i)
.Left = (i - 1) \ 1
.Top = 0 \ 1
.Width = 1
.Height = 1
.FillColor = vbYellow
.FillStyle = 0
End With
Next i
num = 10
Call pro(num, 5)
Shape1(10).FillColor = vbRed
Shape1(10).FillStyle = 0
End Sub
Private Sub Timer1_Timer()
'定义变量记录最近的5个坐标轨迹,以便虫子增长
Static left1 As Double, top1 As Double, left2 As Double, top2 As Double
Static left3 As Double, top3 As Double, left4 As Double, top4 As Double, left5 As Double, top5 As Double
left5 = left4
top5 = top4
left4 = left3
top4 = top3
left3 = left2
top3 = top2
left2 = left1
top2 = top1
left1 = Shape1(1).Left
top1 = Shape1(1).Top '根据方向变量值,确定移动方向
If you = True Then
For j = 1 To num - 3
'判断是否撞到自己的身子
If Abs(Shape1(num).Left - Shape1(j).Left) <= 0.3 And Abs(Shape1(num).Top - Shape1(j).Top) < 0.5 Then GoTo t2
Next j
If Shape1(num).Left < 23 Then ' 向前移动
For i = 1 To num - 1
Shape1(i).Left = Shape1(i + 1).Left
Shape1(i).Top = Shape1(i + 1).Top
Next i
Shape1(num).Left = Shape1(num).Left + 1
Else: GoTo t2
End If
End If
If zuo = True Then
For j = 1 To num - 3
If Abs(Shape1(num).Left - Shape1(j).Left) <= 0.3 And Abs(Shape1(num).Top - Shape1(j).Top) < 0.5 Then GoTo t2
Next j
If Shape1(num).Left >= 1 Then
For i = 1 To num - 1
Shape1(i).Left = Shape1(i + 1).Left
Shape1(i).Top = Shape1(i + 1).Top
Next i
Shape1(num).Left = Shape1(num).Left - 1
Else: GoTo t2
End If
End If
If up = True Then
For j = 1 To num - 3
If Abs(Shape1(num).Top - Shape1(j).Top) <= 0.3 And Abs(Shape1(num).Left - Shape1(j).Left) < 0.5 Then GoTo t2
Next j
If Shape1(num).Top > 1 Then
For i = 1 To num - 1
Shape1(i).Left = Shape1(i + 1).Left
Shape1(i).Top = Shape1(i + 1).Top
Next i
Shape1(num).Top = Shape1(num).Top - 1
Else: GoTo t2
End If
End If
If down = True Then
For j = 1 To num - 3
If Abs(Shape1(num).Top - Shape1(j).Top) <= 0.3 And Abs(Shape1(num).Left - Shape1(j).Left) < 0.5 Then GoTo t2
Next j
If Shape1(num).Top < 24 Then
For i = 1 To num - 1
Shape1(i).Left = Shape1(i + 1).Left
Shape1(i).Top = Shape1(i + 1).Top
Next i
Shape1(num).Top = Shape1(num).Top + 1
Else: GoTo t2
End If
End If
'判断是否吃到数字标签
For i = 1 To 5
If Abs(Shape1(num).Left - bq(i).Left) < 0.5 And Abs(Shape1(num).Top - bq(i).Top) < 0.5 Then
Unload bq(i)
For k = num + 1 To num + i '增加圆圈
Load Shape1(k)
Shape1(k).Visible = True
With Shape1(k)
.FillColor = vbYellow
.FillStyle = 0
.Top = Shape1(k - i).Top
.Left = Shape1(k - i).Left
.Width = 1
.Height = 1
End With
Next k
'把圆圈按号码往后移,为新增的圆圈腾位子
For j = num To i + 1 Step -1
Shape1(j).Left = Shape1(j - i).Left
Shape1(j).Top = Shape1(j - i).Top
Next j
If i = 1 Then
Shape1(1).Left = left1
Shape1(1).Top = top1
End If
If i = 2 Then
Shape1(2).Left = left1
Shape1(2).Top = top1
Shape1(1).Left = left2
Shape1(1).Top = top2
End If
If i = 3 Then
Shape1(1).Left = left3
Shape1(1).Top = top3
Shape1(2).Left = left2
Shape1(2).Top = top2
Shape1(3).Left = left1
Shape1(3).Top = top1
End If
If i = 4 Then
Shape1(1).Left = left4
Shape1(1).Top = top4
Shape1(2).Left = left3
Shape1(2).Top = top3
Shape1(3).Left = left2
Shape1(3).Top = top2
Shape1(4).Left = left1
Shape1(4).Top = top1
End If
If i = 5 Then
Shape1(1).Left = left5
Shape1(1).Top = top5
Shape1(2).Left = left4
Shape1(2).Top = top4
Shape1(3).Left = left3
Shape1(3).Top = top3
Shape1(4).Left = left2
Shape1(4).Top = top2
Shape1(5).Left = left1
Shape1(5).Top = top1
End If
Shape1(num).FillColor = vbYellow
num = num + i
Shape1(num).FillColor = vbRed
fei = False
Call pro(num, i) '把吃掉的数字标签再产生出来
End If
Next i
Exit Sub
'撞墙或撞到自己后 出现提示框
t2: MsgBox "GAME OVER", 0, "snake"
For i = 1 To num
Unload Shape1(i)
Next i
For i = 1 To 5
Unload bq(i)
Next i
'重新出现界面
For i = 1 To 10
Load Shape1(i)
Shape1(i).Visible = True
With Shape1(i)
.Left = i - 1
.Top = 0
.Width = 1
.Height = 1
.FillColor = vbYellow
.FillStyle = 0
End With
Next i
num = 10
fei = True
Call pro(num, 5)
Shape1(10).FillColor = vbRed
Shape1(10).FillStyle = 0
'变量重新赋值
pause = True
Timer1.Enabled = False
Timer2.Enabled = False
up = False
down = False
zuo = False
you = True
End Sub
Private Sub Timer2_Timer()
'窗体标题更换
Static n As Integer
n = n + 1
Form1.Caption = "虫子吃数字(运行):" & n & "秒 " & num & "分"
End Sub
小结
贪吃蛇这游戏我已前是经常玩的,所以开始时我觉得将会很顺利,可是事情的发展却并非如此。动手后,界面很快就弄好了。但接下来就遇到困难了,小圆圈不动了,也就是蛇不走了。仔细检查才发现是变量的赋值发生了错误,纠正后蛇终于动了。接着遇到的是蛇跑到了格子外面而游戏仍不结束,这次一时没找到原因,因为代码里已经明明白白写了判断出格的语句,可是根据运行的效果看明显没有运行该语句。仔细想想,我便断定是判断语句出错了。于是
再试验几次,才发现格子的LEFT和TOP与我所定义的变量类型不同,窗体经SCALE后,照理说已经变成了整型的了,可运行过程中的却仍是SINGLE,这让我百思不得其解,只好用差值的绝对值来判断,这样问题解决了,也同样解决了后面的数字格不与圆圈重合以及撞到自身的问题。而最难的问题则是如何让
蛇增长。如果只是让它沿横或沿竖增长的话都会遇到判断出格或撞到自身的问题,而如果真这样做的话,代码就必须很长了。我做不下去了,停了下来。于是在做其它事情时我都想着如何解决这问题。后来终于想通了,就是随时记住
圆圈移动轨迹的最近的五个位置,然后把它赋给增长的圆圈。这样的话,编程就很快结束了。这个程序给我的启发很大,我认为编程除了有基本功外,还得记住一句--创意才是灵魂。