|
![]() | 作者: 286 [unique]
![]() |
登录 |
首先,这个游戏有如下几个问题要解决: 1 速度控制,这个速度控制应不受用户按键的影响.每隔一定时间下落的方块(以下简称下落物)就无条件下落,并且随着时间的延长速度越来越快.因此可以通过一个 系统变量来控制.其值越来越小.下面程序用Delays控制.闲时可用delay(Delays)进行延时. 2 下落物的表示.可以有各种形式下落物,并且每个下落物又有几种状态.为了表示他们,可以用数组表示,鉴于其形状特点,建一个4X4的数组,数组值为0则表示该位不 显示,为1则显示。这里有个不好处理的地方是每种下落物的状态个数不同。有的只有一个状态,有的却有四个状态。为了处理方便,全部定义为四个状态,只是部 分有重复状态而已。 定义如下: int a[7][4][4][4]={{{1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0}, {1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0}, {1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0}, {1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0}}, {{1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0}, {1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0}, {1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0}, {1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0}}, {{1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0}, {0,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0}, {0,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0}, {1,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0}}, {{1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0}, {0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0}, {1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0}, {0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0}}, {{0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0}, {1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0}, {0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0}, {1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0}}, {{1,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0}, {1,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0}, {1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0}, {0,1,0,0,0,1,0,0,1,1,0,0,0,0,0,0}}, {{0,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0}, {1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0}, {1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0}, {1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0}}}; 图形如下: /* 1 2 3 4 5 6 7 8888 88 888 8 8 88 88 88 8 88 88 8 8 8 8 8 8 8 8 8 8 88 88 88 8 888 8 8 88 88 888 8 8 8 8 888 8 8 88 88 8 88 888 8 8 8 888 */ 3 整个下落区(也就是所有方块可在的地方),可以定义为15X27数组,表示方法同下落物,为0表示该位没有方块,为1有方块,显示出来。 4 下落处理。在下落过程中,有两种可能,一种是半空被挂住,一种是落到底部。无论哪种都不能再继续。 我的处理办法是,把下落物的数组和下落区的数组对应相加。由于二者值都或为0或为1,因此如果出现2,则表示两个有重合的,这样当然就不能下降了。恢复办法也很简单,就是相减一下就变成原来的了。当然这里还有一个必须考虑的地方就是落到底了,也得停,不然就落到无底洞了。 int Touch(int x,int y,int dx,int dy) { NoPass=CAN; for (i=0;i<4;i++) for (j=0;j<4;j++) Position[x+dx+i][y+dy+j]+=b[i][j]; for (i=0;i<MAX;i++) for (j=0;j<MAX;j++) if (Position[i][j]>1) NoPass=CANNOT; for (i=0;i<4;i++) for (j=0;j<4;j++) Position[x+dx+i][y+dy+j]-=b[i][j]; if (NoPass==CANNOT && dx==0 && dy==1) { for (i=0;i<4;i++) for (j=0;j<4;j++) Position[x+i][y+j]+=b[i][j]; NoPass=BOTTOM; } return NoPass; } 5 每一排充满后要消掉。这个处理相对简单,为了刺激玩者,还可以对同时消多排的加大分量。比如同时消两排的分数要比单独两次消一排的分数要多。 void DetectFill() { int Number,Fall,FallTime=0; for (i=Shu-1;i>=0;i--) { Number=0; for (j=0;j<Heng;j++) if (Position[j][i]==1) Number++; if (Number==Heng) { FallTime++; if (Sounds==CAN) { sound(500); delay(500); nosound(); } for (Fall=i;Fall>0;Fall--) for (j=0;j<Heng;j++) { Position[j][Fall]=Position[j][Fall-1]; if (Position[j][Fall]==0) DrawBox(j,Fall,0); else DrawBox(j,Fall,1); } i++; } } switch(FallTime) { case 0:break; case 1:Scores+=1;break; case 2:Scores+=3;break; case 3:Scores+=6;break; case 4:Scores+=10;break; } if (FallTime!=0) { GetScores(); if (Scores%100==0) Delays-=100; } } 6 还有一个,对于TC编程人员来说最困难的可能就是键盘控制了。因为对于DOS系统,可视字符可直接获得ASCII码,但控制字符由于只能获得SCAN扫描码,因此相对比较困难。这里有个函数,用户可方便的一次转换。 int GetKey(void) { int Ch,Low,Hig; Ch=bioskey(0); Low=Ch&0x00ff; Hig=(Ch&0xff00)>>8; return(Low==0?Hig+256:Low); } 这样,不管用户按哪一个键,都可以直接获得。对于其中ASCII部分,得的结果小于128,对于控制字符(比如上下左右键)得到的大于128。 7 完整源代码如下。在DOS环境,TC2。0下调试通过。 #include <stdlib.h> #include <stdio.h> #include <graphics.h> #define ESC 27 #define UP 328 #define DOWN 336 #define LEFT 331 #define RIGHT 333 #define BLANK 32 #define BOTTOM 2 #define CANNOT 1 #define CAN 0 #define MAX 30 #define F1 315 #define ADD 43 #define EQUAL 61 #define DEC 45 #define SOUNDs 115 #define SOUNDS 83 #define PAUSEP 80 #define PAUSEp 112 void Init(); void Down(); void GoOn(); void Display(int color); void Give(); int Touch(int x,int y,int dx,int dy); int GeyKey(); void Select(); void DetectFill(); void GetScores(); void Fail(); void Help(); void Quit(); void DrawBox(int x,int y,int Color); void OutTextXY(int x,int y,char *String); void DispScore(int x,int y,char Ch); void DrawNext(int Color); int Heng=15,Shu=27; int Position[MAX][MAX]; int ActH,ActS; int Act,Staus; int i,j,k; int Wid=10; int NoPass=CAN; int Delays=1000; int BeginH=250,BeginS=7; int Seconds=0; int Scores=0; int Sounds=CAN; int PreAct,NextAct; int a[7][4][4][4]={{{1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0}, {1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0}, {1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0}, {1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0}}, {{1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0}, {1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0}, {1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0}, {1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0}}, {{1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0}, {0,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0}, {0,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0}, {1,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0}}, {{1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0}, {0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0}, {1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0}, {0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0}}, {{0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0}, {1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0}, {0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0}, {1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0}}, {{1,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0}, {1,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0}, {1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0}, {0,1,0,0,0,1,0,0,1,1,0,0,0,0,0,0}}, {{0,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0}, {1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0}, {1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0}, {1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0}}}; int b[4][4]; main(int argc,char *argv[]) { if (argc!=1) { if (argv[1]!="") Heng=atoi(argv[1]); if (argv[2]!="") Shu=atoi(argv[2]); } Init(); PreAct=random(7); for(;;) { NextAct=random(7); DrawNext(1); Act=PreAct; if (Heng%2==0) ActH=Heng/2; else ActH=(Heng-1)/2; ActS=0; Staus=0; NoPass=CAN; Give(); Display(1); GoOn(); PreAct=NextAct; DrawNext(0); } } void Init() { int GraphDriver=DETECT,GraphMode; initgraph(&GraphDriver,&GraphMode,""); if (kbhit()) Sounds=CANNOT; setcolor(1); OutTextXY(10,10,"Tetris"); OutTextXY(30,30,"Version 2.0"); OutTextXY(10,120,"Help:"); OutTextXY(20,140,"+ :Faster"); OutTextXY(20,160,"- :Slower"); OutTextXY(20,180,"Esc :Quit"); OutTextXY(20,200,"F1 :Help"); OutTextXY(10,310,"Copyright(c) 1998.2.22"); OutTextXY(10,320,"By Mr. Unique"); outtextxy(10,250,"Score: 00000"); rectangle(BeginH-3,BeginS-3,BeginH+Heng*(Wid+2)+2,BeginS+Shu*(Wid+2)+2); rectangle(BeginH-5,BeginS-5,BeginH+Heng*(Wid+2)+4,BeginS+Shu*(Wid+2)+4); rectangle(BeginH+(Heng+4)*(Wid+2)-2,BeginS+10,BeginH+(Heng+8)*(Wid+2)+2,BeginS+12+4*(Wid+2)); for (i=0;i<MAX;i++) for (j=0;j<MAX;j++) Position[i][j]=1; for (i=0;i<Heng;i++) for (j=0;j<Shu;j++) Position[i][j]=0; for (i=0;i<Heng;i++) for (j=0;j<Shu;j++) DrawBox(i,j,0); randomize(); } void GoOn() { for(;;) { Seconds++; if (Seconds>=Delays) { Down(); Seconds=0; if (NoPass==BOTTOM) { DetectFill(); if (ActS==0) Fail(); return; } } if (kbhit()) Select(); } } void Down() { Display(0); if (Touch(ActH,ActS,0,1)==CAN) ActS++; Display(1); } int Touch(int x,int y,int dx,int dy) { NoPass=CAN; for (i=0;i<4;i++) for (j=0;j<4;j++) Position[x+dx+i][y+dy+j]+=b[i][j]; for (i=0;i<MAX;i++) for (j=0;j<MAX;j++) if (Position[i][j]>1) NoPass=CANNOT; for (i=0;i<4;i++) for (j=0;j<4;j++) Position[x+dx+i][y+dy+j]-=b[i][j]; if (NoPass==CANNOT && dx==0 && dy==1) { for (i=0;i<4;i++) for (j=0;j<4;j++) Position[x+i][y+j]+=b[i][j]; NoPass=BOTTOM; } return NoPass; } int GetKey(void) { int Ch,Low,Hig; Ch=bioskey(0); Low=Ch&0x00ff; Hig=(Ch&0xff00)>>8; return(Low==0?Hig+256:Low); } void Select() { int OldStaus; switch(GetKey()) { case ESC :Quit();break; case DOWN :Seconds+=1450;break; case LEFT :Display(0); if (ActH>0 && Touch(ActH,ActS,-1,0)==CAN) ActH--; Display(1);break; case RIGHT :Display(0); if (ActH<Heng && Touch(ActH,ActS,1,0)==CAN) ActH++; Display(1);break; case F1 :Help();break; case EQUAL : case ADD :if (Delays>300) Delays-=100;break; case DEC :if (Delays<3000) Delays+=100;break; case PAUSEP : case PAUSEp :getch();break; case SOUNDS : case SOUNDs :if (Sounds==CAN) Sounds=CANNOT; else Sounds=CAN;break; case UP : case BLANK :Display(0); OldStaus=Staus; switch(Act) { case 0: case 3: case 4:if (Staus==1) Staus=0;else Staus=1;break; case 1:break; case 2: case 5: case 6:if (Staus==3) Staus=0;else Staus++;break; } Give(); if (Touch(ActH,ActS,0,0)==CANNOT) { Staus=OldStaus; Give(); } Display(1); break; } } void Quit() { int ch,TopScore; FILE *fp; if ((fp=fopen("Russian.scr","r+"))!=NULL) { fscanf(fp,"%d",&TopScore); if (Scores>TopScore) { setcolor(1); outtextxy(470,80,"Hello !"); outtextxy(470,100,"In all the players,"); outtextxy(470,120,"You are the First !"); outtextxy(470,140,"And your score will"); outtextxy(470,160,"be the NEW RECORD !"); fseek(fp,0L,0); fprintf(fp,"%d",Scores); } fclose(fp); } setcolor(1); OutTextXY(470,220,"Are You Sure (Yes/no)?"); ch=getch(); if (ch=='y'||ch=='Y') { closegraph(); delay(20); exit(0); } setcolor(0); outtextxy(470,220,"Are You Sure (Yes/no)?"); } void OutTextXY(int x,int y,char *String) { int i=0; char a[2]; moveto(x,y); a[1]='\0'; while (*(String+i)!='\0') { a[0]=*(String+i); outtext(a); if (Sounds==CAN && a[0]!=' ') { sound(3000); delay(50); nosound(); } i++; } } void Help() { unsigned Save; void *Buf; Save=imagesize(160,120,500,360); Buf=malloc(Save); getimage(160,120,500,360,Buf); setfillstyle(1,1); bar(160,120,500,280); setcolor(0); OutTextXY(170,130," About & Help"); OutTextXY(170,150," # # # ########## # # # "); OutTextXY(170,160," # ## # # # # # # ###### ### "); OutTextXY(170,170," ########## ########## ## # # "); OutTextXY(170,180," # # # # # # # ## #### "); OutTextXY(170,190," # ## # #### ## # # # "); OutTextXY(170,200," # ## # # # # # ## # # "); OutTextXY(170,210," # # # ## ## # ###### # # "); OutTextXY(170,220," ## # ## # ## # # # # "); OutTextXY(170,230," # ## # #### # ## # "); OutTextXY(170,260," Good Luckly to You !!! "); getch(); putimage(160,120,Buf,0); free(Buf); } void GetScores() { int Sec10000,Sec1000,Sec100,Sec10,Sec1; setfillstyle(0,1); bar(60,250,109,260); Sec1=Scores%10; Sec10=(Scores%100-Scores%10)/10; Sec100=(Scores%1000-Scores%100)/100; Sec1000=(Scores%10000-Scores%1000)/1000; Sec10000=(Scores%100000-Scores%10000)/10000; DispScore(60,250,'0'+Sec10000); DispScore(70,250,'0'+Sec1000); DispScore(80,250,'0'+Sec100); DispScore(90,250,'0'+Sec10); DispScore(100,250,'0'+Sec1); DispScore(110,250,'0'); DispScore(120,250,'0'); } void DispScore(int x,int y,char Ch) { char a[2]; a[1]='\0'; a[0]=Ch; outtextxy(x,y,a); } void Give() { for (i=0;i<4;i++) for (j=0;j<4;j++) b[i][j]=a[Act][Staus][i][j]; } void Display(int color) { for (i=0;i<4;i++) for (j=0;j<4;j++) if (b[i][j]==1) DrawBox(ActH+i,ActS+j,color); } void DrawBox(int x,int y,int Color) { x=BeginH+x*(Wid+2); y=BeginS+y*(Wid+2); setfillstyle(1,Color); bar(x+2,y+2,x+Wid-1,y+Wid-1); if (Color==0) setcolor(1); else setcolor(0); rectangle(x+4,y+4,x+Wid-4,y+Wid-4); } void DrawNext(int Color) { for (i=0;i<4;i++) for (j=0;j<4;j++) if (a[NextAct][0][i][j]==1) DrawBox(Heng+4+i,1+j,Color); } void DetectFill() { int Number,Fall,FallTime=0; for (i=Shu-1;i>=0;i--) { Number=0; for (j=0;j<Heng;j++) if (Position[j][i]==1) Number++; if (Number==Heng) { FallTime++; if (Sounds==CAN) { sound(500); delay(500); nosound(); } for (Fall=i;Fall>0;Fall--) for (j=0;j<Heng;j++) { Position[j][Fall]=Position[j][Fall-1]; if (Position[j][Fall]==0) DrawBox(j,Fall,0); else DrawBox(j,Fall,1); } i++; } } switch(FallTime) { case 0:break; case 1:Scores+=1;break; case 2:Scores+=3;break; case 3:Scores+=6;break; case 4:Scores+=10;break; } if (FallTime!=0) { GetScores(); if (Scores%100==0) Delays-=100; } } void Fail() { if (Sounds==CAN) { for (k=0;k<3;k++) { sound(300); delay(200); nosound(); } } setcolor(1); OutTextXY(440,200,"Game over!"); Quit(); closegraph(); exit(0); } 在DOS环境,TC2。0下调试通过。 由于是早期程序,所以速度、颜色等各处不一定合适,后来也没作过任何修改。请大家指正。 |
地主 发表时间: 09/16 13:25 |
![]() | 回复: jkd [jkd] ![]() |
登录 |
大哥,你真猛!!!!!!!! 哪个大学的? 小弟去找你!!!!!!!!! |
B1层 发表时间: 09/16 13:46 |
![]() | 回复: kert_t8 [kert_t8] ![]() |
登录 |
斑竹就是斑竹,不服不行 |
B2层 发表时间: 09/16 15:45 |
![]() | 回复: ceo_8008 [ceo_8008] ![]() |
登录 |
五体投地 学海无崖・・ |
B3层 发表时间: 09/16 22:02 |
![]() | 回复: 286 [unique] ![]() |
登录 |
不要这么说,其实这些程序很一般,很多地方实现起来并不高明。 再说,听了你的的话我会骄傲的..... ![]() |
B4层 发表时间: 09/17 10:02 |
![]() | 回复: flyfalcon [flyfalcon] ![]() |
登录 |
说实在,286做得很好啊, 其实,我学程序本义也是为了做游戏啊, 谁叫游戏误我的学业呢, 现在得好好向 版主学习啦 请问版主是girl还是boy 啊 [此贴被 枫叶依红(flyfalcon) 在 09月18日13时12分 编辑过] |
B5层 发表时间: 09/18 13:40 |
![]() | 回复: jkd [jkd] ![]() |
登录 |
好厉害1 |
B6层 发表时间: 09/19 15:12 |
![]() | 回复: smx8796 [smx8796] ![]() |
登录 |
大哥就是大哥,小弟佩服的五体投地 我也很想学c,但是不知该从何入手。 请问大哥能否教教小弟 |
B7层 发表时间: 09/22 20:41 |
![]() | 回复: wasdeszwsx [wasdeszwsx] ![]() |
登录 |
支持你 希望在多一写好的 |
B8层 发表时间: 09/22 22:32 |
![]() | 回复: guangtian [guangtian] ![]() |
登录 |
俄罗斯方块我也编过,为什么当时我没遇到你?不然是不好多问题都轻易解决了。 |
B9层 发表时间: 09/28 13:24 |
![]() | 回复: wkbsb [wkbsb] ![]() |
登录 |
我觉的代码并不重要,最主要的是你编这个程序的思路. |
B10层 发表时间: 09/29 23:52 |
![]() | 回复: ceo_8008 [ceo_8008] ![]() |
登录 |
就是算法了・・ 程序的灵魂嘛 也是一个人的高低之分了 |
B11层 发表时间: 09/30 10:02 |
![]() | 回复: lwei889 [lwei889] ![]() |
登录 |
我也是c语言的学习者,但,看到你的程序,我才意思到,我所学的不及你的万分之一啊?能请教你这个程序的核心是什么吗? |
B12层 发表时间: 09/30 12:19 |
![]() | 回复: blindeaf [blindeaf] ![]() |
登录 |
我以前也想编个俄罗斯方块,但没编出来。看了你的程序给我收益不小。 |
B13层 发表时间: 10/07 21:16 |
![]() | 回复: honyry [honyry] ![]() |
登录 |
哎 电脑是网吧的 以前我在学校也是用C编程 能不能教教我 用C语言编个扫描器或者简单的木马什么的!!! 因为我现在还不知道原理啊!上面的程序很好 |
B14层 发表时间: 10/07 21:32 |
![]() | 回复: Answer [_answer] ![]() |
登录 |
![]() |
B15层 发表时间: 04-02-23 19:35 |
![]() | 回复: sniper167 [sniper167] ![]() |
登录 |
强 佩服的全体投地 |
B16层 发表时间: 04-02-24 13:02 |
![]() | 回复: yuncocoon [yuncocoon] ![]() |
登录 |
![]() |
B17层 发表时间: 04-02-25 00:02 |
![]() | 回复: kert_t8 [kert_t8] ![]() |
登录 |
有人想看,又懒得找,只有我给他顶起来了哦 |
B18层 发表时间: 05-01-01 12:58 |
![]() | 回复: mingren123 [mingren123] ![]() |
登录 |
作者已是小有成就了啊 |
B19层 发表时间: 05-01-10 12:47 |
|
20CN网络安全小组版权所有
Copyright © 2000-2010 20CN Security Group. All Rights Reserved.
论坛程序编写:NetDemon
粤ICP备05087286号