贪吃蛇

直接上代码:

  • Model.h
#pragma once

//坐标的结构体
typedef struct Coordinate 
{
	int x;
	int y;
} Coordinate;


//链表的节点结构体
typedef struct Node
{
	Coordinate Coord;
	struct Node* next;
}  Node;


//蛇前进的方向
typedef enum
{
	UP, RIGHT, DOWN, LEFT
} Direction;

//蛇
typedef struct Snake
{
	Node* head;
	Direction direction;
}  Snake;


//游戏元素
typedef struct Game
{
	Snake snake;
	Coordinate food;
	int width;
	int height;
	int	speed;
	int	score;
}  Game;


void GameInit(Game *pGame);
void FoodInit(Coordinate *pFood, int width,
	int height, const Snake *pSnake);
void GameDestroy(Game *pGame);

void AddSnakeHead(Snake* pSnake,Coordinate nextCoord);
void RemoveSnakeTail(Snake* pSnake);
  • Model.c
#define _CRT_SECURE_NO_DEPRECATE 1

#include "Model.h"
#include "stdbool.h"
#include "stdlib.h"
#include "view.h"


void SnakeInit(Snake *pSnake)
{
	pSnake->direction = RIGHT;
	pSnake->head = NULL;

	for (int i = 0; i < 3;i++)
	{
		int x = 3 + i;
		int y = 3;

		Node* node = (Node*)malloc(sizeof(Node));
		node->Coord.x = x;
		node->Coord.y = y;

		node->next = pSnake->head;
		pSnake->head = node;
	}
}


static bool IsOverlapSnake(int x, int y, const Snake *pSnake)
{
	Node* cur = pSnake->head;
	while (cur!=NULL)
	{
		if (cur->Coord.x==x&&cur->Coord.y==y)
		{
			return true;
		}
		cur = cur->next;
	}
	return false;
}


// 生成食物
// 1. 随机
// 2. 不能出框
// 3. 不能和蛇重叠
void FoodInit(Coordinate *pFood, int width, int height, const Snake *pSnake)
{
	int x; int y;
	do 
	{
		x = rand() % width;
		y = rand() % height;
	} while (IsOverlapSnake(x,y,pSnake));

	pFood->x = x;
	pFood->y = y;

	DisplayFood(x, y);
}


void GameInit(Game *pGame)
{
	SnakeInit(&pGame->snake);
	pGame->width = 28;
	pGame->height = 27;
	pGame->speed = 300;
	pGame->score = 0;
	FoodInit(&pGame->food,pGame->width,pGame->height,&pGame->snake);
	DisplayScore(pGame->score);
}


static void SnakeDestroy(Snake *pSnake)
{
	Node* cur = pSnake->head;
	while (cur!=NULL)
	{
		Node* Del = cur;
		cur = cur->next;
		free(Del);
	}
}

void GameDestroy(Game *pGame)
{
	SnakeDestroy(&pGame->snake);
}



void AddSnakeHead(Snake* pSnake,Coordinate nextCoord)
{
	Node* node = (Node*)malloc(sizeof(Node));
	node->Coord.x = nextCoord.x;
	node->Coord.y = nextCoord.y;
	node->next = pSnake->head;
	pSnake->head = node;
	DisplaySnakeBlock(nextCoord.x, nextCoord.y);
}


void RemoveSnakeTail(Snake* pSnake)
{
	Node* cur = pSnake->head;
	while (cur->next->next!=NULL)
	{
		cur = cur->next;
	}
	CleanSnakeBlock(cur->next->Coord.x, cur->next->Coord.y);
	free(cur->next);
	
	cur->next = NULL;
}

Controller.c

#define _CRT_SECURE_NO_DEPRECATE 1

#include "Model.h"
#include "Windows.h"
#include "stdbool.h"
#include "view.h"
#include "time.h"


static void _Pause()
{
	while (1)
	{
		Sleep(300);
		if (GetAsyncKeyState(VK_SPACE))
		{
			break;
		}
	}
}

static Coordinate GetNextCoord(Snake* pSnake)
{
	Coordinate nextCoord = pSnake->head->Coord;
	switch (pSnake->direction)
	{
	case UP:
		nextCoord.y -= 1;
		break;
	case DOWN:
		nextCoord.y += 1;
		break;
	case LEFT:
		nextCoord.x -= 1;
		break;
	case RIGHT:
		nextCoord.x += 1;
		break;
	default:
		break;
	}
	return nextCoord;
}


static bool IsFood(Coordinate nextCord, Coordinate Food)
{
	return nextCord.x == Food.x && nextCord.y == Food.y ? true : false;
}


static bool IsHitWall(int width, int height, Coordinate nextCoord)
{
	if (nextCoord.x<0||nextCoord.x>=width||nextCoord.y<0||nextCoord.y>=height)
	{
		return true;
	}
	return false;
}


static bool IsHitSelf(Snake* pSnake, Coordinate nextCoord)
{
	Node*cur = pSnake->head->next;
	while (cur!=NULL)
	{
		if (cur->Coord.x==nextCoord.x&&cur->Coord.y==nextCoord.y)
		{
			return true;
		}

		cur = cur->next;
	}
	return false;
}



