现在的位置: 首页 > 综合 > 正文

VC环境下简单的贪吃蛇

2012年04月24日 ⁄ 综合 ⁄ 共 6720字 ⁄ 字号 评论关闭

    下午真无聊的不知道干什么了,翻翻自己以前写的代码,偶然看到大一时写的这个简单的贪吃蛇,自己玩了几把后还是决定发到博客吧。(实在无聊,打发时间)

    注:完全基于VC++6.0环境,不支持Linux 下terminal中运行。并且代码风格基本没有,写的十分扯,一大堆代码都在main()函数中,其中用了switch来搞了两关,一个是撞墙over,另一个当然可以穿墙了。代码复用就别提了,两关由于十分相似,代码基本相同,由于只是玩,就没搞个公用调用接口。唉,现在看着以前的代码,感觉那风格简直是扯淡。


 「正文开始」:

 代码开始那段,其实是用来装逼的,什么设置用户名,代码最后重新开始游戏,设置速度(通过sleep的时间实现)之类的,准备着以后修改修改,完善完善,但是现在觉得没时间再玩这些东西了,也一直没改。

由于代码中基本我都写了注释以及打印时的英文标注,在这就说下大体的代码实现思路,其实蛇身是基于双向链表实现的,而蛇的移动是通过以非阻塞的方式从缓冲区中读出按键对应的值,从而控制方向(kbhit()函数可以检测键盘是否按下,以非阻塞的方式从缓冲区读取数据),而蛇的移动是通过检测对用的蛇身位置,通过刷屏

(system(”cls“);)的方式不断打印蛇身的位置,从而实现蛇的移动效果(运动时还需要保证蛇身的运动方向与蛇头是一致的)。本身其实一切都是在开始定义的那个数组


int a[20][20]={0};// 定义布局范围大小

中来实现的,控制的关键是这个数组中每个位置的字符样式(有标记),蛇头就打印实体框,蛇身就是虚体框,而食物就是随机产生的英文咯,每当蛇头与食物在同一个坐标是就新建一个节点,添加到蛇身这条链表。而游戏结束的标志其实也是通过检测蛇头与蛇身的坐标关系,还有与边缘的坐标关系,判断是自残而死还是撞墙而死。

  「废话不多说了」

  上代码:

 


<head.h>

struct Node
{
    int x;
    int y;                      //蛇身节点位置的数据类型、
    struct Node *pre;       
    struct Node *next;        //双向链表,控制蛇身运动的一致性
};

struct Food
{
    int x;
    int y;
    char c;                 // 食物种子的数据类型。
};


这是用到的两个简单的struct,总体实现,其实是基于双向链表的。

在者就是需要用到win环境下的头文件:



#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <time.h>            //key for snake food !
#include <conio.h>
#include "head.h" 

由于比较扯,下面实现代码都是在main函数中,我现在也懒得改了,就这么看吧。


