贪吃蛇(结构体+数组)

zyl 2023-06-04 16:08:08 2025-07-23 23:24:16 73
#include<iostream>
#include<stdio.h>
#include<conio.h>
#include<windows.h>
#include<time.h>

using namespace std;

HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);

// 地图大小
#define W 40
#define H 40

struct snake{
	int x,y;
};
// 蛇结构体数组
snake snakes[W*H];
// 蛇的长度, 移动方向
int len = 0;
char dir = 'r';
// 食物坐标
int foodx = 0,foody = 0;
int FPS = 200;
// 分数        速度
int score = 0, speed = (220-FPS)/20;

// 隐藏光标
void HideCursor(){ 
	CONSOLE_CURSOR_INFO cursor_info = {1, 0};
	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info); 
}

// 设置光标位置
void setPos(int x,int y)  {
	CONSOLE_SCREEN_BUFFER_INFO csbiInfo;                            
	HANDLE hConsoleOut;
	hConsoleOut = GetStdHandle(STD_OUTPUT_HANDLE);
	GetConsoleScreenBufferInfo(hConsoleOut,&csbiInfo);
	csbiInfo.dwCursorPosition.X = x;                                    
	csbiInfo.dwCursorPosition.Y = y;                                    
	SetConsoleCursorPosition(hConsoleOut,csbiInfo.dwCursorPosition);
}

// 带颜色的输出
void COLOR_PRINT(const char* s, int color){
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | color);
	printf(s);
	SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | 7);
}

// 游戏结束
bool GameOver(){
	snake t = snakes[0];
	// 撞墙
	if(t.x <= 0){
		snakes[0].x = W-2;
	}
	if(t.x >= W-1){
		snakes[0].x = 0;
	}
	if(t.y <= 0){
		snakes[0].y = H-2;
	}
	if(t.y >= H-1){
		snakes[0].y = 0;
	}
//	if(t.x >= W-1 || t.x <= 0 || t.y >= H-1 || t.y <= 0){
//		return true;
//	}
	// 吃到自己
	for(int i=3;i<=len-1;i++){
		if(t.x == snakes[i].x && t.y == snakes[i].y){
			return true;
		}
	}
	return false;
}

// 判断食物和蛇身是否重合
bool inSnake(int x, int y){
	for(int i=0;i<len;i++){
		if(snakes[i].x == x && snakes[i].y == y) return false;
	}
	return true;
}

// 随机生成食物
void createFood(){
	srand(time(NULL));
	while(1){
		// 1~(W-1)
		foodx = rand()%(W-2)+1;
		foody = rand()%(H-2)+1;
		if(inSnake(foodx,foody)) return;
	}
}

// 初始化
void init(){
	// 初始化蛇
	len = 4;
	snakes[0].x = 2;
	snakes[0].y = 2;
	for(int i=1;i<len;i++){
		snakes[i].x = snakes[i-1].x + 1;
		snakes[i].y = snakes[i-1].y;
	}
	// 初始化食物
	createFood();
}

// 游戏提示
void tips(){
	setPos(W*2+4, 3);
	printf("游戏说明:\n");
	setPos(W*2+4, 5);
	printf("按W A S D 或者 ↑ ↓ ← → 操控游戏\n");
	setPos(W*2+4, 7);
	printf("按Q减速,按E加速\n");
	setPos(W*2+4, 9);
	printf("当前食物分数:%d\n", 100+10*speed);
	setPos(W*2+4, 11);
	printf("当前速度:%d\n", speed);
	setPos(W*2+4, 13);
	printf("总    分:%d\n", score);
}

// 画地图
void draw(){
	for(int i=0;i<W;i++){
		for(int j=0;j<H;j++){
			if(i==0 || j==0 || i == W-1 || j == H-1) {
				setPos(i*2,j);
				printf("");
			}
		}
	}
	// 画蛇
	for(int i=0;i<len;i++){
		setPos(snakes[i].x*2,snakes[i].y);
//		printf("■");
		if(i == 0) COLOR_PRINT("", 4);
		else COLOR_PRINT("", 1);
	}
	// 画食物
	setPos(foodx*2,foody);
//	printf("■");
	COLOR_PRINT("", 10);
	// 更新数据信息
	FPS = min(FPS, 200);
	FPS = max(FPS, 60);
	speed = (220-FPS)/20;
	tips();
}

