游戏:贪吃蛇

一、Game.h

#ifndef __GAME_H__
#define __GAME_H__

#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#include<windows.h>

//蛇移动区域
#define gamewidth 25
#define gameheigth 25

//墙
#define wallwidth (gamewidth+2)
#define wallheigth (gameheigth+2)

//蛇的方向
#define U 1 //上
#define D 2 //下
#define L 3 //左
#define R 4 //右

typedef struct Snake //蛇身的一个节点
{
	int x;
	int y;
	struct Snake *next;
}Snake;

typedef struct Food //食物节点
{
	int x;
	int y;
}Food;

void Pos(int x, int y); //设置光标位置
void StartInterface(); //开始界面
void CreatWall(); //创建墙
void InitSnake(Snake **pphead); //初始化蛇
void CreateFood(Snake *head, Food **ppfood); //创建食物
void InitGame(Snake **pphead, Food **ppfood); //游戏初始化

int TouchWall(Snake *head); //判断是否碰到墙
int BiteSelf(Snake *head); //判断是否咬到了自己

void Pause(); //暂停
void EndGame(int endflag, int score); //结束游戏
void MoveSnake(Snake **pphead, Food **ppfood, int direction, int *score, int perscore); //控制蛇前进
void ControlGame(Snake **pphead, Food *food, int score, int perscore, int sleeptime); //控制游戏

#endif __GAME_H__

二、Game.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "game.h"

//设置光标位置
void Pos(int x, int y)
{
	COORD pos = { x, y };
	HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleCursorPosition(hOutput, pos);

    CONSOLE_CURSOR_INFO cci;
	GetConsoleCursorInfo(hOutput, &cci); //获取当前光标信息 
	cci.bVisible = FALSE; //设置光标不可见 
	SetConsoleCursorInfo(hOutput, &cci);
}

//开始界面
void StartInterface()
{
	system("cls");
	Pos((50 - strlen("欢迎来到贪食蛇游戏") / 2), 13);
	printf("欢迎来到贪食蛇游戏\n");
	system("pause");
	system("cls");

	Pos((50 - strlen("用↑、↓、←、→分别控制蛇的移动, F1 为加速,F2 为减速") / 2), 13);
	printf("用↑、↓、←、→分别控制蛇的移动, F1 为加速,F2 为减速");
	Pos((50 - strlen("加速将能得到更高的分数") / 2), 15);
	printf("加速将能得到更高的分数\n");
	system("pause");
	system("cls");
}

//创建墙
void CreatWall()
{
	int i = 0;
	// 上
	for (i = 0; i < wallwidth * 2; i = i + 2)
	{
		Pos(i, 0);
		printf("■");
	}
	// 下
	for (i = 0; i < wallwidth * 2; i = i + 2)
	{
		Pos(i, wallheigth - 1);
		printf("■");
	}
	// 左
	for (i = 1; i < wallheigth - 1; i++)
	{
		Pos(0, i);
		printf("■");
	}
	// 右
	for (i = 1; i < wallheigth - 1; i++)
	{
		Pos((wallwidth - 1) * 2, i);
		printf("■");
	}
}

//初始化蛇
void InitSnake(Snake **pphead)
{
	Snake *tail = (Snake *)malloc(sizeof(Snake));
	tail->x = 2;
	tail->y = 2;
	tail->next = NULL;
	for (int i = 1; i < 3; i++) //头插法
	{
		*pphead = (Snake *)malloc(sizeof(Snake));
		(*pphead)->x = 2 + 2 * i;
		(*pphead)->y = 2;
		(*pphead)->next = tail;
		tail = *pphead;
	}
	while (tail != NULL)
	{
		Pos(tail->x, tail->y);
		printf("■");
		tail = tail->next;
	}
}

//创建食物
void CreateFood(Snake *head, Food **ppfood)
{
	int flag = 0;
	srand((unsigned)time(NULL));
	*ppfood = (Food*)malloc(sizeof(Food));

	while (1)
	{
		(*ppfood)->x = (rand() % gameheigth + 1) * 2;
		(*ppfood)->y = rand() % gameheigth + 1;
		Snake *cur = head;
		while (cur)
		{
			if (cur->x == (*ppfood)->x&&cur->y == (*ppfood)->y) //食物不能和蛇身重合
			{
				flag = 1;
				break;
			}
			cur = cur->next;
		}
		if (flag == 0)
		{
			break;
		}
	}

	Pos((*ppfood)->x, (*ppfood)->y);
	printf("■");
}

//游戏初始化
void InitGame(Snake **pphead, Food **ppfood)
{
	StartInterface();
	CreatWall();
	InitSnake(pphead);
	CreateFood(*pphead, ppfood);
}

//判断是否碰到墙
int TouchWall(Snake *head)
{
	if (head->x == 0 || head->x == (wallwidth - 1) * 2 || head->y == 0 || head->y == wallheigth - 1)
	{
		return 1;
	}
	return 0;
}

//判断是否咬到了自己
int BiteSelf(Snake *head)
{
	Snake *cur = head->next;
	while (cur)
	{
		if (cur->x == head->x&&cur->y == head->y)
		{
			return 1;
		}
		cur = cur->next;
	}
	return 0;
}

//暂停
void Pause()
{
	while (1)
	{
		Sleep(300);
		if (GetAsyncKeyState(VK_SPACE))
		{
			break;
		}
	}
}

