【C】链表实现贪吃蛇小游戏

Snake.h

#ifndef _SNAKE_H_
#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
#include<assert.h>
#include<time.h>

#define _SNAKE_H_
#define FOOD "■"
#define INIT_X 24
#define INIT_Y 5

//蛇的节点
typedef struct node{
	int _x;
	int _y;
	struct node *_next;
}SnakeNode,*pSnakeNode;

//蛇的行走方向
enum DIRECTION{UP=1,DOWN,LEFT,RIGHT};

//蛇的当前状态
enum Status{OK,KILL_BY_SELF,KILL_BY_WALL};

//蛇本身
typedef struct snake{
	pSnakeNode _pSnake;//蛇头指针
	pSnakeNode _pFood;//蛇的食物
	enum DIRECTION _Dir;//蛇行走的方向
	enum Status _status;//蛇的当前状态
	int _SleepTime;//每走一步停一步的时间
	int _grade;
}Snake,*pSnake;

void DropMap();
void SetPos(int x,int y);
void Welcome();
int NextHasFood(pSnake ps,pSnakeNode newNode);
void EatFood(pSnake ps,pSnakeNode newNode);
void NoFood(pSnake ps,pSnakeNode newNode);
void KillBySelf(pSnake ps);
void KillByWall(pSnake ps);
void SnakeRun(pSnake ps);
void test1();
#endif


Snake.c

#include"snake.h"

//设置光标所在位置
void SetPos(int x,int y){
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	COORD pos = {0};
	pos.X=x;
	pos.Y=y;
	SetConsoleCursorPosition(handle,pos);
}

//绘制地图
void DropMap(){
	int i;
	system("cls");
	for(i=0;i<58;i+=2){
		SetPos(i,0);
		printf(FOOD);
	}
	for(i=0;i<26;i++){
		SetPos(0,i);
		printf(FOOD);
		SetPos(58,i);
		printf(FOOD);
	}
	for(i=0;i<=58;i+=2){
		SetPos(i,26);
		printf(FOOD);
	}
	SetPos(66,3);
	printf("分数:0");
	SetPos(66,5);
	printf("按空格加速/减速");
}
//初始化蛇
void InitSnake(pSnake ps){
	pSnakeNode cur=NULL;
	int i=0;
	cur = (pSnakeNode)malloc(sizeof(SnakeNode));
	memset(cur,0,sizeof(SnakeNode));
	cur->_x=INIT_X;
	cur->_y=INIT_Y;
	cur->_next=NULL;
	ps->_SleepTime = 500;
	ps->_status = OK;
	ps->_Dir = RIGHT;
	ps->_grade = 0;
	for(i=1;i<=4;i++){
		ps->_pSnake = (pSnakeNode)malloc(sizeof(SnakeNode));
		ps->_pSnake->_next = cur;
		ps->_pSnake->_x = INIT_X+i*2;
		ps->_pSnake->_y = INIT_Y;
		cur=ps->_pSnake;
	}
	while(cur!=NULL){
		SetPos(cur->_x,cur->_y);
		printf(FOOD);
		cur= cur->_next;
	}

}

void CreateFood(pSnake ps){
	pSnakeNode food = NULL;
	pSnakeNode cur = NULL;
	food = (pSnakeNode)malloc(sizeof(SnakeNode));
	srand(time(NULL));

again:
	memset(food,0,sizeof(SnakeNode));
	do{
		food->_x=rand()%56+2;
	}while(food->_x%2!=0);
	food->_y = rand()%25+1;

	cur = ps->_pSnake;
	while(cur!=NULL){
		if(cur->_x == food->_x&&cur->_y == food->_y){
			goto again;			//返回到again
		}
		cur = cur->_next;
	}

	SetPos(food->_x,food->_y);
	printf(FOOD);
	ps->_pFood=food;
}

