一、首先放上全部源码:

  




pythonCSP俄罗斯方块 俄罗斯方块源码c语言_顺时针

pythonCSP俄罗斯方块 俄罗斯方块源码c语言_#define_02

1 #include <stdio.h>
  2 #include <windows.h>
  3 #include <conio.h>
  4 #include <time.h>
  5 //游戏窗口
  6 #define FrameX 4   //游戏窗口左上角的X轴坐标
  7 #define FrameY 4   //游戏窗口左上角的Y轴坐标
  8 #define Frame_height  20 //游戏窗口的高度
  9 #define Frame_width   18 //游戏窗口的宽度
 10 //定义全局变量
 11 int i,j,temp,temp1,temp2; //temp,temp1,temp2用于记住和转换方块变量的值
 12 int a[80][80]={0};   //标记游戏屏幕的图案:2,1,0分别表示该位置为游戏边框、方块、无图案;初始化为无图案
 13 int b[4];     //标记4个"口"方块:1表示有方块,0表示无方块
 14   
 15 //声明俄罗斯方块的结构体
 16 struct Tetris
 17 {
 18  int x;     //中心方块的x轴坐标
 19  int y;     //中心方块的y轴坐标
 20  int flag;    //标记方块类型的序号
 21  int next;    //下一个俄罗斯方块类型的序号
 22  int speed;    //俄罗斯方块移动的速度
 23  int count;    //产生俄罗斯方块的个数
 24  int score;    //游戏的分数
 25  int level;    //游戏的等级
 26 };
 27 //函数原型声明
 28 //光标移到指定位置
 29 void gotoxy(HANDLE hOut, int x, int y);
 30 //制作游戏窗口
 31 void make_frame();
 32 //随机产生方块类型的序号
 33 void get_flag(struct Tetris *);
 34 //制作俄罗斯方块
 35 void make_tetris(struct Tetris *);
 36 //打印俄罗斯方块
 37 void print_tetris(HANDLE hOut,struct Tetris *);
 38 //清除俄罗斯方块的痕迹
 39 void clear_tetris(HANDLE hOut,struct Tetris *);
 40 //判断是否能移动,返回值为1,能移动,否则,不动
 41 int if_moveable(struct Tetris *);
 42 //判断是否满行,并删除满行的俄罗斯方块
 43 void del_full(HANDLE hOut,struct Tetris *);
 44 //开始游戏
 45 void start_game();
 46 
 47 int main()
 48 { 
 49  //制作游戏窗口
 50  make_frame();      
 51  //开始游戏
 52  start_game();
 53 }
 54 /******光标移到指定位置**************************************************************/
 55 void gotoxy(HANDLE hOut, int x, int y)
 56 {
 57  COORD pos;
 58  pos.X = x;  //横坐标
 59  pos.Y = y;  //纵坐标
 60  SetConsoleCursorPosition(hOut, pos);
 61 }
 62 /******制作游戏窗口******************************************************************/
 63 void make_frame()
 64 {
 65  HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);  //定义显示器句柄变量
 66  gotoxy(hOut,FrameX+Frame_width-5,FrameY-2);   //打印游戏名称
 67  printf("俄罗斯方块");
 68  gotoxy(hOut,FrameX+2*Frame_width+3,FrameY+7);  //打印选择菜单
 69  printf("**********下一个方块:");
 70  gotoxy(hOut,FrameX+2*Frame_width+3,FrameY+13);
 71  printf("**********");
 72  gotoxy(hOut,FrameX+2*Frame_width+3,FrameY+17);
 73  printf("↑键:变体");
 74  gotoxy(hOut,FrameX+2*Frame_width+3,FrameY+19);
 75  printf("空格:暂停游戏");
 76  gotoxy(hOut,FrameX+2*Frame_width+3,FrameY+15);
 77  printf("Esc :退出游戏");
 78  gotoxy(hOut,FrameX,FrameY);       //打印框角并记住该处已有图案
 79  printf("╔");
 80  gotoxy(hOut,FrameX+2*Frame_width-2,FrameY);
 81  printf("╗");
 82  gotoxy(hOut,FrameX,FrameY+Frame_height);
 83  printf("╚");
 84  gotoxy(hOut,FrameX+2*Frame_width-2,FrameY+Frame_height);
 85  printf("╝");
 86  a[FrameX][FrameY+Frame_height]=2;     
 87  a[FrameX+2*Frame_width-2][FrameY+Frame_height]=2;
 88  for(i=2;i<2*Frame_width-2;i+=2)
 89  {
 90   gotoxy(hOut,FrameX+i,FrameY);
 91   printf("═");         //打印上横框
 92  }
 93  for(i=2;i<2*Frame_width-2;i+=2)
 94  {
 95   gotoxy(hOut,FrameX+i,FrameY+Frame_height);
 96   printf("═");         //打印下横框
 97   a[FrameX+i][FrameY+Frame_height]=2;    //记住下横框有图案
 98  }
 99  for(i=1;i<Frame_height;i++)
