您的位置:首页 > 编程语言 > C语言/C++

VC++ 6.0 C语言实现俄罗斯方块教程

2015-08-19 20:29 731 查看
今天把我之前写的大作业分享一下吧,并教你们如何实现,希望你们看了前面的教程也能自己写一个。

1.要先下载一个 graphics.h 的头文件来绘图。

2.初始化窗口:initgraph(x, y);这是先创建一个窗口的函数,以左上角为(0,0),向右为x轴,向下为y轴,其中x表示长x个单位,y表示宽y个单位。

3.关闭图像窗口:closegraph();结束时用来关闭用的。

4.按任意键继续:getch();这个就和getchar();差不多,为了防止以运行完就关了,这样能停顿一下,他的头文件是:conio.h 。

5.画线:line(x1, y1, x2, y2);在你创建的那么窗口里以(x1,y1)和(x2,y2)为两个端点画线。

6.画矩形:rectangle(x1,y1,x2,y2);以(x1,y1)和(x2,y2)为对角画一个矩形。

7.画圆:circle(x,y,r);以(x,y)为圆点,r为半径画圆。

8.颜色:setcolor(x);用来设置颜色的,其中x是你要设置的颜色,可以填这16种:黑 BLACK、蓝 BLUE、绿 GREEN、青 CYAN、红 RED、紫 MAGENTA、棕 BROWN、浅灰 LIGHTGRAY、深灰 DARKGRAY、亮蓝 LIGHTBLUE、亮绿 LIGHTGREEN、亮青 LIGHTCYAN、亮红 LIGHTRED、亮紫 LIGHTMAGENTA、黄 YELLOW、白 WHITE;当然,你也可以根据光的三原色来调自己喜欢的颜色,方法是:setcolor(RGB(x,y,z));其中RGB分别代表红绿蓝,对应的x,y,z是你选的该颜色的多少,范围是[0,255]。



根据上面的这些就能画出很多图形了.比如:

# include <graphics.h>
# include <conio.h>
  void main()
  {	  
	  initgraph(640,480);
	  setcolor(BROWN);
	  line(200,200,300,130);
	  line(400,200,300,130);
	  rectangle(200,200,400,380);
	  setcolor(RGB(100,150,200));
	  circle(255,260,20);
	  circle(345,260,20);
	  rectangle(280,300,310,360);
	  getch();
	  closegraph();
  }


还有这个,画一个圆,圆心是(320,240),半径r=200,根据角度的公式画一个圆:

# include <graphics.h>
# include <conio.h>
# include <math.h>
# define PI 3.1415926
  void main()
  {
	  initgraph(640, 480);
	  int x,y,r=200,c;
	  double a;
	  for(a=0; a<PI*2; a+=0.0001)
	  {
		  x=(int)(r*cos(a)+320+0.5);
		  y=(int)(r*sin(a)+240+0.5);
		  c=(int)(a*255/(2*PI));
		  setcolor(RGB(c,200-c/2,100+c/2));
		  line(320,240,x,y);
	  }
	  getch();
	  closegraph();
  }


9.停顿:Sleep(x);停顿x/1000秒。

有了Sleep();函数,就能让线动起来了,原理就是:先画一条线,然后再画一条黑色的线覆盖原来的那条,然后再画一条线,这样不断的画线能行了。



# include <graphics.h>
# include <conio.h>
  void main()
  {
	  int i,y;
	  initgraph(640,480);
	  for(y=0;y<480-2;y++)
	  {
		  setcolor(RGB(y,125,y/2%256));
		  line(0,y,639,y);
		  line(0,y+2,639,y+2);
		  Sleep(10);
		  setcolor(BLACK);
		  line(0,y,639,y);
	  }
	  getch();
	  closegraph();
  }

10.随机数发生器:srand();使用方法:srand(time(NULL));使用时要有头文件time.h。

11.随机函数:rand();随机生成一个数,头文件是:stdlib.h,比如:

