user-0 提问: C语言的贪吃蛇，别人的程序，有个bug，

回复:
user: user-1
content: http://www.easyx.cn

user: user-2
content: /*俄罗斯方块（C代码）*/ /*    —— 晓帝*/   #include <stdio.h> #include <dos.h> #include <conio.h> #include <graphics.h> #include <stdlib.h>  #ifdef __cplusplus  #define __CPPARGS ... #else #define __CPPARGS #endif #define MINBOXSIZE 15 /* 最小方块的尺寸 */ #define BGCOLOR 7 /* 背景着色 */ #define GX 200 #define GY 10 #define SJNUM 10000 /* 每当玩家打到一万分等级加一级*/  /* 按键码*/ #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  /* 定义俄罗斯方块的方向（我定义他为4种）*/ #define F_DONG 0 #define F_NAN 1 #define F_XI 2 #define F_BEI 3  #define NEXTCOL 20 /* 要出的下一个方块的纵坐标*/ #define NEXTROW 12 /* 要出的下一个方块的横从标*/ #define MAXROW 14 /* 游戏屏幕大小*/ #define MAXCOL 20 #define SCCOL 100 /*游戏屏幕大显示器上的相对位置*/ #define SCROW 60   int gril[22][16]; /* 游戏屏幕坐标*/ int col=1,row=7; /* 当前方块的横纵坐标*/ int boxfx=0,boxgs=0; /* 当前寺块的形壮和方向*/ int nextboxfx=0,nextboxgs=0,maxcol=22;/*下一个方块的形壮和方向*/ int minboxcolor=6,nextminboxcolor=6; int num=0; /*游戏分*/ int dj=0,gamedj[10]={18,16,14,12,10,8,6,4,2,1};/* 游戏等级*/ /* 以下我用了一个3维数组来纪录方块的最初形状和方向*/ int boxstr[7][4][16]={{ {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}, {0,1,0,0,1,1,0,0,1,0,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}, {1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0}}, { {1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0}, {1,1,1,0,1,0,0,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}, {0,0,1,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,0,0,0,1,1,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}, {1,1,1,0,0,0,1,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,0,0,0,1,1,1,1,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,0,0,0,1,1,1,1,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}}, { {0,0,0,0,1,1,1,0,0,1,0,0,0,0,0,0}, {1,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0}, {0,1,0,0,1,1,1,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}}  };  /* 随机得到当前方块和下一个方块的形状和方向*/ void boxrad(){ minboxcolor=nextminboxcolor; boxgs=nextboxgs; boxfx=nextboxfx; nextminboxcolor=random(14)+1; if(nextminboxcolor==4||nextminboxcolor==7||nextminboxcolor==8) nextminboxcolor=9; nextboxfx=F_DONG; nextboxgs=random(7); } /*初始化图形模试*/ void init(int gdrive,int gmode){ int errorcode; initgraph(&gdrive,&gmode,"D:\\tc\\"); errorcode=graphresult(); if(errorcode!=grOk){ printf("error of: %s",grapherrormsg(errorcode)); exit(1); } }  /* 在图形模式下的清屏 */ void cls() { setfillstyle(SOLID_FILL,0); setcolor(0); bar(0,0,640,480); } /*在图形模式下的高级清屏*/ void clscr(int a,int b,int c,int d,int color){ setfillstyle(SOLID_FILL,color); setcolor(color); bar(a,b,c,d); } /*最小方块的绘制*/ void minbox(int asc,int bsc,int color,int bdcolor){ int a=0,b=0; a=SCCOL+asc; b=SCROW+bsc; clscr(a+1,b+1,a-1+MINBOXSIZE,b-1+MINBOXSIZE,color); if(color!=BGCOLOR){ setcolor(bdcolor); line(a+1,b+1,a-1+MINBOXSIZE,b+1); line(a+1,b+1,a+1,b-1+MINBOXSIZE); line(a-1+MINBOXSIZE,b+1,a-1+MINBOXSIZE,b-1+MINBOXSIZE); line(a+1,b-1+MINBOXSIZE,a-1+MINBOXSIZE,b-1+MINBOXSIZE); } }  /*游戏中出现的文字*/ void txt(int a,int b,char *txt,int font,int color){ setcolor(color); settextstyle(0,0,font); outtextxy(a,b,txt); } /*windows 绘制*/ void win(int a,int b,int c,int d,int bgcolor,int bordercolor){ clscr(a,b,c,d,bgcolor); setcolor(bordercolor); line(a,b,c,b); line(a,b,a,d); line(a,d,c,d); line(c,b,c,d);  }  /* 当前方块的绘制*/ void funbox(int a,int b,int color,int bdcolor){ int i,j; int boxz[4][4]; for(i=0;i<16;i++) boxz[i/4][i%4]=boxstr[boxgs][boxfx][i]; for(i=0;i<4;i++) for(j=0;j<4;j++) if(boxz[i][j]==1) minbox((j+row+a)*MINBOXSIZE,(i+col+b)*MINBOXSIZE,color,bdcolor); } /*下一个方块的绘制*/ void nextfunbox(int a,int b,int color,int bdcolor){ int i,j; int boxz[4][4]; for(i=0;i<16;i++) boxz[i/4][i%4]=boxstr[nextboxgs][nextboxfx][i]; for(i=0;i<4;i++) for(j=0;j<4;j++) if(boxz[i][j]==1) minbox((j+a)*MINBOXSIZE,(i+b)*MINBOXSIZE,color,bdcolor); } /*时间中断定义*/ #define TIMER 0x1c int TimerCounter=0; void interrupt ( *oldhandler)(__CPPARGS); void interrupt newhandler(__CPPARGS){ TimerCounter++; oldhandler(); } void SetTimer(void interrupt (*IntProc)(__CPPARGS)){ oldhandler=getvect(TIMER); disable(); setvect(TIMER,IntProc); enable(); } /*由于游戏的规则，消掉都有最小方块的一行*/ void delcol(int a){ int i,j; for(i=a;i>1;i--) for(j=1;j<15;j++){ minbox(j*MINBOXSIZE,i*MINBOXSIZE,BGCOLOR,BGCOLOR); gril[i][j]=gril[i-1][j]; if(gril[i][j]==1) minbox(j*MINBOXSIZE,i*MINBOXSIZE,minboxcolor,0); } }  /*消掉所有都有最小方块的行*/ void delete(){ int i,j,zero,delgx=0; char *nm="00000"; for(i=1;i<21;i++){ zero=0; for(j=1;j<15;j++) if(gril[i][j]==0) zero=1; if(zero==0){ delcol(i); delgx++; } } num=num+delgx*delgx*10; dj=num/10000;  sprintf(nm,"%d",num); clscr(456,173,500,200,4); txt(456,173,"Number:",1,15); txt(456,193,nm,1,15); } /*时间中断结束*/ void KillTimer(){ disable(); setvect(TIMER,oldhandler); enable(); } /* 测试当前方块是否可以向下落*/ int downok(){ int i,j,k=1,a[4][4]; for(i=0;i<16;i++) a[i/4][i%4]=boxstr[boxgs][boxfx][i]; for(i=0;i<4;i++) for(j=0;j<4;j++) if(a[i][j] && gril[col+i+1][row+j]) k=0; return(k); } /* 测试当前方块是否可以向左行*/ int leftok(){ int i,j,k=1,a[4][4]; for(i=0;i<16;i++) a[i/4][i%4]=boxstr[boxgs][boxfx][i]; for(i=0;i<4;i++) for(j=0;j<4;j++) if(a[i][j] && gril[col+i][row+j-1]) k=0; return(k); } /* 测试当前方块是否可以向右行*/ int rightok(){ int i,j,k=1,a[4][4]; for(i=0;i<16;i++) a[i/4][i%4]=boxstr[boxgs][boxfx][i]; for(i=0;i<4;i++) for(j=0;j<4;j++) if(a[i][j] && gril[col+i][row+j+1]) k=0; return(k); } /* 测试当前方块是否可以变形*/ int upok(){ int i,j,k=1,a[4][4]; for(i=0;i<4;i++) for(i=0;i<16;i++) a[i/4][i%4]=boxstr[boxgs][boxfx+1][i]; for(i=3;i>=0;i--) for(j=3;j>=0;j--) if(a[i][j] && gril[col+i][row+j]) k=0; return(k); } /*当前方块落下之后，给屏幕坐标作标记*/ void setgril(){ int i,j,a[4][4]; funbox(0,0,minboxcolor,0); for(i=0;i<16;i++) a[i/4][i%4]=boxstr[boxgs][boxfx][i]; for(i=0;i<4;i++) for(j=0;j<4;j++) if(a[i][j]) gril[col+i][row+j]=1; col=1;row=7; } /*游戏结束*/ void gameover(){ int i,j;  for(i=20;i>0;i--) for(j=1;j<15;j++) minbox(j*MINBOXSIZE,i*MINBOXSIZE,2,0); txt(103,203,"Game Over",3,10); } /*按键的设置*/ void call_key(int keyx){ switch(keyx){ case VK_DOWN: { /*下方向键，横坐标加一。*/ if(downok()){ col++; funbox(0,0,minboxcolor,0);} else{ funbox(0,0,minboxcolor,0); setgril(); nextfunbox(NEXTCOL,NEXTROW,4,4); boxrad(); nextfunbox(NEXTCOL,NEXTROW,nextminboxcolor,0); delete(); } break; } case VK_UP: { /*上方向键，方向形状旋转90度*/ if(upok()) boxfx++; if(boxfx>3) boxfx=0; funbox(0,0,minboxcolor,0); break; } case VK_LEFT:{ /*左方向键，纵坐标减一*/ if(leftok()) row--; funbox(0,0,minboxcolor,0); break; } case VK_RIGHT:{ /*右方向键，纵坐标加一*/ if(rightok()) row++; funbox(0,0,minboxcolor,0); break; } case VK_SPACE: /*空格键，直接落到最后可以落到的们置*/ while(downok()) col++; funbox(0,0,minboxcolor,0); setgril(); nextfunbox(NEXTCOL,NEXTROW,4,4); boxrad(); nextfunbox(NEXTCOL,NEXTROW,nextminboxcolor,0); delete(); break; default: { txt(423,53,"worng key!",1,4); txt(428,80,"Plese Enter Anly Key AG!",1,4); getch(); clscr(420,50,622,97,BGCOLOR); } } }  /*时间中断开始*/ void timezd(void){ int key; SetTimer(newhandler); boxrad(); nextfunbox(NEXTCOL,NEXTROW,nextminboxcolor,0); for(;;){ if(bioskey(1)){ key=bioskey(0); funbox(0,0,BGCOLOR,BGCOLOR); if(key==VK_ESC) break; call_key(key); } if(TimerCounter>gamedj[dj]){ TimerCounter=0; if(downok()){ funbox(0,0,BGCOLOR,BGCOLOR); col++; funbox(0,0,minboxcolor,0); } else { if(col==1){ gameover(); getch(); break; } setgril(); delete(); funbox(0,0,minboxcolor,0); col=1;row=7; funbox(0,0,BGCOLOR,BGCOLOR); nextfunbox(NEXTCOL,NEXTROW,4,4); boxrad(); nextfunbox(NEXTCOL,NEXTROW,nextminboxcolor,0); } } } }  /*主程序开始*/ void main(void){ int i,j; char *nm="00000"; init(VGA,VGAHI); cls(); /*屏幕坐标初始化*/ for(i=0;i<=MAXCOL+1;i++) for(j=0;j<=MAXROW+1;j++) gril[i][j]=0; for(i=0;i<=MAXCOL+1;i++) { gril[i][0]=1; gril[i][15]=1; } for(j=1;j<=MAXROW;j++){ gril[0][j]=1; gril[21][j]=1; } clscr(0,0,640,480,15); win(1,1,639,479,4,15); win(SCCOL+MINBOXSIZE-2,SCROW+MINBOXSIZE-2,SCCOL+15*MINBOXSIZE+2,SCROW+21*MINBOXSIZE+2,BGCOLOR,0); nextboxgs=random(8); nextboxfx=random(4); sprintf(nm,"%d",num); txt(456,173,"Number:",1,15); txt(456,193,nm,1,15); txt(456,243,"Next Box:",1,15); timezd(); KillTimer(); closegraph(); }

