#include <stdio.h>
#include <time.h>
#include <windows.h>
#include <stdlib.h>
#include <conio.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
///////////////////////////////////////////////////////////////////////
#define printBeginUIPos 40
#define printPoolUIPos 75
//////////////////////////////////////////////////////////////////////
typedef struct SNAKE //定义蛇的结构
{
POINT snakeHeadPos; //蛇头坐标
int Len; //蛇身长度
char direction; //当前行动方向
int score; //游戏得分
struct SNAKE *next; //指向下一个节点的指针
}Snake;
typedef struct FOOD //定义食物的坐标
{
int x;
int y;
}food;
food *Food;
int gameStatus = 1; //定义当前游戏状态
//1、正常游戏;2、退出游戏;3、暂停游戏;4、撞到墙壁;5、吃到自己
HWND g_hConsoleOutPut; //控制台句柄
Snake *head,*p;
HANDLE hThread;
DWORD ThreadID;
//HHOOK glhHook = NULL;
//HINSTANCE glhInstance;
/////////////////////////////------函数声明-------//////////////////////////////////
void initBeginUI(); //初始化开始界面
void printGamePool(); //打印游戏池
void gotoxy(short x, short y); //鼠标移动到 x,y
void initGame(); //初始化游戏
void createFood(); //产生食物
int playGame();
void decideDirection(key); //由按键字母得到方向
void moveSnake();
void endGame();
void CALLBACK TimeProc(HWND,UINT,UINT,DWORD); //时间类的回调函数
//void CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
void threadMoveSnake(); //线程--蛇移动
/////////////////////////////----Main----////////////////////////
int main()
{
initBeginUI();
initGame();
playGame();
system("pause > nul");
system("cls");
return 0;
}
///////////////////////////////////////////////////////////////////////
void initBeginUI() //初始化开始界面
{
g_hConsoleOutPut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO cursorInfo = { 1, false };
SetConsoleCursorInfo(g_hConsoleOutPut,&cursorInfo);
SetConsoleTitleA("Snake---By fpx");
system("mode con cols=100 lines=30");
SetConsoleTextAttribute(g_hConsoleOutPut, 0x0F); //API设置控制台窗口字体颜色和背景色的函数
gotoxy(printBeginUIPos, 5);
printf("┏━━━━━━━┓");
gotoxy(printBeginUIPos, 6);
printf("┃ %2s%s%2s ┃", "", "-贪吃蛇-", "");
gotoxy(printBeginUIPos, 7);
printf("┗━━━━━━━┛");
gotoxy(printBeginUIPos, 10);
printf(" Made By fpx");
gotoxy(printBeginUIPos-2, 12);
printf("Press any key to continue...");
while (1)
{
if (_kbhit())
{
break;
}
}
//fflush(stdin); //清除标准输入设备(即键盘)的缓冲区。
_getch();
system("cls");
printGamePool();
}
void printGamePool() //打印游戏池
{
int i;
for (i = 0; i < 70; i += 2)
{
gotoxy(i, 0);
printf("■");
gotoxy(i, 29);
printf("■");
}
for (i = 0; i < 30; i++)
{
gotoxy(0, i);
printf("■");
gotoxy(70, i);
printf("■");
}
SetConsoleTextAttribute(g_hConsoleOutPut, 0xB);
gotoxy(printPoolUIPos, 8);
printf("□向左移动:← A");
gotoxy(printPoolUIPos, 10);
printf("□向右移动:→ D");
gotoxy(printPoolUIPos, 12);
printf("□向下移动:↓ S");
gotoxy(printPoolUIPos, 14);
printf("□向下移动:↑ W");
gotoxy(printPoolUIPos, 16);
printf("□Score : 0");
gotoxy(printPoolUIPos, 18);
printf("■By: fpx 15.11.18");
}
void gotoxy(short x, short y)
{
COORD pos = { x, y };
SetConsoleCursorPosition(g_hConsoleOutPut, pos);
}
///////////////////////////////////////////////////////////////////////
void initGame() //初始化游戏
{
int i;
Snake *tail;
tail = (Snake *)malloc(sizeof(Snake)); //定义蛇尾
tail->next = NULL;
tail->snakeHeadPos.x = 20;
tail->snakeHeadPos.y = 5;
for (i = 0; i < 2; i++)
{
head = (Snake *)malloc(sizeof(Snake));
head->next = tail;
head->snakeHeadPos.x = 20 + 2 * (i+1); head->snakeHeadPos.y = 5;
tail = head;
}
head = tail;
head->direction = 'D';
head->Len = 3;
head->score = 0;
while (tail != NULL)
{
gotoxy(tail->snakeHeadPos.x, tail->snakeHeadPos.y);
printf("■");
tail = tail->next;
}
createFood();
}
void createFood() //产生食物
{
food *food_1;
srand((unsigned)time(NULL));
food_1 = (food *)malloc(sizeof(food));
while ((food_1->x % 2) != 0 || food_1->x < 2) //保证食物的横坐标为2的偶数
{
food_1->x = rand() % 67 + 2;
}
food_1->y = rand() % 28 + 1;
p = head;
while (p->next != NULL)
{
if (food_1->x == p->snakeHeadPos.x && food_1->y == p->snakeHeadPos.y)
{
createFood();
return 0;
}
p = p->next;
}
Food = food_1;
gotoxy(food_1->x, food_1->y);
printf("☆");
}
//////////////////////////////////////////////////////////////////////
int playGame()
{
char direction,key;
//clock_t clockNow, clockLast;
//clockLast = clock();
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadMoveSnake, NULL, 0, &ThreadID);
while (1)
{
key = _getch();
if (key == 27)
{
gameStatus = 2;
}
if (gameStatus > 2)
{
return 0;
}
decideDirection(key);
Sleep(150);
}
}
void decideDirection(key) //由按键字母得到方向
{
char returnValue;
switch (key)
{
case 'W':
case 'w':
case 72:
if (head->direction != 'S')
{
head->direction = 'W';
}
break;
case 'S':
case 's':
case 80:
if (head->direction != 'W')
{
head->direction = 'S';
}
break;
case 'A':
case 'a':
case 75:
if (head->direction != 'D')
{
head->direction = 'A';
}
break;
case 'D':
case 'd':
case 77:
if (head->direction != 'A')
{
head->direction = 'D';
}
break;
default:
head->direction = head->direction;
break;
}
}
void moveSnake()
{
//1、判断是否撞墙
//2、由方向确定坐标的变化
//3、判断下一个是否为食物,若是,则加长;否则移动蛇身
//4、判断是否吃到自己
int x, y;
if (head->snakeHeadPos.x < 2 || head->snakeHeadPos.x > 68 || head->snakeHeadPos.y < 1 || head->snakeHeadPos.y > 29)
{
gameStatus = 4;
endGame();
}
x = head->snakeHeadPos.x;
y = head->snakeHeadPos.y;
Snake *nextsnake,*q;
nextsnake = (Snake *)malloc(sizeof(Snake));
q = (Snake *)malloc(sizeof(Snake));
//ZeroMemory(&p,sizeof(p)); //清空结构体
switch (head->direction)
{
case 'W':y--; break;
case 'S':y++; break;
case 'A':x -= 2; break;
case 'D':x += 2; break;
}
nextsnake->snakeHeadPos.x = x; //对新节点赋值
nextsnake->snakeHeadPos.y = y;
nextsnake->Len = head->Len;
nextsnake->direction = head->direction;
nextsnake->score = head->score;
nextsnake->next = head;
if (nextsnake->snakeHeadPos.x == Food->x && nextsnake->snakeHeadPos.y == Food->y)
{
head = nextsnake;
p = head;
while (p != NULL)
{
gotoxy(p->snakeHeadPos.x, p->snakeHeadPos.y);
printf("■");
p = p->next;
}
head->Len += 1;
head->score += 10;
gotoxy(printPoolUIPos, 16);
printf("□Score : %d",head->score);
createFood();
}
else
{
head = nextsnake;
p = head;
while (p->next->next != NULL)
{
gotoxy(p->snakeHeadPos.x, p->snakeHeadPos.y);
printf("■");
p = p->next;
}
gotoxy(p->next->snakeHeadPos.x, p->next->snakeHeadPos.y);
printf(" ");
p->next = NULL;
}
q = head->next;
while (q)
{
if (head->snakeHeadPos.x == q->snakeHeadPos.x && head->snakeHeadPos.y == q->snakeHeadPos.y)
{
gameStatus = 5;
endGame();
}
q = q->next;
}
}
void CALLBACK TimeProc(HWND hwnd, UINT message, UINT idTimer, DWORD dwTime)
{
moveSnake();
}
//void CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
//{
// switch (wParam)
// {
// case VK_UP:
// case 'W':
// case 'w':
// case 72:
// if (head->direction != 'S')
// {
// head->direction = 'W';
// }
// break;
// case VK_DOWN:
// case 'S':
// case 's':
// case 80:
// if (head->direction != 'W')
// {
// head->direction = 'S';
// }
// break;
// case VK_LEFT:
// case 'A':
// case 'a':
// case 75:
// if (head->direction != 'D')
// {
// head->direction = 'A';
// }
// break;
// case VK_RIGHT:
// case 'D':
// case 'd':
// case 77:
// if (head->direction != 'A')
// {
// head->direction = 'D';
// }
// break;
// //default:
// // head->direction = head->direction;
// //break;
// }
//}
void threadMoveSnake() //线程中移动蛇身
{
SetTimer(NULL, 1, 300, TimeProc);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
if (msg.message == WM_TIMER)
{
DispatchMessage(&msg);
}
//if (msg.message == WM_KEYDOWN)
//{
// TranslateMessage(&msg);
// DispatchMessage(&msg);
//}
}
}
////////////////////////////////////////////////////////////////////////////
void endGame()
{
/*TerminateThread(hThread, 0);*/
KillTimer(g_hConsoleOutPut,1);
system("cls");
gotoxy(40, 12);
switch (gameStatus)
{
case 2:
printf("您的已经结束了游戏。"); break;
case 4:
printf("您撞到墙了。游戏结束."); break;
case 5:
printf("您咬到自己了。游戏结束."); break;
}
gotoxy(40, 15);
printf("您的得分是 %d\n", head->score);
//ExitThread(0);
system("pause > nul");
/*system("cls");*/
exit(0);
}