贪吃蛇(一)--用C++编写一个简单的贪吃蛇

本文详细介绍了如何使用C++在控制台上创建一个基础的贪吃蛇游戏,包括内容定位、动态数组、键盘输入处理、随机食物生成及碰撞检测。通过一步步构建,实现了贪吃蛇的基本玩法。

这里简单介绍怎么用C++编写一个简单的黑白框的贪吃蛇游戏,复杂的加了可视化界面程序点击这里贪吃蛇(二)–easyX图形库进行可视化界面制作

首先分析在黑白框中的贪吃蛇需要哪些功能:
(1)需要能在界面指定位置(x,y)直接输出对应内容
(2)需要动态数组储存蛇的身体节点
(3)需要能接收键盘指令对贪吃蛇运动方向进行调整
(4)需要随机生成食物
(5)判断蛇是否撞到墙或者自己的身体

基本满足这些功能就可以实现一个简单的贪吃蛇,但是为了游戏的稳定性我们需要尽可能考虑详细,避免程序出bug。现在依次对这5个功能进行实现。

1.在界面指定位置(x,y)输出对应内容
这里直接引用C语言本身存在的一个操作台函数,代码如下:

#include<iostream>
#include<windows.h>
using namespace std;
//在指定位置显示内容 
void gotoxy(int x,int y,char c)
{
   
   
	CONSOLE_SCREEN_BUFFER_INFO csbiInfo; //variablendklaration
	HANDLE hConsoleOut;
	hConsoleOut = GetStdHandle(STD_OUTPUT_HANDLE);
	GetConsoleScreenBufferInfo(hConsoleOut,&csbiInfo);
	csbiInfo.dwCursorPosition.X = x; //cursorposition X koordinate festlegen
	csbiInfo.dwCursorPosition.Y = y; //cursorposition Y koordinate festlegen
	SetConsoleCursorPosition(hConsoleOut,csbiInfo.dwCursorPosition); //den cursor an die festgelegte koordinate setzen
	printf("%c",c);//输出你指定的字符 
}  
int main()
{
   
   
	gotoxy(5,5,'*');//在坐标(5,5)的位置显示'*' 
	gotoxy(10,10,'#'); //在坐标(10,10)的位置显示'#'
	return 0;
} 

其中的gotoxy函数就是我们可以在指定位置输出指定字符的函数,其对应的库函数为"windows.h",上述代码运行结果为
在这里插入图片描述
于是我们趁热打铁,把贪吃蛇的围墙顺便画出来,围墙为一个矩形,而矩形的左上角和右下角端点坐标就可以确定这个矩形,于是我们只需要定义左上角和右下角坐标即可。

int X1=1,Y1=1;//活动范围的左上角坐标
int X2=60,Y2=30;//活动范围的右下角坐标
void init()//初始化函数 
{
   
   
	for(int i=X1;i<=X2;i++)
	{
   
   
		gotoxy(i,Y1,'#');
		gotoxy(i,Y2,'#');
	}
	for(int j=Y1;j<=Y2;j++)
	{
   
   
		gotoxy(X1,j,'#');
		gotoxy(X2,j,'#');
	}	
} 

在主函数中运行初始化函数init()结果为
在这里插入图片描述于是画出了一个简单的边框了。

2.动态数组储存蛇的身体节点
这里直接用stl库中的vector储存了吧,然后定义一个结构体表示蛇的身体节点,这样书写比较容易,嘿嘿,代码如下。

struct Snake
{
   
   
	int x,y;
};
vector<Snake>snake;

然后库函数部分记得添加vector

#include<iostream>
#include<windows.h>
#include<vector>
using namespace std;

这就是定义简单的蛇节点的动态数组了,然后我们初始化让开始的蛇头在活动范围的中间位置,然后在主函数中一直循环显示出来。这里我让蛇先按朝着往下的方向移动,蛇的节点很多,那么如何让蛇移动呢?其实只需要改变蛇头位置就行,然后往后的节点更新到上一个节点的坐标位置,比如先把蛇头位置更新给第二个节点,蛇头位置再更新成我们调整的位置。