user: user-2
content: 这个画面也太差劲了

user: user-3
content: 自己重新编一个

user: user-4
content: 引用 楼主 sinat_17506531 的回复:就是刚开始运行的时候，蛇头部分清除不了，想了好久，能力有限，希望大家帮我分析一下 [/code] 原因是：第一个蛇头增加1的时候没有备份。 改后的代码如下：  #include<stdio.h> #include<windows.h> #include<stdlib.h> #include<time.h> #include"conio.h" struct Snake { 	int x; 	int y; }snake[150];  struct Smile { 	int x; 	int y; }smile[3];  struct Cross { 	int x; 	int y; }cross[5]; void screen() { 	int i,j; 	HANDLE hout; 	COORD coord; 	for(i=57;i<=58;i++) 	{ 		for(j=0;j<=24;j++) 		{ 			coord.X=i; 			coord.Y=j; 			hout=GetStdHandle(STD_OUTPUT_HANDLE); 			SetConsoleCursorPosition(hout,coord); 			printf("#"); 		} 	} 	for(j=23;j<=24;j++) 	{ 		for(i=0;i<=56;i++) 		{ 			coord.X=i; 			coord.Y=j; 			hout=GetStdHandle(STD_OUTPUT_HANDLE); 			SetConsoleCursorPosition(hout,coord); 			printf("#"); 		} 	} } static int length=3; static int direction=2; static int temp; void rubber() { 	HANDLE hout; 	COORD coord; 	coord.X=snake[length].x; 	coord.Y=snake[length].y; 	hout=GetStdHandle(STD_OUTPUT_HANDLE); 	SetConsoleCursorPosition(hout,coord); 	printf(" "); }  void clescr() { 	system("cls"); }  void ifcollide() { 	int i; 	for(i=3;i<=length;i++) 	{ 		if((snake[0].x==snake[i].x)&&(snake[0].y==snake[i].y)) exit(0); 	} }  void over() { 	if(((snake[0].x>=57)||(snake[0].x<0))||((snake[0].y>=23)||(snake[0].y<0))) 		exit(0); }  void moveon() { 	int i; 	for(i=length;i>0;i--) 	{ 		snake[i].x=snake[i-1].x; 		snake[i].y=snake[i-1].y; 	} }  void keybd() { 	Sleep(temp-300);//这个函数也来自于windows.h头文件，作用是程序暂停一段时间，这里的作用很明显，那就是一个简单的计时功能，如果没有它，整个蛇就会处在不断前进前进前进的疯癫状 	if(kbhit())//一开始有提到过的判断键盘是否输入的函数，即如果有输入，执行： 	{ 		switch (getch())//getch（）就是键盘信息，72,80,75,77分别对应上下左右方向键，在百度搜索keybdevent()，有详细的各种键盘值对应，当然这里只需要这四个 		{ 		case 72: 			direction=1; 			break;//direction 就是一开始开辟的静态变量，纪录方向 		case 80: 			direction=2; 			break; 		case 75: 			direction=3; 			break; 		case 77: 			direction=4; 			break; 		default: 			break; 		} 	} 	switch(direction)//根据方向判定，如果有键盘输入，在上面的时候已经改变过一次direction的值，如果没有，direction就衍用上次的值，这也是好处之一 	{ 	case 1: 		snake[0].y-=1;break;//snake〔0〕就是蛇头坐标结构体 	case 2: 		snake[0].y+=1;break; 	case 3: 		snake[0].x-=1;break; 	case 4: 		snake[0].x+=1;break; 	default: 		exit(0); 	} }  void ifcolobs() {     int i;     for(i=0;i<=4;i++) 	{ 		if((snake[0].x==cross[i].x)&&(snake[0].y==cross[i].y)) //判断是不是有撞倒障碍 		{ 			printf("Fail!"); 			getch(); 			exit(0); 		} 	} } int main(void) { 	char ch; 	int j=0,k; 	printf("碰到%c蛇会死亡,吃到%c蛇的长度增加一节!注意了,有时候%c会被%c所替代!\n尽管如此,你还是不能吃掉它,所以如果你运气太差,会因此而死亡\n",29,2,29,2); 	printf("请输入游戏难度:\n"); 	printf("A.easy\n"); 	printf("B.medium\n"); 	printf("C.difficult\n"); 	printf("D.death challenge\n"); 	scanf("%c",&ch); 	switch(ch) 	{ 	case'A': 	case'a':     		temp=800; 		break; 	case'B': 	case'b':     		temp=700; 		break; 	case'C': 	case'c':     		temp=500; 		break; 	case'D': 	case'd':     		temp=400; 		break; 	default: 		printf("you are kidding..."); 		exit(0); 	} 	printf("游戏初始化中...");//到此为止，主函数第一步完成，一个简单的选择界面就出来了。。 	for(k=0;k<3;k++) 	{ 		snake[k].x=j; 		snake[k].y=2-k; 	} 	srand((unsigned)time(NULL)); 	for(k=0;k<=4;k++) 	{ 		cross[k].x=rand()%50+5; 		cross[k].y=rand()%20+1; 	} 	for(j=0;j<=2;j++) 	{ 		smile[j].x=rand()%54+1; 		smile[j].y=rand()%15+8; 	} 	clescr(); 	screen(); 	 	 	for(j=0;j<3;j++) 	{ 		HANDLE hout; 		COORD coord; 		coord.X=snake[j].x; 		coord.Y=snake[j].y; 		hout=GetStdHandle(STD_OUTPUT_HANDLE); 		SetConsoleCursorPosition(hout,coord); 		printf("%c",4); 	}//不再赘述，主要就是清屏，画边界，画一开始的蛇 	for(j=0;j<=4;j++) 	{ 		HANDLE hout; 		COORD coord; 		coord.X=cross[j].x; 		coord.Y=cross[j].y; 		hout=GetStdHandle(STD_OUTPUT_HANDLE); 		SetConsoleCursorPosition(hout,coord); 		printf("%c",29); 	} 	for(j=0;j<3;j++) 	{ 		HANDLE hout; 		COORD coord; 		coord.X=smile[j].x; 		coord.Y=smile[j].y; 		hout=GetStdHandle(STD_OUTPUT_HANDLE); 		SetConsoleCursorPosition(hout,coord); 		printf("%c",2); 	} 	while(1) 	{ 		moveon(); 		keybd(); 		int i; 		HANDLE hout; 		COORD coord; 		coord.X=snake[0].x; 		coord.Y=snake[0].y; 		hout=GetStdHandle(STD_OUTPUT_HANDLE); 		SetConsoleCursorPosition(hout,coord); 		printf("%c",4);//正如思路里面所述，获取方向键信息之后画蛇头 		over(); 		ifcollide(); 		ifcolobs(); 		 		for(i=0;i<=2;i++) 		{ 			int a=0; 			if((snake[0].x==smile[i].x)&&(snake[0].y==smile[i].y)) 				a=1;//判断是不是有吃到笑脸 			if(a==1) 			{  				int b=0;//如果有吃到，长度加一，对于被吃到的笑脸，把那个结构体的坐标重新随机一遍，再画出来，当然随机完需要判断一下是不是有和谁重叠 				length++; 				while(b==0) 				{ 					int c; 					srand((unsigned)time(NULL)); 					smile[i].x=rand()%56+1; 					smile[i].y=rand()%16+1; 					for(c=0;c<=length;c++) 					{ 						if((snake[c].x==smile[i].x)&&(snake[c].y==smile[i].y)) 						{ 							c=length+1; 							b--; 						} 					} 					b++; 				} 				HANDLE hout; 				COORD coord; 				coord.X=smile[i].x; 				coord.Y=smile[i].y; 				hout=GetStdHandle(STD_OUTPUT_HANDLE); 				SetConsoleCursorPosition(hout,coord); 				printf("%c",2); 			} 			rubber(); 		} 		rubber(); 		//moveon(); 	} 	return 0; }

user: user-5
content: 控制台版的贪吃蛇