累了吗?来个贪吃蛇吧
  • 板块灌水区
  • 楼主HenryLin11
  • 当前回复6
  • 已保存回复6
  • 发布时间2024/6/16 18:36
  • 上次更新2024/6/16 20:50:33
查看原帖
累了吗?来个贪吃蛇吧
987047
HenryLin11楼主2024/6/16 18:36

注意事项

该程序仅能在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;
}
2024/6/16 18:36
加载中...