/*
* 原理很简单,只要懂队列跟_kbhit() 这个函数
* 用队列保存蛇身,_kbhit()相应键盘,printf绘图
* 剩下的就是完善一下逻辑就行
* 注意上下左右键是双键值,getch() 要连续读取两次
* Sleep() 控制速度
*/
#include <bits/stdc++.h>
#include <conio.h>
#include <windows.h>
using namespace std;
int const x_max = 25;
int const y_max = 70;
int const snake_speed = 200;
const char FOODchar = '+';
const char SNAKEchar = '*';
const char MAZEchar = '*';
const int SNAKEleight = 3;
const int start_x = 5;
const int start_y = 5;
COORD ST_CD;
/// w s a d;
const int d = 4;
const int s = 2;
const int w = 1;
const int a = 3;
int Maze[x_max+10][y_max+10]= {0};
queue <COORD> CD;
int score = 0;
void gotoXY(int a,int b);
void HideConsole();
void clearXY(COORD cd);
void printXY(COORD cd);
void flagXY(const COORD &cd);
int RandomNumble(int a,int b);
void makeFood();
void printMaze();
void STARTmaze(int len = SNAKEleight);
int getdec();
void Next_cd(int dec,COORD & cd);
void SNAKE_step(const COORD & now_cd,queue<COORD> & CD,int & isNothavefood);
void SNAKE_move();
void PrintFail();
int contrary_dec(int const &dec);
void printScore();
int main(){
srand((int)time(NULL));
ST_CD.X = start_y;
ST_CD.Y = start_x;
HideConsole();
printMaze();
STARTmaze();
SNAKE_move();
PrintFail();
return 0;
}
void SNAKE_step(const COORD &now_cd,queue<COORD>&CD,bool &isNothavefood){
COORD clear_cd;
printXY(now_cd);
if ( Maze[now_cd.Y][now_cd.X] == 2){
score ++;
printScore();
Maze[now_cd.Y][now_cd.X] = 1;
CD.push(now_cd);
isNothavefood = 1;
}else {
Maze[now_cd.Y][now_cd.X] = 1;
CD.push(now_cd);
clear_cd = CD.front();
CD.pop();
Maze[clear_cd.Y][clear_cd.X] = 0;
clearXY(clear_cd);
}
}
void SNAKE_move(){
int now_dec = d;
COORD now_cd = ST_CD ;
bool isNothavefood = 1;
while (1){
if (isNothavefood){
makeFood();
isNothavefood = 0;
}
while( _kbhit() ){
int cpy_dec = now_dec;
cpy_dec = getdec();
if ( cpy_dec == contrary_dec(now_dec) ) continue;
now_dec = cpy_dec;
Next_cd(now_dec,now_cd);
if ( Maze[now_cd.Y][now_cd.X] == 1 ) break;
SNAKE_step(now_cd,CD,isNothavefood);
Sleep(70);
}
Sleep(snake_speed);
Next_cd(now_dec,now_cd);
if ( Maze[now_cd.Y][now_cd.X] == 1 ) break;
SNAKE_step(now_cd,CD,isNothavefood);
}
}
void Next_cd(int dec,COORD & cd){
switch(dec){
case a: cd.X--;return;
case s: cd.Y++;return;
case w: cd.Y--;return;
case d: cd.X++;return;
}
}
int getdec(){
int b;
b = getch();
while(b == 'p') b = getch();
b = getch();
switch (b){
case 72:return w;
case 80:return s;
case 75:return a;
case 77:return d;
}
return 0;
}
void STARTmaze(int len){
printXY(ST_CD);
flagXY(ST_CD);
CD.push(ST_CD);
len--;
while(len--){
ST_CD.X++;
CD.push(ST_CD);
printXY(ST_CD);
flagXY(ST_CD);
}
}
void HideConsole(){
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO cci;
GetConsoleCursorInfo(hOut,&cci);
cci.bVisible = false;
SetConsoleCursorInfo(hOut,&cci);
}
void gotoXY( int a,int b){
COORD cd;
cd.X = a;
cd.Y = b;
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hOut , cd);
}
void clearXY(COORD cd){
gotoXY(cd.X,cd.Y);
printf(" ");
}
void printXY(COORD cd){
gotoXY(cd.X,cd.Y);
printf("%c",SNAKEchar);
}
void printMaze(){
for (int i = 0;i <= x_max; ++i){
for (int j = 0;j <= y_max; ++j){
if (i == 0 || i == x_max || j == 0 || j == y_max ){
Maze[i][j] = 1;
printf("%c",MAZEchar);
}else printf(" ");
}
printf("\n");
}
gotoXY(2,x_max + 2);
printf("your score is : %d\n\n",score);
printf(" please press p to pause");
}
void printScore(){
gotoXY(17,x_max + 2);
printf("%d",score);
}
int RandomNumble(int a,int b){
return ( rand() % (b-a+1) )+a;
}
void flagXY(const COORD &cd){
Maze[cd.Y][cd.X] = 1;
}
void makeFood(){
int y = RandomNumble(1,y_max-1);
int x = RandomNumble(1,x_max-1);
while( Maze[x][y] ){
y = RandomNumble(1,y_max-1);
x = RandomNumble(1,x_max-1);
}
Maze[x][y] = 2;
gotoXY(y,x);
printf("%c",FOODchar);
}
void PrintFail(){
gotoXY(20,10);
printf("you are failed!");
gotoXY(0,x_max+1);
}
int contrary_dec(int const &dec){
switch(dec){
case 1:return 2;
case 2:return 1;
case 3:return 4;
case 4:return 3;
}
printf("please call LQM");
exit(1);
return 0;
}