但是蛇移动后原来位置输出的内容是需要清除的,这里我需要补充说一下了,可能在很多其他的贪吃蛇的写法中,为了书写方便直接用了system(“cls”)清空了整个界面内容,再把新的界面信息输出,这样没问题,但是黑白框不是专门用于可视化界面程序的,这样会让贪吃蛇程序看起来很卡顿,后期的可视化界面的贪吃蛇确实需要直接清空整个界面,但是现在的这个黑白框的程序没必要,我为了减小程序时间复杂度,考虑到贪吃蛇实际每次运动都是两个节点在变化,蛇头和蛇尾,蛇头是新输出的内容不管,蛇尾移动后原来的蛇尾就需要清空,于是我们在每次更新蛇的节点信息前,先把原来的蛇尾的位置清除,用gotoxy(x,y,’ ');空格就会显示没有,看起来就是清除的作用。
然后到这里完整的代码就是这样了:

#include<iostream>
#include<windows.h>
#include<vector>
using namespace std;
//在指定位置显示内容 
void gotoxy(int x,int y,char c)
{
   
   
	CONSOLE_SCREEN_BUFFER_INFO csbiInfo; //variablendklaration
	HANDLE hConsoleOut;
	hConsoleOut = GetStdHandle(STD_OUTPUT_HANDLE);
	GetConsoleScreenBufferInfo(hConsoleOut,&csbiInfo);
	csbiInfo.dwCursorPosition.X = x; //cursorposition X koordinate festlegen
	csbiInfo.dwCursorPosition.Y = y; //cursorposition Y koordinate festlegen
	SetConsoleCursorPosition(hConsoleOut,csbiInfo.dwCursorPosition); //den cursor an die festgelegte koordinate setzen
	printf("%c",c);//输出你指定的字符 
}  
int X1=1,Y1=1;//活动范围的左上角坐标
int X2=60,Y2=30;//活动范围的右下角坐标
struct Snake
{
   
   
	int x,y;
};
vector<Snake>snake;
void init()//初始化函数 
{
   
    
	for(int i=X1;i<=X2;i++)
	{
   
   
		gotoxy(i,Y1,'#');
		gotoxy(i,Y2,'#');
	}
	for(int j=Y1;j<=Y2;j++)
	{
   
   
		gotoxy(X1,j,'#');
		gotoxy(X2,j,'#');
	}
	snake.clear();//初始化清空	
	Snake t;
	t.x=(X1+X2)/2;
	t.y=(Y1+Y2)/2;
	snake.push_back(t);
} 
//更新的位置,上下左右 
int XX[4]={
   
   0,0,-1,1};
int YY[4]={
   
   -1,1,0,0}; 
void Print(int direction)//显示蛇的内容
{
   
   
	int n=snake.size()-1;
	gotoxy(snake[n].x,snake[n].y,' ');//先清除蛇尾留下的痕迹 
	
以下是使用Dev-C++编写贪吃蛇的基本步骤: 1. 创建一个新的C++项目,并命名为“贪吃蛇”。 2. 在项目中创建一个新的C++源文件,并将其命名为“main.cpp”。 3. 在“main.cpp”文件中,包含必要的头文件和命名空间: ``` #include <iostream> #include <conio.h> #include <windows.h> using namespace std; ``` 4. 定义贪吃蛇和食物的结构体: ``` struct Snake{ int x, y; }; struct Food{ int x, y; }; ``` 5. 定义全局变量和常量: ``` const int mapWidth = 20; const int mapHeight = 20; const int snakeMaxLen = 100; const int interval = 100; int direction = 0; int score = 0; int snakeLen = 3; Snake snake[snakeMaxLen]; Food food; ``` 6. 初始化游戏窗口和贪吃蛇的初始位置: ``` void init(){ system("mode con cols=40 lines=25");//设置窗口大小 srand((unsigned)time(NULL));//初始化随机数种子 snake[0].x = 10; snake[0].y = 10; snake[1].x = 9; snake[1].y = 10; snake[2].x = 8; snake[2].y = 10; food.x = rand() % mapWidth; food.y = rand() % mapHeight; } ``` 7. 定义绘制函数,用于绘制游戏界面: ``` void draw(){ system("cls");//清屏 for(int i = 0; i < mapHeight; i++){ for(int j = 0; j < mapWidth; j++){ if(i == 0 || i == mapHeight - 1 || j == 0 || j == mapWidth - 1){ cout << "#";//绘制边框 }else if(i == snake[0].y && j == snake[0].x){ cout << "H";//绘制蛇头 }else if(i == food.y && j == food.x){ cout << "*";//绘制食物 }else{ bool isBody = false; for(int k = 1; k < snakeLen; k++){ if(i == snake[k].y && j == snake[k].x){ cout << "o";//绘制蛇身 isBody = true; break; } } if(!isBody){ cout << " ";//绘制空格 } } } cout << endl; } cout << "Score: " << score << endl;//显示得分 } ``` 8. 定义移动函数,用于控制贪吃蛇的移动: ``` void move(){ for(int i = snakeLen - 1; i > 0; i--){ snake[i].x = snake[i - 1].x; snake[i].y = snake[i - 1].y; } switch(direction){ case 0://向上移动 snake[0].y--; break; case 1://向下移动 snake[0].y++; break; case 2://向左移动 snake[0].x--; break; case 3://向右移动 snake[0].x++; break; } } ``` 9. 定义碰撞检测函数: ``` bool check(){ if(snake[0].x == 0 || snake[0].x == mapWidth - 1 || snake[0].y == 0 || snake[0].y == mapHeight - 1){ return true;//撞到边界 } for(int i = 1; i < snakeLen; i++){ if(snake[0].x == snake[i].x && snake[0].y == snake[i].y){ return true;//撞到自己 } } if(snake[0].x == food.x && snake[0].y == food.y){ score += 10;//吃到食物 snakeLen++; food.x = rand() % mapWidth; food.y = rand() % mapHeight; } return false; } ``` 10. 在主函数中,循环执行绘制、移动和碰撞检测等操作: ``` int main(){ init(); while(true){ if(_kbhit()){ char ch = _getch(); switch(ch){ case 'w'://向上移动 if(direction != 1){ direction = 0; } break; case 's'://向下移动 if(direction != 0){ direction = 1; } break; case 'a'://向左移动 if(direction != 3){ direction = 2; } break; case 'd'://向右移动 if(direction != 2){ direction = 3; } break; } } move(); if(check()){ cout << "Game Over!" << endl; break; } draw(); Sleep(interval);//延迟 } return 0; } ``` 11. 编译并运行程序,即可开始游戏
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值