贪吃蛇

// ChangePartitionNumber.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <stdio.h>
#include <tchar.h>
#include<stdlib.h>		//即standard library标志库头文件,里面定义了一些宏和通用工具函数
#include<conio.h>		//接收键盘输入输出
#include<time.h>			//用于获得随机数
#include <afxwin.h>		//MFC
#include <windows.h>
#include <Locale.h>


POINT meat;//蛇爱吃的肉
wchar_t *str = _T("头学习计算机技术\0");

int nextChar = 1;

int width = 66;
int height = 38;

POINT preHead;

enum DIRECTION{
	UP,
	DOWN,
	LEFT,
	RIGHT
};

typedef struct Snake{
	wchar_t ch;
	DIRECTION dir;
	POINT point;
	Snake * next;
}S;

void drawWall();
void printfSnake(S s);
void followHead(S * s);
BOOL isDoublication(S s);


void gotoxy(POINT head)
{
	COORD c;
	c.X = head.x;
	c.Y = head.y;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
}

void ControlCursorPosition()
{
	drawWall();

	int second;

	second = GetTickCount();
	meat.x = second % width;
	meat.y = second % height;

	//判断奇偶数,因为奇数坐标,蛇吃不到实物
	if (meat.x & 1)
	{
		meat.x++;
	}
	if (meat.y & 1)
	{
		meat.y++;
	}

	S s;//🐍头

	s.point.x = 30;
	s.point.y = 30;
	s.ch = str[0];
	s.dir = UP;
	s.next = NULL;

	S ** tail = (S**)malloc(sizeof(S));
	tail = &(s.next);//空的
	S *tailBody = &s;//保存末尾的身体



	gotoxy(s.point);
	wprintf(L"%c", s.ch);
	preHead = s.point;



	gotoxy(meat);
	wprintf(L"%c", str[nextChar]);

	while (true)
	{

		//产生移动了
		if (preHead.x != s.point.x || preHead.y != s.point.y)
		{



			//吃到食物
			if (s.point.x == meat.x && s.point.y == meat.y)
			{
				//找到最后一个NULL指针
				while (*tail != NULL)
				{
					tailBody = *tail;
					tail = &((*tail)->next);
				}

				*tail = (S*)malloc(sizeof(S));//为最后一个空指针分配内存,准备添加吃到的食物


				(*tail)->ch = str[nextChar];
				//添加到尾部的身体,要添加到前一个的后面,根据最后一个身体的坐标,方向
				if ((*tailBody).dir == UP)
				{
					(*tail)->point.y = (*tailBody).point.y + 1;
					(*tail)->point.x = (*tailBody).point.x;
					(*tail)->dir = (*tailBody).dir;
				}
				else if ((*tailBody).dir == DOWN)
				{
					(*tail)->point.y = (*tailBody).point.y - 1;
					(*tail)->point.x = (*tailBody).point.x;
					(*tail)->dir = (*tailBody).dir;
				}
				else if ((*tailBody).dir == LEFT)
				{
					(*tail)->point.y = (*tailBody).point.y;
					(*tail)->point.x = (*tailBody).point.x + 2;
					(*tail)->dir = (*tailBody).dir;
				}
				else if ((*tailBody).dir == RIGHT)
				{
					(*tail)->point.y = (*tailBody).point.y;
					(*tail)->point.x = (*tailBody).point.x - 2;
					(*tail)->dir = (*tailBody).dir;
				}

				(*tail)->next = NULL;

				nextChar++;
				if (nextChar == (wcslen(str)))
				{
					nextChar = 0;
				}
			}

			system("cls");

			drawWall();
			//画蛇
			printfSnake(s);

			//逆序跟随蛇头
			followHead(&s);//这一行如果放在画蛇前面会吞掉一个字

			//画食物
			gotoxy(meat);
			wprintf(L"%c", str[nextChar]);

			preHead = s.point;

		}

		Sleep(10);

		//printf("a");
		DIRECTION preDir = s.dir;
		if (GetAsyncKeyState(VK_UP) & 0x8000 && s.dir != DOWN){
			s.point.y--;//这里只是蛇头动了,所以食物不能跟随蛇头
			s.dir = UP;

			if (isDoublication(s))
			{
				s.point.y++;
				s.dir = preDir;
			}
		}
		else if (GetAsyncKeyState(VK_DOWN) & 0x8000 && s.dir != UP){
			s.point.y++;
			s.dir = DOWN;

			if (isDoublication(s))
			{
				s.point.y--;
				s.dir = preDir;
			}
		}
		else if (GetAsyncKeyState(VK_LEFT) & 0x8000 && s.dir != RIGHT){
			s.point.x -= 2;
			s.dir = LEFT;
			if (isDoublication(s))
			{
				s.point.x += 2;
				s.dir = preDir;
			}
		}
		else if (GetAsyncKeyState(VK_RIGHT) & 0x8000 && s.dir != LEFT){
			s.point.x += 2;
			s.dir = RIGHT;
			if (isDoublication(s))
			{
				s.point.x -= 2;
				s.dir = preDir;
			}
		}

	}
}


//撞到自己
BOOL isDoublication(S s){
	POINT headPoint = s.point;
	S * next = s.next;
	while (next != NULL)
	{
		if (headPoint.x == next->point.x && headPoint.y == next->point.y)
		{
			return TRUE;
		}
		next = next->next;
	}
	return FALSE;
}





//跟随蛇头, 把所有的节点向前移动
//递归逆序遍历链表
void followHead(S * s)
{
	S * next = s->next;
	S first = *s;

	if (next != NULL)
	{
		followHead(next);
	}
	else
	{
		return;
	}
	next->point = first.point;
	next->dir = first.dir;

}



void printfSnake(S s){
	gotoxy(s.point);
	wprintf(L"%c", s.ch);
	S * next = s.next;
	while (next != NULL)
	{
		gotoxy((*next).point);
		wprintf(L"%c", (*next).ch);

		next = next->next;
	}
}




void drawWall(){
	COORD c;

	for (int i = 0; i < width; i += 2){
		c.X = i;
		c.Y = 0;
		SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
		printf("■");
	}

	for (int i = 0; i < width; i += 2){
		c.Y = height;
		c.X = i;
		SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
		printf("■");
	}

	for (int i = 0; i < height + 1; i++){
		c.Y = i;
		c.X = 0;
		SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
		printf("■");
	}

	for (int i = 0; i < height + 1; i++){
		c.Y = i;
		c.X = width;
		SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
		printf("■");
	}
}




int _tmain(int argc, _TCHAR* argv[])
{
	//隐藏光标
	HANDLE fd = GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_CURSOR_INFO cinfo;
	cinfo.bVisible = 0;
	cinfo.dwSize = 1;
	SetConsoleCursorInfo(fd, &cinfo);

	//设置区域
	_wsetlocale(LC_ALL, L"chs");

	ControlCursorPosition();

	getchar();

	return 0;
}

  //内存没有释放

posted @ 2019-03-07 23:34  巫居树  阅读(239)  评论(0编辑  收藏  举报