贪吃蛇游戏

view.h:

#pragma once

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


void SetPos(int X, int Y)
{
	HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
	COORD coord;
	coord.X = X;
	coord.Y = Y;

	SetConsoleCursorPosition(hStdout, coord);
}

// 显示外墙
void DisplayWall(int width, int height)
{
	int i;

	// 上边的墙
	SetPos(0, 0);
	for (i = 0; i < width + 2; i++) {
		printf("█");
	}

	// 下边的墙
	SetPos(0, height + 1);
	for (i = 0; i < width + 2; i++) {
		printf("█");
	}

	// 左边的墙
	for (i = 0; i < height + 2; i++) {
		SetPos(0, i);
		printf("█");
	}

	// 右边的墙
	for (i = 0; i < height + 2; i++) {
		SetPos(2 * (width + 1), i);
		printf("█");
	}
}

void DisplaySnakeNode(Position pos)
{
	SetPos(2 * (pos.x + 1), pos.y + 1);
	printf("◆");
}

void CleanSnakeNode(Position pos)
{
	SetPos(2 * (pos.x + 1), pos.y + 1);
	printf("  ");
}


void DisplayFood(Position pos)
{
	SetPos(2 * (pos.x + 1), pos.y + 1);
	printf("⊙");
}

void DisplaySnake(const Snake *pSnake)
{
	Node *pNode = pSnake->pHead;
	while (pNode) {
		DisplaySnakeNode(pNode->data);
		pNode = pNode->pNext;
	}
}

controller.h

#pragma once

#include "Model.h"
#include "View.h"
#include <windows.h>
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>

void SnakeInit(Snake *pSnake)
{
	int i;

	pSnake->pHead = NULL;
	for (i = 0; i < 3; i++) {
		Position pos;
		pos.x = i + 5;
		pos.y = 5;

		Node *pNewNode = (Node *)malloc(sizeof(Node));
		assert(pNewNode);
		pNewNode->data = pos;
		pNewNode->pNext = pSnake->pHead;
		pSnake->pHead = pNewNode;
	}

	pSnake->direction = RIGHT;
}

// 1 重叠
// 0 不重叠
int IsOverlapSnake(int x, int y, const Snake *pSnake)
{
	Node *pNode;
	for (pNode = pSnake->pHead; pNode; pNode = pNode->pNext) {
		if (pNode->data.x == x && pNode->data.y == y) {
			return 1;
		}
	}

	return 0;
}

// 生成食物
// 1. 随机
// 2. 范围内
// 3. 不和蛇重叠
void FoodInit(Position *pFood, int width, int height, const Snake *pSnake)
{
	int x, y;

	do {
		x = rand() % width;
		y = rand() % height;
	} while (IsOverlapSnake(x, y, pSnake));

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

void GameInit(Game *pGame)
{
	pGame->width = 28;
	pGame->height = 32;
	system("mode con cols=60 lines=38");

	SnakeInit(&(pGame->snake));
	FoodInit(
		&(pGame->foodPosition),
		pGame->width,
		pGame->height,
		&(pGame->snake));

	pGame->score = 0;
	pGame->scorePerFood = 10;
	pGame->speed = 200; // 毫秒
}

// 得到下一步的坐标
Position GetNextPosition(const Snake *pSnake)
{
	Position nextPos;
	nextPos.x = pSnake->pHead->data.x;
	nextPos.y = pSnake->pHead->data.y;

	switch (pSnake->direction) {
	case UP:
		nextPos.y -= 1;
		break;
	case DOWN:
		nextPos.y += 1;
		break;
	case LEFT:
		nextPos.x -= 1;
		break;
	case RIGHT:
		nextPos.x += 1;
		break;
	}

	return nextPos;
}

// 头插
void PushFront(Snake *pSnake, Position nextPos)
{
	Node *pNewNode = (Node *)malloc(sizeof(Node));
	assert(pNewNode);
	pNewNode->data = nextPos;

	pNewNode->pNext = pSnake->pHead;
	pSnake->pHead = pNewNode;

	DisplaySnakeNode(nextPos);
}

// 尾删
void PopBack(Snake *pSnake)
{
	Node *pNode = pSnake->pHead;
	while (pNode->pNext->pNext != NULL) {
		pNode = pNode->pNext;
	}

	CleanSnakeNode(pNode->pNext->data);
	free(pNode->pNext);
	pNode->pNext = NULL;
}

// 1 表示撞了
// 0 表示没有
int IsCrashByWall(int width, int height, Position nextPos)
{
	if (nextPos.x < 0 || nextPos.x >= width) {
		return 1;
	}

	if (nextPos.y < 0 || nextPos.y >= height) {
		return 1;
	}

	return 0;
}

// 1 表示撞了
// 0 表示没撞
int IsCrashHimself(const Snake *pSnake)
{
	Node *pHead = pSnake->pHead;	// 第一个结点
	Node *pNode = pSnake->pHead->pNext;	// 第二个结点

	while (pNode != NULL) {
		if (pHead->data.x == pNode->data.x && pHead->data.y == pNode->data.y) {
			return 1;
		}

		pNode = pNode->pNext;
	}

	return 0;
}

void GameStart()
{
	Game	game;

	GameInit(&game);
	DisplayWall(game.width, game.height);
	DisplaySnake(&(game.snake));
	DisplayFood(game.foodPosition);

	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;
		}

		Position nextPos = GetNextPosition(&(game.snake));
		if (nextPos.x == game.foodPosition.x && nextPos.y == game.foodPosition.y) {
			// 吃到食物

			// 蛇增长一格
			PushFront(&(game.snake), nextPos);

			// 加分
			game.score += game.scorePerFood;

			// 生成新食物
			FoodInit(&(game.foodPosition),
				game.width, game.height,
				&(game.snake));

			DisplayFood(game.foodPosition);

		}
		else {
			// 没吃到食物

			// 蛇向前一步
			PushFront(&(game.snake), nextPos);
			PopBack(&(game.snake));
		}

		if (IsCrashByWall(game.width, game.height, nextPos)) {
			break;
		}

		if (IsCrashHimself(&(game.snake))) {
			break;
		}

		Sleep(game.speed);
	}
}

model.h

#pragma once

// 坐标原点位于左上角,
// 向右为 x 轴的正方向,
// 向下为 y 轴的正方向,
typedef struct Position {
	int	x;
	int y;
}	Position;

// 链表结点(单向)
typedef struct Node {
	Position	data;
	struct Node *pNext;
}	Node;


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

// 蛇的结构
typedef struct Snake {
	Direction direction;
	Node *pHead;
}	Snake;

// 一盘游戏中用到的其他非独立字段
typedef struct Game {
	Snake		snake;
	Position	foodPosition;

	int	score;	// 当前得分
	int scorePerFood;	// 每吃一个食物得分
	int speed;	//	蛇的前进速度
	int width;	// 宽
	int height;	// 高
}	Game;

main.c

int main()
{
	printf("欢迎\n");
	system("pause");
	system("cls");

	printf("欢迎\n");
	system("pause");
	system("cls");

	printf("热烈欢迎\n");
	system("pause");
	system("cls");
	GameStart();

	return 0;
}

猜你喜欢

转载自blog.csdn.net/ZY_20181010/article/details/82467000