100  {
101   gotoxy(hOut,FrameX,FrameY+i); 
102   printf("║");         //打印左竖框
103   a[FrameX][FrameY+i]=2;       //记住左竖框有图案
104  }
105  for(i=1;i<Frame_height;i++)
106  {
107   gotoxy(hOut,FrameX+2*Frame_width-2,FrameY+i); 
108   printf("║");         //打印右竖框
109   a[FrameX+2*Frame_width-2][FrameY+i]=2;   //记住右竖框有图案
110  }
111 }
112 /******制作俄罗斯方块********************************************************************/
113 void make_tetris(struct Tetris *tetris)
114 {
115  a[tetris->x][tetris->y]=b[0];    //中心方块位置的图形状态:1-有,0-无
116  switch(tetris->flag)      //共6大类,19种类型
117  {
118   case 1:         //田字方块
119    {  
120     a[tetris->x][tetris->y-1]=b[1];
121     a[tetris->x+2][tetris->y-1]=b[2];
122     a[tetris->x+2][tetris->y]=b[3];
123     break;
124    }
125   case 2:         //直线方块:----
126    {  
127     a[tetris->x-2][tetris->y]=b[1];
128     a[tetris->x+2][tetris->y]=b[2];
129     a[tetris->x+4][tetris->y]=b[3];
130     break;
131    }
132   case 3:         //直线方块: |
133    {  
134     a[tetris->x][tetris->y-1]=b[1];
135     a[tetris->x][tetris->y-2]=b[2];
136     a[tetris->x][tetris->y+1]=b[3];
137     break;
138    }
139   case 4:         //T字方块
140    {  
141     a[tetris->x-2][tetris->y]=b[1];
142     a[tetris->x+2][tetris->y]=b[2];
143     a[tetris->x][tetris->y+1]=b[3];
144     break;
145    }
146   case 5:         //T字顺时针转90度方块
147    {  
148     a[tetris->x][tetris->y-1]=b[1];
149     a[tetris->x][tetris->y+1]=b[2];
150     a[tetris->x-2][tetris->y]=b[3];
151     break;
152    }
153   case 6:         //T字顺时针转180度方块
154    {  
155     a[tetris->x][tetris->y-1]=b[1];
156     a[tetris->x-2][tetris->y]=b[2];
157     a[tetris->x+2][tetris->y]=b[3];
158     break;
159    }
160   case 7:         //T字顺时针转270度方块
161    {  
162     a[tetris->x][tetris->y-1]=b[1];
163     a[tetris->x][tetris->y+1]=b[2];
164     a[tetris->x+2][tetris->y]=b[3];
165     break;
166    }
167   case 8:         //Z字方块
168    {  
169     a[tetris->x][tetris->y+1]=b[1];
170     a[tetris->x-2][tetris->y]=b[2];
171     a[tetris->x+2][tetris->y+1]=b[3];
172     break;
173    }
174   case 9:         //Z字顺时针转90度方块
175    {  
176     a[tetris->x][tetris->y-1]=b[1];
177     a[tetris->x-2][tetris->y]=b[2];
178     a[tetris->x-2][tetris->y+1]=b[3];
179     break;
180    }
181   case 10:        //Z字顺时针转180度方块
182    {  
183     a[tetris->x][tetris->y-1]=b[1];
184     a[tetris->x-2][tetris->y-1]=b[2];
185     a[tetris->x+2][tetris->y]=b[3];
186     break;
187    }
188   case 11:        //Z字顺时针转270度方块
189    {  
190     a[tetris->x][tetris->y+1]=b[1];
191     a[tetris->x+2][tetris->y-1]=b[2];
192     a[tetris->x+2][tetris->y]=b[3];
193     break;
194    }
195   case 12:        //7字方块
196    {  
197     a[tetris->x][tetris->y-1]=b[1];
198     a[tetris->x][tetris->y+1]=b[2];
199     a[tetris->x-2][tetris->y-1]=b[3];
200     break;
201    }
202   case 13:        //7字顺时针转90度方块
203    {  
204     a[tetris->x-2][tetris->y]=b[1];
205     a[tetris->x-2][tetris->y+1]=b[2];
206     a[tetris->x+2][tetris->y]=b[3];
207     break;
208    }
209   case 14:        //7字顺时针转180度方块
210    {  
211     a[tetris->x][tetris->y-1]=b[1];
212     a[tetris->x][tetris->y+1]=b[2];
213     a[tetris->x+2][tetris->y+1]=b[3];
214     break;
215    }
216   case 15:        //7字顺时针转270度方块
217    {
218     a[tetris->x-2][tetris->y]=b[1];
219     a[tetris->x+2][tetris->y-1]=b[2];
220     a[tetris->x+2][tetris->y]=b[3];
221     break;
222    }
223   case 16:        //倒7字方块
224    { 
225     a[tetris->x][tetris->y+1]=b[1];
226     a[tetris->x][tetris->y-1]=b[2];
227     a[tetris->x+2][tetris->y-1]=b[3];
228     break;
229    }
230   case 17:        //倒7字顺指针转90度方块
231    { 
232     a[tetris->x-2][tetris->y]=b[1];
233     a[tetris->x-2][tetris->y-1]=b[2];
234     a[tetris->x+2][tetris->y]=b[3];
235     break;
236    }
237   case 18:        //倒7字顺时针转180度方块
238    {  
239     a[tetris->x][tetris->y-1]=b[1];
240     a[tetris->x][tetris->y+1]=b[2];
241     a[tetris->x-2][tetris->y+1]=b[3];
242     break;
243    }
244   case 19:        //倒7字顺时针转270度方块
245    {  
246     a[tetris->x-2][tetris->y]=b[1];
247     a[tetris->x+2][tetris->y+1]=b[2];
248     a[tetris->x+2][tetris->y]=b[3];
249     break;
250    }
251  } 
252 }
253 //******判断是否可动*************************************************************************/
254 int if_moveable(struct Tetris *tetris)
255 {
256  if(a[tetris->x][tetris->y]!=0)//当中心方块位置上有图案时,返回值为0,即不可移动
257  {
258   return 0;
259  }
260  else
261  {
262   if( //当为田字方块且除中心方块位置外,其他"口"字方块位置上无图案时,返回值为1,即可移动
263    ( tetris->flag==1  && ( a[tetris->x][tetris->y-1]==0   &&
264     a[tetris->x+2][tetris->y-1]==0 && a[tetris->x+2][tetris->y]==0 ) ) ||
265    //或为直线方块且除中心方块位置外,其他"口"字方块位置上无图案时,返回值为1,即可移动
266    ( tetris->flag==2  && ( a[tetris->x-2][tetris->y]==0   && 
267     a[tetris->x+2][tetris->y]==0 && a[tetris->x+4][tetris->y]==0 ) )   ||
268    ( tetris->flag==3  && ( a[tetris->x][tetris->y-1]==0   &&
269     a[tetris->x][tetris->y-2]==0 && a[tetris->x][tetris->y+1]==0 ) )   ||
270    ( tetris->flag==4  && ( a[tetris->x-2][tetris->y]==0   &&
271     a[tetris->x+2][tetris->y]==0 && a[tetris->x][tetris->y+1]==0 ) )   ||
272    ( tetris->flag==5  && ( a[tetris->x][tetris->y-1]==0   &&
273     a[tetris->x][tetris->y+1]==0 && a[tetris->x-2][tetris->y]==0 ) )   ||
274    ( tetris->flag==6  && ( a[tetris->x][tetris->y-1]==0   &&
275     a[tetris->x-2][tetris->y]==0 && a[tetris->x+2][tetris->y]==0 ) )   ||
276    ( tetris->flag==7  && ( a[tetris->x][tetris->y-1]==0   &&
277     a[tetris->x][tetris->y+1]==0 && a[tetris->x+2][tetris->y]==0 ) )   ||
278    ( tetris->flag==8  && ( a[tetris->x][tetris->y+1]==0   &&
279     a[tetris->x-2][tetris->y]==0 && a[tetris->x+2][tetris->y+1]==0 ) ) ||
280    ( tetris->flag==9  && ( a[tetris->x][tetris->y-1]==0   &&
281     a[tetris->x-2][tetris->y]==0 && a[tetris->x-2][tetris->y+1]==0 ) ) ||
282    ( tetris->flag==10 && ( a[tetris->x][tetris->y-1]==0   &&
283     a[tetris->x-2][tetris->y-1]==0 && a[tetris->x+2][tetris->y]==0 ) ) ||
284    ( tetris->flag==11 && ( a[tetris->x][tetris->y+1]==0   &&
285     a[tetris->x+2][tetris->y-1]==0 && a[tetris->x+2][tetris->y]==0 ) ) ||
286    ( tetris->flag==12 && ( a[tetris->x][tetris->y-1]==0   &&
287     a[tetris->x][tetris->y+1]==0 && a[tetris->x-2][tetris->y-1]==0 ) ) ||
288    ( tetris->flag==13 && ( a[tetris->x-2][tetris->y]==0   &&
289     a[tetris->x-2][tetris->y+1]==0 && a[tetris->x+2][tetris->y]==0 ) ) ||
290    ( tetris->flag==14 && ( a[tetris->x][tetris->y-1]==0   &&
291     a[tetris->x][tetris->y+1]==0 && a[tetris->x+2][tetris->y+1]==0 ) ) ||
292    ( tetris->flag==15 && ( a[tetris->x-2][tetris->y]==0   &&
293     a[tetris->x+2][tetris->y-1]==0 && a[tetris->x+2][tetris->y]==0 ) ) ||
294    ( tetris->flag==16 && ( a[tetris->x][tetris->y+1]==0   &&
295     a[tetris->x][tetris->y-1]==0 && a[tetris->x+2][tetris->y-1]==0 ) ) ||
296    ( tetris->flag==17 && ( a[tetris->x-2][tetris->y]==0   &&
297     a[tetris->x-2][tetris->y-1]==0 && a[tetris->x+2][tetris->y]==0 ) ) ||
298    ( tetris->flag==18 && ( a[tetris->x][tetris->y-1]==0   &&
299     a[tetris->x][tetris->y+1]==0 && a[tetris->x-2][tetris->y+1]==0 ) ) ||
300    ( tetris->flag==19 && ( a[tetris->x-2][tetris->y]==0   &&
301     a[tetris->x+2][tetris->y+1]==0 && a[tetris->x+2][tetris->y]==0 ) ) )
302    {
303     return 1;
304    }
305  }
306  return 0;
307 }
308 /******随机产生俄罗斯方块类型的序号**********************************************************/
309 void get_flag(struct Tetris *tetris)
310 {
311  tetris->count++;     //记住产生方块的个数
312  srand((unsigned)time(NULL));  //初始化随机数
313  if(tetris->count==1)
314  {
315   tetris->flag = rand()%19+1;  //记住第一个方块的序号
316  }
317  tetris->next = rand()%19+1;   //记住下一个方块的序号
318 }
319 /******打印俄罗斯方块**********************************************************************/
320 void print_tetris(HANDLE hOut,struct Tetris *tetris)
321 {
322  for(i=0;i<4;i++)
323  {
324   b[i]=1;         //数组b[4]的每个元素的值都为1
325  }
326  make_tetris(tetris);      //制作俄罗斯方块
327  for( i=tetris->x-2; i<=tetris->x+4; i+=2 )
328  {
329   for(j=tetris->y-2;j<=tetris->y+1;j++)
330   {
331    if( a[i][j]==1 && j>FrameY )
332    {
333     gotoxy(hOut,i,j);
334     printf("□");     //打印边框内的方块
335    }
336   }
337  }
338  //打印菜单信息
339  gotoxy(hOut,FrameX+2*Frame_width+3,FrameY+1);
340  printf("level : %d",tetris->level);
341  gotoxy(hOut,FrameX+2*Frame_width+3,FrameY+3);
342  printf("score : %d",tetris->score);
343  gotoxy(hOut,FrameX+2*Frame_width+3,FrameY+5);
344  printf("speed : %dms",tetris->speed);
345 }
346 /******清除俄罗斯方块的痕迹****************************************************************/
347 void clear_tetris(HANDLE hOut,struct Tetris *tetris)
348 {
349  for(i=0;i<4;i++)
350  {
351   b[i]=0;         //数组b[4]的每个元素的值都为0
352  }
353  make_tetris(tetris);      //制作俄罗斯方块
354  for( i=tetris->x-2; i<=tetris->x+4; i+=2 )
355  {
356   for(j=tetris->y-2;j<=tetris->y+1;j++)
357   {
358    if( a[i][j]==0 && j>FrameY )
359    {
360     gotoxy(hOut,i,j);
361     printf("  ");     //清除方块
362    }
363   }
364  }
365 }
366 /******判断是否满行并删除满行的俄罗斯方块****************************************************/
367 void del_full(HANDLE hOut,struct Tetris *tetris)
368 {       //当某行有Frame_width-2个方块时,则满行
369  int k,del_count=0;  //分别用于记录某行方块的个数和删除方块的行数的变量
370  for(j=FrameY+Frame_height-1;j>=FrameY+1;j--)
371  {
372   k=0;
373   for(i=FrameX+2;i<FrameX+2*Frame_width-2;i+=2)
374   {  
375    if(a[i][j]==1) //竖坐标依次从下往上,横坐标依次由左至右判断是否满行
376    {
377     k++;  //记录此行方块的个数
378     if(k==Frame_width-2)
379     {
380      for(k=FrameX+2;k<FrameX+2*Frame_width-2;k+=2)
381      {  //删除满行的方块
382       a[k][j]=0;
383       gotoxy(hOut,k,j);
384       printf("  ");
385       Sleep(1);
386      }
387      for(k=j-1;k>FrameY;k--)
388      {  //如果删除行以上的位置有方块,则先清除,再将方块下移一个位置
389       for(i=FrameX+2;i<FrameX+2*Frame_width-2;i+=2)
390       {
391        if(a[i][k]==1)
392        {
393         a[i][k]=0;
394         gotoxy(hOut,i,k);
395         printf("  ");
396         a[i][k+1]=1;
397         gotoxy(hOut,i,k+1);
398         printf("□");
399        }
400       }
401      }
402      j++;   //方块下移后,重新判断删除行是否满行
403      del_count++; //记录删除方块的行数
404     }
405    }
406   }
407  }
408  tetris->score+=100*del_count; //每删除一行,得100分
409  if( del_count>0 && ( tetris->score%1000==0 || tetris->score/1000>tetris->level-1 ) )
410  {        //如果得1000分即累计删除10行,速度加快20ms并升一级
411   tetris->speed-=20;
412   tetris->level++;
413  }
414 }
415 /******开始游戏******************************************************************************/
416 void start_game()
417 {
418  HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);  //定义显示器句柄变量
419  struct Tetris t,*tetris=&t;       //定义结构体的指针并指向结构体变量
420  unsigned char ch;         //定义接收键盘输入的变量
421  tetris->count=0;      //初始化俄罗斯方块数为0个
422  tetris->speed=300;      //初始移动速度为300ms
423  tetris->score=0;      //初始游戏的分数为0分
424  tetris->level=1;      //初始游戏为第1关
425  while(1)
426  {//循环产生方块,直至游戏结束
427   get_flag(tetris);     //得到产生俄罗斯方块类型的序号
428   temp=tetris->flag;     //记住当前俄罗斯方块序号
429   //打印下一个俄罗斯方块的图形(右边窗口)
430   tetris->x=FrameX+2*Frame_width+6;
431   tetris->y=FrameY+10;
432   tetris->flag = tetris->next;
433   print_tetris(hOut,tetris);
434   tetris->x=FrameX+Frame_width;  //初始中心方块x坐标
435   tetris->y=FrameY-1;     //初始中心方块y坐标
436   tetris->flag=temp;     //取出当前的俄罗斯方块序号
437   while(1)
438   {//控制方块方向,直至方块不再下移
439    label:print_tetris(hOut,tetris);//打印俄罗斯方块
440    Sleep(tetris->speed);   //延缓时间
441    clear_tetris(hOut,tetris);  //清除痕迹
442    temp1=tetris->x;    //记住中心方块横坐标的值
443    temp2=tetris->flag;    //记住当前俄罗斯方块序号
444    if(kbhit())   
445    {        //判断是否有键盘输入,有则用ch↓接收
446     ch=getch(); 
447     if(ch==75)     //按←键则向左动,中心横坐标减2
448     {      
449      tetris->x-=2;
450     }
451     if(ch==77)     //按→键则向右动,中心横坐标加2
452     {      
453      tetris->x+=2;    
454     }
455     if(ch==72)     //按↑键则变体即当前方块顺时针转90度
456     {      
457      if( tetris->flag>=2 && tetris->flag<=3 )
458      {
459       tetris->flag++; 
460       tetris->flag%=2;
461       tetris->flag+=2;
462      }
463      if( tetris->flag>=4 && tetris->flag<=7 )
464      {
465       tetris->flag++;
466       tetris->flag%=4;
467       tetris->flag+=4;
468      }    
469      if( tetris->flag>=8 && tetris->flag<=11 )
470      {
471       tetris->flag++;
472       tetris->flag%=4;
473       tetris->flag+=8;
474      }    
475      if( tetris->flag>=12 && tetris->flag<=15 )
476      {
477       tetris->flag++;
478       tetris->flag%=4;
479       tetris->flag+=12;
480      }    
481      if( tetris->flag>=16 && tetris->flag<=19 )
482      {
483       tetris->flag++;
484       tetris->flag%=4;
485       tetris->flag+=16;
486      }
487     }
488     if(ch==32)     //按空格键,暂停
489     {
490      print_tetris(hOut,tetris);
491      while(1)
492      {
493       if(kbhit())   //再按空格键,继续游戏
494       {
495        ch=getch();
496        if(ch==32)
497        {
498         goto label;
499        }
500       }
501      }
502     }
503     if(if_moveable(tetris)==0) //如果不可动,上面操作无效
504     {
505      tetris->x=temp1;
506      tetris->flag=temp2;
507     }
508     else      //如果可动,执行操作
509     {
510      goto label;
511     }
512    }
513    tetris->y++;     //如果没有操作指令,方块向下移动
514    if(if_moveable(tetris)==0)  //如果向下移动且不可动,方块放在此处
515    {    
516     tetris->y--;
517     print_tetris(hOut,tetris);
518     del_full(hOut,tetris);
519     break;
520    }
521   }
522   for(i=tetris->y-2;i<tetris->y+2;i++)
523   {//游戏结束条件:方块触到框顶位置
524    if(i==FrameY)
525    {
526     j=0;      //如果游戏结束,j=0
527    }
528   }
529   if(j==0)       
530   {
531    system("cls");
532    getch();
533    break;
534   }
535   //清除下一个俄罗斯方块的图形(右边窗口)
536   tetris->flag = tetris->next;
537   tetris->x=FrameX+2*Frame_width+6;
538   tetris->y=FrameY+10;
539   clear_tetris(hOut,tetris);  
540  }
541 }


View Code


 

二、整个游戏的流程图

  

pythonCSP俄罗斯方块 俄罗斯方块源码c语言_pythonCSP俄罗斯方块_03

三、函数解析