// 控制移动
void move(){
	int dx = 0, dy = 0;
	if(dir == 'u') dy = -1;
	else if(dir == 'd') dy = 1;
	else if(dir == 'l') dx = -1;
	else if(dir == 'r') dx = 1;
	setPos(snakes[len-1].x*2,snakes[len-1].y);
	printf("  ");
	for(int i=len-1;i>=1;i--){
		snakes[i].x = snakes[i-1].x;
		snakes[i].y = snakes[i-1].y;
	}
	snakes[0].x = snakes[0].x + dx;
	snakes[0].y = snakes[0].y + dy;	
}

// 按键响应
void keyDown(){
	char key;
	while(kbhit()) key = _getch();  // 看不见的输入获取
	switch(key){
		case 'W':
		case 'w':
		case 72:
			if(dir != 'd') dir = 'u';
			break;
		case 'S':
		case 's':
		case 80:
			if(dir != 'u') dir = 'd';
			break;
		case 'A':
		case 'a':
		case 75:
			if(dir != 'r') dir = 'l';
			break;
		case 'D':
		case 'd':
		case 77:
			if(dir != 'l') dir = 'r';
			break;
		case 'E':
		case 'e':
			FPS -= 20;
			break;
		case 'Q':
		case 'q':
			FPS += 20;
			break;
	} 
} 

// 吃到食物
void eatFood(){
	if(snakes[0].x == foodx && snakes[0].y == foody){
		len++;
		for(int i=len-1;i>=1;i--){
			snakes[i].x = snakes[i-1].x;
			snakes[i].y = snakes[i-1].y;
		}
		snakes[0].x = foodx;
		snakes[0].y = foody;
		setPos(foodx*2,foody);
		printf("  ");
		score += 100+speed*10;
		createFood();
	}
}


int main(){
	HideCursor(); // 隐藏光标
	init();   // 初始化游戏内容
	tips();
	while(1){
		if(GameOver()) break;  // 游戏结束判断
		keyDown();  // 键盘按键
		move();  // 蛇移动
		eatFood(); // 判断是否吃到食物
		draw();  // 画出地图和蛇
		Sleep(FPS);
	}
	setPos((W+1)/2,(H-1)/2);
	COLOR_PRINT("游戏结束!,您获得了", 4);
	printf("%d", score);
	setPos(0,H+2);
	system("pause");
	return 0;
}
{{ vote && vote.total.up }}

共 20 条回复

CPP 刷题王

最后那段代码怎么搞的格式

cyx15 二百五

liuser 帅帅

棒~

Joshua Microsoft

有点抖,而且报错了 修正代码如下:

#include<iostream>
#include<stdio.h>
#include<conio.h>
#include<windows.h>
#include<time.h>

using namespace std;

HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);

// 地图大小
#define W 40
#define H 40

struct snake{
	int x,y;
};
// 蛇结构体数组
snake snakes[W*H];
// 蛇的长度, 移动方向
int len = 0;
char dir = 'd';
// 食物坐标
int foodx = 0,foody = 0;
int FPS = 200;
// 分数        速度
int score = 0, speed = (220-FPS)/20;

// 隐藏光标
void HideCursor(){ 
	CONSOLE_CURSOR_INFO cursor_info = {1, 0};
	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info); 
}

// 设置光标位置
void setPos(int x,int y)  {
	CONSOLE_SCREEN_BUFFER_INFO csbiInfo;                            
	HANDLE hConsoleOut;
	hConsoleOut = GetStdHandle(STD_OUTPUT_HANDLE);
	GetConsoleScreenBufferInfo(hConsoleOut,&csbiInfo);
	csbiInfo.dwCursorPosition.X = x;                                    
	csbiInfo.dwCursorPosition.Y = y;                                    
	SetConsoleCursorPosition(hConsoleOut,csbiInfo.dwCursorPosition);
}

// 带颜色的输出
void COLOR_PRINT(const char* s, int color){
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | color);
	printf(s);
	SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | 7);
}

// 游戏结束
bool GameOver(){
	// 撞墙
	snake t = snakes[0];
	if(t.x >= W-1 || t.x <= 0 || t.y >= H-1 || t.y <= 0){
		return true;
	}
	// 吃到自己
	for(int i=3;i<=len-1;i++){
		if(t.x == snakes[i].x && t.y == snakes[i].y){
			return true;
		}
	}
	return false;
}

// 判断食物和蛇身是否重合
bool inSnake(int x, int y){
	for(int i=0;i<len;i++){
		if(snakes[i].x == x && snakes[i].y == y) return false;
	}
	return true;
}

// 随机生成食物
void createFood(){
	srand(time(NULL));
	while(1){
		// 1~(W-1)
		foodx = rand()%(W-2)+1;
		foody = rand()%(H-2)+1;
		if(inSnake(foodx,foody)) return;
	}
}

