#include <iostream>
#include <conio.h>
#include <ctime>
#include <windows.h>
using namespace std;
const int ROW = 20;
const int line = 35;
class snake;
class Node
{
private:
	Node() :x(0), y(0), llink(NULL), next(NULL){}
	Node *llink, *next;
	int x, y;
	friend class snake;
};
class snake
{
public:
	snake();
	~snake();
	void move();
	void chioce_key(char);
	void output();
private:
	Node *head, *tail;
	int game[ROW][line];
	enum { UP, DOWN, RIGHT, LEFT }point;
	int food_x, food_y;
	void get_food();
	void gotoxy(int, int);
	void add_head(int, int);
	void delete_tail();
};
snake::snake() :food_x(0), food_y(0), head(NULL), tail(NULL), point(RIGHT)
{
	int i, j;
	for (i = 0; i<ROW; ++i)
	{
		for (j = 0; j<line; ++j)
		{
			game[i][0] = game[i][line - 1] = 1;
			game[0][j] = game[ROW - 1][j] = 1;
		}
	}
	head = tail;
	add_head(6, 4);
	add_head(6, 5);
	add_head(6, 6);
	get_food();
}
snake::~snake()
{
	while (head)
	{
		Node *temp = head;
		head = head->next;
		delete temp;
	}
}
void snake::add_head(int a, int b)
{
	Node *temp = new Node;
	temp->x = a;
	temp->y = b;
	if (head == NULL)
	{
		head = tail = temp;
	}
	else
	{
		head->llink = temp;
		temp->next = head;
		head = head->llink;
	}
	game[a][b] = 1;
}
void snake::delete_tail()
{
	Node *temp = tail;
	game[tail->x][tail->y] = 0;
	tail = tail->llink;
	tail->next = NULL;
	delete temp;
}
void snake::chioce_key(char key)
{
	switch (key)
	{
	case 'w':
	case 'W':point = UP; break;
	case 'a':
	case 'A':point = LEFT; break;
	case 'd':
	case 'D':point = RIGHT; break;
	case 's':
	case 'S':point = DOWN; break;
	}
}
void snake::output()
{
	int i, j;
	gotoxy(0, 0);
	for (i = 0; i<ROW; ++i)
	{
		for (j = 0; j<line; ++j)
		{
			if (game[i][j] == 1)
			{
				cout << "* ";
			}
			else
			{
				cout << "  ";
			}
		}
		cout << endl;
	}
}
void snake::get_food()
{
	srand(unsigned(time(NULL)));
	do
	{
		food_x = rand() % 18 + 1;
		food_y = rand() % 18 + 1;
	} while (game[food_x][food_y] == 1);
	game[food_x][food_y] = 1;
}
void snake::move()
{
	int a = head->x;
	int b = head->y;
	switch (point)
	{
	case UP:--a; break;
	case DOWN:++a; break;
	case LEFT:--b; break;
	case RIGHT:++b; break;
	}
	if (game[a][b] == 1 && food_x != a&&food_y != b)
	{
		output();
		cout << "失败了" << endl;
		this->~snake();
		exit(0);
	}
	if (food_x == a&&food_y == b)
	{
		add_head(a, b);
		get_food();
		return;
	}
	add_head(a, b);
	delete_tail();
}
void snake::gotoxy(int x, int y)
{
	HANDLE hOutput;
	COORD loc;
	loc.X = x;
	loc.Y = y;
	hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleCursorPosition(hOutput, loc);
}
int main()
{
	snake s;
	s.output();
	cout << "操作方法:W ↑ S ↓ A ← D →\n";
	while (true)
	{
		char keydown = _getch();
		s.chioce_key(keydown);
		while (!_kbhit())
		{
			s.move();
			s.output();
			Sleep(100);
		}
	}
	return 0;
}