CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
IBM Rational 系统开发最佳实践工具包 WebSphere MQ 最佳实践 TOP 15
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  C/C++ >  C语言

c\c++怎么 设计 <俄罗斯方块>

楼主Dugowe(我不是火星人,我家狗狗才是..)2006-03-04 17:14:17 在 C/C++ / C语言 提问

我是一名大一的学生,从痴迷程序设计.无奈,无人讨论进步很慢.  
   
  今天老师说这学期要用c写俄罗斯方块,  
   
  我对c和c++都有所了解,现正c++,看到私有继承那一章了,  
  但对老师说的用c写俄罗斯方块一点思路也没有,据说可能用到图形编程,,,  
   
  望高手指点,小弟先谢过了.. 问题点数:40、回复次数:16Top

1 楼ox_thedarkness()回复于 2006-03-04 17:23:23 得分 0

恩阿,用纯C++也可以阿...   全部用字符Top

2 楼ox_thedarkness()回复于 2006-03-04 17:24:48 得分 0

技术关键在于:  
  1   二维数组   2   键位判断   3   计时Top

3 楼primercpp(初学者)回复于 2006-03-04 17:48:50 得分 0

生成方块可用5*5数组,这样旋转也方便些Top

4 楼Dugowe(我不是火星人,我家狗狗才是..)回复于 2006-03-04 21:17:15 得分 0

可是我好像见过老师用的是四维数组,而且我根本一点思路也没有,  
  555Top

5 楼mfs(玩命蚂蚁)回复于 2006-03-04 21:39:08 得分 40

很多编程爱好者都编写过俄罗斯方块的游戏程序。很久以前,我用Tc2.0也做过一个;最近有好些朋友看见我以前的俄罗斯方块的程序后,  
  问我是怎么做的。我一直想把这个程序的整个过程写一份详细的东西,与各位编程爱好者分享,一直没空。正好现在放假了,而且离回家还有几天。于是我就把这个程序重新写了一遍,尽量使程序的结构比较清晰好懂一些。同时写了下面的这份东西。  
   
    俄罗斯方块游戏的程序中用到了一些方法。为了比较容易理解这些方法,我在讲述的同时写了些专门针对这些方法的示例程序。这些示例程序力求短小,目的是用最小的代码能够清楚的示例所用的方法。这些示例程序都经过tc2.0测试。最后还附了完整的俄罗斯方块游戏的源代码,和最终的可执行程序。如果你看了这份东东,有什么意见和想法,请发电子邮件告诉我。我将会继续更新这分东东,最新的版本可以在我的个人主页上下载。  
   
    下面的问题是有关俄罗斯方块程序的,其中有些是朋友问我的,有些是我认为可能会被问到的。我尽量按问题从易到难排列这些问题。   关于俄罗斯方块程序的一些问题:  
  ******************************************************  
  Tc2.0中怎么样设置图形显示?  
  Tc2.0中常用图形函数的用法?  
  怎样获取鍵盘输入?  
  怎样控制方块的移动?  
  怎样控制时间间隔(用于游戏中控制形状的下落)?  
  游戏中的各种形状及整个游戏空间怎么用数据表示?  
  游戏中怎么判断左右及向下移动的可能性?  
  游戏中怎么判断某一形状旋转的可能性?  
  按向下方向键时加速某一形状下落速度的处理?  
  怎么判断某一形状已经到底?  
  怎么判断某一已经被填满?  
  怎么消去已经被填满的一行?  
  怎么消去某一形状落到底后能够消去的所有的行?(如长条最多可以消去四行)  
  怎样修改游戏板的状态?  
  怎样统计分数?  
  怎样处理升级后的加速问题?  
  怎样判断游戏结束?  
  关于计分板设计的问题。  
  关于“下一个”形状取法的问题。  
  剩下的问题。  
   
  ******************************************************  
  新的问题:  
      我想有一个最高记录的显示,应该怎么做呀?  
      我想实现一个进度存储功能,应该怎么做呀?  
   
   
   
  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,   errorcode;  
   
  /*   initialize   graphics   mode   */  
  initgraph(&gdriver,   &gmode,   "e:\\tc2");  
   
  /*   read   result   of   initialization   */  
  errorcode   =   graphresult();  
   
  if   (errorcode   !=   grOk)   /*   an   error   occurred   */  
  {  
  printf("Graphics   error:   %s\n",   grapherrormsg(errorcode));  
  printf("Press   any   key   to   halt:");  
  getch();  
  exit(1);   /*   return   with   error   code   */  
  }  
   
  /*   return   to   text   mode   */  
  closegraph();  
   
   
  Tc2.0中常用图形函数的用法?  
   
  在这里讲几个游戏中用到的绘图用的图形函数:  
  setcolor();  
  line();  
  rectangle();  
  settextjustify();  
  outtextxy();  
  setfillstyle();  
  bar();  
   
   
   
  Top

