C语言小项目--贪吃蛇游戏

5 篇文章 3 订阅
1 篇文章 0 订阅

一、贪吃蛇小游戏简介:

        用上下左右控制蛇的方向,寻找吃的东西,每吃一口就能得到一定的积分,而且蛇的身子会越吃越长,身子越长玩的难度就越大,不能碰墙,也不能咬到自己的身体,等到了一定的分数,就能过关。

 

二、函数框架

三、数据结构

typedef struct Snake
{
	size_t x;  //行
	size_t y;  //列
	struct Snake* next;
}Snake, *pSnake;

定义蛇的结构体,利用单链表来表示蛇,每个结点为蛇身体的一部分。

 

四、代码实现(vs2010  c语言)

1.Snake.h

#ifndef __SNAKE_H__
#define __SNAKE_H__

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <time.h>
#include <malloc.h>
#include <assert.h>
//标识地图大小
#define ROW_MAP 10    //地图的行
#define COL_MAP 20    //地图的列
#define SUCCESS_SCORE 10//通关分数
enum Direction //蛇行走的方向
{
	R, //右
	L, //左
	U, //上
	D  //下
}Direction;

enum State
{
	ERROR_SELF, //咬到自己
	ERROR_WALL, //撞到墙
	NORMAL,     //正常状态
	SUCCESS     //通关
}State;

typedef struct Snake
{
	size_t x;  //行
	size_t y;  //列
	struct Snake* next;
}Snake, *pSnake;


void StartGame();
void RunGame();
void EndGame();

#endif


2.Snake.c

#include "Snake.h"


pSnake head = NULL; //定义蛇头指针
pSnake Food = NULL; //定义食物指针

int sleeptime = 500;//间隔时间,用来控制速度
int Score = 0;  //总分
int everyScore = 1; //每步得分

//定义游戏中用到的符号
const char food = '#';
const char snake = '*';

void Pos(int x, int y)   //控制输出光标
{
	COORD pos;  //pos为结构体
	pos.X = x;  //控制列
	pos.Y = y;  //控制行
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);//读取标准输出句柄来控制光标为pos
}

void Face()
{
	system("color 0C");
	printf("*******************************************************\n");
	printf("*                Welcome to Snake Game!               *\n");
	printf("*                                                     *\n");
	printf("*             ->开始游戏请按 enter键                  *\n");
	printf("*             ->退出游戏请按 esc键                    *\n");
	printf("*             ->暂停游戏请按 space键                  *\n");
	printf("*             ->通过上下左右键来控制蛇的移动          *\n");
	printf("*             ->通过F1键减速        F2键加速          *\n");
	printf("*******************************************************\n");
}
void Map()   //初始化地图
{
	int i = 0;
	for(i = 0; i<COL_MAP; i+=2)   //打印上下边框(每个■占用两列)
	{
		Pos(i, 0);
		printf("■");
		Pos(i, ROW_MAP-1);
		printf("■");
	}
	for(i = 0; i<ROW_MAP; i++)   //打印左右边框
	{
		Pos(0, i);
		printf("■");
		Pos(COL_MAP-2, i);
		printf("■");
	}
}
void PrintSnake()  //打印蛇
{
	pSnake cur = head;
	while(cur)
	{
		Pos(cur->y, cur->x);
		printf("%c", snake);
		cur = cur->next;
	}
}
void InitSnake()    //初始化蛇身
{
	int initNum = 3;
	int i = 0;
	pSnake cur;
	head = (pSnake)malloc(sizeof(Snake));
	head->x = 5;
	head->y = 10;
	head->next = NULL;

	cur = head;
	for(i = 1; i < initNum; i++)
	{
		pSnake newNode = (pSnake)malloc(sizeof(Snake));
		newNode->x = 5+i;
		newNode->y = 10;
		newNode->next = NULL;
		cur->next = newNode;
		cur = cur->next;
	}

	PrintSnake();
}

void CreateFood()  //在地图上随机产生一个食物
{
	pSnake cur = head;
	Food = (pSnake)malloc(sizeof(Snake));

	//产生x~y的随机数 k=rand()%(Y-X+1)+X;
	srand((unsigned)time(NULL));
	Food->x = rand()%(ROW_MAP-2 - 1 + 1)+1;
	Food->y = rand()%(COL_MAP-3 - 2 + 1)+2;
	Food->next = NULL;
	while(cur)   //检查食物是否与蛇身重合
	{
		if(cur->x == Food->x && cur->y == Food->y)
		{
			free(Food);
			Food = NULL;
			CreateFood();
			return;
		}
		cur = cur->next;
	}
	Pos(Food->y, Food->x);
	printf("%c", food);
}

void StartGame()  //游戏开始的所有设置
{
	Face();
	system("pause");

	if(GetAsyncKeyState(VK_RETURN))
	{
		system("cls");
		Pos(COL_MAP+5, 1);
		printf("当前分数/通关分数:");
		Pos(COL_MAP+20, 1);
		printf("%d/%d", Score, SUCCESS_SCORE);
		Pos(COL_MAP+5, 2);
		printf("当前分每步得分:");
		Pos(COL_MAP+20, 2);
		printf("%d", everyScore);
		Pos(COL_MAP+5, 3);
		printf("\n");
		Pos(COL_MAP+5, 4);
		printf("速度越快 得分越高哦!!\n");

		Map();
		InitSnake();
		CreateFood();
	}
	else if(GetAsyncKeyState(VK_ESCAPE))
	{
		exit(0);
	}
}

