VC環境下簡單的貪喫蛇

    下午真無聊的不知道幹什麼了,翻翻自己以前寫的代碼,偶然看到大一時寫的這個簡單的貪喫蛇,自己玩了幾把後還是決定發到博客吧。(實在無聊,打發時間)

    注:完全基於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;
}


大概就寫到這裏吧,唉,還是那句話,代碼風格慘不忍睹。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章