void Welcome(){
	system("color 73");
	system("mode con cols=100 lines=32");
	SetPos(25,6);
	printf("贪吃蛇游戏
");
	SetPos(22,8);
	printf("↑ ↓ ← → 控制方向
");
}

void start(pSnake ps){
	Welcome();
	getchar();
	DropMap();
	InitSnake(ps);
	CreateFood(ps);
}

int NextHasFood(pSnake ps,pSnakeNode newNode){
	return (ps->_pFood->_x==newNode->_x) && (ps->_pFood->_y==newNode->_y);
}

void EatFood(pSnake ps,pSnakeNode newNode){
	pSnakeNode cur = ps->_pSnake;
	newNode->_next = cur;
	ps->_pSnake = newNode;
	cur = ps->_pSnake;
	ps->_grade+=4;
	while(cur!=NULL){
		SetPos(cur->_x,cur->_y);
		printf(FOOD);
		cur=cur->_next;
	}
	if(ps->_SleepTime>300)
		ps->_SleepTime-=100;
	else if(ps->_SleepTime>100)
		ps->_SleepTime-=50;

	SetPos(72,3);
	printf("%d",ps->_grade);
	CreateFood(ps);
}

void NoFood(pSnake ps,pSnakeNode newNode){
	pSnakeNode cur = ps->_pSnake;
	newNode->_next = cur;
	ps->_pSnake = newNode;
	
	cur=ps->_pSnake;
	while(cur->_next->_next!=NULL){
		SetPos(cur->_x,cur->_y);
		printf(FOOD);
		cur=cur->_next;
	}
	SetPos(cur->_next->_x,cur->_next->_y);
	printf(" ");
	free(cur->_next);
	cur->_next=NULL;
}

enum DIRECTION getDir(pSnake ps){
	do{
		if(GetAsyncKeyState(VK_DOWN)&&ps->_Dir!=DOWN)
			ps->_Dir=DOWN;
		if(GetAsyncKeyState(VK_DOWN)&&ps->_Dir!=UP)
			ps->_Dir=UP;
		if(GetAsyncKeyState(VK_DOWN)&&ps->_Dir!=LEFT)
			ps->_Dir=LEFT;
		if(GetAsyncKeyState(VK_DOWN)&&ps->_Dir!=RIGHT)
			ps->_Dir=RIGHT;
	}while(ps->_status==OK);
	return ps->_Dir;
}

void SnakeMove(pSnake ps){
	pSnakeNode newNode = (pSnakeNode)malloc(sizeof(SnakeNode));
	memset(newNode,0,sizeof(SnakeNode));
	newNode->_x = ps->_pSnake->_x;
	newNode->_y = ps->_pSnake->_y;

	switch(ps->_Dir){
	case UP:
		newNode->_y--;
		break;
	case DOWN:
		newNode->_y++;
		break;
	case LEFT:
		newNode->_x-=2;
		break;
	case RIGHT:
		newNode->_x+=2;
		break;
	default:
		break;
	}
	if(NextHasFood(ps,newNode)){
		EatFood(ps,newNode);
	}
	else{
		NoFood(ps,newNode);	
	}

}
void KillBySelf(pSnake ps){
	pSnakeNode cur = ps->_pSnake->_next;
	while(cur){
		if(cur->_x==ps->_pSnake->_x&&cur->_y==ps->_pSnake->_y){
			ps->_status=KILL_BY_SELF;
			SetPos(66,7);
			printf("自杀");
			SetPos(0,27);
		}		
		cur = cur->_next;
	}
}
				
void KillByWall(pSnake ps){
	if(ps->_pSnake->_x==0||ps->_pSnake->_x==58||
		ps->_pSnake->_y==0||ps->_pSnake->_y==26){
			ps->_status = KILL_BY_WALL;
			SetPos(66,7);
			printf("撞墙");
			SetPos(0,27);
	}
}

void SnakeRun(pSnake ps){
	int flag = 0;
	do{
		if(GetAsyncKeyState(VK_DOWN)&&ps->_Dir!=UP){
			ps->_Dir = DOWN;
		}
		else if(GetAsyncKeyState(VK_UP)&&ps->_Dir!=DOWN){
			ps->_Dir = UP;
		}
		else if(GetAsyncKeyState(VK_LEFT)&&ps->_Dir!=RIGHT){
			ps->_Dir = LEFT;
		}
		else if(GetAsyncKeyState(VK_RIGHT)&&ps->_Dir!=LEFT){
			ps->_Dir = RIGHT;
		}
		else if(GetAsyncKeyState(VK_SPACE)){    //按下空格来控制蛇的加速减速
			if(flag==0){
				ps->_SleepTime/=2;
				flag=1;
			}
			else if(flag==1){
				ps->_SleepTime*=2;
				flag=0;
			}
		}
		SnakeMove(ps);
		KillBySelf(ps);
		KillByWall(ps);
		Sleep(ps->_SleepTime);
	}while(ps->_status == OK);
	
}

void test1(){
	Snake snake;
	start(&snake);
	SnakeRun(&snake);
}

main.c

#include"snake.h"

int main(){
	test1();
	getchar();
	system("pause");
	return 0;
}


原文地址:https://www.cnblogs.com/yongtaochang/p/13615375.html