int IsCrossWall()             //判断是否碰到墙
{
	if(head->x <= 0 || head->x >= ROW_MAP-1
		||head->y <= 1 || head->y >= COL_MAP-2)
	{
		State = ERROR_WALL;
		return 0;
	}
	return 1;
}

int IsEatSelf(pSnake newHead)  //判断是否咬到自己
{
	pSnake cur = head;
	assert(newHead);
	while(cur)
	{
		if(cur->x == newHead->x && cur->y == newHead->y)
		{
			State = ERROR_SELF;
			return 0;
		}
		cur = cur->next;
	}
	return 1;
}

int IsFood(pSnake pos)  //判断该位置是不是食物
{
	assert(pos);
	if(pos->x == Food->x && pos->y == Food->y)
	{
		return 1;
	}
	return 0;
}

void SnakeMove()   //蛇移动一次
{
	pSnake newHead = NULL;
	newHead = (pSnake)malloc(sizeof(Snake));

	if(Direction == R)
	{
		newHead->x = head->x;
		newHead->y = head->y+1;
		newHead->next = head;
	}
	else if(Direction == L)
	{
		newHead->x = head->x;
		newHead->y = head->y-1;
		newHead->next = head;
	}
	else if(Direction == U)
	{
		newHead->x = head->x-1;
		newHead->y = head->y;
		newHead->next = head;
	
	}
	else if(Direction == D)
	{
		newHead->x = head->x+1;
		newHead->y = head->y;
		newHead->next = head;
	}

	if(IsFood(newHead))
	{
		head = newHead;
		PrintSnake();
		CreateFood();
		Score += everyScore;
		Pos(COL_MAP+20, 1);
		printf("%d/%d", Score, SUCCESS_SCORE);
		if(Score >= SUCCESS_SCORE)
		{
			State = SUCCESS;
		}
	}
	else 
		{
			if(IsCrossWall() && IsEatSelf(newHead))
			{
				pSnake cur = NULL;
				head = newHead;
				cur = head;
				//删除蛇尾并打印
				while(cur->next->next != NULL)
				{
					Pos(cur->y, cur->x);
					printf("%c", snake);
					cur = cur->next;
				}
				
				Pos(cur->y, cur->x);
				printf("%c", snake);
				Pos(cur->next->y, cur->next->x);
				printf(" ");  //打印空格来覆盖频幕上的蛇尾
				free(cur->next);
				cur->next = NULL;
			}
			else
			{
				free(newHead);
				newHead = NULL;
			}
	}
}

void Pause()
{
	while(1)
	{
		Sleep(sleeptime);
		if(GetAsyncKeyState(VK_SPACE))
		{
			break;
		}
	}
}

void ControlSnake() //用键盘控制游戏
{
	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 != 500)
		{
			sleeptime = 500;
			everyScore = 1;
			Pos(COL_MAP+20, 2);
			printf("%d", everyScore);
		}
	}
	else if(GetAsyncKeyState(VK_F2))
	{
		if(sleeptime != 300)
		{
			sleeptime = 300;
			everyScore = 2;
			Pos(COL_MAP+20, 2);
			printf("%d", everyScore);
		}
	}
	else if(GetAsyncKeyState(VK_SPACE))
	{
		Pause();
	}
	else if(GetAsyncKeyState(VK_ESCAPE))
	{
		exit(0);
	}
}

void StateGame() //判断游戏失败或成功
{
	if(State == ERROR_SELF)
	{
		system("cls");
		printf("很遗憾,蛇咬到自己,游戏失败!\n");
	}
	else if(State == ERROR_WALL)
	{
		system("cls");
		printf("很遗憾,蛇碰到墙壁,游戏失败!\n");
	}
	else if(State == SUCCESS)
	{
		system("cls");
		printf("恭喜您,已通关!!!\n");
	}
	
}
void RunGame()
{
	Direction = R; //蛇初始行走方向为右
	State = NORMAL;//游戏初始为正常状态
	while(1)
	{
		ControlSnake();
		SnakeMove();
		if(State != NORMAL)
		{
			StateGame();
			break;
		}
		Sleep(sleeptime);
	}
}

void EndGame()  //释放链表并恢复默认值
{
	pSnake cur = head;
	while(cur)
	{
		pSnake del = cur;
		cur = cur->next;
		free(del);
		del = NULL;
	}
	head = NULL;
	if(Food != NULL)
	{
		free(Food);
		Food = NULL;
	}
	Score = 0;
	everyScore = 1;
	sleeptime = 500;
}

3.Test.c

#include "Snake.h"

int main()
{
	while(1)
	{
		StartGame();
		RunGame();
		EndGame();
	}
	system("pause");
	return 0;
}

 

五、运行界面展示

1.欢迎界面

2.游戏界面


小小的c语言项目,用来练手,仅供参考哦!!

谢谢阅读,如有问题,欢迎提出,拜拜喽!!

 

  • 30
    点赞
  • 134
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值