// 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;
}
//内存没有释放
原文:https://www.cnblogs.com/wangxingzhou/p/10493369.html