# include <stdio.h>
# include <time.h>
# include <graphics.h>
  void main()
  {
	  int t=10;
	  while(t--)
	  {
		  srand(time(NULL));
		  printf("%d\n",rand());
		  Sleep(1000);
	  }
}


12.判断键盘是否有输入:kbhit();如果有的话返回1,否则返回0.

13.方向键:方健健的ASCII值我们不知道,普通的getchar();也不能输入,但是getch();通过运行程序可以发现方向比较特殊,分别是:上 224+72、下 224+80、左 224+75、右 224+77,就是说他们是由两个字符组成的,所以判断上下左右时就先判断if(kbhit()),然后判断if(getch()==224),如果是的话在判断if(getch()==72),是的话就是上,下左右同理。



# include <stdio.h>
# include <graphics.h>
# include <conio.h>
  void main()
  {
	  int key;
	  while(1)
	  {
		  if(kbhit())
		  {
			  key=getch();
			  if(key==224)
				  key=getch();
			  printf("%d",key);
		  }
		  else
			  printf("*");
		  Sleep(500);
	  }
  }


14.输出:outtextxy(x,y,s);在坐标为(x,y)的地方输出字符串s。

15.数字转字符串:sprintf(s,"%d",a);将数字a,转化为字符串s,头文件是stdio.h。

16.设置字体:setfont(x,y,"字体");其中x表示你你要输出的字的大小,y会改变形状一般都是设为0,"字体"为你想要输出的字体,比如:setfont(40,0,"楷体");

# include <graphics.h>
# include <conio.h>
# include <stdio.h>
  void main()
  {
	  char s[10];
	  initgraph(640,480);
	  setfont(42,0,"隶体");
	  outtextxy(200,200,"俄罗斯方块");
	  sprintf(s,"%d",2015);
	  outtextxy(250,250,s);
	  getch();
	  closegraph();
  }


上面这些都学会了的话,差不多就能够自己完成编写一个俄罗斯方块了,下面分享一下我写的代码。