void RunGame()
{
	Game game;
	GameInit(&game);
	ViewInit(game.width, game.height);
	DisplayWall(game.width, game.height);
	DisplaySnake(&game.snake);
	while (1)
	{
		if (GetAsyncKeyState(VK_UP)&&game.snake.direction!=DOWN)
		{
			game.snake.direction = UP;
		}
		else if (GetAsyncKeyState(VK_DOWN) && game.snake.direction != UP)
		{
			game.snake.direction = DOWN;
		}
		else if (GetAsyncKeyState(VK_LEFT) && game.snake.direction != RIGHT)
		{
			game.snake.direction = LEFT;
		}
		else if (GetAsyncKeyState(VK_RIGHT) && game.snake.direction != LEFT)
		{
			game.snake.direction = RIGHT;
		}
		else if (GetAsyncKeyState(VK_SPACE))
		{
			_Pause();
		}
		else if (GetAsyncKeyState(VK_ESCAPE)) 
		{
			break;
		}
		else if (GetAsyncKeyState(VK_F1)) 
		{
			game.speed = 100;
		}

		Coordinate nextCoord = GetNextCoord(&game.snake);

		if (IsFood(nextCoord,game.food))
		{
			AddSnakeHead(&game.snake, nextCoord);
			game.score += 10;
			if (game.speed>=100)
			{
				game.speed -= 10;
			}

			DisplayScore(game.score);
			FoodInit(&game.food, game.width, game.height, &game.snake);
		}
		else
		{
			RemoveSnakeTail(&game.snake);
			AddSnakeHead(&game.snake, nextCoord);
		}
		if (IsHitWall(game.width, game.height, nextCoord))
		{
			break;
		}
		if (IsHitSelf(&game.snake,nextCoord))
		{
			break;
		}
		Sleep(game.speed);
	}
	GameDestroy(&game);
}



int main()
{
	srand((unsigned)time(NULL));
	Menu();
	RunGame();
	return 0;
}

View.h

#pragma once

#include "Model.h"

void DisplaySnake(const Snake *pSnake);
void DisplaySnakeBlock(int x, int y);
void CleanSnakeBlock(int x, int y);
void ViewInit(int width, int height);
void DisplayWall(int width, int height);
void DisplayFood(int x, int y);
void DisplayScore(int score);

View.c

#define _CRT_SECURE_NO_DEPRECATE 1

#include "Model.h"
#include <Windows.h>
#include <stdio.h>

static void SetCurPos(int X, int Y)
{
	HANDLE hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
	// 标准输入/标准输出/标准错误输出
	COORD coord = { X, Y };
	//设置终端光标位置
	SetConsoleCursorPosition(hStdOutput, coord);
}

void ViewInit(int width, int height)
{
	HANDLE hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_CURSOR_INFO info;
	GetConsoleCursorInfo(hStdOutput, &info);
	info.bVisible = 0;
	SetConsoleCursorInfo(hStdOutput, &info);
}


void DisplayWall(int width, int height)
{
	SetCurPos(0, 0);
	for (int i = 0; i < width + 2; i++)
	{
		printf("█");
	}

	SetCurPos(0, height + 1);
	for (int i = 0; i < width + 2; i++)
	{
		printf("█");
	}


	for (int j = 0; j < height + 2; j++)
	{
		SetCurPos(0, j);
		printf("█");
	}

	for (int j = 0; j < height + 2; j++)
	{
		SetCurPos(2*(width+1), j);
		printf("█");
	}
}


void Menu()
{
	SetCurPos(46, 10);
	printf("※※※贪吃蛇小游戏※※※\n");
	SetCurPos(50, 12);
	system("pause");
	system("cls");
}



void DisplaySnake(const Snake *pSnake)
{
	for (Node* cur = pSnake->head; cur != NULL;cur=cur->next)
	{
		SetCurPos(2*(cur->Coord.x+1), cur->Coord.y+1);
		printf("█");
	}
}

void DisplaySnakeBlock(int x, int y)
{
	SetCurPos(2*(x+1), y+1);	// 先统一两个坐标系
	printf("█");
}


void CleanSnakeBlock(int x, int y)
{
	SetCurPos(2*(x+1), y+1);	// 先统一两个坐标系
	printf("  ");
}


void DisplayFood(int x, int y)
{
	SetCurPos(2 * (x + 1), y+1);
	printf("█");
}


void DisplayScore(int score)
{
	SetCurPos(2 * 31, 24);
	for (int i = 0; i < 10;i++)
	{
		printf("※");
	}
	SetCurPos(2 * 31, 28);
	for (int i = 0; i < 10; i++)
	{
		printf("※");
	}

	for (int j = 0; j < 5;j++)
	{
		SetCurPos(2 * 31, 24 + j);
		printf("※");
	}
	for (int j = 0; j < 5; j++)
	{
		SetCurPos(2 * 40, 24 + j);
		printf("※");
	}
	SetCurPos(2 * 32, 26);
	printf("分数:%d", score);
}

演示:

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值