int main(int argc,char *argv[])
{
	int a[20][20]={0};// 定义布局范围大小。
	char user_name[15];
        int i,j,flag=0;
	int speed;                  //蛇运行速度的控制,用sleep()实现,其实也是清屏的间歇速度。。
        char c='d',c1='d';        //运动方向初始化
	char key;
	char speed_key,user_key,stage_key;
        struct Food food={9,15,'*'};        //食物得初始位置
	int stage;       //选择关卡
        int gameover=0;           //key data
        struct Node *head,*p,*rear,*pt;
	int score;
	printf("************************ <! careful !> *****************************\n\n");
	
	puts("\n<*>*<*>every time when you touch  foods and you will get five points !<*><*>\n\n when you want to stop at once ,please press ‘t’\n\nwhen you want to have a pause ,please press '0'\n\n ");
	puts("Direction control help: ** <  UP:w > < DOMN :s > < left :a > < right :d > **\n\n\n ");
	printf("*****************************************\n");
	
	printf("please input the speed of this snake ( between 0 ~~ 300 ):");
	scanf("%d",&speed);
	printf("\n\nplease input your user_name :");
	scanf("%s",user_name);
        key='y';
	printf("\n\nplease choose which stage to start game(input the int value bellow:)?\n\n【(*0*):without the wall to stop game,(*1*): with  the wall to stop your touch】\n\n");
	flushall();
	scanf("%d",&stage);
	while(key=='y')
	{
		score=0;
		head=(struct Node *)malloc(sizeof(struct Node));
		head->x=10;
		head->y=10;                                    // 蛇身头节点的初始位置
		head->pre=NULL;
		head->next=NULL;                                  
		rear=head;
		
		srand((unsigned)time(NULL));   //随机函数的产生:【食物种子】
		switch (stage)
		{
			
		case 0:
			while(1)
			{
				
				if(food.x==head->x && food.y==head->y)
				{
					p=(struct Node *)malloc(sizeof(struct Node));        //产生曾长段。
					pt=head;
					
					while(pt->next!=NULL)
						pt=pt->next ;        //找出蛇体增长位置pt为尾指针
					p->pre= pt;
					pt->next = p;
					p->next=NULL;
					rear=p;           //尾指针 
					
					score+=5;           //分数增加
					
					food.x=rand()%20;                   //食物产生的随机位置算法
					food.y=rand()%20;
					food.c=65+rand()%26;
					
					flag=1;  
					
				}
				
				pt=rear;

				if(kbhit())            // key point : 【 检查键盘有无按下。。输入任意字符继续  ,要么,程序只能执行一次,即打一次
				{                      //              kbhit()可以保证循环时可以连续地以非阻塞方式从缓冲区读入字符。。
					c1=getch();      //              清除缓存,从缓冲区读入一个字符】
					if(c1=='0')
					{
						system("pause");
						
					}
					
					if(c1=='t')
					{
						exit(0);
					}
					
					if(c!='d' && c1=='a')
						c=c1;
					else if(c!='a' && c1=='d')          //保证运行时当蛇延直线前行时,按下与直线方向相反的键时,出现游戏结束。。
						c=c1;
					else if(c!='w' && c1=='s')
						c=c1;
					else if(c!='s' && c1=='w')
						c=c1;
				}
				
				
				while(pt!=head)
				{                       //控制每一节蛇身的运动与头保持一致
					pt->x=pt->pre->x;
					pt->y=pt->pre->y;
					pt=pt->pre;
				}
				
				if(c=='d')       //方向控制
				{
					head->y +=1;
					if(head->y >=20)
						head->y -=20;
				}
				else if(c=='a')
				{
					head->y -=1;
					if(head->y <0)
						head->y +=20;
				}
				else if(c=='w')
				{
					head->x -=1;
					if(head->x < 0)
						head->x +=20;
				}
				else if(c=='s')
				{
					head->x+=1;
					if(head->x >=20)
						head->x -=20;
				}
				
				pt=head->next;
				while(pt!=NULL)
				{
					if(head->x==pt->x && head->y==pt->y)
					{
						gameover=1;      //蛇头与身体相遇时退出游戏
						break;
					}
					pt=pt->next ;
				}
				if(gameover==1)
					break;
				
				system("cls");   //每次清屏。。。
				
				printf("************************ <! game start !> *****************************\n\n");
				printf("your user_name : %s\n\nthe current speed is %d\n\n",user_name,speed);
				printf(" the current stage is %d\n\n",stage);
				
				printf("*****************************************\n");
				for(i=0;i<20;i++)  //打印循环开始,也是游戏的可视化布局
				{
					printf("|");
					for(j=0;j<20;j++)
					{
						
						flag=0;
						pt=head;
						while(pt!=NULL)
						{
							if(i==pt->x && j==pt->y)
							{
								if(pt==head)
									printf("■");          //当pt=head 时,在那个位置打出头标,
								else
									printf("□");         //要么打出身标
								flag=1;
								break;
							}
							pt=pt->next;//一直找,直到蛇尾结束打印
						}
						
						
						if(flag==0)
						{
							if(i==food.x && j==food.y)
							{
								putchar(food.c);   //如果此位置是food的位置,则打印出food的字符,否则打印空格(必须填满方格布局)。
								putchar(food.c);
								continue;   //转去执行下一次循环判断
							}
							printf("  ");   //不是蛇身,则打印空格
						}
					}
					printf("|\n");
					
				}
				printf("*****************************************\n");
				
				_sleep(speed);   
		   }  
		   break;
		   case 1 :
			  while(1)
			  {
				  
				  if(food.x==head->x && food.y==head->y)
				  {
					  p=(struct Node *)malloc(sizeof(struct Node));        //产生曾长段。
					  pt=head;
					  
					  while(pt->next!=NULL)
						  pt=pt->next ;        //找出蛇体增长位置pt为尾指针
					  p->pre= pt;
					  pt->next = p;
					  p->next=NULL;
					  rear=p;           //尾指针 
					  
					  score+=5;           //分数
					  
					  food.x=rand()%20;                   //食物产生的随机位置算法
					  food.y=rand()%20;
					  food.c=65+rand()%26;
					  
					  flag=1;  
					  
				  }
				  
				  pt=rear;
				  
				  if(kbhit())            // key point : 【 检查键盘有无按下。。输入任意字符继续  ,要么,程序只能执行一次,即打一次
				  {                      //              kbhit()可以保证循环时可以连续地以非阻塞方式从缓冲区读入字符。。
					  c1=getch();      //              清除缓存,从缓冲区读入一个字符】
					  if(c1=='0')
					  {
						  system("pause");
						  
					  }
					  
					  if(c1=='t')
					  {
						  exit(0);
					  }
					  
					  if(c!='d' && c1=='a')
						  c=c1;
					  else if(c!='a' && c1=='d')          //保证运行时当蛇延直线前行时,按下与直线方向相反的键时,出现游戏结束。。
						  c=c1;
					  else if(c!='w' && c1=='s')
						  c=c1;
					  else if(c!='s' && c1=='w')
						  c=c1;
				  }
				  
				  
				  while(pt!=head)
				  {                       //控制每一节蛇身的运动与头保持一致
					  pt->x=pt->pre->x;
					  pt->y=pt->pre->y;
					  pt=pt->pre;
				  }
				  
				  if(c=='d')       //方向控制
				  {
					  head->y +=1;
					  if(head->y >=20)
					  {
						  gameover=1;
						  break;	
					  }
				  }
				  else if(c=='a')
				  {
					  head->y -=1;
					  if(head->y <0)
					  {
						  gameover=1;
						  break;
					  }
				  }
				  else if(c=='w')
				  {
					  head->x -=1;
					  if(head->x < 0)
					  {
						  gameover=1;
						  break;
					  }
				  }
				  else if(c=='s')
				  {
					  head->x+=1;
					  if(head->x >=20)
					  {
						  gameover=1;
						  break;
					  }
				  }
				  
				  pt=head->next;
				  while(pt!=NULL)
				  {
					  if(head->x==pt->x && head->y==pt->y)
					  {
						  gameover=1;      //蛇头与身体相遇时退出游戏
						  break;
					  }
					  pt=pt->next ;
				  }
				  if(gameover==1)
					  break;
				  
				  system("cls");   //每次清屏。。。
				  
				  printf("************************ <! game start !> *****************************\n\n");
				  printf("your user_name : %s\n\nthe current speed is %d\n\n",user_name,speed);
				  
				  printf("*****************************************\n");
				  
				  for(i=0;i<20;i++)
				  {
					  printf("|");
					  for(j=0;j<20;j++)
					  {
						  
						  flag=0;
						  pt=head;
						  while(pt!=NULL)
						  {
							  if(i==pt->x && j==pt->y)
							  {
								  if(pt==head)
									  printf("■");          //当pt=head 时,在那个位置打出头标,
								  else
									  printf("□");         //要么打出身标
								  flag=1;
								  break;
							  }
							  pt=pt->next;//一直找,直到蛇尾结束打印
						  }
						  
						  
						  if(flag==0)
						  {
							  if(i==food.x && j==food.y)
							  {
								  putchar(food.c);   //如果此位置是food的位置,则打印出food的字符,否则打印空格(必须填满方格布局)。
								  putchar(food.c);
								  continue;   //转去执行下一次循环判断
							  }
							  printf("  ");   //不是蛇身,则打印空格
						  }
					  }
					  printf("|\n");
					  
				  }
				  printf("*****************************************\n");
				  
				  _sleep(speed);   
			  }
			  
			  break;
	}
	
    
	
	if(gameover==1) {
		
		puts("************************《Now the game over!》*****************************\n\n         ********!< _ >!*******\n\n");
		printf("\n your score is  :%d\n",score);
		
		puts("if you want to continue ? (y/n)\n");
		flushall();
		scanf("%c",&key); 
		
		if(key=='y')
		{
			gameover=0;
			flushall();
			printf("\nif you want to change speed  ? (y/n):");
			scanf("%c",&speed_key);
			if(speed_key=='y')
			{
				printf("input speed value:\n");
				scanf("%d",&speed);
			}
			else
				printf("\n");
			flushall();
			printf("\nif you want to change user_name  ? (y/n):");
			scanf("%c",&user_key);
			if(user_key=='y')
			{
				flushall();
				printf("input new user_name:\n");
				scanf("%s",user_name);
				
			}
			else
				printf("\n");
			flushall();
			printf("\n if you want to change the stage ? (y/n):");
			scanf("%c",&stage_key);
			if(stage_key=='y')
			{
				flushall();
				printf("\nplease input the stage value :");
				scanf("%d",&stage);
			}
			else
				printf("\n");
			continue; 
		}
		else 
			exit(0);
	 } 
	
	
 }
 return 0;
}


大概就写到这里吧,唉,还是那句话,代码风格惨不忍睹。

抱歉!评论已关闭.