# include <stdio.h>
# include <time.h>
# include <conio.h>
# include <graphics.h>
  int a,visit[30][15],Color[30][15],minX=30,minY=30,maxX=310,maxY=610,speed=500,score=0,rank=0;
  int color[]={GREEN,CYAN,MAGENTA,BROWN,LIGHTGRAY,LIGHTBLUE,LIGHTGREEN,LIGHTRED,YELLOW};
  int block[36][5][5]=
  {
	  {0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0},
	  {0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0},
	  {0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0},
	  {0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0},
	  {0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0},
	  {0,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,0,0,0,1,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0},
	  {0,0,0,0,0,0,0,0,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0},
	  {0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0},
	  {0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0},
	  {0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0},
	  {0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0},
	  {0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0},
	  {0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0},
	  {0,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0},
	  {0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0},
	  {0,0,1,1,0,0,0,1,0,0,0,0,1,1,0,0,0,1,0,0,0,0,1,1,0},
	  {0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,1,0,1,0,0,0,0,0},
	  {0,1,1,0,0,0,0,1,0,0,0,1,1,0,0,0,0,1,0,0,0,1,1,0,0},
	  {0,0,0,0,0,1,0,1,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0},
	  {0,0,0,0,0,0,1,0,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0},
	  {0,0,0,0,0,0,0,1,1,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0},
	  {0,0,0,0,0,0,1,1,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0},
	  {0,1,1,0,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0},
	  {0,0,0,0,0,0,1,1,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0},
	  {0,0,0,0,0,0,0,0,1,0,0,1,1,1,0,0,1,0,0,0,0,0,0,0,0},
	  {0,0,0,0,0,0,1,1,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0},
	  {0,0,0,0,0,0,0,0,1,0,0,1,1,1,0,0,1,0,0,0,0,0,0,0,0},
	  {0,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0},
	  {0,0,0,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0},
	  {0,0,0,0,0,0,1,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0},
	  {0,0,0,0,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0},
	  {0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0},
	  {0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0},
	  {0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0},
	  {0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0}
  };
  void Interface();//界面的设计
  void nextblock();//生成下一个方块
  void newblock();//将下一个放到主方框中
  void move(int x,int y,int A);//移动方块
  int couldmove(int x0,int y0,int A,char dir,int next);//判断能否移动
  int couldrotate(int x0,int y0,int A,int next);//判断能否旋转
  void mark(int x0,int y0,int A,int next);//标记方块固定后的位置
  void full();//判断有没有能够消行的
  void down(int x);//有消行的将上面的方块下移一行
  int gameover();//判断游戏是否结束
  int main()
  {
	  int i,j;
	  Interface();
	  nextblock();
	  Sleep(500);
	  memset(visit,0,sizeof(visit));
	  while(1)
	  {
	  newblock();
	  full();
	  if(gameover())
		  break;
	  }
	  getch();
	  closegraph();
	  return 0;
  }
  void Interface()
  {
	  int i,j;
	  char str[10];
	  initgraph(550, 660);
	  HWND hwnd = GetHWnd();
	  SetWindowText(hwnd, "NEW俄罗斯方块                 ***:丶阿明");
	  Sleep(2000);
	  setfont(40,0,"隶体");
	  setcolor(RED);
	  outtextxy(145,200,"NEW");
	  setfont(40,0,"楷体");
	  for(i=0;i<=255;i++)
		  for(j=0;j<=255;j++)
		  {
			  setcolor(RGB((i+j+128)%255,i,j));
			  outtextxy(205,200,"俄罗斯方块!");
		  }
		  Sleep(2000);
		  setcolor(YELLOW);
		  setfont(22,0,"隶体");
		  outtextxy(310,300,"←_←");
		  setfont(22,0,"楷体");
		  outtextxy(180,300,"这逼装的可以");
		  setcolor(LIGHTMAGENTA);
		  Sleep(2500);
		  outtextxy(175,300,"请按任意键开始游戏!");
		  getch();
		  cleardevice();
		  setcolor(WHITE);
		  rectangle(29,29,334,633);
		  rectangle(28,28,335,634);
		  rectangle(370,50,515,195);
		  setfont(24,0, "楷体");
		  setcolor(LIGHTGRAY);
		  outtextxy(405,215,"下一个:");
		  setcolor(RED);
		  outtextxy(405,280,"分数:");
		  sprintf(str,"%d",score);
		  outtextxy(415,310,str);
		  outtextxy(405,375,"等级:");
		  sprintf(str,"%d",rank);
		  outtextxy(425,405,str);
		  setfont(22,0, "楷体");
		  setcolor(LIGHTBLUE);
		  outtextxy(390,475,"操作说明:");
		  outtextxy(390,500,"↑: 旋转");
		  outtextxy(390,525,"↓: 下降");
		  outtextxy(390,550,"←: 左移");
		  outtextxy(390,575,"→: 右移");
		  outtextxy(390,600,"空格: 暂停");
  }
  void nextblock()
  {
	  int i,j,x=391,y=71;
	  setfont(23,0,"楷体");
	  setcolor(BLACK);
	  for(i=0;i<5;i++)
		  for(j=0;j<5;j++)
			  outtextxy(x+20*j,y+20*i,"■");
		  srand(time(NULL));
		  a=rand()%9;
		  setcolor(color[a]);
		  for(i=0;i<5;i++)
			  for(j=0;j<5;j++)
				  if(block[4*a][i][j]==1)
					  outtextxy(x+20*j,y+20*i,"■");
  }
  void newblock()
  {
	  int i,j,x=130,y=30,A=a;
	  if(A==0||A==1||A==6)
		  y-=60;
	  else if(A==2||A==3||A==5||A==7||A==8)
		  y-=40;
	  else
		  y-=80;
	  setfont(23,0,"楷体");
	  setcolor(color[A]);
	  for(i=0;i<5;i++)
		  for(j=0;j<5;j++)
			  if(block[4*A][i][j]==1&&y+20*i>=30)
				  outtextxy(x+20*j,y+20*i,"■");
			  Sleep(100);
			  nextblock();
			  move(x,y,A);
  }
  void move(int x,int y,int A)
  {
	  int i,j,f,k=0,next=0,Speed=speed,key,nex;
	  while(1)
	  {
		  f=couldmove(x,y+k,A,'x',next);
		  if(f==0)
		  {
			  mark(x,y+k,A,next);
			  break;
		  }
		  if(kbhit())
		  {
			  key=getch();
			  if(key==32)
				  getch();
		  }
		  setcolor(BLACK);
		  for(i=0;i<5;i++)
			  for(j=0;j<5;j++)
				  if(block[4*A+next][i][j]==1&&y+20*i+k>=30)
					  outtextxy(x+20*j,y+20*i+k,"■");
				  if(kbhit())
				  {
					  key=getch();
					  if(key==72)
					  {
						  nex=(next+1)%4;
						  if(couldrotate(x,y+k,A,nex))
							  next=nex;
					  }
					  else if(key==80)
						  Speed=50;
					  else if(key==75&&couldmove(x,y+k+20,A,'z',next))
						  x-=20;
					  else if(key==77&&couldmove(x,y+k+20,A,'y',next))
						  x+=20;
				  }
				  setcolor(color[A]);
				  for(i=0;i<5;i++)
					  for(j=0;j<5;j++)
						  if(block[4*A+next][i][j]==1&&y+20*i+k+20>=30)
							  outtextxy(x+20*j,y+20*i+k+20,"■");
						  Sleep(Speed);
						  k+=20;
			  }
  }
  int couldmove(int x0,int y0,int A,char dir,int next)
  {
	  int i,j,x,y,f=1;
	  x=(y0-minY)/20;
	  y=(x0-minX)/20;
	  if(dir=='x')
	  {
		  for(i=0;i<5;i++)
			  for(j=0;j<5;j++)
			  if(block[4*A+next][i][j]==1&&(x+i+1==30||(x+i+1>=0&&x+i+1<30&&y+j>=0&&y+j<15&&visit[x+i+1][y+j]==1)))
				  f=0;
	  }
	  else if(dir=='z')
	  {
		  for(i=0;i<5;i++)
			  for(j=0;j<5;j++)
				  if(block[4*A+next][i][j]==1&&(y+j==0||(x+i>=0&&x+i<30&&y+j-1>=0&&y+j-1<15&&visit[x+i][y+j-1]==1)))
					  f=0;
	  }
	  else if(dir=='y')
	  {
		  for(i=0;i<5;i++)
			  for(j=0;j<5;j++)
				  if(block[4*A+next][i][j]==1&&(y+j+1==15||(x+i>=0&&x+i<30&&y+j+1>=0&&y+j+1<15&&visit[x+i][y+j+1]==1)))
					  f=0;
	  }
	  return f;
  }
  int couldrotate(int x0,int y0,int A,int next)
  {
	  int i,j,x,y,f=1;
	  x=(y0-minY)/20;
	  y=(x0-minX)/20;
	  if(!couldmove(x0,y0,A,'x',next))
		  f=0;
	  for(i=0;i<5;i++)
		  for(j=0;j<5;j++)
			  if(block[4*A+next][i][j]==1&&(y+j==-1||y+j==15||(x+i>=0&&x+i<30&&y+j>=0&&y+j<15&&visit[x+i][y+j]==1)))
				  f=0;
			  return f;
  }
  void mark(int x0,int y0,int A,int next)
  {
	  int i,j,x,y;
	  x=(y0-minY)/20;
	  y=(x0-minX)/20;
	  for(i=0;i<5;i++)
		  for(j=0;j<5;j++)
			  if(block[4*A+next][i][j]==1)
			  {
				  visit[x+i][y+j]=1;
				  Color[x+i][y+j]=color[A];
			  }
  }
  void full()
  {
	  int i,j,k=0;
	  char str[10];
	  for(i=29;i>=0;i--)
	  {
		  for(j=0;j<15;j++)
			  if(visit[i][j]==0)
				  break;
			  if(j==15)
			  {
				  k++;
				  down(i);
				  i++;
			  }
	  }
	  setcolor(RED);
	  score+=10*k;
	  sprintf(str,"%d",score);
	  outtextxy(415,310,str);
	  rank=(score/50);
	  sprintf(str,"%d",rank);
	  outtextxy(425,405,str);
	  speed=500-100*rank;
	  if(speed==0)
		  speed=100;
	  if(score>=300)
		  speed=75;
  }
  void down(int x)
  {
	  int i,j;
	  for(i=x;i>0;i--)
		  for(j=0;j<15;j++)
			  if(visit[i-1][j]==1)
			  {
				  visit[i][j]=visit[i-1][j];
				  Color[i][j]=Color[i-1][j];
				  setcolor(Color[i-1][j]);
				  outtextxy(minX+20*j,minY+20*i,"■");
			  }
			  else
			  {
				  visit[i][j]=visit[i-1][j];
				  setcolor(BLACK);
				  outtextxy(minX+20*j,minY+20*i,"■");
			  }
			  setcolor(BLACK);
			  for(j=0;j<15;j++)
			  {
				  visit[0][j]=0;
				  outtextxy(minX+20*j,minY,"■");
			  }
  }
  int gameover()
  {
	  int i,j;
	  for(i=0;i<15;i++)
		  if(visit[0][i]==1)
		  {
			  for(i=0;i<=7;i++)
			  {
				  setcolor(RGB(35*i,255-35*i,255));
				  for(j=i;j<30-i;j++,Sleep(20))
					  outtextxy(30+20*i,30+20*j,"■");
				  for(j=i;j<15-i;j++,Sleep(20))
					  outtextxy(30+20*j,30+20*(29-i),"■");
				  for(j=30-1-i;j>=i;j--,Sleep(20))
					  outtextxy(30+20*(14-i),30+20*j,"■");
				  for(j=15-1-i;j>=i;j--,Sleep(20))
					  outtextxy(30+20*j,30+20*i,"■");
			  }
			  setcolor(WHITE);
			  setfont(45,0,"隶体");
			  outtextxy(75,300,"GAME OVER!");
			  Sleep(5000);
			  return 1;
		  }
		  return 0;
  }