6 楼mfs(玩命蚂蚁)回复于 2006-03-04 21:39:25 得分 0

void   far   setcolor(int   color);  
       设置画线、画框和在图形模式下显示文字的当前颜色。这个函数将影响line()、rectangle()和outtextxy()函数绘图的颜色。  
  color可以取常的颜色常量:  
  BLACK   ?   0  
  BLUE   ?   1  
  GREEN   ?   2  
  CYAN   ?   3  
  RED   ?   4  
  MAGENTA   ?   5  
  BROWN   ?   6  
  LIGHTGRAY   ?   7  
  DARKGRAY   ?   8  
  LIGHTBLUE   ?   9  
  LIGHTGREEN   ?10  
  LIGHTCYAN   ?11  
  LIGHTRED   ?12  
  LIGHTMAGENTA   ?13  
  YELLOW   ?14  
  WHITE   ?15  
   
  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  
   
   
  怎样获取鍵盘输入?  
   
    在Tc2.0中有一个处理键盘输入的函数bioskey();  
  int   bioskey(int   cmd);  
       当cmd为1时,bioskey()检测是否有键按下。没有键按下时返回0;有键按下时返回按键码(任何按键码都不为0),但此时并不将检测到的按  
  键码从键盘缓冲队列中清除。  
       当cmd为0时,bioskey()返回键盘缓冲队列中的按键码,并将此按键码从键盘缓冲队列中清除。如果键盘缓冲队列为空,则一直等到有键按  
  下,才将得到的按键码返回。  
   
    Escape键的按键码为0x11b,下面的小程序可以获取按键的按键码。  
   
  for   (;;)  
  {  
  key=bioskey(0);   /*   wait   for   a   keystroke   */  
  printf("0x%x\n",key);  
  if   (key==0x11b)   break;   /*   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这个程序完整地贴在下面,并加上详细的解释。  
   
  Top

7 楼mfs(玩命蚂蚁)回复于 2006-03-04 21:39:54 得分 0

/*   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键提前退出程序   。*/  
   
  #include   <stdio.h>  
  #include   <dos.h>  
  #include   <conio.h>  
   
  /*   Escape   key   */  
  #define   VK_ESC   0x11b    
   
  #define   TIMER   0x1c   /*   时钟中断的中断号   */  
   
  /*   中断处理函数在C和C++中的表示略有不同。  
  如果定义了_cplusplus则表示在C++环境下,否则是在C环境下。   */  
   
  #ifdef   __cplusplus  
  #define   __CPPARGS   ...  
  #else  
  #define   __CPPARGS  
  #endif  
   
  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);  
  enable();  
  }  
   
   
  void   main(void)  
  {  
  int   key,time=0;  
   
  SetTimer(newhandler);   /*   修改时钟中断   */  
   
  for   (;;)  
  {  
  if   (bioskey(1))  
  {  
  key=bioskey(0);  
  if   (key==VK_ESC)   /*   按escape键提前退出程序   */  
  {  
  printf("User   cancel!\n");  
  break;  
  }  
  }  
  if   (TimerCounter>18)   /*   1秒钟处理一次   */  
  {  
  /*   恢复计时变量   */  
  TimerCounter=0;  
  time++;  
  printf("%d\n",time);  
  if   (time==10)   /*   10秒钟后结束程序   */  
  {  
  printf("Program   terminated   normally!\n");  
  break;  
  }  
  }  
  }  
  KillTimer();   /*   恢复时钟中断   */  
   
  }  
   
   
  游戏中的各种形状及整个游戏空间怎么用数据表示?  
   
  以后我提到的形状都是指下面七种形之一及它们旋转后的变形体。  
   
  □□□□   □□□□   □□□□   □□□□    
  □■□□   □■■□   □□□□   □□□□    
  □■□□   □■□□   □■□□   □■■□    
  □■■□   □■□□   ■■■□   ■■□□    
   
  □□□□   □■□□   □□□□    
  □□□□   □■□□   □□□□    
  ■■□□   □■□□   □■■□    
  □■■□   □■□□   □■■□    
   
  我定义了一个结构来表示形状。  
  struct   shape  
  {  
  int   xy[8];  
  int   color;  
  int   next;  
  }  
  -1   0   1   2  
  -3□□□□  
  -2□□□□  
  -1□□□□  
  0□■□□  
   
    所有的各种形状都可以放在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就表示当前形状逆时针旋转后的下一个形状的序号。例如:第一种形状及其旋  
  转变形的形状用结构表示如下。  
   
  □□□□   □□□□   □□□□   □□□□    
  □■□□   □□□□   □■■□   □□□□    
  □■□□   □□■□   □□■□   ■■■□    
  □■■□   ■■■□   □□■□   ■□□□    
   
  Top

