请问有没有用c语言编程软件写俄罗斯方块的视频教程,急需,谢谢了,好的加分!

C语言俄罗斯方块的问题,没用图形库,困扰好多天了,自己写了一半,真心求高手指导!_百度知道
C语言俄罗斯方块的问题,没用图形库,困扰好多天了,自己写了一半,真心求高手指导!
加企鹅聊,二六一五二四七一五
提问者采纳
我有个不用图形库的俄罗斯方块,已发送到qq邮箱,希望对你有用
提问者评价
其他类似问题
您可能关注的推广
俄罗斯方块的相关知识
按默认排序
其他1条回答
网上搜 EasyX 可以下载下来用的
我只是想不用图形库写一个
哦哦,那就等高手解决吧我也在学C语言
为您推荐:
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁谁写过俄罗斯方块,最好是c++_百度知道
谁写过俄罗斯方块,最好是c++
高分送上本人现在在学习软件工程,所以就想写一个小游戏,所以从简单的入手,所以就请教一下有没有人写过俄罗斯方块,急,还不知道难度,所以要制作一个小项目,认为俄罗斯方块比较简单,有写过的希望可以介绍一下需要学习的东西
提问者采纳
如果你不考虑GUI的话就更简单了:对楼上无语。要做带点图形的,也很快,尽管去试,就算失败了积累经验也是非常值的?搞笑吧,俄罗斯方块半年,而且写过很多次。看你学软件工程,对数据结构应该比较了解,就去学学GDI(假设你做Windows平台的游戏)。PS我写过,最基本的数据结构一摆,连带从头学MFC都用不了这么多,ok,我假定你之前至少学过一些东西。C++的稍微费时些一个上午。VB的两个小时就可以写完。不要有恐惧心理,有编过一些程序。另外楼主问游戏开发你贴那么多Web开发和数据库开发的东西过来干吗。最基本的俄罗斯方块还是挺简单的
提问者评价
兄台高手,高分送上!
其他类似问题
俄罗斯方块的相关知识
其他5条回答
C#的要不?我也是下载来的,不是我写的。
我有VC的源程序,个人资料里有联系方式。
NO。我觉得俄罗斯方块也不太好弄,我写过,差不多写了半年,自己越看越不满意,说不定你有这方面的天赋,我当初是在一个网站上看到的,然后自己做了一个,虽然不满意,放到网上,点击率还挺高呢!资料附上:送你一个很好的学习网址: 对于广大编程初学者来说,存在着这样普遍的认识:学习程序设计选择编程语言 很重要,开口闭口就是VisualBasic、Visual C++、Delphi、Power Builder等一些现在比较流行的开发工具。经常看见有初学者问:我学C/C++,究竟是学 VisualC++好,还是学Borland C++ Builder好呢?或者就是要求在Visual Basic和Delphi之间作出选择。学习程序设计和学习程序设计语言究竟是怎么一个关系?初学者究竟应该如何取舍呢?就此我们打个简单的比方:学习程序设计就好比学习射击,而程序设计语言就对应射击中的气枪、手枪、步枪等各种枪械。学习射击必须要选择一种枪械,不可能没有枪还能学好射击的,也不可能同时学会使用所有的枪械。但是,如果掌握一种枪械的射击,再学别的也就触类旁通了。因为在熟悉一种枪械的同时,也学习了射击技术本身。再学其他的,自然事半功倍。学习程序设计也是一样,必然要从学习一门程序设计语言开始入手。同时在学习的过程中? 建议:学习程序设计不必苛求一定要从某一种语言入手,可以在Visual Basic、Delphi、Borland C++ Builder或者DOS下的Pascal、Turbo C(或Borland C)中间选择自己比较容易接受的一种进行学习。从中主要学习的是编程本身的思想,学习的是用程序设计的眼光来看待问题。或许,学习的效果不能马上看到,但是可以学到扎实的基本功,而这对于将来的进一步发展是有很大好处的。这些基本功包括: 一、强化逻辑分析和建立数学模型的能力 编程的目的是什么?是要解决现实中的问题。而现实中的问题是用自然语言描述的,目前的计算机对其无法理解。我们要做的就是必须用计算机能理解的方式将问题“告诉”计算机。也就需要我们对现实问题进行逻辑分析,建立合理的数学模型,然后以程序和数据的形式输入计算机,R、G、B三色份量来各表示一种颜色,对于颜色的处理被转化为对R、G、B三个整数的处理。我们只要改变这三个整数,就可以将其改变成另外一种颜色。对于其它的现实问题,我们也要像 这样使其可以被计 二、数据结构和算法知识 程序设计发展到现在,已经有了一套比较普遍、完整的数学模型(我们称之为 数据结构)和对应这些数学模型的处理方法(也就是算法)。目前的程序就是以 此为基础的。在程序员中间流传着一句经验之谈:“好的数据结构是程序的一 半。”其重要性可见一斑。作为一个程序员 三、丰富的实践经验 程序设计本身就是一门实践性很强的学科。一个只存在于纸上的程序如同没 有翅膀的鸟永远不能飞翔在现实的天空。任由代码写得再巧妙,风格再优美,也 只是一张纸上的一连串字符而已。就好比是一份作文练习,或许写得很好,但是 不交给老师去批阅,和一张白纸又有什么区别呢?!最后,作为一个程序员还有一点小要求:那就是身体素质要好,能熬夜才行。 Top of Form 1 选其器与善其事——纵谈编程工具的选择选其器相同主题的文章 “工欲善其事,必先利其器”——《论语》。很多人在学习软件编程时,都希望 选择一款优秀的编程工具。到书店逛逛,可以看到各种琳琅满目的编程书籍,可 是你还没有想好选择学习什么编程语言,也就无所适从,不知道该买什么书看。 要想学好编程,必须认真了解各种语言的特点,找准自己的学习方向。那么你首 先必须明确你想要做什么,你所感兴趣的是什么?进一步说就是:你现在想要完 成哪一方面的程序设计,你的程序主要完成的功能是什么?由此在众多软件中, 选择出适合自己的开发工具。 一、基础语言开发工具 诸如Delphi、VC++、VB等语言都是一种面向对象的程序设计语言,虽然每种语言在对面向对象的支持不尽相同,但它们始终贯穿整个程序设计的思维方式的主线。因此,要学好这些语言最开始不应该将重点放在某种语言的具体语法格式上,而应该注重学习面向对象的基本理论 最容易的入门语言——Visual Basic 在掌握面向对象编程的基本概念的基础上,相对来讲,VB是比较容易入门的 一门语言。在学习VB时,应该注意抓住对象的精髓,避免凌乱和繁杂,注意掌握 对象和控件的属性和事件以及它们的功能和用法、主要函数的简单功能。最有效 的方法就是自己组织一个由简到繁的学习步骤,比如:在学习VB简单绘图功能时,学着自己绘制正弦曲线;学习使用picturecl控件来制作一个液晶效果显示时间;在学习API函数时,制作自己的任务栏图标。这种方法能够很好的帮助你掌握VB中常用对象、事件的使用。 最灵活的语言——Delphi 对于Delphi来讲,如果你曾经学过PASCAL的话,你会发现很多东西都是“似曾相识”的。确实如此,Delphi本身就是由和PASCAL结构类似的Object Pascal编写而成。如果你有一定的PASCAL基础,学习起来当然更轻松一些。另外,还应注意对Delphi中包的理解和应用。比如,对运行期包、设计期包以及自己建立包应该注意的事项。在熟练掌握Object Pascal语言的基础上,可以把学习Delphi时的重点放到如何使用Delphi编写Windows应用程序,Delphi数据库编程和创建控件以及程序开发上面。 最强大的语言——Visual C++ VC++中由于有较完整的微软基本类库,使开发Windows应用程序变得简单而 高效。它提供的复杂的资源编辑器,可以很方便地编辑对话框、菜单、工具栏以及其他组成元素,因此它的功能强大,使用方便,但是和VB、Delphi相比,入门较难、不容易掌握。学习VC++,应该首先把重点方在基本数据类型、输入/输出、循环和数组、模板以及如何创建C++应用程序上面。在此之后,才应该进一步学习VC++中资源编辑器的使用、ActiveX控件的使用以及编辑器优化等内容。目前很多关于VC++的书籍中大部份都是对使用VC++各个版本开发应用程序的介绍,而忽略了C++的基本知识,实际上,对于初学者来讲,直接从具体应用程序设计入手而忽略基本知识,反而会在很大程度上加大学习难度,很容易丧失学习的信心?!----& 当然在上述这些语言中,都提供有自己的数据库编程和Internet编□'7b。在对程序本身熟练掌握的基础上,你还可根据自己的需要选择学习。当你已具有一定程序设计能力时,不妨自己设计一个现实、有兴趣的课题,自行开发、自行设计。这样可以帮你很好地熟练 二、数据库编程 如果你主要是想完成数据库方面的设计,那么应该选择专门的数据库开发工具,常见的有:SQLServer、PowerBulider等。假如只是需要完成相对简单的数据库功能,那就仔细看看Access吧。花不多的时间,也能让你有很大的收获,另外,还有一些专门用于大型数据库开发的工具如:DB2、Sysbase以及Oracle,这一类的软件一般都需要有较扎实的数据库基础知识和一定的软件开发能力。如果你是从头开始的话,建议不要一开始就去学习这一类软件。PB和SQLServer主要是用于完成数据处理和数据库的访问。由于SQLServer和操作系统兼容性较好以及在网络中的广泛应用,目前很多业余爱好者都选择学习它,在学习SQLServer时,应把重点放在SQL语言的组成、SQL的事务管理以及SQL的查询和优化上面。而PB则一直都是很多从事数人来讲,在学习数据库基本使用技巧的同时,还应注意到在PB中,对于需要访问Windows特殊功能的应用程序需要调用API函数,比如:控制鼠标、创建目录以及闪□'7b窗口等。 在学习数据库编程时,可以尝试着完成一个完整的软件开发周期。从需求分析隍7d始,亲身经历设计数据库、创建数据库前端、创建表格、完成常见查询以及输出报表等全部过程。 三、网络编程 目前较为流行的网络编程工具可谓“风格迥异,百花齐放”。每一种工具都有其独特的特点,在互联网实现上都有各自的优势。 在学习Java时,应该明确其中对象、继承等面向对象的基本理论,从根本上掌握Java的运行机制。在学习中应把重点放在其语言基础、Java与ActiveX以及JavaBeans等组件之间的编程技术以及应用上来。你可以自己编一些较为经典的小程序来加深基本技能的掌握:用Java的图形处理能力编写纸牌游戏,用AWT编写扫雷或者俄罗斯方块、用Java的网络功能编写网络聊天室等等。 相对来讲,ASP编辑方式简单、容易上手、功能强大,早已被广泛采用。在学 习ASP时,应该首先对ASP相关的网络知识、Web Server设置、HTML语言等方面有 一定了解,在此基础上,注重ASP的主要编程语言VBScript、ASP的常用对象和组 件的学习。如果想对ASP有较深入的了解的话,还必须对其常用的数据库 SQLServer、Acess等具有基本的使用技能。你可以自己尝试编一个简单的网上投票、网上超市等程序来加深对上述知识的掌握。 另外,值得一提的还有网络编程语言的“新秀”——PHP。它□'5c脱了ASP只能使用NT或者Windows 2000为服务器操作系统的限制,对于数据库的访问较ASP更快、更直接。但是目前对于初学者来讲,其语言比较难理解,安装相对复杂、可供参考和学习的资料远不及ASP。同时在Windows中使用PHP,并不能够很好地体现其优越性。因此,我们建议对于没有Linux/Uninx基础的初学者,最好不要从PHP学起。 网络编程还有一个很大的特点:处处留心皆学问。时常留意互联网上各个网站的设计,留心他人的设计思想和创意,会使你的网络编程技巧进步很快。总的来讲,网络编答7b本身难度并不大,但是由于其在具体项目设计上涉及范围较广,比如涉及到与各种各样的数据库直接的接口、 学习语言的过程,是自己创造、自己编程的过程,也是逐渐掌握、逐渐应用的过程。在学习过程中逐渐培养起良好的编程思维、经验,逐步提高程序设计能力、找到更好的设计方案才是编程开发的真正精髓和乐趣所在! 懂数据结构怕不行,我说的高手,不是在会不会的界限上,而是在能不能的界限上
int a[4][4]; a[4][4]={{0,0,0,0},{1,0,0,0},{1,1,1,0},{0,0,0,0}}; int m[4][4]; for(int i=0;i&4;i++) { for(int j=0;j&4;j++) { m[i][j]=a[3-j][i]; } } for(i=0;i&4;i++) { for(int j=0;j&4;j++) { block[i][j]=m[i][j]; } } }
为您推荐:
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁急用!!!哪位大侠帮忙用 C语言 写一个 俄罗斯方块 的程序。_百度知道
急用!!!哪位大侠帮忙用 C语言 写一个 俄罗斯方块 的程序。
上下左右移动,满行消行,能够实现6!多谢多谢哪位大侠帮忙用C语言写一个俄罗斯方块的程序,可以实现这几个功能就行,简单点的就好,出方块、7个基本功能就行
再给个系统流程图,谢谢啦!
提问者采纳
p=fx+x[i][j].h&n&#92,
0,&r;printf(&dltm==1){dla=20000;
putch(219);
if (s==0) return,a;
} } full(){
int fj=0,219);
if(k==3) score+=7;
tf=tm[0];c&j&lt,0,0: turn(),
} z++; #include &=23;
int y[8][4]={
test(),2),-1;=23,c;
if(level&lt,
0;conio,p,int t){
display(i;
putch(219);
if(s==1){ fy--;
if(tf==32){
gotoxy(p,t;4,
0,&level);
k=getch().h&gt,1,i:&
fy=5; #include & fy=5;
display(i;
r,1;4;4,0;i++){
for(c=1; x[i][j]=c;textcolor(i),q.h&&#92,
0; fx=16;)!=32) s=1;j& case 72,219);j& int randtmp=3,e2,0;
printf(&z&gt,q;i++){
textcolor(i);fy=2,j;
delay(3200);score=%d&
if(tmp[0];\ x[i][j]=-y[i][j]: right();
printf(&quot,12),p;gotoxy(12;z--){
if (m[z]==12){k++;}
if(level==3){dla=60000;
gotoxy(c; case 75; display(;j++){
c=y[i][j];
gotoxy(c,1;
if(s==1) fx=ox.cx=0x2000,32),
0,i); display( int nx[5],t);j++){
textcolor(i);q--){ for (p=11; fx=9;
randtmp=rand()%7+1,1,q; } test(){
char tmp[2],p,
} } left(){
switch(k){ case 77,q,h[5];nINPUT LEVEL[Difficult=1 Normal=2 Easy=3]; int x[8][4]={
ox=fx,1.x,
for(z=23,ny[5],0;a&);putch(219);=24;c++){
textcolor(i);
for(j=0,begin=0,t).x;
display(NEXT,-1;
if((s==1) && (fy==5)) { over();
levelchooser(),a,s,0;
for(i=10;}
if(level==1){dla=20000; y[i][j]=c,r;
if (fj==1) {kill(),0;
display(i,q,
gettext(p;delay(dla),0;
textcolor(3); &
ox=fx,m[25],2,fq,i),yj,
union REGS r,1.ax=0x0100;
if(m[yj]==12)
fj=1,219): left();=3){dla=60000,&r);
for(i=1;i++){
m[i]=0,32);
printf(&} } m[q+1]=m[q];4;fy=2;printf(&n\
q=fy+y[i][j],-1; putch(t),score=0;
if(k==27) exit(0); #include &
delay(dla);n\
p=fx+x[i][j],0;j++){
yj=fy+y[i][j],
display(i,a).h&}
if(level&i&lt,0;
textmode(C40),
} } box(){
gotoxy(11,3;
gotoxy(i; break,q+1); } main(){
int e1;),219),-2;c++){
textcolor&#169,&tm);
if(kbhit()){
k=getch();dltm=
putch(219),1;,
0; } func(){
i= } inkey(){
int k,0,24);
randomize();
func();i&a++){
gotoxy(5;4;
t=219;); dla=dltm,2; display(i;
for(i=4,0;
display(i;n&#92,a);}
putch(219),
} } levelchooser(){ } } kill(){
char tm[2].h&gt,k=0;p&lt,0,q+1);}
if(level==2){dla=40000,1,i):&quot,
},32); } over(){
fx++; case 80,
0,0;=4) score+=13,-1;j++){
q=fy+y[i][j];j++){
c=x[i][j];
for(q=z-1; full();
for(j=0,z,
},score);dltm=
test(),0: dla=8888;
if(s==1) fx=ox,0,0,1);%d& int dla=32000;
display(i;dltm=delay(dla),1,1;
inkey();=24; } right(){
gotoxy(23;
} } turn(){
for(j=1; #include &
delay(32000); fy++,0;nWelcome Pfy=5,1,1;
}else{gotoxy(p;
int86(0x10#include &
if(k==1) score++;
if(k==2) score+=3;i&
fx--;n\ ;
gotoxy(10;
putch(219),1;dltm==40;
delay(32000);=40; test();j&4,1;j&
gotoxy(1; y[i][j]=-x[i][j],p++){
gettext(p;c&4,q),&tmp),0,0;=22;
test();stdio
这就完啦,这可以实现什么功能啊?谢谢啊,还有就是系统流程图有没有啊?
没空去non,自己解决吧,那样才能学到东西
好地!那麻烦告诉我这个程序都实现了哪些功能!十分非常特别的感谢
最简单的功能,你可以试试,也可以改的,总之你要求的功能都有了
其他类似问题
俄罗斯方块的相关知识
为您推荐:
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁怎样编写用C语言编写坦克大战,俄罗斯方块,等游戏?(我不是要代码)请各位高手推荐几本教材?_百度知道
怎样编写用C语言编写坦克大战,俄罗斯方块,等游戏?(我不是要代码)请各位高手推荐几本教材?
因为现在的书本基本上都没有涉及到游戏编程的一些知识,比如谭浩强的,还有很多的,我希望大家能给我推荐几本C语言游戏珐激粹刻诔灸达熏惮抹编程的书,感激不尽!
提问者采纳
推荐一本书《C游戏编程从入门到精通》(第二版)浦滨 编著,我再图书馆借的书
提问者评价
谢谢你了!
其他类似问题
按默认排序
其他2条回答
这么问的话,说明你对编程理解还是太浅了,再慢慢修炼一段时间吧。只要坚持学习下去,某一天你会突然发现自己没看任何游戏编程的书却知道珐激粹刻诔灸达熏惮抹怎么编游戏了。再说得具体一点,你现在输出字符是用printf之类的吧?研究一下怎么自己绘制一个字体,好了,你就学会绘图了。高中的时候学物理学过自由落体运动吧,站在山崖上水平扔石头的题做过吧,计算出某个时候石头的位置(xy轴座标)不难吧,写个函数,好了,你的物理引擎出来了。好了,激动人心的时刻到了,你把这函数给出的即时x、y座标用来绘制一个字体,再稍微调整一下,好了,你写完了第一个游戏:高空抛字体。
如果想在游戏方面有所突破的话必须学好graphics.h....
您可能关注的推广
坦克大战的相关知识
为您推荐:
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁利用C语言编写的俄罗斯方块 实现源码
Tc2.0中怎么样设置图形显示?
  Tc2.0中有两种显示模式,一种是我们所熟知的字符模式,另一种是图形模式。在字符模式下只能显式字符,如ASCII字符。一般是显示25
行,每行80个字符。程序缺省的是字符模式。在字符模式下不能显式图形和进行绘图操作。要想进行图形显示和绘图操作,必须切换到图形模
  Tc2.0中用initgraph()函数可以切换到图形模式,用closegraph()可以从图形模式切换回字符模式。initgraph()和closegraph()都是图形
函数,使用图形函数必须包括头文件graphics.h。
  void far initgraph(int far *graphdriver,int far *graphmode,char far *pathtodriver);graphdriver是上涨指向图形驱动序号变量的指针;graphmode是在graphdriver选定后,指向图形显示模式序号变量的指针。pathtodriver表示存放图形驱动文件的路径。
  Tc2.0中有多种图形驱动,每种图形驱动下又有几种图形显示模式。在我的程序中图形驱动序号为VGA,图形显示模式序号为VGAHI。这是一种分辨率为640*480(从左到右坐标依次为0-639,从上到下坐标依次为0-479),能够显示16种颜色的图形模式。别的图形驱动序号和图形显示模式序号,可以从手册或联机帮助中找到。
  pathtodriver指示存放图形驱动文件的路径。图形驱动序号不同,图形驱动文件也不同。序号为VGA图形驱动对应egavga.bgi这个图形驱动文件。egavga.bgi一般在Tc目录下。
void far closegraph(void);
  没有参数,从图形模式直接返回字符模式。
initgraph()和closegraph()的常用用法如下:
int gdriver = VGA, gmode=VGAHI,
/* initialize graphics mode */
initgraph(&gdriver, &gmode, e:tc2);
/* read result of initialization */
errorcode = graphresult();
if (errorcode != grOk) /* an error occurred */
printf(Graphics error: %sn, grapherrormsg(errorcode));
printf(Press any key to halt:);
exit(1); /* return with error code */
/* return to text mode */
closegraph();
Tc2.0中常用图形函数的用法?
在这里讲几个游戏中用到的绘图用的图形函数:
setcolor();
rectangle();
settextjustify();
outtextxy();
setfillstyle();
void far setcolor(int color);
  设置画线、画框和在图形模式下显示文字的当前颜色。这个函数将影响line()、rectangle()和outtextxy()函数绘图的颜色。
color可以取常的颜色常量:
MAGENTA ? 5
LIGHTGRAY ? 7
DARKGRAY ? 8
LIGHTBLUE ? 9
LIGHTGREEN ?10
LIGHTCYAN ?11
LIGHTRED ?12
LIGHTMAGENTA ?13
YELLOW ?14
void far line(int x1,int y1,int x2,int y2);
用当前颜色从(x1,y1)画一条到(x2,y2)的线段。
void far rectangle(int left,int top,int right,int bottom);
用当前颜色画一个左上角为(left,top)、右下角为(right,bottom)的矩形框。
void far settextjustify(int horz,int vert);
设置图形模式下文字输出的对齐方式。主要影响outtextxy()函数。
horiz和vert可取如下枚举常量:
horiz ?LEFT_TEXT ? 0 ?Left-justify text
?CENTER_TEXT ? 1 ?Center text
?RIGHT_TEXT ? 2 ?Right-justify text
vert ?BOTTOM_TEXT ? 0 ?Justify from bottom
?CENTER_TEXT ? 1 ?Center text
?TOP_TEXT ? 2 ?Justify from top
void far outtextxy(int x,int y,char * textstring);
在(x,y)处用当前字体(缺省的字体是DEFAULT_FONT)显示字符串textstring,字符串的对齐方式由settextjustify()指定。
void far setfillstyle(int pattern,int color);
设置图形的填充模式和填充颜色,主要影响bar()等函数。
pattern一般取枚举常量值SOLID_FILL,color的取值与setcolor(int color)中color的取值范围相同。
  介绍完了前面两个问题,现在来写一个程序。这个程序演示前了面所介绍的几个图形函数。
程序prog1.c
怎样获取I盘输入?
  在Tc2.0中有一个处理键盘输入的函数bioskey();
int bioskey(int cmd);
  当cmd为1时,bioskey()检测是否有键按下。没有键按下时返回0;有键按下时返回按键码(任何按键码都不为0),但此时并不将检测到的按
键码从键盘缓冲队列中清除。
  当cmd为0时,bioskey()返回键盘缓冲队列中的按键码,并将此按键码从键盘缓冲队列中清除。如果键盘缓冲队列为空,则一直等到有键按
下,才将得到的按键码返回。
  Escape键的按键码为0x11b,下面的小程序可以获取按键的按键码。
key=bioskey(0); /* wait for a keystroke */
printf(0x%xn,key);
if (key==0x11b) /* Escape */
常用按键的按键码如下:
#define VK_LEFT 0x4b00
#define VK_RIGHT 0x4d00
#define VK_DOWN 0x5000
#define VK_UP 0x4800
#define VK_HOME 0x4700
#define VK_END 0x4f00
#define VK_SPACE 0x3920
#define VK_ESC 0x011b
#define VK_ENTER 0x1c0d
  完整的程序请参见prog2.c、prog3.c。
prog2.c获取按键的按键码,按Escape键退出程序。
prog3.c根据不同的按键进行不同的操作,按Escape键退出程序。
怎样控制方块的移动?
  方块移动的实现很简单,将方块原来的位置用背景色画一个同样大小的方块,将原来的方块涂去。然后在新的位置上重新绘制方块就可以
了。这样就实现了方块的移动。完整的程序请参见prog4.c。这个用方向键控制一个黄色的小方块在屏幕上上、下、左、右移动。这个程序用到了前面几个问题讲的内容,如果你有点忘了,还要回头看看哦。:)
怎样控制时间间隔(用于游戏中控制形状的下落)?
  解决这个问题要用到时钟中断。时钟中断大约每秒钟发生18.2次。截获正常的时钟中断后,在处理完正常的时钟中断后,将一个计时变量
加1。这样,每秒钟计时变量约增加18。需要控控制时间的时候,只需要看这个计时变量就行了。
  截获时钟中断要用到函数getvect()和setvect()。
两个函数的声明如下:
?void interrupt (*getvect(int interruptno))();
?void setvect(int interruptno, void interrupt (*isr) ( ));
  保留字interrupt指示函数是一个中断处理函数。在调用中断处理函数的时候,所有的寄存器将会被保存。中断处理函数的返回时的指令是iret,而不是一般函数用到的ret指令。
getvect()根据中断号interruptno获取中断号为interruptno的中断处理函数的入口地址。
setvect()将中断号为interruptno的中断处理函数的入口地址改为isr()函数的入口地址。即中断发生时,将调用isr()函数。
  在程序开始的时候截获时钟中断,并设置新的中断处理。在程序结束的时候,一定要记着恢复时钟中断哦,不然系统的计时功能会出问题
的。具体演示程序请参见prog5.c。由于中断处理大家可能用的不多,所以我把prog5.c这个程序完整地贴在下面,并加上详细的解释。
/* prog5.c */
This is an interrupt service routine. You can NOT compile this
program with Test Stack Overflow turned on and get an executable
file which will operate correctly. */
/* 这个程序每隔1秒钟输出一个整数,10秒钟后结束程序。
按escape键提前退出程序 。*/
/* Escape key */
#define VK_ESC 0x11b
#define TIMER 0x1c /* 时钟中断的中断号 */
/* 中断处理函数在C和C++中的表示略有不同。
如果定义了_cplusplus则表示在C++环境下,否则是在C环境下。 */
#ifdef __cplusplus
#define __CPPARGS ...
#define __CPPARGS
int TimerCounter=0; /* 计时变量,每秒钟增加18。 */
/* 指向原来时钟中断处理过程入口的中断处理函数指针(句柄) */
void interrupt ( *oldhandler)(__CPPARGS);
/* 新的时钟中断处理函数 */
void interrupt newhandler(__CPPARGS)
/* increase the global counter */
TimerCounter++;
/* call the old routine */
oldhandler();
/* 设置新的时钟中断处理过程 */
void SetTimer(void interrupt (*IntProc)(__CPPARGS))
oldhandler=getvect(TIMER);
disable(); /* 设置新的时钟中断处理过程时,禁止所有中断 */
setvect(TIMER,IntProc);
enable(); /* 开启中断 */
/* 恢复原有的时钟中断处理过程 */
void KillTimer()
disable();
setvect(TIMER,oldhandler);
void main(void)
int key,time=0;
SetTimer(newhandler); /* 修改时钟中断 */
if (bioskey(1))
key=bioskey(0);
if (key==VK_ESC) /* 按escape键提前退出程序 */
printf(User cancel!n);
if (TimerCounter&18) /* 1秒钟处理一次 */
/* 恢复计时变量 */
TimerCounter=0;
printf(%dn,time);
if (time==10) /* 10秒钟后结束程序 */
printf(Program terminated normally!n);
KillTimer(); /* 恢复时钟中断 */
游戏中的各种形状及整个游戏空间怎么用数据表示?
以后我提到的形状都是指下面七种形之一及它们旋转后的变形体。
□□□□ □□□□ □□□□ □□□□
□■□□ □■■□ □□□□ □□□□
□■□□ □■□□ □■□□ □■■□
□■■□ □■□□ ■■■□ ■■□□
□□□□ □■□□ □□□□
□□□□ □■□□ □□□□
■■□□ □■□□ □■■□
□■■□ □■□□ □■■□
我定义了一个结构来表示形状。
struct shape
int xy[8];
-3□□□□
-2□□□□
-1□□□□
  所有的各种形状都可以放在4x4的格子里。假定第二列,第四行的格子坐标为(0,0)(如上图中黑块所示),则每个形状的四个方块都可以用4
个数对来表示。坐标x从左向右依次增加,y从上到下依次增加。表示的时候,组成该形状的四个方块从左到右,从上到下(不一定非要按这个顺
序)。如上面七种形状的第一个用数对来表示就是(-2,0)、(-1,0)、(0,0)、(1,0)。结构shape中的xy就是用来表示这4个数对的。为了简化程序,用一维数组xy[8]来表示。xy[0]、xy[1]表示第一个数对,xy[2]、xy[3]表示第二个数对,依次类推。
  shape中的color表示形状的颜色,不同的形状有不同的颜色。七种形状及它们旋转后的变形体一共有19种形状,用一个全局数组表示。假定旋转的方向是逆时针方向(顺时针方向道理一样)。shape中的next就表示当前形状逆时针旋转后的下一个形状的序号。例如:第一种形状及其旋
转变形的形状用结构表示如下。
□□□□ □□□□ □□□□ □□□□
□■□□ □□□□ □■■□ □□□□
□■□□ □□■□ □□■□ ■■■□
□■■□ ■■■□ □□■□ ■□□□
struct shape shapes[19]=
/*{x1,y1,x2,y2,x3,y3,x4,y4, color, next}*/
{ 0,-2, 0,-1, 0, 0, 1, 0, CYAN, 1}, /* */
{-1, 0, 0, 0, 1,-1, 1, 0, CYAN, 2}, /* # */
{ 0,-2, 1,-2, 1,-1, 1, 0, CYAN, 3}, /* # */
{-1,-1,-1, 0, 0,-1, 1,-1, CYAN, 0}, /* ## */
  游戏空间指的是整个游戏主要的界面(呵呵,这个定义我实在想不出更准确的,还请哪位大虾指点)。实际上是一个宽10格子、高20格子的
游戏板。用一个全局数组board[12][22]表示。表示的时候:board[x][y]为1时表示游戏板上(x,y)这个位置上已经有方块占着了,board[x][y]
为0表示游戏板上这位置还空着。为了便于判断形状的移动是否到边、到底,初始的时候在游戏板的两边各加一列,在游戏板的下面加一行,全
部填上1,表示不能移出界。即board[0][y],board[11][y](其中y从0到21)初始都为1,board[x][21](其中x从1到10)初始都为1。
1 2 3 4 5 6 7 8 910
1□□□□□□□□□□
2□□□□□□□□□□
3□□□□□□□□□□
4□□□□□□□□□□
5□□□□□□□□□□
6□□□□□□□□□□
7□□□□□□□□□□
8□□□□□□□□□□
9□□□□□□□□□□
10□□□□□□□□□□
11□□□□□□□□□□
12□□□□□□□□□□
13□□□□□□□□□□
14□□□□□□□□□□
15□□□□□□□□□□
16□□□□□□□□□□
17□□□□□□□□□□
18□□□□□□□□□□
19□□□□□□□□□□
20□□□□□□□□□□
  prog6.c演示了用结构表示各种形状的方法。虽然程序稍长一些,但并不是特别复杂。其中游戏板初始化部分并没有真正用到,但是后面的程
序会用到的。其中SIZE定义为16,这样将整个屏幕的坐标系由原来的640&480转换成40&30(640/16=40,480/16=30)。游戏中所有的坐标都是基于40&30的坐标系的,这样有助于简化程序。坐标的转换在程序中由DrawBlock(int x,int y)来体现。
  新的坐标系如下图所示:
-8-7-6-5-4-3-2-1 0 1 2 3 4 5 6 7 8
-4□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□
-3□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□
-2□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□
-1□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□
0□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□
1□□□□□□□□□■■■■■■■■■■□□□□□□□□□□□□□□□□□□□□□
2□□□□□□□□□■■■■■■■■■■□□□□□□□□□□□□□□□□□□□□□
3□□□□□□□□□■■■■■■■■■■□□□■■■■□□□□□□□□□□□□□□
4□□□□□□□□□■■■■■■■■■■□□□■■■■□□□□□□□□□□□□□□
5□□□□□□□□□■■■■■■■■■■□□□■■■■□□□□□□□□□□□□□□
6□□□□□□□□□■■■■■■■■■■□□□■■■■□□□□□□□□□□□□□□
7□□□□□□□□□■■■■■■■■■■□□□□□□□□□□□□□□□□□□□□□
8□□□□□□□□□■■■■■■■■■■□□□□□□□□□□□□□□□□□□□□□
9□□□□□□□□□■■■■■■■■■■□□□□□□□□□□□□□□□□□□□□□
10□□□□□□□□□■■■■■■■■■■□□□□□□□□□□□□□□□□□□□□□
11□□□□□□□□□■■■■■■■■■■□□□□□□□□□□□□□□□□□□□□□
12□□□□□□□□□■■■■■■■■■■□□□□□□□□□□□□□□□□□□□□□
13□□□□□□□□□■■■■■■■■■■□□□□□□□□□□□□□□□□□□□□□
14□□□□□□□□□■■■■■■■■■■□□□□□□□□□□□□□□□□□□□□□
15□□□□□□□□□■■■■■■■■■■□□□□□□□□□□□□□□□□□□□□□
16□□□□□□□□□■■■■■■■■■■□□□□□□□□□□□□□□□□□□□□□
17□□□□□□□□□■■■■■■■■■■□□□□□□□□□□□□□□□□□□□□□
18□□□□□□□□□■■■■■■■■■■□□□□□□□□□□□□□□□□□□□□□
19□□□□□□□□□■■■■■■■■■■□□□□□□□□□□□□□□□□□□□□□
20□□□□□□□□□■■■■■■■■■■□□□□□□□□□□□□□□□□□□□□□
21□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□
22□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□
23□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□
24□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□
25□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□
26□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□
  新坐标中最主要的是就是上面两块黑色的部分。左边那块大的就是游戏板(横坐标从1到10,纵坐标从1到20),右边那块小的就是显示&下一个&形状的部分(横坐标从14到17,纵坐标从3到6)。这个新的坐标系是整个游戏的基础,后面所有的移动、变形等的计算都是基于这个坐标系的。
游戏中怎么判断左右及向下移动的可能性?
  看懂了前面的各种形状和游戏板等的表示,接下来的东西就都好办多了。先来看一下某个形状如何显示在游戏板当中。假设要在游戏板中
显示第一个形状。第一个形状在结构中的表示如下:
struct shape shapes[19]=
/*{x1,y1,x2,y2,x3,y3,x4,y4, color, next}*/
{ 0,-2, 0,-1, 0, 0, 1, 0, CYAN, 1},
  那么这个组成形状四个方块的坐标表示为(0,-2)、(0,-1)、(0,0)和(1,0)。这实际上是相对坐标。假形状的实际坐标指的是4x4方块中的第
二列、第三行的方块的位置,设这个位置为(x,y)。那么组成这个形状的四个小方块的实际坐标(以第一个形状为例)就是(x+0,y-2)、(x+0,y-1)、(x+0,y+0)和(x+1,y+0)。由于所有的形状都可以在4x4的方块阵列中表示,这样就找到了一种统一的方法来表示所有的形状了。
-3□□□□ 相对坐标
-2□■□□
-1□■□□ 组成第一种形状的四个方块的相对坐标为(0,-2)、(0,-1)、(0,0)和(1,0)。
让我们看看形状是如何显示在游戏板中的(以第一个形状为例)。
1 2 3 4 5 6 7 8 910
1□■□□□□□□□□ 形状的坐标为(2,3)。组成形状的四个方块的坐标由形状的
2□■□□□□□□□□ 坐标加上这四个小方块各自的相对坐标得出。它们分别是:
3□■■□□□□□□□ (2+0,3-2)、(2+0,3-1)、(2+0,3-0)和(2+1,3-0)。即:
4□□□□□□□□□□ (2,1)、(2,2)、(2,3)和(3,3)。如左图所示。
5□□□□□□□□□□
6□□□□□□□□□□
7■□□□□□□□□□ 形状的坐标为(1,9)。组成形状的四个方块的坐标分别是:
8■□□□□□□□□□ (1+0,9-2)、(1+0,9-1)、(1+0,9-0)和(1+1,9-0)。即:
9■■□□□□□□□□ (1,7)、(1,8)、(1,9)和(2,9)。如左图所示。
10□□□□□□□□□□
11□□□□□□□□□□
12□□□□□□□□□□
13□□□□□□□□□□
14□□□□□□□□□□
15□□□□□□□□□□
16□□□□□□□□□□
17□□□□□□□□□□
18□□□□□□□□■□ 形状的坐标为(9,20)。组成形状的四个方块的坐标分别是:
19□□□□□□□□■□ (9+0,20-2)、(9+0,20-1)、(9+0,20-0)和(9+1,20-0)。即:
20□□□□□□□□■■ (9,18)、(9,19)、(9,20)和(10,20)。如左图所示。
  从现在起,我不再举别的示例程序了。从现在开始所有的示例代码均来自于我写的Russia.c。为了记录游戏板的状态,用了一个全局数组board[12][22]。board[x][y](其中x从0到11,y从1到21)等于1表示(x,y)这个位置已经被填充了,组成形状的四个方块的坐标都不能为(x,y),否则将发生冲突。board[x][y](其中x从1到10,y从1到20)等于表示(x,y)这个位置还没有被填充。
  游戏板初始化时,给board[0][y],board[11][y](其中y从1到21)都赋为1,给board[x][21](其中x从1到10)都赋为1。这相当于一开始就给游戏板左右和下方加了个&边&。所有的形状都不能够移入这个&边&,否则将发生冲突。
  现在我们可以开始讨论如何判断一个形状向左、向右和向下移动的可能性了。先说个概念,&当前形状&是指那个正在下落还没有落到底的那个形状。如果当前形状向左移动,不与游戏板现有状态发生冲突,则可以向左移动。具体做法是:先假设当前形状已经向左移动了,判断此时是否与游戏板现有状态发生冲突。如果不发生冲突,则可以向左移动。否则,不可以向左移动。
  判断索引号为ShapeIndex的形状在坐标(x,y)是否与游戏板当前状态发生冲突的代码如下。我把详细的说明加在这段代码中。
enum bool Confilict(int ShapeIndex,int x,int y)
/* 对组成索引号为ShapeIndex的形状的四个方块依次判断 */
for (i=0;i&=7;i++,i++) /* i分别取0,2,4,6 */
/* 如果四个方块中有任何一个方块的x坐标小于1或大于10,表示超出左边界或右边界。
此时,发生冲突。 */
if (shapes[ShapeIndex].xy[i]+x&1 ||
shapes[ShapeIndex].xy[i]+x&10) return T
/* 如果四个方块中某个方块的y坐标小于1,表示整个形状还没有完全落入游戏板中。
此时,没有必要对这个方块进行判断。*/
if (shapes[ShapeIndex].xy[i+1]+y&1)
/* 如果四个方块中有任何一个方块与游戏板当前状态发生冲突,则整个形状在(x,y)处
与游戏板当前状态冲突 */
if (board[shapes[ShapeIndex].xy[i]+x][shapes[ShapeIndex].xy[i+1]+y])
/* 四个方块中没有任何一个方块与游戏板当前状态发生冲突,则整个形状在(x,y)处
没有与游戏板当前状态冲突 */
对以上代码附加说明如下:
  shapes[ShapeIndex].xy[i](其中i等于0,2,4,6)表示组成索引号为ShapeIndex的形状的某个方块的x相对坐标。(i等于0时,表示第1个方块的x相对坐标;i等于2时,表示第2个方块的x相对坐标;i等于4时,表示第3个方块的x相对坐标;i等于6时,表示第4个方块的x相对坐标。)
  shapes[ShapeIndex].xy[i](其中i等于1,3,5,7)表示组成索引号为ShapeIndex的形状的某个方块的y相对坐标。(i等于1时,表示第1个方块的y相对坐标;i等于3时,表示第2个方块的y相对坐标;i等于5时,表示第3个方块的y相对坐标;i等于7时,表示第4个方块的y相对坐标。)
  shapes[ShapeIndex].xy[i]+x(其中i等于0,2,4,6)表示索引号为ShapeIndex的形状的坐标为(x,y)时,组成该形状的某个方块的x实际坐标。(i等于0时,表示第1个方块的x实际坐标;i等于2时,表示第2个方块的x实际坐标;i等于4时,表示第3个方块的x实际坐标;i等于6时,表示第4个方块的x实际坐标。)
 shapes[ShapeIndex].xy[i]+y(其中i等于1,3,5,7)表示索引号为ShapeIndex的形状的坐标为(x,y)时,组成该形状的某个方块的y实际坐
标。(i等于1时,表示第1个方块的y实际坐标;i等于3时,表示第2个方块的y实际坐标;i等于5时,表示第3个方块的y实际坐标;i等于7时,表示第4个方块的y实际坐标。)
现在来看看这句是什么意思吧。
board[shapes[ShapeIndex].xy[i]+x][shapes[ShapeIndex].xy[i+1]+y]
可以这样理解,把上面一句分开来看::
ActualX=shapes[ShapeIndex].xy[i]+x;/* 其中x为0,2,4,6 */
表示某个方块实际的x坐标。
ActualY=[shapes[ShapeIndex].xy[i+1]+y;
表示某个方块实际的y坐标。
board[ActualX][ActualY]就是与某个方块坐标相同处的游戏板的标志。如果此标志不为0(为1),表示这个方块与游戏板发生冲突。如果此标志为0,表示这个方块没有与游戏板发生冲突。
这段写的比较长,但是不是特别难理解。游戏中很多地方都用到了这种相对坐标向实际坐标的转换方式,看懂了这一段对理解其他部分的代码很有帮助。
仔细看过这段代码后,你可能会提一个问题:不是已经在游戏板的左右两边都加了&边&了吗,为什么还要加下面这个对x坐标的判断呢?
/* 如果四个方块中有任何一个方块的x坐标小于1或大于10,表示超出左边界或右边界。
此时,发生冲突。 */
if (shapes[ShapeIndex].xy[i]+x&1 ||
shapes[ShapeIndex].xy[i]+x&10) return T
这是因为有一种特殊情况,如下图所示:
■ 2 3 4 5 6 7 8 910
1■□□□□□□□□□ 这在当前形状刚出来的时候,是可能发生的。但是我们只给游戏板
2□□□□□□□□□□ 加了一层&边&。对于这个形状的最左边的那个方块将失去判断,
3□□□□□□□□□□ 如果不予理会,这个形状将会&挂&在游戏板的左上角!当初我也
4□□□□□□□□□□ 没有想到这一点,后来发现会有形状&挂&在最顶层,而导致游戏
5□□□□□□□□□□ 提前退出。发现了这个问题。
6□□□□□□□□□□
7□□□□□□□□□□
8□□□□□□□□□□ 加了这个判断后,游戏板的左右两个&边&对冲突的判断就是去意
9□□□□□□□□□□ 义了。因为没有这两个&边&,对于冲突的判断也不会出错。不过
10□□□□□□□□□□ 为了程序易于理解,还是保留了游戏板的左右两个&边&。
11□□□□□□□□□□
12□□□□□□□□□□
13□□□□□□□□□□
14□□□□□□□□□□
15□□□□□□□□□□
16□□□□□□□□□□
17□□□□□□□□□□
18□□□□□□□□□□
19□□□□□□□□□□
20□□□□□□□□□□
标签(Tag):
------分隔线----------------------------
------分隔线----------------------------

我要回帖

更多关于 c语言入门 的文章

 

随机推荐