#include <cstdio>
#include <conio.h>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <windows.h>
#include <algorithm>
#define REP(i,a,b) for (int i=(a);i<=(b);i++)
#define PER(i,a,b) for (int i=(a);i>=(b);i--)
#define max(x,y) ((x)<(y)?(y):(x))
#define min(y,x) ((x)<(y)?(x):(y))
#define MEM(a,b) memset(a,(b),sizeof(a))
#define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0)//判断这个键是否按下
#define KEY_UP(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 0 : 1)//判断这个键是否弹起
#define KEY_EVERY(lpkeyState) GetKeyboardState(lpKeyState)//获得所有的256个键(键盘按键、鼠标按键等等)的状态,lpKeyState是指向一个256bit的数组,存放所有键的状态。
#define KEY_NOW(nVirtKey) GetKeyState(nVirtKey)//用于判断nVirtKey的状态。用返回值的最高位表示,最高位为1表示当前键处于down的状态;最高位为0当前键处于up状态。此函数从消息队列中读取消息进行处理。
#define setcolor(x) SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),x)//设置颜色
#define getkey(x) GetAsyncKeyState(x)
#define GetWindow() GetForegroundWindow();//得到窗口信息
/*
鼠标左键 : MOUSE_MOVED
鼠标右键 :MOUSE_EVENT
鼠标滚轮 : MOUSE_WHEELED
MK_CONTROL当CTRL键按下时。
MK_LBUTTON当鼠标左键按下时。
MK_MBUTTON当鼠标中键按下时。
MK_RBUTTON当鼠标右键按下时.
MK_SHIFT当SHIFT按下时。
*/
using std::cin;
using std::cout;
using std::endl;
int brand();
void GOTO(int x,int y);
int brand(){return (rand()<<16)|(rand()<<1)|(rand()&1);}
void bsrand(){srand(GetTickCount());}
void cls(){system("cls");}
void retr(){//退出程序
HWND hWnd=GetForegroundWindow();
ShowWindow(hWnd,SW_HIDE);
exit(0);
}
void Window_Hide(HWND hWnd){ShowWindow(hWnd,0);}//隐藏窗口
void Window_Show(HWND hWnd){ShowWindow(hWnd,1);}//显示窗口
int getmouse_y(){//获取鼠标在屏幕中x的位置
POINT pt;
GetCursorPos(&pt);
return pt.x;
}
int getmouse_x(){//获取鼠标在屏幕中y的位置
POINT pt;
GetCursorPos(&pt);
return pt.y;
}
void setmouse(int y,int x){SetCursorPos(x,y);}//设置鼠标在屏幕中的位置
void click_left(){//鼠标左键点击
mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
Sleep(5);//要留给某些应用的反应时间
mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);
}
void click_right(){//鼠标右键点击
mouse_event(MOUSEEVENTF_RIGHTDOWN,0,0,0,0);
Sleep(5);
mouse_event(MOUSEEVENTF_RIGHTUP,0,0,0,0);
}
void GOTO(int x,int y){//将光标移动到屏幕中的位置
CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
HANDLE hConsoleOut;
hConsoleOut = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hConsoleOut,&csbiInfo);
csbiInfo.dwCursorPosition.Y = x;
csbiInfo.dwCursorPosition.X = y;
SetConsoleCursorPosition(hConsoleOut,csbiInfo.dwCursorPosition);
}
using namespace std;
const int flg[4][2]={{1,0},{0,2},{0,-2},{-1,0}};//下右左上
int n=28,m=76,tim;
struct xcw{int x,y;}tan[1000005];//1头 tot尾
int tot,f,score,food,ground=0;
bool vis[1005][1005];
int main();
//void retr(){
// HWND hWnd=GetForegroundWindow();
// ShowWindow(hWnd,SW_HIDE);//隐藏窗口
// exit(0);
//}
bool check(int x,int y){//是否撞到东西
if(x<1||x>n||y<2||y>m) return 0;
bool t=1;
for(int i=1;i<=tot;i++)
if(x==tan[i].x&&y==tan[i].y){t=0;break;}
return t;
}
void fnd(int x,int y){
if(check(x,y)) return;
setcolor(7+ground);cls();
printf("Lose\n");//游戏结束
printf("分数:%d\n",score);
printf("E键退出,R键重来\n");
char ch=getch();
while(ch!='E'&&ch!='e'&&ch!='R'&&ch!='r') ch=getch();
if(ch=='E'||ch=='e') retr();
else{main();exit(0);}
}
void rand_food(){//随机产生食物,不能重复
setcolor(12+ground);
int x=brand()%(n+1),y=(brand()%m/2)*2;
while(!check(x,y)) x=brand()%(n+1),y=(brand()%m/2)*2;
GOTO(x,y);printf("▇");
if(!vis[x][y]) food++;vis[x][y]=1;
x=brand()%(n+1),y=(brand()%m/2)*2;
while(!check(x,y)) x=brand()%(n+1),y=(brand()%m/2)*2;
GOTO(x,y);printf("▇");
if(!vis[x][y]) food++;vis[x][y]=1;
setcolor(10+ground);
}
void draw(){//画地图
setcolor(14+ground);
for(int i=0;i<=n+1;i++) GOTO(i,m+2),printf("▇"),GOTO(i,0),printf("▇");
for(int i=1;i<=m/2+1;i++) GOTO(n+1,i*2),printf("▇"),GOTO(0,i*2),printf("▇");
setcolor(10+ground);
}
int main(){
system("mode con cols=80 lines=31");//设置窗口大小
cls();//清屏
printf("小Z的程序:请设置速度(豪秒/格)(建议100):");
cin>>tim;bsrand();MEM(vis,0);food=0;MEM(tan,0);score=0;
setcolor(10+ground);//设置颜色
cls();
draw();
f=1;tan[1]=(xcw){1,6};tan[2]=(xcw){1,4};tan[tot=3]=(xcw){1,2};//初始化蛇
for(int i=1;i<=tot;i++) GOTO(tan[i].x,tan[i].y),printf("0");//画蛇
while(1){
while(!kbhit()){//判断是否有键按下
Sleep(tim);//延时
if(food==0) rand_food();
int x=tan[1].x,y=tan[1].y;
x+=flg[f][0],y+=flg[f][1];
for(int i=tot;i;i--) tan[i+1]=tan[i];//移动蛇
GOTO(tan[tot+1].x,tan[tot+1].y);
printf(" ");//清除蛇尾
if(vis[x][y]) vis[x][y]=0,score++,food--,++tot,GOTO(tan[tot].x,tan[tot].y),printf("▇");//吃到食物长度加一
fnd(x,y);
tan[1]=(xcw){x,y};
GOTO(tan[1].x,tan[1].y);
printf("▇");//画蛇头
}
char ch=getch();
bool t=0;
if(ch=='E'||ch=='e') retr();
if(ch==-32) ch=getch(),t=1;
if((ch==75&&t||ch=='A'||ch=='a')&&f^1) f=2;//改变方向
if((ch==77&&t||ch=='D'||ch=='d')&&f^2) f=1;
if((ch==80&&t||ch=='S'||ch=='s')&&f^3) f=0;
if((ch==72&&t||ch=='W'||ch=='w')&&f^0) f=3;
}
return 0;
}