我设置的一行能放15个小格子,一共能放30行,二维数组visit[30][15],来判断某个位置是否有方块,比如visit[29][5]=1表示第30行第6个方块的位置有方块了,0表示没方块,Color[30][15]用来记录某个位置的方块的颜色。minX=30,minY=30表示左上角的方块也就是第1行第1列的方块对应在界面的坐标,maxX,maxY同理。speed表示方块的下落速度,一开始初始化为500,没0.5s往下落一行,score记录分数,每消一行加10分,rank表示等级,每50分等级+1,且速度减100,当速度减到100时,就不变了,只有当分数超过300速度才会减为75,且以后都不会再减少了。

我一个设计了9种方块,每种方块都有4种形态,每顺时针旋转90°就有一种形态,所以一共是36个方块。每个方块都用5*5的二维数组来表示,36种就是36个二维数组,所以用block[36][5][5]来表示,block[k][5][5],(k<36&&k%4==0)表示每种方块的初始形态,k+1,+2,+3,分别表示第k种方块选择90°、180°、270°之后的形态。比如block[1][5][5]保存的是第1种方块旋转90°的方块,其中block[1][i][j]=1表示这个方块第i+1行,j+1列有一个小方块,=0代表没有,所以我的block[36][5][5],有36行,一行25个数列,表示一种方块。一维数组color[]依次表示9种方块的颜色。

附上效果图:




















内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: