该程序仅能在Windows系统上运行
如果有高亮的选项想让你选择,按下←、→键来选择,按下Enter键确定。
开始游戏后会让你选择模式,Start为正常开始,接着会让你选择目标分数;Endless Mode为无尽模式,Exit为退出。
按下W、S、A、D键操控贪吃蛇上、下、左、右,爬向$。
游玩时如果想退出这局,可按下Esc键,程序会再次让你选择是否退出,退出选Yes,不退出并继续选No。
#include<bits/stdc++.h>
#include<stdlib.h>
#include<windows.h>
#include<conio.h>
#define frame_width 50
#define frame_height 25
#define info_width 60
#define _CRT_SECURE_NO_WARNINGS
#define xyyes(x,y) (((x<24)&&(x>35)&&(y<8)&&(y>13))||(w<=tim))
using namespace std;
HANDLE hOut;//是控制台输出句柄,对控制台进行输入输出操作,比如设置光标位置、设置文本颜色等。
HWND myconsole;//对窗口操作
HDC hdc;//设备环境句柄
CONSOLE_SCREEN_BUFFER_INFO cinfo;//包含有关控制台屏幕缓冲区的信息
typedef struct{
int x, y;
} Food;//食物坐标
typedef struct{
int x[100], y[100], len, state;
} Snake;//贪吃蛇的位置,长度,移动方向
inline void gotoxy(int x, int y); //最重要的一个函数,控制光标的位置
inline void print_map();//绘制地图
inline void get_newfood();//生成新食物
inline bool check_foodinsnake();//检查新食物有没有在蛇身上
inline bool move_snake(); // 移动蛇
inline void check_foodeating();//是否吃到食物
inline bool check_snakealive();//贪吃蛇是否还存活
inline void update_state(char* x);
inline void update_tim(int time);
inline void set_color(int color);
inline int input_cos(int x0,int y0);
inline int input_target(int x0,int y0);
inline bool askexit(int x0,int y0);
inline void show_cursor(BOOL hide);
inline void update_aim(int x);
inline void showtext();
typedef struct//记录雨滴的结构体
{
int x, y;
char ch;
}RAINDROP;
//需要用到的全局变量
int score;//分数
Snake snake;//贪吃蛇
Food food;//食物
bool check_eaten;
int aim;//目标分数
const int greenblue=FOREGROUND_GREEN|FOREGROUND_BLUE;
const int yellow=FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_INTENSITY;
const int lyellow=FOREGROUND_RED|FOREGROUND_GREEN;
const int purple=FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_INTENSITY;
int color;//文字颜色
int colo;//贪吃蛇背景颜色
char win_text[20]="You won this game!";
char welcome_text[35]="WELCOME TO THE GAME OF RETRO SNAKE";
char* state;
const int BUFFER_SIZE = 30;
const int RAIN_LENGTH = 10;
int WIDTH = 80;
int HEIGHT = 30;
int tim=40;//显示文字的时间
RAINDROP raindropLine[BUFFER_SIZE];
HANDLE HOUT = GetStdHandle(STD_OUTPUT_HANDLE);//获得标准输出的句柄
inline void gotoxy(int x, int y)//移动光标
{
COORD pos;//COORD是一种自带结构体,表示一个字符在控制台屏幕上的坐标
pos.X = y, pos.Y = x;
SetConsoleCursorPosition(HOUT, pos);//定位光标的函数
return;
}
inline void show_win_info(){
system("cls");
set_color(yellow);//
for (int i = 0; i<frame_height; i++)
{
gotoxy(i, 0);
printf("#");
gotoxy(i, info_width);//因为这个标记是长度,从零开始所以最后要减1
printf("#");
}
for (int i = 0; i<info_width; i++)
{
gotoxy(0, i);
printf("#");
gotoxy(frame_height, i);
printf("#");
}
set_color(greenblue);
gotoxy(12,21);
printf("%s",win_text);
gotoxy(13,21);
printf("Your score is %d",score);
gotoxy(14,21);
printf("The target score is %d",aim);
}
inline void show_welcome_info(){
system("cls");
set_color(lyellow);//
for (int i = 0; i<frame_height; i++)
{
gotoxy(i, 0);
printf("#");
gotoxy(i, info_width);//因为这个标记是长度,从零开始所以最后要减1
printf("#");
}
for (int i = 0; i<info_width; i++)
{
gotoxy(0, i);
printf("#");
gotoxy(frame_height, i);
printf("#");
}
set_color(greenblue);
gotoxy(12,11);
printf("%s",welcome_text);
gotoxy(14,12);
printf("Operation of Snake Snakes Method");
gotoxy(15,13);
printf("UP:W DOWN:S LEFT:A RIGHT:D");
return;
}
inline void print_map(bool outtarget)
{
//打印墙壁
for (int i = 0; i<frame_height; i++)
{
gotoxy(i, 0);
printf("#");
gotoxy(i, frame_width);//因为这个标记是长度,从零开始所以最后要减1
printf("#");
}
for (int i = 0; i<frame_width; i++)
{
gotoxy(0, i);
printf("#");
gotoxy(frame_height, i);
printf("#");
}
//蛇身初始化
snake.len = 3;
snake.state = 'w';
snake.x[1] = frame_height / 2;
snake.y[1] = frame_width / 2;
gotoxy(snake.x[1], snake.y[1]);
set_color(purple);
printf("@");
for (int i = 2; i <= snake.len; i++)
{
snake.x[i] = snake.x[i - 1] + 1;
snake.y[i] = snake.y[i - 1];
gotoxy(snake.x[i], snake.y[i]);
printf("@");
}
set_color(colo);
//打印初始食物
get_newfood();
//打印右边状态栏
gotoxy(2, frame_width + 3);
printf("WELCOME TO THE GAME OF RETRO SNAKE");
gotoxy(4, frame_width + 3);
printf("UP: w");
gotoxy(6, frame_width + 3);
printf("DOWN: s");
gotoxy(8, frame_width + 3);
printf("LEFT: a");
gotoxy(10, frame_width + 3);
printf("RIGHT:d");
gotoxy(12, frame_width + 3);
printf("Your score:%d", score);
if(outtarget){
gotoxy(14, frame_width + 3);
printf("Target score:%d", aim);
}
return;
}
inline void get_newfood()//更新食物位置
{
do{
srand(time(0));
food.x = rand() % (frame_height - 3) + 2;
food.y = rand() % (frame_width - 3) + 2;
} while (check_foodinsnake());;
gotoxy(food.x, food.y);
set_color(lyellow);
cout << "$" << endl;
set_color(colo);
}
inline bool check_foodinsnake()
{
for (int i = 1; i <= snake.len; i++){
if(snake.x[i] == food.x&&snake.y[i] == food.y){
return 1;
}
}
return 0;
}
inline void check_foodeating()
{
if (snake.x[1] == food.x&&snake.y[1] == food.y)
{
score += 10;
check_eaten = 1;
gotoxy(12, frame_width + 3);
printf("Your score:%d", score);
snake.len++;
get_newfood();
}
}
inline bool move_snake()
{
char com = 'n';
while(_kbhit()){//键盘有输入
com = _getch();//从控制台读取一个字符,但不显示在屏幕上
if(com==27){
return 1;
}
}
//没有吃到去除蛇尾
if (!check_eaten)
{
gotoxy(snake.x[snake.len], snake.y[snake.len]);
printf(" ");
}
//将除蛇头外的其他部分向前移动
for (int i = snake.len; i>1; i--)
snake.x[i] = snake.x[i - 1],
snake.y[i] = snake.y[i - 1];
//移动蛇头
switch (com)
{
case 'w':
{
if (snake.state == 's') //如果命令与当前方向相反不起作用
snake.x[1]++;
else
snake.x[1]--, snake.state = 'w';
break;
}
case 's':
{
if (snake.state == 'w')
snake.x[1]--;
else
snake.x[1]++, snake.state = 's';
break;
}
case 'a':
{
if (snake.state == 'd')
snake.y[1]++;
else
snake.y[1]--, snake.state = 'a';
break;
}
case 'd':
{
if (snake.state == 'a')
snake.y[1]--;
else
snake.y[1]++, snake.state = 'd';
break;
}
default: //按其余键保持状态前进
{
if (snake.state == 's')
snake.x[1]++;
else if (snake.state == 'w')
snake.x[1]--;
else if (snake.state == 'd')
snake.y[1]++;
else if (snake.state == 'a')
snake.y[1]--;
break;
}
}
gotoxy(snake.x[1], snake.y[1]);
set_color(purple);
printf("@");
set_color(colo);
check_eaten = 0;
gotoxy(frame_height, 0);
return 0;
}
inline bool check_snakealive()
{
//检查有没有撞到墙
if (snake.x[1] == 0 || snake.x[1] == frame_height - 1 || snake.y[1] == 0 || snake.y[1] == frame_width - 1){
//撞墙
update_state("You hit the wall while moving!");
return 0;
}
//检查有没有吃到自己
for (int i = 2; i <= snake.len; i++){
if (snake.x[i] == snake.x[1] && snake.y[i] == snake.y[1]){
update_state("You ate yourself while moving!");
return 0;
}
}
return 1;
}
inline void set_snake(){
set_color(colo);
show_welcome_info();
int x0=17,y0=11;
bool exitrace=0;
do
{
int cos=input_cos(x0,y0);
set_color(colo);
if (cos == 3){
break;
}
if(cos==1){
update_aim(input_target(x0,y0));
}
x0=17,y0=11;
system("cls");
score = 0, check_eaten = 0;
print_map(cos!=2);
//贪吃蛇的每回合运行控制
while(1)
{
check_foodeating();
if((score>=aim)&&(cos!=2)){
show_win_info();
x0=20,y0=13;
score=0;
break;
}
if(move_snake()){
exitrace=askexit(16, frame_width + 3);
}
Sleep(max(50, 300 - score));//控制速度(与长度呈反比)
if(!check_snakealive()){
gotoxy(2, frame_width + 3);
printf("GAME OVER! ");
gotoxy(4, frame_width + 3);
printf("%s",state);
gotoxy(6, frame_width + 3);
printf("Your score:%d", score);
gotoxy(8, frame_width + 3);
printf(" ");
gotoxy(10, frame_width + 3);
printf(" ");
gotoxy(12, frame_width + 3);
printf(" ");
gotoxy(28, frame_width + 3);
printf(" ");
show_cursor(FALSE);
x0=27,y0=0;
break;
}
if(exitrace){
break;
}
}
if(exitrace){
exitrace=0;
system("cls");
show_welcome_info();
}
} while (1);
return;
}
inline void update_state(char* x){
state=x;
return;
}
inline void show_cursor(BOOL hide)
{
CONSOLE_CURSOR_INFO cciCursor;
if (GetConsoleCursorInfo(HOUT, &cciCursor)) //获得光标信息
{
cciCursor.bVisible = hide; //隐藏光标
SetConsoleCursorInfo(HOUT, &cciCursor); //重新设置光标
}
}
inline void set_color(int color)
{
SetConsoleTextAttribute(HOUT, color); //设置输出颜色
}
inline void showtext(){
set_color(color|FOREGROUND_INTENSITY);
gotoxy(8,24);
printf("We are glad that you have come to this game");
gotoxy(9,24);
printf("We hope you can feel happy while playing");
gotoxy(10,24);
printf("We hope we can still meet again");
gotoxy(11,24);
printf("See you!");
set_color(color);
}
inline void set_virus()
{
CONSOLE_SCREEN_BUFFER_INFO info;
GetConsoleScreenBufferInfo(HOUT, &info); //获得控制台窗体信息
HEIGHT = info.srWindow.Bottom; //根据控制台的宽高设置显示的宽高
WIDTH = info.srWindow.Right;
srand((unsigned int)time(NULL));
for (int i=0; i<BUFFER_SIZE; i++) //随机设置雨滴下落的位置
{
raindropLine[i].x = rand()%WIDTH;
raindropLine[i].y = rand()%HEIGHT;
raindropLine[i].ch = rand() %2 + 48; //设置雨滴内容0或1
}
show_cursor(FALSE);
for(int w=0;true;w++){
GetConsoleScreenBufferInfo(HOUT, &info); //当窗体大小变化时,重新设置宽高信息
HEIGHT = info.srWindow.Bottom;
WIDTH = info.srWindow.Right;
for (int i=0; i<BUFFER_SIZE; ++i)
{
if (raindropLine[i].y <= HEIGHT)
{
set_color(color); //设置雨滴颜色
gotoxy(raindropLine[i].y, raindropLine[i].x);
putchar(raindropLine[i].ch);
}
gotoxy(raindropLine[i].y - RAIN_LENGTH, raindropLine[i].x); //擦除过长的雨滴
putchar(' ');
raindropLine[i].y++;
raindropLine[i].ch = rand() % 2 + 48;
if (raindropLine[i].y > HEIGHT + RAIN_LENGTH)
{
raindropLine[i].x = rand() % WIDTH;
raindropLine[i].y = rand() % HEIGHT;
}
if ( raindropLine[i].y <= HEIGHT)
{
gotoxy(raindropLine[i].y,raindropLine[i].x);
set_color(color|FOREGROUND_INTENSITY); //高亮最下方的雨滴
putchar(raindropLine[i].ch);
set_color(color);
}
if(w>tim){
showtext();
gotoxy(12,24);
if(w<60){
printf("(Press Esc key to exit)");
}
if(w==60){
printf(" ");
}
}
}
// Sleep(50);
while(_kbhit()){
int com3=_getch();//从控制台读取一个字符,但不显示在屏幕上
if(com3==27){
exit(0);
}
}
}
}
inline void FullScreen(){
keybd_event(VK_MENU,0x38,0,0);
keybd_event(VK_RETURN,0x1c,0,0);
keybd_event(VK_RETURN,0x1c,KEYEVENTF_KEYUP,0);
keybd_event(VK_MENU,0x38,KEYEVENTF_KEYUP,0);
}//强制全屏
inline int input_cos(int x0,int y0){
int com2=0;
int cos=1;
set_color(colo);
gotoxy(x0,y0);
printf("1:Start 2:Endless Mode 3:Exit");
while(com2!=13){
switch(cos){
case 1:
gotoxy(x0,y0);
printf("1:Start 2:Endless Mode 3:Exit");
gotoxy(x0,y0+2);
set_color(BACKGROUND_GREEN|BACKGROUND_BLUE|BACKGROUND_INTENSITY);
printf("Start");
set_color(colo);
break;
case 2:
gotoxy(x0,y0);
printf("1:Start 2:Endless Mode 3:Exit");
gotoxy(x0,y0+13);
set_color(BACKGROUND_GREEN|BACKGROUND_BLUE|BACKGROUND_INTENSITY);
printf("Endless Mode");
set_color(colo);
break;
case 3:
gotoxy(x0,y0);
printf("1:Start 2:Endless Mode 3:Exit");
gotoxy(x0,y0+31);
set_color(BACKGROUND_GREEN|BACKGROUND_BLUE|BACKGROUND_INTENSITY);
printf("Exit");
set_color(colo);
break;
}
com2=_getch();
if(com2==224){
com2=_getch();
if(com2==75&&cos>1){
cos--;
}
else if(com2==77&&cos<3){
cos++;
}
}
}
return cos;
}
inline int input_target(int x0,int y0){
int com2=0;
int cos=1;
set_color(colo);
gotoxy(x0,y0);
printf("Target score: 20 50 80 100 150");
while(com2!=13){
switch(cos){
case 1:
gotoxy(x0,y0);
printf("Target score: 20 50 80 100 150");
gotoxy(x0,y0+15);
set_color(BACKGROUND_GREEN|BACKGROUND_BLUE|BACKGROUND_INTENSITY);
printf("20");
set_color(colo);
break;
case 2:
gotoxy(x0,y0);
printf("Target score: 20 50 80 100 150");
gotoxy(x0,y0+19);
set_color(BACKGROUND_GREEN|BACKGROUND_BLUE|BACKGROUND_INTENSITY);
printf("50");
set_color(colo);
break;
case 3:
gotoxy(x0,y0);
printf("Target score: 20 50 80 100 150");
gotoxy(x0,y0+23);
set_color(BACKGROUND_GREEN|BACKGROUND_BLUE|BACKGROUND_INTENSITY);
printf("80");
set_color(colo);
break;
case 4:
gotoxy(x0,y0);
printf("Target score: 20 50 80 100 150");
gotoxy(x0,y0+27);
set_color(BACKGROUND_GREEN|BACKGROUND_BLUE|BACKGROUND_INTENSITY);
printf("100");
set_color(colo);
break;
case 5:
gotoxy(x0,y0);
printf("Target score: 20 50 80 100 150");
gotoxy(x0,y0+32);
set_color(BACKGROUND_GREEN|BACKGROUND_BLUE|BACKGROUND_INTENSITY);
printf("150");
set_color(colo);
break;
}
com2=_getch();
if(com2==224){
com2=_getch();
if(com2==75&&cos>1){
cos--;
}
else if(com2==77&&cos<5){
cos++;
}
}
}
switch(cos) {
case 1:
return 20;
break;
case 2:
return 50;
break;
case 3:
return 80;
break;
case 4:
return 100;
break;
case 5:
return 150;
break;
}
return 20;
}
inline bool askexit(int x0,int y0){
int com2=0;
int cos=2;
set_color(colo);
gotoxy(x0,y0);
printf("Are you sure you want to exit? Yes No");
while(com2!=13){
switch(cos){
case 1:
gotoxy(x0,y0);
printf("Are you sure you want to exit? Yes No");
gotoxy(x0,y0+31);
set_color(BACKGROUND_GREEN|BACKGROUND_BLUE|BACKGROUND_INTENSITY);
printf("Yes");
set_color(colo);
break;
case 2:
gotoxy(x0,y0);
printf("Are you sure you want to exit? Yes No");
gotoxy(x0,y0+35);
set_color(BACKGROUND_GREEN|BACKGROUND_BLUE|BACKGROUND_INTENSITY);
printf("No");
set_color(colo);
break;
}
com2=_getch();
if(com2==224){
com2=_getch();
if(com2==75&&cos>1){
cos--;
}
else if(com2==77&&cos<2){
cos++;
}
}
}
gotoxy(x0,y0);
printf(" ");
return cos==1;
}
inline void update_snake_color(int cx){
colo=cx;
}
inline void update_aim(int x){
aim=x;
}
inline void update_tim(int time){
tim=time;
}
inline void update_color(int cx){
color=cx;
}
int main() {
update_aim(20);//修改贪吃蛇目标分数
update_snake_color(FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY);//修改贪吃蛇整体颜色颜色
update_color(FOREGROUND_GREEN);//修改文字颜色
update_tim(10);
show_cursor(FALSE);
set_snake();
system("cls");
set_virus();
return 0;
}