//控制蛇前进
void MoveSnake(Snake **pphead, Food **ppfood, int direction, int *score, int perscore)
{
	Snake *nextnode = (Snake *)malloc(sizeof(Snake));
	switch (direction)
	{
	case U:
	{
			  nextnode->x = (*pphead)->x;
			  nextnode->y = (*pphead)->y - 1;
	}
		break;
	case D:
	{
			  nextnode->x = (*pphead)->x;
			  nextnode->y = (*pphead)->y + 1;
	}
		break;
	case L:
	{
			  nextnode->x = (*pphead)->x - 2;
			  nextnode->y = (*pphead)->y;
	}
		break;
	case R:
	{
			  nextnode->x = (*pphead)->x + 2;
			  nextnode->y = (*pphead)->y;
	}
		break;
	}

	if (nextnode->x == (*ppfood)->x&&nextnode->y == (*ppfood)->y) //下一个位置是食物
	{
		nextnode->next = *pphead;
		*pphead = nextnode;
		Snake *cur = *pphead;
		while (cur)
		{
			Pos(cur->x, cur->y);
			printf("■");
			cur = cur->next;
		}
		*score += perscore;
		
		free(*ppfood);
		CreateFood(*pphead, ppfood); //创建新的食物
	}
	else //下一个位置不是食物
	{
		nextnode->next = *pphead;
		*pphead = nextnode;
		Snake *cur = *pphead;
		while (cur->next->next) //找到蛇身倒数第二个节点
		{
			Pos(cur->x, cur->y);
			printf("■");
			cur = cur->next;
		}
		Pos(cur->next->x, cur->next->y);
		printf(" ");
		free(cur->next);
		cur->next = NULL;
	}
}

//结束游戏
void EndGame(int endflag, int score)
{
	system("cls");
	if (endflag == 1)
	{
		Pos((50 - strlen("您已结束了游戏") / 2), 13);
		printf("您已结束了游戏\n");
	}
	else if (endflag == 2)
	{
		Pos((50 - strlen("游戏结束,您撞到墙了") / 2), 13);
		printf("游戏结束,您撞到墙了\n");
	}
	else if (endflag == 3)
	{
		Pos((50 - strlen("游戏结束,您撞到自己了") / 2), 13);
		printf("游戏结束,您撞到自己了\n");
	}

	Pos((50 - strlen("您的最终得分是:  ") / 2), 15);
	printf("您的最终得分是:%d\n", score);
}

//控制游戏
void ControlGame(Snake **pphead, Food *food, int score, int perscore, int sleeptime)
{
	Pos(wallwidth * 2 + 10, 12);
	printf("不能撞到墙,不能撞到自己");
	Pos(wallwidth * 2 + 10, 13);
	printf("用↑、↓、←、→分别控制蛇的移动");
	Pos(wallwidth * 2 + 10, 14);
	printf("F1为加速,F2为减速");
	Pos(wallwidth * 2 + 10, 15);
	printf("Esc为退出游戏,Space为暂停");

	int direction = R; //蛇的初始前进方向
	while (1)
	{
		Pos(wallwidth * 2 + 10, 10);
		printf("得分:%d    每个食物得分:%2d", score, perscore);
		if (GetAsyncKeyState(VK_UP) && direction != D)
		{
			direction = U;
		}
		else if (GetAsyncKeyState(VK_DOWN) && direction != U)
		{
			direction = D;
		}
		else if (GetAsyncKeyState(VK_LEFT) && direction != R)
		{
			direction = L;
		}
		else if (GetAsyncKeyState(VK_RIGHT) && direction != L)
		{
			direction = R;
		}
		else if (GetAsyncKeyState(VK_F1))
		{
			if (sleeptime > 100)
			{
				sleeptime -= 200;
				perscore += 5;
			}
		}
		else if (GetAsyncKeyState(VK_F2))
		{
			if (sleeptime < 500)
			{
				sleeptime += 200;
				perscore -= 5;
			}
		}
		else if (GetAsyncKeyState(VK_SPACE))
		{
			Pause();
		}
		else if (GetAsyncKeyState(VK_ESCAPE))
		{
			EndGame(1, score);
			return;
		}

		MoveSnake(pphead, &food, direction, &score, perscore);
		Sleep(sleeptime);

		if (TouchWall(*pphead))
		{
			EndGame(2, score);
			return;
		}
		if (BiteSelf(*pphead))
		{
			EndGame(3, score);
			return;
		}
	}
}

三、Test.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "game.h"

void Menu()
{
	printf("**********贪吃蛇游戏**********\n");
	printf("**                          **\n");
	printf("**        1.开始游戏        **\n");
	printf("**        0.退出游戏        **\n");
	printf("**                          **\n");
	printf("******************************\n");
}

int main()
{
	system("mode con cols=100 lines=32");
	int op = 0;
	do{
		Menu();
		printf("请选择:");
		scanf("%d", &op);
		switch (op)
		{
		case 1:
		{
				  Snake *head = NULL;
				  Food *food = NULL;
				  int perscore = 10;
				  int score = 0;
				  int sleeptime = 300;

				  InitGame(&head, &food);
				  ControlGame(&head, food, score, perscore, sleeptime);

				  Snake* tail = NULL;
				  while (head)
				  {
					  tail = head->next;
					  free(head);
					  head = tail;
				  }

				  free(food);
				  food = NULL;
				  	  
				  system("pause");
				  system("cls");
		}
			break;
		case 0:
		{
				  system("pause");
				  return 0;
		}
			break;
		}
	} while (op);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值