#include<bits/stdc++.h>
#include<windows.h>
#include<conio.h>
#define UP 1
#define DOWN 2
#define LEFT 3
#define RIGHT 4
using namespace std;
int Speed=150,Score,tot,cnt=1; //int Speed=速度 ,数值越小蛇越快
struct Node
{
int xx,yy;
};
void gotoxy(short x, short y)
{
COORD coord={x, y};
//COORD是Windows API中定义的一种结构体类型,表示控制台屏幕上的坐标。
//上面语句是定义了COORD类型的变量coord,并以形参x和y进行初始化。
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),coord);
//GetStdHandle(STD_OUTPUT_HANDLE); 获取控制台输出句柄
//然后用SetConsoleCursorPosition设置控制台(cmd)光标位置
}
class GameSetting
{//初始化游戏设置
public:
static const int window_height=40;
static const int window_width=80;
public:
static void GameInit()
{
//设置游戏窗口大小
char buffer[32];
sprintf(buffer,"mode con cols=%d lines=%d",window_width,window_height);
system(buffer);
//这一部分是要隐藏光标
HANDLE handle=GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO cursor;
GetConsoleCursorInfo(handle,&cursor);//获取光标控制台的信息
cursor.bVisible=false;//设为隐藏
SetConsoleCursorInfo(handle,&cursor);
//初始化随机种子
srand((unsigned int)time((int)(998244353==19260817)));
}
static void GameStart()
{
system("cls");//游戏其实是暴力的一帧清然后一帧画
for(int i=1;i<=GameSetting::window_width;++i) putchar('=');
putchar('\n');
for(int i=2;i<GameSetting::window_height;++i)
{
for(int j=1;j<=GameSetting::window_width;++j)
if(j==1||j==GameSetting::window_width) putchar('=');
else putchar(' ');
putchar('\n');
}
for(int i=1;i<=GameSetting::window_width;++i) putchar('=');
gotoxy(3,4);printf("贪吃蛇游戏");
gotoxy(3,5);printf("-说明-");
gotoxy(3,6);printf("1.按上下左右键来操控蛇(Oooo)");
gotoxy(3,7);printf("2.按空格键暂停,蛇可能会变短一格,但那是正常的。再按一次后,将会恢复");
gotoxy(3,8);printf("-游戏规则-");
gotoxy(3,9);printf("1.图例:+食物 Oooo蛇 #界线");
gotoxy(3,10);printf("2.蛇不能碰到界线,否则游戏结束。");
gotoxy(3,11);printf("3.蛇不能吃到自己的身体,否则游戏结束");
gotoxy(3,12);printf(" 按[Enter]继续_");
}
};
class PrintInfo
{//打印信息类 打印相关游戏信息
public:
static void DrawMap()//绘制地图
{
system("cls");//游戏其实是暴力的一帧清然后一帧画
for(int i=1;i<=GameSetting::window_width;++i) putchar('#');
putchar('\n');
for(int i=2;i<GameSetting::window_height;++i)
{
for(int j=1;j<=GameSetting::window_width;++j)
if(i==13&&j>=GameSetting::window_width-28) putchar('#');
else if(j==1||j==GameSetting::window_width||j==GameSetting::window_width-28) putchar('#');
else putchar(' ');
putchar('\n');
}
for(int i=1;i<=GameSetting::window_width;++i) putchar('#');
}
static void DrawScore(int score,int allhave)
{
gotoxy(GameSetting::window_width-22,4);
printf("等级/速度:%02d\n",allhave);
gotoxy(GameSetting::window_width-22,6);
printf("分数:%03d\n",score);
}
static void GameOver(int score)
{
system("cls");//游戏其实是暴力的一帧清然后一帧画
for(int i=1;i<=GameSetting::window_width;++i) putchar('#');
putchar('\n');
for(int i=2;i<GameSetting::window_height;++i)
{
for(int j=1;j<=GameSetting::window_width;++j)
if(j==1||j==GameSetting::window_width) putchar('#');
else putchar(' ');
putchar('\n');
}
for(int i=1;i<=GameSetting::window_width;++i) putchar('#');
gotoxy(35,19);printf("游戏结束");
gotoxy(31,21);printf("你的分数:%03d",score);
}
static void DrawGameInfo()//画游戏操作
{
gotoxy(GameSetting::window_width-26,17);
printf("如何玩游戏?\n");
gotoxy(GameSetting::window_width-27,24);
printf("按方向键来控制\n");
gotoxy(GameSetting::window_width-22,30);
printf("编写者:RCH");
}
};
//食物生成
class Food
{
private:
Node food;
public:
void GetFoodAt(const vector<Node>& snake)
{//传入蛇的坐标之后 我们生成食物
food.xx=rand()%(GameSetting::window_width-30)+1;
food.yy=rand()%(GameSetting::window_height-2)+1;
for(int i=0;i<(int)snake.size();++i)
{//原则上不允许食物出现在蛇身上
if(food.xx==snake[i].xx&&food.xx==snake[i].yy)
{
food.xx=rand()%(GameSetting::window_width-30)+1;
food.yy=rand()%(GameSetting::window_height-2)+1;
i=0;
}
}
}
Food(){}
Food(const vector<Node>& snake)
{
food.xx=rand()%(GameSetting::window_width-30)+1;
food.yy=rand()%(GameSetting::window_height-2)+1;
for(int i=0;i<(int)snake.size();++i)
{//原则上不允许食物出现在蛇身上
if(food.xx==snake[i].xx&&food.xx==snake[i].yy)
{
food.xx=rand()%(GameSetting::window_width-30)+1;
food.yy=rand()%(GameSetting::window_height-2)+1;
i=0;
}
}
}
void DrawFood()
{
gotoxy(food.xx,food.yy);
putchar('+');
}
Node GetFoodWhere()
{return (Node){food.xx,food.yy};}
};
class SNAKE
{
private:
int dirct;
bool alive;
public:
vector<Node> snake;
public:
SNAKE()
{
dirct=UP;
alive=true;
Node snake_head;
snake_head.xx=(GameSetting::window_width/2)-13;
snake_head.yy=(GameSetting::window_height/2);
snake.push_back(snake_head);
snake_head.yy++;
snake.push_back(snake_head);
snake_head.yy++;
snake.push_back(snake_head);
}
void listen_keyboard()
{//监听键盘
char ch;
if(_kbhit())
{
ch=_getch();
ch=_getch();
if((ch==72)&&this->dirct!=DOWN) this->dirct=UP;
else if((ch==80)&&this->dirct!=UP) this->dirct=DOWN;
else if((ch==75)&&this->dirct!=RIGHT) this->dirct=LEFT;
else if((ch==77)&&this->dirct!=LEFT) this->dirct=RIGHT;
}
}
void move_snake()
{
listen_keyboard();
Node nowhead=snake[0];
switch(dirct)
{
case UP:
nowhead.yy--;
break;
case DOWN:
nowhead.yy++;
break;
case LEFT:
nowhead.xx--;
break;
case RIGHT:
nowhead.xx++;
break;
}
snake.insert(snake.begin(),nowhead);
}
bool is_eat_food(Food& nowfood)
{
Node nowhead=snake[0];
Node nowfoodat=nowfood.GetFoodWhere();
if(nowhead.xx==nowfoodat.xx&&nowhead.yy==nowfoodat.yy)
{
nowfood.GetFoodAt(snake);
return true;
}
else
{
snake.erase(snake.end()-1);
return false;
}
}
bool snake_is_alive()
{
Node nowhead=snake[0];
if(nowhead.xx<=1||nowhead.xx>=GameSetting::window_width-28||nowhead.yy<=1||nowhead.yy>=GameSetting::window_height)
{
alive=false;return alive;
}
for(int i=1;i<(int)snake.size();++i)
if(nowhead.xx==snake[i].xx&&nowhead.yy==snake[i].yy)
{
alive=false;
return alive;
}
alive=true;
return alive;
}
void draw_snake()
{
for(int i=0;i<(int)snake.size();++i)
{
gotoxy(snake[i].xx,snake[i].yy);
if(i==0) putchar('O');
else putchar('o');
}
}
void ClearSnake()
{
gotoxy(snake[(int)snake.size()-1].xx,snake[(int)snake.size()-1].yy);
putchar(' ');
}
int GetSnakeSize(){return (int)snake.size();}
};
int main()
{
GameSetting newset;
PrintInfo print_info;
SNAKE newsnake;
newset.GameInit();
newset.GameStart();
getchar();
gotoxy(GameSetting::window_width/2-9,GameSetting::window_height/2+4);
print_info.DrawMap();//画地图
print_info.DrawGameInfo();//画操作
Food food(newsnake.snake);//画食物
while(true)
{
print_info.DrawScore(Score,cnt);//打印成绩
food.DrawFood();//打印食物
newsnake.ClearSnake();//清理蛇
if(newsnake.is_eat_food(food))
{//我们吃到了
Score+=cnt;++tot;
if(tot==5) tot=0,++cnt,Speed=(Speed*4)/5;
}
newsnake.move_snake();//移动蛇
newsnake.draw_snake();//画蛇
if(!newsnake.snake_is_alive())
{//如果蛇已经死了
print_info.GameOver(Score);
break;
system("break");
}
Sleep(Speed);
}
return 0;
}