8 楼Dugowe(我不是火星人,我家狗狗才是..)回复于 2006-03-04 21:56:06 得分 0

谢谢   蚂蚁大哥!!!!!!!!!Top

9 楼jianchidaodihahaha(水疑)回复于 2006-03-04 22:58:50 得分 0

我是一个c语言的初学者,请问要到什么时候才能编出一些小游戏程序阿?Top

10 楼hua2325(Master)回复于 2006-03-05 04:41:31 得分 0

其实很简单的~~~~~~~~~~~~~~Top

11 楼Tangxiang(来,让我们一起跳舞吧。)回复于 2006-03-05 10:22:16 得分 0

恩   一起学习一起进步Top

12 楼Vo5(娜娜)回复于 2006-03-05 11:26:15 得分 0

哇  
  收藏~Top

13 楼wjd7623054(千古风流)回复于 2006-03-05 12:59:40 得分 0

都写的这么详细,其实我认为算法其实是很多的,主要是找一个在空间和时间表现比较优秀的算法,存储我认为数组比较好,旋转,消去等方法很多,显示,键盘输入都是次要的Top

14 楼vision2004()回复于 2006-03-05 13:24:55 得分 0

我在VC下做过一个,可惜现在连代码都丢了,好后悔。Top

15 楼caitian6()回复于 2006-03-05 18:21:19 得分 0

markTop

16 楼wcg_jishuo()回复于 2006-03-05 22:49:32 得分 0

支持   蚂蚁这样的热心的网友,不过觉得用vc写好些吧Top

相关问题

  • 请问如何用c++设计oo思想的俄罗斯方块
  • 俄罗斯方块中的检测函数怎么写(c语言200分)
  • 请问如何用OO思想设计俄罗斯方块
  • c语言实现俄罗斯方块,急。
  • 怎样用C编一个俄罗斯方块
  • 如何用C#写俄罗斯方块的程序
  • 求俄罗斯方块游戏的C#原代码!
  • 谁能给我一个俄罗斯方块的C/C++程序!(给分了。。。。。)
  • 高分求俄罗斯方块c++源程序,不是c++bulider and vc啊?
  • 请问如何用BCB设计OO思想的俄罗斯方块

关键词

  • c++
  • 函数
  • 图形
  • 中断
  • 字符
  • 模式
  • 驱动
  • 俄罗斯方块
  • 游戏
  • 键盘

得分解答快速导航

  • 帖主:Dugowe
  • mfs

相关链接

  • C/C++ Blog
  • C/C++类图书
  • C/C++类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo