控制台贪吃蛇

/*
*Name:Greedy Snake
*Date:2015/8/15
*Author:YangShuoliu
*/
#include <queue>		//deque<int>
#include <stdio.h>	// printf()
#include <conio.h>
#include <ctime>		//srand() rand()
#include <Windows.h>	//Sleep(),SetConsoleCursorPosition(),GetStdHandle()
/方向码
#define SNK_UP			0
#define SNK_DOWN			1
#define SNK_LEFT			2
#define SNK_RIGHT			3

#define CTL_ESC			4
#define CTL_PAUSE			5
#define GAME_OVER			6
/屏幕大小
#define SCREEN_X			70
#define SCREEN_Y			30
屏幕单位类型
#define SCREEN_FOOD		2	//食物
#define SCREEN_NONE		0	//空
#define SCREEN_BARRIER		1	//障碍
#define SCREEN_SNK		3	//蛇身体
using namespace std;		//导入命名空间
struct Point
{
	Point(){}
	Point(int _x, int _y) :x(_x), y(_y){}
	int x;
	int y;
};

char Screen[SCREEN_Y][SCREEN_X];	/*屏幕矩阵*/
COORD curPos;						/*光标位置*/
int scores = 0;
typedef char ScreenType;
typedef char Direction;
typedef char ExitType;
typedef deque<Point> SNAKE;
void DrawPoint(HANDLE hInstance, int x, int y, ScreenType st)
{
	curPos.X = x;
	curPos.Y = y;
	DWORD rNum;
	SetConsoleCursorPosition(hInstance, curPos);
	switch (st)
	{
	case SCREEN_SNK:
		printf("O");
		break;
	case SCREEN_BARRIER:
		printf("*");
		//WriteConsoleOutputCharacter(hInstance, TEXT("*"), 1, curPos, &rNum);
		break;
	case SCREEN_FOOD:
		printf("#");
		//WriteConsoleOutputCharacter(hInstance, TEXT("@"), 1, curPos, &rNum);
		break;
	case SCREEN_NONE:
		printf(" ");
		//WriteConsoleOutputCharacter(hInstance, TEXT(" "), 1, curPos, &rNum);
		break;
	default:
		break;
	}
}
//	绘制整个屏幕性能不好,不用这个函数,只在初始化的时候用一下
void DrawScreen()
{
	for (int i = 0; i < SCREEN_Y; i++)
	{
		for (int j = 0; j < SCREEN_X; j++)
		{
			if (Screen[i][j] == SCREEN_BARRIER)
				printf("*");
			else if (Screen[i][j] == SCREEN_FOOD)
				printf("@");
			else
				printf(" ");
		}
		printf("\n");
	}
}
//
void MakeFood(HANDLE hInstance,const SNAKE & snake)		//随机产生食物
{
	/**/
	int crood_x;
	int crood_y;
	bool same = true;
	while (same)
	{
		/*same = false;*/
		crood_x = rand() % (SCREEN_X - 1) + 1;
		crood_y = rand() % (SCREEN_Y - 1) + 1;
		if (Screen[crood_y][crood_x] == SCREEN_NONE)
			same = false;
		if (same == true)
		{
			crood_x = rand() % (SCREEN_X - 1) + 1;
			crood_y = rand() % (SCREEN_Y - 1) + 1;
			same = false;
		}
	}
	Screen[crood_y][crood_x] = SCREEN_FOOD;
	DrawPoint(hInstance, crood_x, crood_y, SCREEN_FOOD);
}
/******************************/
void UpdateScores(HANDLE hInstance)
{
	curPos.X = 5;
	curPos.Y = 0;
	SetConsoleCursorPosition(hInstance, curPos);
	DWORD rNum;
	WriteConsoleOutputCharacter(hInstance, TEXT("SCORES="), 7, curPos, &rNum);
	curPos.X = 12;
	curPos.Y = 0;
	SetConsoleCursorPosition(hInstance, curPos);
	printf("%d", scores);
}
/******************************/
void init(HANDLE hInstance,SNAKE & snake)
{
	/*初始化墙壁*/
	for (int i = 0; i < SCREEN_Y; i++)
	{
		for (int j = 0; j < SCREEN_X; j++)
		{
			if (i == 0 || i == SCREEN_Y - 1 || j == 0 || j == SCREEN_X - 1)
				Screen[i][j] = SCREEN_BARRIER;
			else
				Screen[i][j] = SCREEN_NONE;
		}
	}

	srand((unsigned)time(NULL));		//随机数种子
	int crood_x;
	int crood_y;
	crood_x = rand() % (SCREEN_X - 1) + 1;//产生蛇头随机位置
	crood_y = rand() % (SCREEN_Y - 1) + 1;
	snake.push_front(Point(crood_x, crood_y));
	Screen[crood_y][crood_x] = SCREEN_SNK;
	//产生异于蛇身体的食物的位置
	DrawScreen();
	UpdateScores(hInstance);
	MakeFood(hInstance,snake);
}
/*
*根据当前头部位置,和上一次的方向以及将要行进的方向,给出下一次的方向,并且返回蛇的上一个状态的方向码
*/
Direction NextPoint(Point * LastPoint, Direction LastDirection, Direction NextDirection)
{
	switch (NextDirection)
	{
	case SNK_UP:
		if (SNK_LEFT == LastDirection || SNK_RIGHT == LastDirection)
		{
			LastPoint->y--;
			return NextDirection;
		}
		else if (SNK_UP == LastDirection)
			LastPoint->y--;
		else
			LastPoint->y++;
		return LastDirection;
		break;
	case SNK_DOWN:
		if (SNK_LEFT == LastDirection || SNK_RIGHT == LastDirection)
		{
			LastPoint->y++;
			return NextDirection;
		}
		else if (SNK_UP == LastDirection)
			LastPoint->y--;
		else
			LastPoint->y++;
		break;
	case SNK_LEFT:
		if (SNK_UP == LastDirection || SNK_DOWN == LastDirection)
		{
			LastPoint->x--;
			return NextDirection;
		}
		else if (SNK_LEFT == LastDirection)
			LastPoint->x--;
		else
			LastPoint->x++;
		break;
	case SNK_RIGHT:
		if (SNK_UP == LastDirection || SNK_DOWN == LastDirection)
		{
			LastPoint->x++;
			return NextDirection;
		}
		else if (SNK_RIGHT == LastDirection)
			LastPoint->x++;
		else
			LastPoint->x--;
		break;
	default:
		break;
	}
	return LastDirection;
}
/*
*
*根据蛇身的位置坐标,更新屏幕矩阵,没用过
***/
inline void UpdateScreen(const SNAKE & snake)
{
	for (SNAKE::const_iterator itr = snake.begin(); itr != snake.end(); ++itr)
		Screen[(*itr).y][(*itr).x] = SCREEN_SNK;
}
/*
*根据单个元素的类型,更新屏幕矩阵
*/
inline void UpdateScreen(const Point * point, ScreenType st)
{
	Screen[point->y][point->x] = st;
}
/*
*判断蛇头是不是会碰撞
**/
inline bool Collision(Point * snakeHead)
{
	if (Screen[snakeHead->y][snakeHead->x] == SCREEN_BARRIER || Screen[snakeHead->y][snakeHead->x] == SCREEN_SNK)
		return true;
	return false;
}
/*
*从键盘获得方向按键
**/
inline char GetDirection(Direction lastDireciton)
{
	if (GetAsyncKeyState(VK_UP))
		return SNK_UP;
	if (GetAsyncKeyState(VK_LEFT))
		return SNK_LEFT;
	if (GetAsyncKeyState(VK_RIGHT))
		return SNK_RIGHT;
	if (GetAsyncKeyState(VK_DOWN))
		return SNK_DOWN;
	if (GetAsyncKeyState(VK_ESCAPE))
		return CTL_ESC;
	if (GetAsyncKeyState(VK_SPACE))
		return CTL_PAUSE;
	return lastDireciton;
}
/*
*返回类型:
*GAME_OVER=游戏结束
*CTL_ESC=返回主菜单
*/
ExitType Game(HANDLE hInstance,SNAKE & snake,Direction initialDirection,int bodySize,DWORD level)
{
	Direction lastDirection = initialDirection;		//初始方向
	Direction nextDirection;
	Point snakeHead, snakeTail;
	while (1)
	{
		nextDirection = GetDirection(lastDirection);
		if (nextDirection == CTL_ESC)
			return CTL_ESC;
		//else if (nextDirection == CTL_PAUSE)		//暂停
			//_getch();							//按任意键开始
		snakeHead = snake.front();					//取出蛇头位置
		lastDirection = NextPoint(&snakeHead, lastDirection, nextDirection);
		if (Screen[snakeHead.y][snakeHead.x] == SCREEN_FOOD)
		{
			snake.push_front(Point(snakeHead.x, snakeHead.y));
			UpdateScreen(&Point(snakeHead.x, snakeHead.y), SCREEN_SNK);
			DrawPoint(hInstance,snakeHead.x,snakeHead.y,SCREEN_SNK);
			MakeFood(hInstance,snake);
			scores++;
			UpdateScores(hInstance);
		}
		else
		{
			snakeTail = snake.back();
			UpdateScreen(&Point(snakeTail.x, snakeTail.y), SCREEN_NONE);
			if (Collision(&snakeHead))//碰撞则游戏结束
				return GAME_OVER;
			snake.pop_back();
			DrawPoint(hInstance, snakeTail.x, snakeTail.y, SCREEN_NONE);//清楚尾部的点
			snake.push_front(Point(snakeHead.x, snakeHead.y));		//添加新位置的蛇头
			UpdateScreen(&Point(snakeHead.x, snakeHead.y), SCREEN_SNK);
			DrawPoint(hInstance, snakeHead.x, snakeHead.y, SCREEN_SNK);
		}
		Sleep(level);
	}
}
int main()
{
	HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);		//获取控制台句柄
	SetConsoleDisplayMode(hStdOut, 1, NULL);	//全屏显示
	CONSOLE_CURSOR_INFO curInfo;				//光标信息
	GetConsoleCursorInfo(hStdOut, &curInfo);
	curInfo.bVisible = FALSE;
	SetConsoleCursorInfo(hStdOut, &curInfo);	//光标不可见
	SNAKE snake;				//贪吃蛇身体双端队列
	init(hStdOut,snake);		//初始化屏幕矩阵,食物和蛇身的位置
	Game(hStdOut,snake,SNK_DOWN,1,1000);		//开始游戏
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值