// 初始化
void init(){
	// 初始化蛇
	len = 4;
	snakes[0].x = 2;
	snakes[0].y = 2;
	for(int i=1;i<len;i++){
		snakes[i].x = snakes[i-1].x + 1;
		snakes[i].y = snakes[i-1].y;
	}
	// 初始化食物
	createFood();
}

// 游戏提示
void tips(){
	setPos(W*2+4, 3);
	printf("游戏说明:\n");
	setPos(W*2+4, 5);
	printf("按W A S D 或者 ↑ ↓ ← → 操控游戏\n");
	setPos(W*2+4, 7);
	printf("按Q减速,按E加速\n");
	setPos(W*2+4, 9);
	printf("当前食物分数:%d\n", 100+10*speed);
	setPos(W*2+4, 11);
	printf("当前速度:%d\n", speed);
	setPos(W*2+4, 13);
	printf("总    分:%d\n", score);
}

// 画地图
void draw(){
	for(int i=0;i<W;i++){
		for(int j=0;j<H;j++){
			if(i==0 || j==0 || i == W-1 || j == H-1) {
				setPos(i*2,j);
				printf("");
			}
		}
	}
	// 画蛇
	for(int i=0;i<len;i++){
		setPos(snakes[i].x*2,snakes[i].y);
		if(i == 0) COLOR_PRINT("", 4);
		else COLOR_PRINT("", 1);
	}
	// 画食物
	setPos(foodx*2,foody);
	COLOR_PRINT("", 10);
	// 更新数据信息
	FPS = min(FPS, 200);
	FPS = max(FPS, 60);
	speed = (220-FPS)/20;
	tips();
}

// 控制移动
void move(){
	int dx = 0, dy = 0;
	if(dir == 'u') dy = -1;
	else if(dir == 'd') dy = 1;
	else if(dir == 'l') dx = -1;
	else if(dir == 'r') dx = 1;
	setPos(snakes[len-1].x*2,snakes[len-1].y);
	printf("  ");
	for(int i=len-1;i>=1;i--){
		snakes[i].x = snakes[i-1].x;
		snakes[i].y = snakes[i-1].y;
	}
	snakes[0].x = snakes[0].x + dx;
	snakes[0].y = snakes[0].y + dy;
	
	setPos(snakes[0].x*2, snakes[0].y);
	COLOR_PRINT("", 4);
}

// 按键响应
void keyDown(){
	char key = ' '; // 给key一个默认值,以防止未初始化的情况发生
	while(kbhit()) key = _getch();  // 看不见的输入获取
	switch(key){
		case 'W':
		case 'w':
		case 72:
			if(dir != 'd') dir = 'u';
			break;
		case 'S':
		case 's':
		case 80:
			if(dir != 'u') dir = 'd';
			break;
		case 'A':
		case 'a':
		case 75:
			if(dir != 'r') dir = 'l';
			break;
		case 'D':
		case 'd':
		case 77:
			if(dir != 'l') dir = 'r';
			break;
		case 'E':
		case 'e':
			FPS -= 20;
			break;
		case 'Q':
		case 'q':
			FPS += 20;
			break;
	} 
} 

// 吃到食物
void eatFood(){
	if(snakes[0].x == foodx && snakes[0].y == foody){
		len++;
		for(int i=len-1;i>=1;i--){
			snakes[i].x = snakes[i-1].x;
			snakes[i].y = snakes[i-1].y;
		}
		snakes[0].x = foodx;
		snakes[0].y = foody;
		setPos(foodx*2,foody);
		printf("  ");
		score += 100+speed*10;
		createFood();
	}
}


int main(){
	HideCursor(); // 隐藏光标
	init();   // 初始化游戏内容
	tips();
	while(1){
		if(GameOver()) break;  // 游戏结束判断
		keyDown();  // 键盘按键
		move();  // 蛇移动
		eatFood(); // 判断是否吃到食物
		Sleep(FPS);
	}
	setPos((W+1)/2,(H-1)/2);
	COLOR_PRINT("游戏结束!,您获得了", 4);
	printf("%d", score);
	setPos(0,H+2);
	system("pause");
	return 0;
} 
qym 山顶洞人

@lixinyan 谁抄袭了他只是重发了 OK?

ykj39 西瓜

建议地图大小调到20到30之间(我不专业但我试过)

outman008

11740分,又望各位编程大佬(bushi贪吃蛇大佬来破

lixinyan 爱因斯坦

抄袭CPP

outman008

贪吃蛇:“我是怎么出生的思密达?” 我:“我看不懂所以我不知道啊思密达。”

csr 陈俊豪-幺爸

6666666666666666666666666666666666666