为了正常的体验网站,请在浏览器设置里面开启Javascript功能!
首页 > 俄罗斯方块c语言详解

俄罗斯方块c语言详解

2011-11-23 50页 doc 149KB 39阅读

用户头像

is_837753

暂无简介

举报
俄罗斯方块c语言详解俄罗斯方块最详解   做每一件事前,都会有一个粗略的构想。编程更应该这样,现在先说一些大的、粗略的东西。 **************************************************************************************** **************************************************************************************** 目录:   ●屏幕的划分   ●图形显示   ●三种坐标。 绝对坐标...
俄罗斯方块c语言详解
俄罗斯方块最详解   做每一件事前,都会有一个粗略的构想。编程更应该这样,现在先说一些大的、粗略的东西。 **************************************************************************************** **************************************************************************************** 目录:   ●屏幕的划分   ●图形显示   ●三种坐标。 绝对坐标、相对坐标、左上角坐标   ●方块的构造   ●动画效果   ●键盘控制   ●判断方块碰撞   ●消行   ●变形   ●关于菜单的制作   ●附录(完整的源程序) **************************************************************************************** **************************************************************************************** 1、屏幕的划分   将整个屏幕划分成四部分:a、一个没盖的杯子;b、一个不断下落4*4数组的盒子;c、一个给 预览下一个方块4*4数组的盒子;d、提示信息。由于提示信息比较简单,这里只讨论前三样。 没盖的杯子:       即平时说玩这款游戏时,下落方块不可超出的那个边界,下落的方块从这个“杯口”的上方往下下落,方块只在“杯子”里移动、变形、停止。     游戏空间指的是整个游戏主要的界面(呵呵,其实就是所说的“杯子”)。实际上是一个宽10格子、高20格子的 游戏板。用一个全局数组GameSpace[22][12]示。表示的时候:GameSpace[x][y]为1时表示游戏板上(x,y)这个位置上已经有方块占着了,GameSpace[x][y]为0表示游戏板上这位置还空着。为了便于判断形状的移动是否到边、到底,初始的时候在游戏板的两边各加一列,在游戏板的下面加一行,全 部填上1,表示不能移出界。即GameSpace[x][0],GameSpace[x][11](其中x从0到20)初始都为1,GameSpace[20][y](其中y从0到11)初始都为1。   0 1 2 3 4 5 6 7 8 910 0■□□□□□□□□□□■ 1■□□□□□□□□□□■ 2■□□□□□□□□□□■ 3■□□□□□□□□□□■ 4■□□□□□□□□□□■ 5■□□□□□□□□□□■ 6■□□□□□□□□□□■ 7■□□□□□□□□□□■ 8■□□□□□□□□□□■ 9■□□□□□□□□□□■ 10■□□□□□□□□□□■ 11■□□□□□□□□□□■ 12■□□□□□□□□□□■ 13■□□□□□□□□□□■ 14■□□□□□□□□□□■ 15■□□□□□□□□□□■ 16■□□□□□□□□□□■ 17■□□□□□□□□□□■ 18■□□□□□□□□□□■ 19■□□□□□□□□□□■ 20■■■■■■■■■■■■ 下落的4*4盒子:   即7种的方块形状,如我认为比较经典的测试方块“7字形” 可看作: 0 1 2 3 0□□□□   {{0,0,0,0}, 1□■■□ 用数组表示则是   {0,1,1,0}, 2□□■□             {0,0,1,0}, 3□□■□             {0,0,1,0}} 预览4*4数组盒子:   即玩这款游戏时,给看下一个方块是什么样的窗口。   这三样东西可以这样联系起来:一个不断下落的盒子由杯子的上方下落到杯子底部,之后将预览盒子的东西放到下落的4*4盒子中,如此循环反复…… 2、图形显示   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表示存放图形驱动文件的路径。 特别值得一提的是驱动文件路径的写法,由于有转义字符,如bgi文件夹(一般这个文件夹就在Tc文件夹目录下,这个文档黙认bgi在c:\,后面举的例子亦然)在c:\,写的时候很多人写成"c:\bgi",少了个\,应写成"c:\\bgi",切记。   此外,我还强烈建议借一本叫《c作图与c汉字技术》的书,这是我见过介绍c 绘图方面最全面的书了,为了节省时间,可以直接看这几个函数,这些函数均包含在头文件#include 中 void line( int x,int y,int xx,int yy); /*从(x,y)到(xx,yy)处以setcolor()决定的颜色画直线*/ void setlinestyle(int linestyle , unsigned upattern ,int thickness );                             /*linestyle 变化范围为 0 ~ 4,也可以是大写的英文*/                         /*分别表示实线,点线,中心线,点画线,用户自定义线*/                         /*upattern处一般写0*/                     /*thickness只有1、3两个值,分别表示一个像素宽,三个像素宽*/                           void setcolor (int color );   /*决定前景颜色,color 变化范围为 0 ~ 15也可以是大写的英文*/ void setbkcolor(int color);   /*决定背景颜色,color 变化范围为 0 ~ 15也可以是大写的英文*/ void rectangle(int x,int y,int xx,int yy);/*以(x,y)为左上角,以(xx,yy)为右下角画矩形*/ void bar(int x,int y,int xx,int yy);   /*以(x,y)为左上角,以(xx,yy)为右下角画条形*/ void bar3d(int x,int y,int xx,int yy,int depth,int topflag);                           /*以(x,y)为左上角,以(xx,yy)为右下角画立体条形*/                           /*depth决定了三维直方图的长度*/                           /*当topflag非0时,画出三维顶,否则不画出三维顶*/ void setfillstyle(int pattern,int color);/*pattern变化范围为 0 ~ 12也可以是大写的英文*/                           /*color 变化范围为 0 ~ 15也可以是大写的英文*/ char* itoa(int n,char* str,int radix); /*n是要转的整型变量 */   /*str用来存的字符串*/   /*radix是按什么进制转化*/             /*能将整型数字转成字符型数字,结合outtextxy()*/                           /*可将得分、菜单上的数值等简单地显示在屏幕上*/ void settextjustify(int horiz,int vert); /*horiz变化范围为 0 ~ 2,也可以是大写的英文,分别代表左对齐,字符串中心对齐,右对齐*/ /*vert 变化范围为 0 ~ 2,也可以是大写的英文,分别代表底部对齐,中心对齐,顶部对齐*/ void settextstyle(int font,int direction,int charsize); /*font变化范围为 0 ~ 12也可以是大写的英文*/ /*direction只能是0、1,也可以是大写的英文,0、1分别代表水平输出,垂直输出*/ /*charsize变化范围为 1 ~ 10也可以是大写的英文,数值越大,字体越大*/ void outtextxy(int x,int y,char* str);   /*按settextjustify()决定的对齐方式*/                           /*以setcolor()决定的颜色,在(x,y)附近输出字符串*/ (在第10点的小程序中有以上的大部分函数的实现) 3、三种坐标。 绝对坐标、相对坐标、左上角坐标 绝对坐标:   图形屏幕其实是个y轴的正方向朝下,原点在屏幕最左上角的直角坐标系,vga模式下的一般分辨率为640*480,这样就把屏幕横向、纵向分别平分640等分、480等分,横、纵坐标变化范围分别为0 ~ 639,0 ~ 479,每个像素点占用一个1的长度。我们说的绝对坐标就是以屏幕原点为相对点的切切实实的坐标。 相对坐标:   即以屏幕上某个绝对坐标为相对点(或把它看成原点),在这个基础上再计算的坐标。   如以(0,0)为相对点,(1,1)的绝对坐标为(1,1),相对坐标为(1,1);以(2,2)相对点,(1,1)的绝对坐标为(1,1),相对坐标为(-1,-1)。 左上角坐标:   特别提出这个,是因为在俄罗斯方块中解决数组与屏幕连接的关健所在。如画个小正方形时用函数rectangle(x,y,x+单位长度,y+单位长度) (其中(x,y)为这个正方形的左上角坐标,单位长度可以是10,16,我就取了16,这样在640*480中便变成了 (640/16)*(480/16) = 40*30 ),又如前面说的GameSpace[21][12]可以这样化散为整成GameSpace[(x-相对原点的x)/单位长度][(y-相对原点的y)/单位长度]。 4、方块的构造   为了简单处理,我选择了数组构造方块,而不是坐标描点,但这样浪费空间。在要画的地方赋1,不画的地方赋0,如长条可表示为 0 1 2 3 0□■□□             {{0,1,0,0},     到了这里,我们应   ____ 1□■□□ 用数组表示则是   {0,1,0,0},     已深入的将各种方   ■■ 2□■□□             {0,1,0,0},     块看成由四个小正     | |   看成   ■ 3□■□□             {0,1,0,0}}     形组成,如         |_|         ■ 为突出立体感,可以在画了一个小正方形后,再用line()函数在这个小正方形的左上角坐标附近画横、纵两条白线,再在小正方形的右侧画一条黒线,如图是放大的小正方形   ________   | ______ | (其中,里面的横线为白,里面左侧的纵线为白,里面右侧的纵线为黒) ||     || ||     || ||     ||     |________|     在我的程序里就没搞立体感,只为体现算法而已。   现在,整个屏幕在我们眼里应达到这样理性的看法: □□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□ □□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□ □□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□ □□□□□□■□□□□□□□□□□■□□□□□□□□□□□□□ □□□□□□■□□□□□□□□□□■□□□□□□□□□□□□□ □□□□□□■□□□□□□□□□□■□□□■■■■■■□□□□ □□□□□□■□□□□□■■□□□■□□□■□□□□■□□□□ □□□□□□■□□□□■■□□□□■□□□■□■■□■□□□□ □□□□□□■□□□□□□□□□□■□□□■□■■□■□□□□ 其中每个小正方形放大看为 □□□□□□■□□□□□□□□□□■□□□■□□□□■□□□□ □□□□□□■□□□□□□□□□□■□□□■■■■■■□□□□       (x,y)______ □□□□□□■□□□□□□□□□□■□□□□□□□□□□□□□         |     | □□□□□□■□□□□□□□□□□■□□□□□□□□□□□□□         |     | □□□□□□■□□□□□□□□□□■□□□□□□□□□□□□□         |     | □□□□□□■□□□□□□□□□□■□□□□□□□□□□□□□         |_______|   □□□□□□■□□□□□□□□□□■□□□□□□□□□□□□□ □□□□□□■□□□□□□□□□□■□□□□□□□□□□□□□   (x,y)为左上角坐标 □□□□□□■□□□□□□□□□□■□□□□□□□□□□□□□ □□□□□□■□□□□□□□□□□■□□□□□□□□□□□□□ □□□□□□■□□□□□□□□□□■□□□□□□□□□□□□□ □□□□□□■□□□□□□□■□□■□□□□□□□□□□□□□ □□□□□□■□□□□□□□■□□■□□□□□□□□□□□□□ □□□□□□■□□□□□□□■■□■□□□□□□□□□□□□□ □□□□□□■■■■■■■■■■■■□□□□□□□□□□□□□ □□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□ 5、动画效果   说穿了就是先画一个图形显示出来,延时一小段时间认人看清楚后,再将显示的图形在原来的位置涂黒(或涂成背景颜色)。其中延时函数为delay (数值),包含在头文件#include 中。 括号中的数值越大,延时越长,数值最大为65535,可配合for 循环让delay()超过65535这个数,下面给出的小程序是熟悉这个函数的.功能是一个红色的正方形斜斜地移动 /*animation.c*/ #include #include     /*delay()函数的头文件*/ void main() {   int gr = DETECT , gm = 0;   int x = 50 , y = 50;   int i , j; initgraph( &gr , &gm , "c:\\bgi" ) ; for( i = 0 ; i < 8 ; ++ i , x += 50 , y += 50) { setfillstyle( SOLID_FILL , RED ); bar( x , y , x + 50 , y + 50 ); for (j = 0 ; j < 30 ; ++ j)   delay( 10000 );                   /*不同的编译器显示的快慢不同,10000这个数值可根据不同的编译器改*/ setfillstyle( SOLID_FILL , BLACK ); bar( x , y , x + 50 , y + 50 ); } } 6、键盘控制   键盘上的每个键都有自己的键盘码,为了得到想要的,下面介绍一个函数 在Tc2.0中有一个处理键盘输入的函数bioskey(); int bioskey(int cmd);   当cmd为1时,bioskey()检测是否有键按下。没有键按下时返回0;有键按下时返回键盘码(任何键盘码都不为0),但此时并不将检测到的按 键码从键盘缓冲队列中清除。   当cmd为0时,bioskey()返回键盘缓冲队列中的键盘码,并将此按键码从键盘缓冲队列中清除。如果键盘缓冲队列为空,则一直等到有键按下,才将得到的键盘码返回。   Escape键的按键码为0x11b,下面的小程序可以获取按键的键盘码 /*keyboard_code.c*/ #include #include void main() {   int key ;   while ( 1 )   {       key = bi oskey( 0 );     /* wait for a keystrike */       printf ( "0x%x\n" , key );       if ( key == 0x11b )         break;           /* Escape */   } } 常用按键的按键码如下: #define LEFT 0x4b00 #define RIGHT 0x4d00 #define DOWN 0x5000 #define UP   0x4800 #define HOME 0x4700 #define END   0x4f00 #define SPACE 0x3920 #define ESC   0x011b #define ENTER 0x1c0d   这样只要事先用#define 这个宏定义,将要用的键盘码定义好,然后用switch语句分支各个键的功能即可。这里多加说明一个函数kbhit(),其头文件为#include .当没有按键时,返回0值;有按键时,返回非0值,结合while循环,就可实现键盘控制了。下面的函数功能是按上下左右键,屏幕上的正方形跟着做出相应地移动,按逃跑键退出 /*control.c*/ #include     /*delay()函数的头文件*/ #include #include #include #define LEFT 0x4b00 #define RIGHT 0x4d00 #define DOWN 0x5000 #define UP   0x4800 #define ESC   0x011b void main() {   int gr = DETECT , gm = 0;   int x = 100 , y = 100;   int i , key; initgraph( &gr , &gm , "c:\\bgi" ) ; while ( 1 ) { while ( !kbhit() )         /*前面刚说完,不记得了?往上翻翻*/ {   setfillstyle( SOLID_FILL , RED );   bar( x , y , x + 50 , y + 50 );   for (i = 0 ; i < 30 ; ++ i)   delay( 10000 );       setfillstyle( SOLID_FILL , BLACK );   bar( x , y , x + 50 , y + 50 ); } key = bioskey( 0 );   /*前面刚说完,不记得了?往上翻翻*/ switch ( key ) {   case LEFT:   x -= 50;   break;   case RIGHT:   x += 50;   break;   case UP:   y -= 50;   break;   case DOWN:   y += 50;   break;   case ESC:   exit( 0 ); } } } 7、判断方块碰撞(即方块是否还能下落)   用一个带有返回值的函数,若碰撞则说明不能下落,返回1;反则说明没有碰撞,返回0.   具体一点就是整个4*4方块数组下落一个单位长度,与游戏空间数组(即前面说的“无盖的杯子”)有重叠的1,则在当前位置4*4数组是1的地方赋值给游戏空间对应的数组元素,表示停止下落,并画有1 的地方。对于左移、右移一个单位长度有重叠的1 ,则不允许左移、右移,继续自然下落。 8、消行   总的想法是先认为每一行都是满1的,从游戏空间的数组由上到下扫描,一旦测试到某一行中某个列元素为0,则认为这一行没满,跳出这行的扫描循环,进入下一行的扫描。   若扫描完某一行的元素都没有发现0,则以这行以上的每一行完完整整地将上一行的元素赋值给下一行,这个过程以由下到上进行,然后将整个游空间(GameSpace)画黒,再在GameSpace[21][12]中有1的地方画小正方形,如示例 A 0 0 0 1 0 0   从A行到D行扫描,             A 0 0 0 0 0 0 B 1 1 0 1 0 1   扫描后发现C行是满的,         B 0 0 0 1 0 0 C 1 1 1 1 1 1   则从B行起B行赋给C行,A行赋给B行, C 1 1 0 1 0 1 D 0 1 1 1 1 1   最后在最行A行赋全0 ,变成       D 0 1 1 1 1 1 对应的   ↓                           对应的   ↓ 图形   ↓                           图形   ↓ A□□□■□□                         A□□□□□□ B■■□■□■                         B□□□■□□ C■■■■■■                         C■■□■□■ D□■■■■■                         D□■■■■■ 读者可能会问这样不是每次都消一行而己,若要一次消两行以上怎么办(如恰好有一长条一次能消4行)?这个简单,因为即使一次消多行也是建立在一行一行消的基础上的。把消行函数再细化成两部分,一部分为为扫描哪行满行并返回这个满行的行号的值,另一部分就消这个满行行号的行,用一个while 循环,判断条件为 “扫描函数(在我的程序里是fullrow())!= 0”,形如 while(fullrow() != 0 ) {                 其中flrw是个整型变量,用来记录哪行满行,而clearrow(flrw)   flrw=fullrow();         则消指定的行。由于计算速度快,人眼看多次消行,就像一   clearrow( flrw );         次搞掂的样子 } 9、极度重要的变形函数   分两部分讲 a、怎么变         b、变后插入到已有方块里的处理(即卡位处理),情况如图:                 □■□□□□□         □■□□□□□                 □■◆□□□□         □■□□□□□ □■◆□□□□         □■□□□□□                 □■◆□□□□   变形后   ◆◆◆◆□□□                 □■◆□□□□   有可能   □■□□□□□                 □■□□□□□         □■□□□□□                 □■□□□□□         □■□□□□□ a、怎么变。   其实我能想到两种方法,一种是把每个方块各种变形的样子都用结构体定义好(这样有19种),形成一个封闭的链表,变形一次指针指向下一种形状; 另一种是旋转90度,也是我选择的方法。   后一种是一种通法,但执行效率不比前一种方法快。下面针对旋转90度详细讲解。   网上说的旋转90度只是泛泛地说而已,经过毛概课上偷偷画方格,折纸,终于想到了一种主对角线对折,再翻来达到90度旋转的方法。请拿上一张纸,标上正面,反面,|、||,跟着图示做: 正面               反面                   正面 ________           _______                 _______ |\   |           |\   |         __|__     |   /| | \ || |   沿对角线 ;   | \ —| 再沿中轴 | | |     | — / | | \   |   对折后     | \   | 翻过来   | | | 得   |   / | |   \ |           |   \ |         |__|__|     | /   | | | \ |           | 〓 \ |           |       | / 〓 | |_____\|           |_____\|                 |/_____| 图(a)             图(b)                   图(c)   对比图(a),图(c),则发现原来坚的东西变横了,也实现了顺时针转了90度。概念是这样,接下来是4*4数组怎么对折,只要仔细研究发现主对角线上的元素不必动,只要     0 1 2 3   0■□□□     0-1号与1-0号   1-2号与2-1号   2-3与3-2号     1□■□□     0-2号与2-0号   1-3号与3-1号         互相交换值,   2□□■□     0-3号与3-0号         3□□□■     再沿中轴互相交换值       0 1|2 3       0□□|□□     0-0号与0-3号   0-1号与0-2号   1□□|□□     1-0号与1-3号   1-1号与1-2号   2□□|□□     2-0号与2-3号   2-1号与2-2号   3□□|□□     3-0号与3-3号   3-1号与3-2号       | 这样就完成了第一部分。 b、变后插入到已有方块里的处理 (即卡位处理)   整体思路是先执行上面的第一部分,但不显示出来,然后判断是不是插到了已有方块中,   若可以左移或右移之后就可以的,我们就人为地移动它,后显示。   若左移或右移,又插入了右侧或左侧的方块,则逆序地执行第一部分,先执行中轴交换值,再对角线交换值,变回原来的形状,认为不具备变形的条件,后原形显示。   对于第一种情况,为分析情况,我们讨论每行的0、1、2、3号位置(注意这里的0、1、2、3号位置是4*4数组的每一行的,须要用循环一行行扫描),由于1、2号位置情况复杂且出现的机会少,故舍弃。因为(注意这里为了更好地说明,把长条■■■■变成◆◆◆◆,实际作图时还是■■■■)     0 1 2 3             0 1 2 3               0 1 2 3     □□◆□             □□□□               □□□□   □■◆□   ■         □■□□   ■         ■□□□□■   □■◆□   ■         ◆◆◆◆   ■         ■◆◆◆◆■   □■◆□   ■   变形后   □■□□   ■ 这时1号卡 ■□□□□■       ■     ■   有可能   ■ ■ 右移 两位 ■     ■     ■     ■         ■     ■         ■     ■     ■□□□□■         ■□□□□■         ■□□□□■ 又如     0 1 2 3           0 1 2 3               0 1 2 3     □□◆□           □□□□               □□□□   □■◆□ ■         □■□□ ■         ■ □□■□   □■◆□ ■         ◆◆◆◆ ■         ■ ◆◆◆◆   □■◆□ ■   变形后   □■□□ ■ 这时1号卡 ■ □□■□   这时2号又卡了     ■     ■   有可能   ■     ■ 右移两位   ■     ■     ■     ■         ■     ■         ■     ■     ■□□□■ ■□□□■         ■□□□■                                     0 1 2 3                                     □□□□                                   ■□□□■                                   ■◆◆◆◆                           若右移一位 ■□□□■   这时3号又卡了                                   ■     ■ ■     ■                                   ■□□□■ 由于1、2 号位的情况只会在长条(因为其它的方块长度最长为3)时出现,虽然存在移两位可行的情况,但实在是少,如要都完善的编写上,显得麻烦,故舍弃。   现在重点讨论0、3号位置。   0号位置由于变形后,有可能因为左侧位置不够而不能变形,只须稍微右移一个单位长度就可以了,如     0 1 2 3         0 1 2 3         0 1 2 3   □◆□□         □□□□       ■□□□□   ■◆□□         ■□□□       ■□□□□   ■◆□□   变形后   ◆◆◆◆ 移动后   ■◆◆◆◆   ■◆□□         ■□□□       ■□□□□   ■             ■           ■   ■             ■           ■ 而人为地移动后,对应的1,2,3号位置又有可能插入了已有的方块中,如   0 1 2 3         0 1 2 3         0 1 2 3   □◆□□         □□□□       □□□□   ■◆■□ ;       ■□■□       ■□■□□   ■◆■□   变形后   ◆◆◆◆ 右移一 ■◆◆◆◆   1号又卡了   ■◆■□         ■□■□ 位后   ■□■□□   ■ ■           ■ ■       ■ ■   ■ ■           ■ ■       ■ ■   0 1 2 3         0 1 2 3         0 1 2 3   □◆□■         □□□□         □□□□   ■◆□■         ■□□■       ■□□■□   ■◆□■   变形后   ◆◆◆◆ 右移一   ■◆◆◆◆   2号又卡了   ■◆□■         ■□□■ 位后     ■□□■□   ■   ■         ■   ■       ■   ■   ■   ■         ■   ■       ■   ■   0 1 2 3           0 1 2 3           0 1 2 3   □◆□□■         □□□□ □□□□   ■◆□□■         ■□□□■       ■□□□■   ■◆□□■   变形后   ◆◆◆◆■ 右移一   ■◆◆◆◆   3号又卡了   ■◆□□■         ■□□□■ 位后     ■□□□■   ■     ■         ■     ■       ■     ■   ■     ■         ■     ■       ■     ■ 对于这些情况我们无奈,只能逆序变回原形。   3号位置的情况亦然,只不过是把左移变成右移,移动后讨论的是0,1,2号位置。 10、关于菜单的制作   我认为不会很难。概念上是把要显示的动态数值改变后,涂黒原来的地方,将新的数值在原来 的地方再显示即可。特别值得一提的是,这之中可能用到的itoa()函数,头文件#include 。也许有人会问,为什么要用itoa()函数,这是因为在图形模式下,用printf()输出只能是8*8点阵,白色字体。若想搞点比较艺术的字体,输出的字体大点的,就看下面的函数是怎么实现的。 功能是按一下回车,数值增大100,按ESC退出。 /*itoa.c*/ #include #include #include #include #define ESC   0x011b #define ENTER 0x1c0D main() {   int gr = DETECT , gm = 0;   int key , value = 100 ;   /*value是要转的整型变量*/   char str[10];           /*用来存的字符串*/ initgraph( &gr , &gm , "c:\\bgi" ) ; setbkcolor( BLACK ); /*设置背景颜色*/                       /*对应的数值形式是setbkcolor( 0 )*/         setfillstyle( SOLID_FILL,BLACK );/*设置bar函数填充样式,这里为实心、黑色*/                       /*对应的数值形式是setfillstyle( 1 , 0 )*/         settextjustify( LEFT_TEXT , CENTER_TEXT );/*设置文本输出的样式,*/                                 /*这里是左对齐,中心对齐*/                               /*对应的数值形式是settextjustify( 0 , 1)*/     setcolor( CYAN );             /*设置输出文本的颜色,这里是青色*/                             /*对应的数值形式是setcolor( 3 )         settextstyle ( SANS_SERIF_FONT , HORIZ_DIR , 3 );/*设置文本的字型,*/                           /*这里是无衬线笔画字体,水平输出,3是24*24点阵*/                       /*对应的数值形式是settextstyle ( 3 , 0 , 3 )         itoa( value , str , 10 ); /*前一个是要转成字符的整型变量名,*/                           /*后一个是转成字符后用来存的字符串首址*/                       /*itoa中的10是按10进制转化*/     while (1)     { while ( !kbhit() ) {   outtextxy(320,240,str); } key=bioskey( 0 ); switch ( key ) {   case ENTER:   bar(300,200,400,300);   value += 100 ;   itoa( value , str , 10 );   break;   case ESC:   exit( 0 ); } } }   好了,看到这相信你对这款游戏的制作已有所把握。   你可以先搞个没有键盘控制垂直下落的单一的测试方块,然后把向左、向右、向下加上,再把无盖的杯子画出来,让其有个范围,顺道搞掂碰撞,之后把消行功能加上,又将单一的测试方块变成7种随机的方块出现且最难搞的变形函数也完成了,补上记分功能,把菜单给做了,最后加上了自己的新功能。记住千里之行始于足下,聚沙成塔。我们有的是朩头、钉子、石头等各种零件,却不能忘记心中那宏伟的城堡!现在就一点点来吧。 ************************************************************************************************************************************************************** 实现的源程序(菜单上好像还有小bugs,不影响大体) /*Russian_Diamond.c*/ #include #include     /*主要应用于作图*/ #include       /*主要应用于键盘*/ #include #include       /*主要应用于产生随即数*/ #include         /*主要应用于延时*/ /************************** 第一个界面的主要函数 ***************************/ void hello();   /*第一个界面的入口函数*/ void interface();   /*输出不许改变的文字信息 */ void activemenu();   /*选择菜单的动态显示函数*/ void menu_up();   /*选择菜单的向上函数*/ void menu_down();   /*选择菜单的向下函数*/ void menu_left();   /*选择菜单的减少速度值,难度值的函数*/ void menu_right();   /*选择菜单的增大速度值,难度值的函数*/ void menu_enter();   /*确定选项的函数*/ void menu_escape();   /*选择退出的函数*/ /************************ 第二个界面的主要函数 ************************/ void game();   /*选择开始游戏的入口函数*/ void gamestart();   /*第一次产生随机数*/ void initgamespace(); /*初始化游戏空间*/ void drawwal();   /*画边框与预览框*/ void drawsqa();   /*画下落方块*/ void showtext();   /*显示游戏过程中提示信息*/ void showvalue();   /*显示游戏过程中数值信息*/ void up();   /*游戏中变形函数*/ void down();   /*向下函数*/ void left();   /*向左函数*/ void right();   /*向右函数*/ void pause();   /*暂停函数*/ void escape();   /*显示退出菜单的函数*/ void speed_up();   /*加速函数*/ void speed_down();   /*减速函数*/ void wipe();   /*使用橡皮函数*/ void if_end();   /*判断游戏结束的函数*/ void preview(int );   /*预览框函数*/ void clearrow(int ); /*消行函数*/ void showscore(int ); /*显示分数的函数*/ void id(int );   /*为了能按照预览框的形状开始掉落而写的函数*/ int crash();   /*判断碰撞的函数*/ int fullrow();   /*侦测满行的函数*/ int next(); /*产生随机数的函数*/ /************************ 退出界面 ***********************/ void goodbye();   /*退出函数的入口*/ /************************ 第一个界面的主要参数值 ************************/ int start_color=14;   /*说明当前选项到了确定选择的各个参数准备开始游戏的地方*/ int speed_color=3;   /*说明当前选项到了选择速度的speed的地方*/ int difficulty_color=3;   /*说明当前选项到了选择难度的difficulty的地方*/ int end_color=3;   /*说明当前选项到了选择退出的end的地方*/ int menu_color=0;   /*控制当前选项到了哪的重要判断标记*/ /************************ 游戏主体的各个全局变量 ************************/ #define LEFT 0x4b00 #define RIGHT 0x4d00 #define DOWN 0x5000 #define UP   0x4800 #define ESC   0x011b #define ENTER 0x1c0D #define SPACE 0x3920 #define W   0x1177 #define S   0x1f73 #define D   0x2064 #define UNIT 16 /*单位长度*/ #define spaLeft 188   /*游戏框的左上角*/ #define spaTop 34 /*由于作品上交时间急又由于出现了bug,已改动故现在已不是真正的左上角的数值了,只能是概念上有个游戏框的左上角*/ #define staLeft 252 /*方块出现的初始地方*/ #define staTop 34 /*如上面说的那样,出现bug,而中间画图判断等用到原始的34,其实左上角y的数值为staTop-UNIT*/ int a[ 11 ][ 4 ][ 4 ]={         /*************************           7 字形         *************************/         { {0,0,0,0},       {0,1,0,0},       {0,1,0,0},           {0,1,1,0} },                 /*************************反 7 字形         *************************/         { {0,0,0,0},           {0,1,1,0},           {0,1,0,0},           {0,1,0,0} },                 /*************************           t 字形         *************************/         { {0,0,0,0},           {0,1,0,0},           {1,1,1,0},           {0,0,0,0} },         /*************************           小z 字形         *************************/         { {0,0,0,0},         {1,1,0,0},         {0,1,1,0},         {0,0,0,0} },         /*************************           小反 z 字形 *************************/         { {0,0,0,0},         {0,1,1,0},         {1,1,0,0},         {0,0,0,0} },               /*************************           长条         ************************/         { {0,1,0,0},         {0,1,0,0},         {0,1,0,0},         {0,1,0,0} },         /*************************           田 字形         *************************/         { {0,0,0,0},         {0,1,1,0},         {0,1,1,0},         {0,0,0,0} },         /*******************************         选了难度为困难时才有的图形         ********************************/         /********************************           杯子形         *********************************/         { {1,1,1,0},         {1,0,1,0},         {1,0,1,0},           {0,0,0,0} },         /*************************           大 Z 字形         *************************/         { {1,1,0,0},         {0,1,0,0},         {0,1,1,0},           {0,0,0,0} },         /*************************           大 Z 字形         *************************/         { {0,1,1,0},         {0,1,0,0},         {1,1,0,0},           {0,0,0,0} },     /*************************           一点         *************************/         { {0,0,0,0} {0,1,0,0},         {0,0,0,0},         {0,0,0,0} },       } ; int speed=0;   /*速度变量*/ int d
/
本文档为【俄罗斯方块c语言详解】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索