电脑编程做方块游戏
‘壹’ 怎么用vb制作俄罗斯方块游戏啊,简单点的。
visual basic继承了basic语言易学易用的特点,特别适合于初学者学习windows系统编程。随着21世纪信息社会的到来,计算机在人们的工作和生活中的深入,要求我们越来越多地与计算机打交道,为了使用户在繁忙的日程工作中得到放松,于是出现了各种各样的休闲软件,如聊天工具,游戏等等。于是我们小组着手设计开始一个这样的游戏软件。通过这学期来Visual Basic的学习,我初步掌握了Visual Basic语言的最基本的知识,于是在牛荣和李鹏等老师的指导下动手用Visual Basic编写俄罗斯方块游戏。
我们之所以选择开发俄罗斯方块游戏,无可争议,《俄罗斯方块》是有史以来最伟大的游戏之一。 在曾经发布过的所有游戏中,《俄罗斯方块》还被认为是仅有的一个能够真正吸引广泛人群的作品。谁能说清楚,迄今为止人们究竟花了多少万个小时在这个游戏上?也许这些时间本来可以被花在更具生产力的活动上。某些批评家也许会声称,《俄罗斯方块》要比过去二十年间出现的任何东西都要浪费人们的时间。至于我们,则要欣然提名它为GameSpot评选出的历史上最伟大游戏之一。
为了怀念经典,也为了能够给大多的计算机用户在工作之余找到一个休闲、娱乐的一个方式,我们小组开始着手用VB语言开发一个经典的俄罗斯方块游戏。
工程概况
2.1 项目名称
俄罗斯方块游戏
2.2 设计平台
VB 全称Visual Basic,它是以Basic语言作为其基本语言的一种可视化编程工具。
Vb是microsoft公司于1991年退出的windows应用程序开发工具visual意思是“可视化的”。在它刚推出来时,自身还存在一些缺陷,功能也相对少一些。但是经过多年的开发研究。最近microsoft公司又推出了VB6.0版本
VB6.0运行环境:硬件,要求486以上的处理器、16MB以上内存,50MB 以上的硬盘,cd-rom驱动器,鼠标。软件:要求windows 95以上版本。
2.3程序设计思想
游戏是用来给大家娱乐的,所以要能在使用的过程中给大家带来快乐,消除大家的疲劳,所以我们在游戏中添加了漂亮的场景和动听的音乐,设置了过关升级的功能,激发大家的娱乐激情。
从游戏的基本玩法出发,主要就是俄罗斯方块的形状和旋转,我们在设计中在一个图片框中构造了一个4*4的网状小块,由这些小块组合成新的形状,每四个小块连接在一起就可以构造出一种造型,因此我们总共设计了7中造型,每种造型又可以通过旋转而变化出2到4种形状,利用随机函数在一个欲览窗体中提前展示形状供用户参考,然后将展示的形状复制到游戏窗体中进行摆放,在游戏窗体中用户就可以使用键盘的方向键来控制方块的运动,然后利用递归语句对每一行进行判断,如果有某行的方块是满的,则消除这行的方块,并且使上面的方块自由下落,其中,方块向下的速度是有时钟控件控制的,在游戏中,用户也可以使用向下键加快下落速度,定义一个变量,对消除的函数进行记录,最后就可以得出用户的分数,用if 语句对分数判断,达到一定的积分就可以升级到下一个档次。
俄罗斯方块游戏设计的主要步骤为以下10个方面:
(1)游戏界面的设计。
(2)俄罗斯方块的造型。
(3)俄罗斯方块的旋转。
(4)俄罗斯方块的运动情况(包括向左,向右和向下)。
(5)俄罗斯方块的自动消行功能。
(6)游戏级别的自由选择。
(7)游戏速度的自由选择。
(8)游戏得分的计算。
(9)游戏菜单选项的设计及功能实现。
(10)游戏的背景音乐及特效。
2.4运用的控件和主要对象
我们在设计过程中主要用到的控件有:command控件,image控件,picture控件,label控件,timer控件,text控件,windows media player控件等等。
2.5主要实现的功能
我们开发的俄罗斯方块游戏,主要实现了以下几种功能:
1.可以灵活控制方块在图形框中运动。
2.游戏过程中方块可以自由旋转。
3.当某一行的方块排列满时,将自动将这一行方块消除,然后将上面所有方块向下移动,可以支持连续消行。
4.游戏前可以选择游戏的速度和游戏的等级,游戏速度既为方块下落速度,游戏等级为初始游戏时在基层随机生成一定行数的无规律方块,生成的行数由你来选择,每行至少产生5个以上的无规律方块,这样增加了游戏难度,对于游戏高手来说,无疑不是一个新的挑战。
5.游戏的得分支持积分,并且按照公式:
得分 = 原来分数+ 100 * (2 ^ 同时消除的行数-1)
这样,你同一时间消除的行数越多,你的得分也就越高,当游戏积分到了一定时可以自动升级,这个升级指速度升级。
6.游戏中提供了一个漂亮的场景和动听的音乐,给你带来无限激情。
2.6开发人员
由于这次课程设计所选的题目太复杂,而时间又比较紧张,指导老师建议和同学分工完成。我们小组成员包括组长孙磊周,副组长邹海星,此游戏由我们两个人共同开发而成。
正文
3.1游戏设计的具体实现
在我们两个人共同努力下,此次设计,终于能够圆满完成。由于时间的紧促,在设计中,也许会有一些考虑不周之处,但其功能已经能够满足大多用户的需求,相信假以时日,一定能做出一个更经典,更完美的俄罗斯方块游戏,下面我们将对每一步的具体如何实现展示给大家。
3.1.1游戏界面的设计和背景音乐及特效的实现
俄罗斯方块游戏主要由两个界面构成,登陆界面和开始游戏界面,在登陆界面中我们可以首先看到圣诞节的晚上飘梅花的场景,梅花从窗体顶部做函数曲线的下落运动,在窗体中定义一个Image控件组,在通用中定义梅花X坐标变量动态数组,Y坐标变量动态数组,步距X的变量动态数组,步距Y的变量动态数组,以及振幅变量动态数组。然后在窗体form_load中可以定义梅花的数量,利用随机函数产生随机的梅花坐标,步距和振幅,Image控件在运行时候就调用梅花图片,Image控件就可以由时钟控件控制下落速度,可以自由调节,梅花按snow(i).Left = xp(i) + am(i) * Sin(dx(i))函数在做纵向的正玄函数轨迹运动,竖直方向上为自由下落运动,,有am(i)来控制梅花的左右移动振幅。因此,我们就可以看到一个梅花在空中自由飘舞的画面了。
背景画面是用photoshop软件处理的漂亮图案,原本画面中的动画效果都是由Image控件制作的,还有点击进入游戏的按钮是由Label控件实现的,因为Image控件没有置前置后功能,不能将下雪的场景体现完整性,所以将这些图案全部放在背景上,不影响雪花飘落的效果,当点击画面的时候一样可以进入游戏界面。
游戏的背景音乐是由一段代码调用系统播放器Windows Player播放背景音乐,由于本次设计主要是针对游戏如何设计的,所以在这里就不对播放背景音乐的功能做介绍了。
3.1.2俄罗斯方块的造型
相信朋友们都玩过俄罗斯方块,对这个游戏的玩法和方块形状都比较熟悉。我们这个游戏只选择了最基本的7中造型,包括长条型,正方型,正S型,反S型,正7型,反7型,T型。如果需要我们可以添加更多的造型。将游戏界面的游戏区图片框分割成10*20的小块,每个小块放置一个command控件,预览区图片框按同样比例分割成4*4的小块,同样有command控件构成,我们可以把预览区图片框看作是从游戏区图片框中选取的一个部分,游戏区的小方块编号和欲览区编号如下图:
0 1 2 3 4 5 6 7 8 9
… … … … … … … … … …
… … … … … … … … … …
90 91 92 93 94 95 96 97 98 99
3 4 5 6
13 14 15 16
23 24 25 26
33 34 35 36
游戏区编号 欲览区编号
利用Select将方块的7中造型列出,比如长条型的设计,在欲览区中分别有3.4.5.6和5.15.25.35四个方块构成两中形态,用数组为:
m(0) = 3: m(1) = 4: m(2) = 5: m(3) = 6: situation2 = 0
m(0) = 5: m(1) = 15: m(2) = 25: m(3) = 35: situation2 = 1
将它的形状编号为0和1,在后面方便调用,其他的方块造型同样的方法。
3.1.3俄罗斯方块的旋转
俄罗斯方块的旋转主要将方块的位置加以变换得到的,例如上述范例,长条型有两中样式,根据小方块的编号变动来实现整个造型的旋转,比如:
If n(0) - 18 >= 2 And n(3) + 9 <= 198 Then
If cmdfang(n(0) - 18).Visible = False And _
cmdfang(n(1) - 9).Visible = False And _
cmdfang(n(3) + 9).Visible = False Then
hidefang 0
n(0) = n(0) - 18
n(1) = n(1) - 9
n(3) = n(3) + 9
showfang 0
situation = 1
End If
End If
方块的造型在旋转的时候存在一个公式,当然首先要判断是否满足旋转的要求,以上是一个长条型由横着变成竖立状态的旋转,我们以它的造型中的第三个小方块n(3)为中心旋转,这样,在开始运动的时候,长条形要发生旋转最少要运动到第三行,才能由横着变成竖立状态,游戏区图形框中第三行的第一个方块的编号为20,所以长条造型的第一个小方块的编号n(0)必须要大于20。同样,长条型方块在下落到底部的时候也有限制。如果长条下落到最后一行也将无法由横着变成竖立状态。
3.1.4如何实现方块的运动和自动消除满行的方块
我们的这个俄罗斯方块游戏主要是利用command控件的visible属性完成效果的,其实在游戏区图形框可以看成是由许多的command小方块组成,方块运动的过程就是造型里方块显示或者隐藏,就像现在的霓虹灯效果一样,由时钟控件控制visible属性改变的速度,上一层的消失,下一层的显示,这样,从视觉效果可以看到方块的下落运动效果。
方块在下落的过程中会自动判断每一行方块的visible属性,如果全部为true时,就会将这一行小方块的visible属性全部变成false,在将上面的小方块向下移动,利用for语句进行循环判断,将所有这样情况的行改变小方块visible属性。当有多行同时出现这样情况时使用递归调用,实现连续消行。具体程序代码如下:
For i = 190 To 10 Step -10
If cmdfang(i).Visible = True And _
cmdfang(i + 1).Visible = True And _
cmdfang(i + 2).Visible = True And _
cmdfang(i + 3).Visible = True And _
cmdfang(i + 4).Visible = True And _
cmdfang(i + 5).Visible = True And _
cmdfang(i + 6).Visible = True And _
cmdfang(i + 7).Visible = True And _
cmdfang(i + 8).Visible = True And _
cmdfang(i + 9).Visible = True Then
For j = i + 4 To i Step -1
t = 1
cmdfang(j).Visible = False
cmdfang(2 * i + 9 - j).Visible = False
For k = 1 To 4000
DoEvents
Next
t = 0
Next
linenum = linenum + 1
For j = i - 1 To 0 Step -1
If cmdfang(j).Visible = True Then
cmdfang(j).Visible = False
cmdfang(j + 10).Visible = True
End If
Next
clearline '为了实现连消数行,这里使用递归调用
End If
Next
3.1.5游戏速度和游戏级别自由选择
游戏速度的自由选择无非就是改变时钟控件的频率,我们在菜单中添加了选择速度的功能,还有添加了考验功能,将欲览窗中的方块造型隐藏,给玩家提高了难度,如果你不愿意接受考验也可以点击显示还原成原来状态。
游戏级别的自由选择是让用户选择游戏开始时候,游戏区底部出现一定行数的随机方块,同样给玩家增加了难度,功能代码如下:
For i = 19 To 20 - Val(txthard.Text) Step -1
For j = i * 10 To i * 10 + 9
If Rnd >= 0.5 Then cmdfang(j).Visible = True
Next
Next
可以根据你选择的难度系数在底层的每一行随机产生超过半数(即5个以上)以上的小方块,这样适合喜欢高难度的玩家。
3.1.6游戏得分的计算和游戏菜单的编辑
游戏得分的计算主要是根据消除的行数来决定的,当然每一次同时消除的行数不一样,每一行的得分也不一样,如果你每次消除的行数为1,则最后得分是100分,如果同时消除2行,则最后得分是300分,同时消除3行,得分为700分,同时消除4行,得分为1500分,这由公式:得分 = 原来分数+ 100 * (2 ^ 同时消除的行数-1)。
游戏的编辑,读者可以参照下面的功能介绍。
3.2 游戏功能的介绍
文件-------开始:开始游戏。
继续:继续游戏。
暂停:暂时停止游戏,点击继续的时候可以继续游戏。
退出:退出游戏。
设置-------选择游戏级别。
选择游戏速度。
考验-------显示:显示欲览去方块。
隐藏:隐藏欲览去方块。
帮助-------操作提示以及版本信息和作者资料。
用户界面具体如图:
图—登陆界面 图—游戏界面
图—菜单编辑界面 图—游戏帮助界面
有关说明
经过两个多星期的设计和开发,俄罗斯方块游戏已经成功。其功能基本符合用户需求,能够完成游戏的控制,方块的变换以及消层等功能。并提供游戏设置,对于一些技术性比较过硬的玩家,可以调游戏级别、以及游戏速度,使得玩家能够充分的发挥竞技游戏的特色,可以不断的挑战自我,挑战极限。
4.1游戏设计中的不足之处
但是由于课程设计时间较短,所以该游戏还有许多不尽如人意的地方,比如方块类型太少,退出游戏不能存储进度等多方面问题。这些都有待进一步改善,我们在游戏中还可以更换背景音乐,以适合不同的玩家,在每通过一关可以给玩家播放一段flash,吸引玩家去挑战极限,不断提高玩家的兴趣,相信在以后的制作过程中我们将给大家带来一个更新功能更全面的游戏。
4.2VB与C语言之间的不同之处
我们这个小游戏也可以用C语言来实现,在程序的编程上没有VB语言方便实用,C语言和VB语言之间存在很多的共同点,虽然语法方面有点差异,但是在编程思路上完全一样,VB能够实现很多C#不能做到的功能,如When语句、Optional参数、局部Static变量、对象实例访问静态方法、Handles绑定事件、On Error处理异常、Object直接后期绑定等等。VB和C#语言,编译出来的是同样的CIL,但为什么VB支持很多有趣的特性呢。我们一起来探究一下。
4.21局部静态变量
VB支持用Static关键字声明局部变量,这样在过程结束的时候可以保持变量的数值:
Public Sub Test1()
Static i As Integer
i += 1 '实现一个过程调用计数器
End Sub
我们实现了一个简单的过程计数器。每调用一次Test,计数器的数值就增加1。其实还有很多情况我们希望保持变量的数值。而C#的static是不能用在过程内部的。因此要实现过程计数器,我们必须声明一个类级别的变量。这样做明显不如VB好。因为无法防止其他过程修改计数器变量。这就和对象封装一个道理,本来应该是一个方法的局部变量,现在我要被迫把它独立出来,显然是不好的设计。那么VB是怎么生成局部静态变量的呢?将上述代码返汇编,我们可以清楚地看到在VB生成的CIL中,i不是作为局部变量,而是作为类的Field出现的: .field private specialname int32 $STATIC$Test1$2001$i
也就是说,i被改名作为一个类的字段,但被冠以specialname。在代码中试图访问$STATIC$Test1$2001$i是不可能的,因为它不是一个有效的标识符。但是在IL中,将这个变量加一的代码却与一般的类字段完全一样,是通过ldfld加载的。我觉得这个方法十分聪明,把静态变量变成生命周期一样的类字段,但是又由编译器来控制访问的权限,让它成为一个局部变量。同时也解释了VB为什么要用两个不同的关键字来声明静态变量——Static和Shared。由于局部静态变量的实质是类的字段,所以它和真正的局部变量还是有所不同的。比如在多线程条件下,对局部静态变量的访问就和访问字段相同。
4.2.2Handles和WithEvents
VB除了可以用C#那样的方法来处理事件响应以外,还有从VB5继承下来的独特的事件处理方式——WithEvents。
我喜欢称这种事件处理方式为静态的事件处理,书写响应事件的方法时就已经决定该方法响应的是哪一个事件,而C#则是在代码中绑定事件的。VB中WithEvents静态方法是非常有用的,它可以显着增强代码可读性,同时也让VB.net中的事件处理非常方便,不像C#那样离开了窗体设计器就必须手工绑定事件。
4.2.3类型转换运算符
在Visual Basic 2005中将加入一个新的运算符——TryCast,相当于C#的as运算符。我一直希望VB有这样一个运算符。VB目前的类型转换运算符主要有CType和DirectCast。他们的用法几乎一样。我详细比较了一下这两个运算符,得出以下结论:
1.在转换成引用类型时,两者没有什么区别,都是直接调用castclass指令,除非重载了类型转换运算符CType。DirectCast运算符是不能重载的。
2.转换成值类型时,CType会调用VB指定的类型转换函数(如果有的话),比如将String转换为Int32时,就会自动调用。
4.2.4默认属性和属性参数
在原先的VB6里,有一项奇特的功能——默认属性。在VB6中,对象的名称可以直接表示该对象的默认属性。
4.2.5可选参数和按名传递
VB从4.0开始支持“可选参数”这一特性。就是说,函数或子程序的参数有些是可选的,调用的时候可以不输入。其实VB从1.0开始就有一些函数带有可选参数,只不过到了4.0才让用户自己开发这样的过程。在VB4里,可选参数可以不带默认值,而在VB里,如果使用可选参数,则必须带有默认值。在调用的时候,VB若发现参数被省略,则自动读取.param部分的默认值,并显式传递给过程。这一部分完全由编译器处理,而且没有任何性能损失,和手工传递所有参数是完全一样的。至于按名传递,VB会自动调整参数的顺序,其结果与传统方式的传递也没有任何的不同。这说明我们可以放心地使用这项便利。而且带有可选参数的过程拿到C#中,顶多变成不可选参数,也不会造成什么其他的麻烦。
PS.很多COM组件都使用了默认参数,而且有些过程的参数列表非常长,在VB里可以轻松地处理它们,而在C#中经常让开发者传参数传到吐血。
4.2.6在经过对比之后可得以下一个结论:
1.目前的主流编程语言没有简单的,如果你想学精通的话。
2.VB的门槛比较低,编程思想较容易接受。
3.学习C不能短期内见到成效。
4.据用户调查69%的考生觉得VB更容易接受
致谢
在本次课程设计中,我从指导老师牛荣和李鹏身上学到了很多东西。老师认真负责的工作态度,严谨的治学精神和深厚的理论水平都使我收益匪浅。他无论在理论上还是在实践中,都给与我很大的帮助,使我得到不少的提高这对于我以后的工作和学习都有一种巨大的帮助,感谢他耐心的辅导。
另外,在游戏开发过程中化希耀老师和杜义君老师也给于我们很大的帮助,帮助解决了不少的难点,使得游戏能及时开发完成,还有所有的同学同样给与我不少帮助,这里一并表示感。
参考文献:
[1]Vsual Basic 程序设计教程 作者:龚沛曾,陆慰民,杨志强 高等教育出版社出版
[2]Vsual Basic 6.0程序设计 作者:刘新民,蔡琼,白糠生 清华大学出版社出版
[3]80例上手 VB6 编程 作者:唐凯军,汤惠莉 山东电子音像出版社
[4]Vsual Basic 实例教程 作者:卢毅 科学出版社出版
[5]Vsual Basic 经典范例50讲 作者:赵欣胜,亢慧娟,刘晟宏 科学出版社出版
‘贰’ 只会C语言编程还要学哪些才能做俄罗斯方块这样的小游戏
熟练掌握学懂C语言,再加上 microsoft visual c++ 6 作为编译器 就可以制作出俄罗斯方块这样的小游戏。也可以制作
2D游戏、 3D游戏 、动画、音乐播放器、 网站网页系统等。
C语言是一种计算机程序设计语言,属高级语言范畴。它既具有高级语言的特点,又具有汇编语言的特点。它可以作为工作系统设计语言,编写系统应用程序,也可以作为应用程序设计语言,编写不依赖计算机硬件的应用程序,代码清晰精简,十分灵活。
相关的特性:
1、对齐处理(Alignment)的标准化(包括_Alignas标志符,alignof运算符,aligned_alloc函数以及<stdalign.h>头文件。
2、_Noreturn 函数标记,类似于 gcc 的 __attribute__((noreturn))。
3、_Generic 关键字。
4、多线程(Multithreading)支持,包括:_Thread_local存储类型标识符,<threads.h>;头文件,里面包含了线程的创建和管理函数。
5、增强的Unicode的支持,基于C Unicode技术报告ISO/IEC TR 19769:2004,增强了对Unicode的支持。包括为UTF-16/UTF-32编码增加了char16_t和char32_t数据类型,提供了包含unicode字符串转换函数的头文件<uchar.h>.
6、删除了 gets() 函数,使用一个新的更安全的函数gets_s()替代。
7、增加了边界检查函数接口,定义了新的安全的函数,例如 fopen_s(),strcat_s() 等等。
8、增加了更多浮点处理宏。
9、匿名结构体/联合体支持,这个在gcc早已存在,C11将其引入标准。
10、静态断言(Static assertions),_Static_assert(),在解释 #if 和 #error 之后被处理。
11、新的 fopen() 模式,(“…x”),类似 POSIX 中的 O_CREAT|O_EXCL,在文件锁中比较常用。
12、新增 quick_exit() 函数作为第三种终止程序的方式。当 exit()失败时可以做最少的清理工作。
13、_Atomic类型修饰符和<stdatomic.h>头文件。
‘叁’ 如何用C语言编写一个俄罗斯方块的小游戏(配注释)
#include <windows.h>
#include <time.h>
#include <conio.h>
#include <stdio.h>
const int back=34;
const int speed[]={0,12,9,6,3,1};
const int number[]={0,2,3,5,7,11,15};
const int col[]={11,15,12,12,13,13,14};
int rank=1;
int level=0; //0表示既不是向右也不是向左,1表示向左,2表示向右
int kind;
int pri_kind; // 7大类,颜色标记,调用col[col_kind];
int revolve=0; // 旋转状态标记
struct
{
int x;
int y;
}current,before;
struct
{
int x;
int y;
int color;
bool having;
}board[15][25];
struct
{
int vary_x[4];
int vary_y[4];
} vary[]={
{{0, 2, 4, 6},{0, 0, 0, 0}},{{0, 0, 0, 0},{0,-1,-2,-3}},
{{0, 2, 2, 0},{0, 0,-1,-1}},{{0,-2,-2,-4},{0 ,0,-1,-1}},
{{0, 0, 2, 2},{0,-1,-1,-2}},{{0, 2, 2, 4},{0, 0,-1,-1}},
{{0, 0,-2,-2},{0,-1,-1,-2}},{{0, 0, 2, 4},{0,-1, 0, 0}},
{{0, 0, 0, 2},{0,-1,-2,-2}},{{0, 0,-2,-4},{0,-1,-1,-1}},
{{0, 2, 2, 2},{0, 0,-1,-2}},{{0, 2, 4, 4},{0, 0, 0,-1}},
{{0,-2,-2,-2},{0, 0,-1,-2}},{{0, 0, 2, 4},{0,-1,-1,-1}},
{{0, 0, 0,-2},{0,-1,-2,-2}},{{0 ,2, 4, 2},{0, 0, 0,-1}},
{{0, 0, 2, 0},{0,-1,-1,-2}},{{0,-2, 0, 2},{0,-1,-1,-1}},
{{0, 0,-2, 0},{0,-1,-1,-2}},
};
struct
{
int sum;
int connection_x[5];
int connection_y[5];
}connection[]={
{2,{-2,2},{0,1}},
{1,{0},{0}},
{2,{2,-2},{0,0}},
{2,{-2,2},{0,0}},
{4,{-2,0,4,-2},{0,0,-1,1}},
{4,{-4,2,-2,4},{0,0,-1,1}},
{4,{-2,2,0,0},{0,0,0,0}},
};
void gotoxy(int x, int y)
{
COORD pos;
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}
void color(int b)
{
HANDLE hConsole = GetStdHandle((STD_OUTPUT_HANDLE)) ;
SetConsoleTextAttribute(hConsole, b) ;
}
void PrintGarphy()
{
color(1593);
int i,j;
gotoxy(2,2);
for(i=0;i<26;i++)
printf("▓");
gotoxy(2,28);
for(i=0;i<26;i++)
printf("▓");
for(i=0;i<26;i++)
{
gotoxy(2,2+i);
puts("▓");
gotoxy(34,2+i);
if(i==8||i==16)
printf("▓▓▓▓▓▓▓▓▓");
else
puts("▓");
gotoxy(52,2+i);
puts("▓");
}
int t;
FILE *fp=fopen("C:\\els.txt","r");
fscanf (fp,"%d",&t);
fclose(fp);
color(43);
gotoxy(37,12);
printf("最高纪录: %d",t);
color(46);
gotoxy(37,14);
puts("当前得分: 0");
color(44);
gotoxy(37,16);
puts("级数 ");
color(39);
gotoxy(37,20);
puts(" ↑ ↓ ← →");
gotoxy(37,22);
puts(" 按空格 暂停");
gotoxy(37,24);
puts(" 按 ESC 退出");
gotoxy(37,26);
puts(" 编写人 ");
color(back);
for(i=0;i<15;i++)
{
for(j=0;j<25;j++)
{
board[i][j].x=4+2*i;
board[i][j].y=3+j;
board[i][j].having=0;
gotoxy(board[i][j].x,board[i][j].y);
puts(" ");
}
}
}
void GameOver()
{
color(391);
for(int i=24;i>=0;i--)
for(int j=0;j<15;j++)
{
gotoxy(32-j*2,3+i);
puts("▆");
Sleep(5);
}
color(back);
for(int j=0;j<25;j++)
for(int i=0;i<15;i++)
{
board[i][j].having=0;
gotoxy(4+2*i,j+3);
puts("▆");
Sleep(5);
}
gotoxy(42,16);
while(rank--)
printf(" ");
color(46);
gotoxy(47,14);
puts(" ");
}
void GetDepth(int *pdepth)
{
(*pdepth)=24;
for(int j=0;j<4;j++)
{
int sum=0;
int n=(current.x+vary[kind].vary_x[j]-4)/2;
int m=current.y+vary[kind].vary_y[j]-3;
if(m<0) m=0;
for(++m;m<25;m++)
if(board[n][m].having==0&&n>=0&&n<15&&m>=0&&m<25)
sum++;
else
break;
if(sum<(*pdepth))
(*pdepth)=sum;
}
}
void CheckFull(int *pscore)
{
int i,j;
int sum=0;
int s[]={0,1,3,6,10};
for(i=0;i<25;i++)
{
bool mark=1;
for(j=0;j<15;j++)
{
if(board[j][i].having==0)
{
mark=0;
board[j][i].color=back;
}
}
if(mark)
{
sum++;
for(int t=i;t>0;t--)
{
gotoxy(4,3+t);
for(j=0;j<15;j++)
{
if(board[j][t-1].having)
{
color(board[j][t-1].color);
printf("▆");
board[j][t].color=board[j][t-1].color;
board[j][t].having=1;
board[j][t-1].having=0;
}
else
{
color(back);
printf(" ");
board[j][t].color=board[j][t].color;
board[j][t].having=0;
board[j][t-1].having=0;
}
}
}
}
}
(*pscore)+=s[sum];
color(46);
gotoxy(47,14);
printf("%d",*pscore);
if(*pscore>=140) rank=5;
else if(*pscore>=90) rank=4;
else if(*pscore>=50) rank=3;
else if(*pscore>=20) rank=2;
else if(*pscore>=1) rank=1;
color(44);
gotoxy(42,16);
for(i=0;i<rank&&*pscore;i++)
printf("★");
int t;
FILE *fp=fopen("C:\\els.txt","r");
fscanf (fp,"%d",&t);
fclose(fp);
if(*pscore>t)
{
fp=fopen("C:\\els.txt","w");
fprintf (fp,"%d",*pscore);
fclose(fp);
color(43);
gotoxy(47,12);
printf("%d",*pscore);
}
fclose(fp);
}
void PrintNext(int pkind)
{
int i;
int x=43,y=6;
color(34);
for(i=0;i<4;i++)
{
gotoxy(x-3,y+i-2);
puts(" ");
}
pri_kind=pkind;
if(pkind==6) pkind=15,x--;
else if(pkind==5) pkind=11,x--;
else if(pkind==4) pkind=7,x--;
else if(pkind==3) pkind=5,x-=2;
else if(pkind==2) pkind=3,x+=2;
else if(pkind==1) pkind=2,x--;
else pkind=0,x-=3;
color(col[pri_kind]);
for(i=0;i<4;i++)
{
gotoxy(x+vary[pkind].vary_x[i],y+vary[pkind].vary_y[i]);
puts("▆");
}
}
void CheckBoundary()
{
int i,n,m;
for(i=0;i<4;i++)
{
m=current.x+vary[kind].vary_x[i];
if(m<4||m>32)
{
current.x+=(m<4?2:-2);
i=0;
}
}
for(i=0;i<4;i++) // 对四个方块分别检查
{
m=current.x+vary[kind].vary_x[i];
n=current.y+vary[kind].vary_y[i];
m=(m-4)/2;
n-=3;
if(n<0||n>24||board[m][n].having)
{
if(level==1) // 左移
current.x+=2; //复原
else if(level==2) // 右移
current.x-=2; //复原
level=0;
break;
}
}
}
void LevelMove()
{
CheckBoundary();
if(level==0) return;
int i;
color(back);
for(i=0;i<4;i++)
{
if(current.y+vary[kind].vary_y[i]>2)
{
gotoxy(before.x+vary[kind].vary_x[i],before.y+vary[kind].vary_y[i]);
puts(" ");
}
}
color(col[pri_kind]);
for(i=0;i<4;i++)
{
if(current.y+vary[kind].vary_y[i]>2)
{
gotoxy(current.x+vary[kind].vary_x[i],current.y+vary[kind].vary_y[i]);
puts("▆");
}
}
before.x=current.x;
}
void Revolve(int **prev_count) //旋转函数
{
int i;
before.x=current.x;
before.y=current.y;
(**prev_count)++;
(**prev_count)%=connection[pri_kind].sum;
current.x=current.x+connection[pri_kind].connection_x[**prev_count];
current.y=current.y+connection[pri_kind].connection_y[**prev_count];
CheckBoundary();
for(i=0;i<4;i++)
{
int m=(current.x-4+vary[number[pri_kind]+**prev_count].vary_x[i])/2;
int n=current.y+vary[number[pri_kind]+**prev_count].vary_y[i]-3;
if(board[m][n].having||m>14||m<0||n>24)
{
current.x=current.x-connection[pri_kind].connection_x[**prev_count];
current.y=current.y-connection[pri_kind].connection_y[**prev_count];
revolve=0;
(**prev_count)--;
before.x=current.x;
before.y=current.y;
return ;
}
}
color(back);
for(i=0;i<4;i++)
{
if(before.y+vary[kind].vary_y[i]>2)
{
gotoxy(before.x+vary[kind].vary_x[i],before.y+vary[kind].vary_y[i]);
puts(" ");
}
}
kind=number[pri_kind]+**prev_count;
color(col[pri_kind]);
for(i=0;i<4;i++)
{
if(current.y+vary[kind].vary_y[i]>2)
{
gotoxy(current.x+vary[kind].vary_x[i],current.y+vary[kind].vary_y[i]);
puts("▆");
}
}
Sleep(speed[rank]);
before.x=current.x;
before.y=current.y;
}
void ChoiceDirection(int *prev_count)
{
int t=50/rank;
while(t--)
{
if(_kbhit())
{
char c=_getch();
switch(c)
{
case 0x48:// up
revolve=1;
Revolve(&prev_count);
break;
case 0x50: //down
level=0;
return;
case 0x4b: //left
before.x=current.x;
current.x-=2;
level=1;
LevelMove();
break;
case 0x4d: //right
before.x=current.x;
current.x+=2;
level=2;
LevelMove();
break;
case ' ':
_getch();
break;
case 27:
color(back);
exit(1);
default:break;
}
}
Sleep(speed[rank]);
}
}
void StraightFall(int depth)
{
int i;
int rev_count=0;
before.x=current.x;
before.y=current.y;
while(GetDepth(&depth),depth--)
{
ChoiceDirection(&rev_count);
GetDepth(&depth);
if(depth==0)
{
revolve=0;
before.x=current.x;
before.y=current.y;
break;
}
color(back);
for(i=0;i<4;i++)
{
if(before.y+vary[kind].vary_y[i]>2)
{
gotoxy(before.x+vary[kind].vary_x[i],before.y+vary[kind].vary_y[i]);
puts(" ");
}
}
current.y++;
color(col[pri_kind]);
for(i=0;i<4;i++)
{
if(current.y+vary[kind].vary_y[i]>2)
{
gotoxy(current.x+vary[kind].vary_x[i],current.y+vary[kind].vary_y[i]);
puts("▆");
}
}
revolve=0;
before.x=current.x;
before.y=current.y;
}
ChoiceDirection(&rev_count);
if(level||revolve)
{
level=0;
revolve=0;
ChoiceDirection(&rev_count);
StraightFall(depth); //递归调用
}
}
int main()
{
srand((unsigned long)time(0));
system("mode con cols=56 lines=30");
system("color 24");
int score=0;
FILE *fp=fopen("C:\\els.txt","r");
if(fp==NULL)
{
fp=fopen("C:\\els.txt","w");
fprintf (fp,"%d",score);
fclose(fp);
}
PrintGarphy();
kind=rand()%7;
int depth;
while(1)
{
int pkind=rand()%7;
PrintNext(pkind);
current.x=18;
current.y=2; // 方块初始出现的坐标
GetDepth(&depth); // 初始深度
if(depth==0)
{
GameOver();
score=0;
rank=1;
}
pri_kind=kind;
if(kind==6) kind=15,current.x-=2;
else if(kind==5) kind=11;
else if(kind==4) kind=7;
else if(kind==3) kind=5;
else if(kind==2) kind=3,current.x+=2;
else if(kind==1) kind=2;
else kind=0,current.x-=2;
StraightFall(depth);
for(int i=0;i<4;i++)
{
int m=(current.x-4+vary[kind].vary_x[i])/2;
int n=current.y-3+vary[kind].vary_y[i];
board[m][n].having=1;
board[m][n].color=col[pri_kind];
}
CheckFull(&score);
kind=pkind;
}
return 0;
}
‘肆’ 怎么用C#写俄罗斯方块游戏还有控件需要哪些 总之就是详细步骤
刚学编程的时候写过一个VB的很烂的俄罗斯方块,全部都是用button来显示方块的,主要就是逻辑方面的计算来着。C# 道理差不多
另外也可以用GDI画图
总之单纯用C# 写的话其实不需要太多控件,button、label什么的都可以,GDI+画图也行,感觉俄罗斯主要是逻辑而已
‘伍’ 如何用电脑制作游戏
那要看你做什么游戏了,如果像俄罗斯方块这样的小游戏,VB和Flash就可以做。
如果是大的3D游戏,那很可能就要用到C++和Direct3D什么的。总之都是要编程的。
还有要制作大型的3D游戏有时还会用到3DMAX的
总之,游戏编程是一个很漫长的过程,在开始这个过程之前,请你一定要做好心理准备。
如果你没有接触过任何相关的知识的话,那么,一定要做好1~2年的准备,应为在开始正式开发游戏之前,你还有很多的工作要做。我的建议是,最好要从一些简单的编程做起。编程的语言有很多种,有简单,有难,但是如果可以的话,最好还是从C语言开始把,毕竟这是一门很实用的语言,而且他的移植性很好,学完后也便于一些更高级语言的学习,如C++,VC++或者JAVA。
当你有了一定的编程基础后(往往这是很不够的),不要急于求成,因为你至少还要了解很多的相关知识,比如说你可以先看看操作系统是如何运作的,在通过学习一下计算机组成来了解一下各个部件的关系和执行方式,如果可以的话,在看看汇编吧,毕竟知道更多的东西会有助于你其他方面的提高。
其实开发一个游戏真是一件很辛苦的事情,要学习的东西真的很多。在享受最终那份成就感之前,需要熬过无数枯燥的日子。
‘陆’ 用c语言编写俄罗斯方块程序 求详解
1、用C语言绘制图形界面
EasyX图形库(http://www.easyx.cn)即TC的图形库在VC下的移植。
包含库#include <graphics.h>
先初始化图形窗口
initgraph(WINDOW_WIDTH, WINDOW_HIGH) ;WINDOW_WIDTH为窗口的宽带,WINDOW_HIGH为窗口的高度。
清空绘图设备
cleardevice();
设置画笔颜色
setcolor(RED) ;
设置线条风格
setlinestyle(PS_SOLID, NULL, 0);
画矩形
rectangle
还有画线、显示文字等函数,可以参照其帮助文档。
注意:由于我们用的是EasyX图形库,故源文件后缀要为.cpp,但其中内容都是C的语法。
2、存储表示出俄罗斯方块的形状
一、我们可以用编号,不同的编号代表不同的俄罗斯方块,根据编号把不同方块的画法写在代码中,这样19种
方块就得有19种相应的代码来描绘。而且这样扩展性不好,若以后设计了新的方块,则需要更改大量源代码。
二、我们很自然的想到可用字模点阵的形式来表示,即设置一个4行4列的数组,元素置1即代表这个位置有小
方块,元素置0即代表这个位置无小方块,这个整个的4*4的数组组成俄罗斯方块的形状。
1000
1000
1100
0000
我们把俄罗斯方块点阵的数位存在rockArray中,我们可以事先把这19种方块的字模点阵自己转化成十六进制,然后在rockArray数组的初始化时赋值进去。
但这样做未免有点太费力,且扩展性也不太好,若以后设计的新方块种类加入,要改变数组rockArray中的值。
我们可以考虑把所有俄罗斯方块的点阵存储在配置文件中,在程序初始化时读取文件,把这些点阵转换成unsigned int的变量存储在rockArray中。
这样,以后我们增添新的方块形状只需要在配置文件中增加新的点阵即可。
@###
@###
@@##
####(为使得看起来更醒目,我们用@表示1,用#表示0)
3、让图形动起来
在某位置处用函数DrawRock在屏幕上画出俄罗斯方块,然后再擦除掉(即用背景色在原位置处重绘一次方块),最后在下落的下一个位置处用函数DrawRock在屏幕上画出俄罗斯方块,如此循环,中间用计时器间隔一段时间以控制下落的速度。
同理,按下屏幕的左右键也是如此,只是在按下键盘时把方块的位置重新计算了。
那么按下上方向键时,如何让方块翻转呢?
我们在配置文件中就把方块的顺时针翻转形态放在了一起:
@###
@###
@@##
####
@@@#
@###
####
####
@@##
#@##
#@##
####
##@#
@@@#
####
####
我们每按一次上方向键改变一次方块的形状即可。若一直按上键,形状应该是循环地翻滚。
我们想到了循环链表的数据结构可实现这个效果。
可是我们若把这些一种类的方块的各种形态串成循环链表形式,那么每次重新生成方块时我们就难以随机地生成方块了。
故还是得用数组来存储,但又要有循环链表的功能,于是我们想到了静态循环链表。
我们用结构体来作为一个方块在rockArray中的元素
typedef struct ROCK
{ //用来表示方块的形状(每一个字节是8位,用每4位表示方块中的一行)
unsigned int rockShapeBits ;
int nextRockIndex ; //下一个方块,在数组中的下标
} RockType ;
这样,当我们按下上方向键时,把传入函数DrawRock中的rockIndex变为当前方块结构体中的nextRockIndex即可。
‘柒’ 如何用mfc编写俄罗斯方块游戏,求详细解决过程!!!
控制台只能用字符串来话,要求基础还是蛮高的,
假如要做,首先要确定游戏的架构,有主体 全局 有地图 角色 NPC个个模块都分开,就是面向对象思想,
控制台游戏重点是,要把画的东西都写入缓冲区,然后再画出,否者会闪屏
我写个重要的给你吧
这是写入缓冲数组里面
void DrawBufferString( int iX, int iY, const char* szText, int iFRColor, int iBGColor )
{
if( iX < 0 || iX >= GAME_WIDTH ||
iY < 0 || iY >= GAME_HEIGHT )
{
return;
}
int iLen = strlen( szText );
WORD clr = iFRColor|iBGColor;
int l = ( iX + iLen > GAME_WIDTH )?( GAME_WIDTH - iX ):iLen;
strncpy( &g_ScreenBuffer[iY][iX], szText, l );
for( int i = 0; i < l; i++)
{
g_ColorBuffer[iY][iX+i] = clr;
}
}
这是写出
void DrawBufferToString()
{
HANDLE hConsole = GetStdHandle( STD_OUTPUT_HANDLE );
COORD rd = ;
DWORD wd = 0;
for( int i = 0; i < GAME_HEIGHT; i++)
{
WriteConsoleOutputCharacter( hConsole, g_ScreenBuffer[i], GAME_WIDTH, rd, &wd );
rd.Y++;
}
rd.Y = 0;
for( int i = 0; i < GAME_HEIGHT; i++)
{
WriteConsoleOutputAttribute( hConsole, g_ColorBuffer[i], GAME_WIDTH, rd, &wd );
rd.Y++;
}
DeleteObject( hConsole );
}