贪吃蛇的原型是在windows控制台下即在字符模式下利用C++编写贪吃蛇。
主要实现的效果就是,用户利用'w'、's'、'a'、'd'分别表示上下左右,当蛇碰到障碍物时通不过,当碰到食物时,分数加1,同时,在另外一个地方生成新的食物,并且身体会增加一个字符的长度。
在实现该原型前必须实现两项技术:
什么意思呢?主要是因为考虑到在通常情况下,在控制台下编写的程序,默认都是黑白色的,颜色单一,而且蛇和障碍物、食物之间无法被互相区分,所以加上更多的颜色,视觉上会更舒服些。字符位置控制呢,是必不可缺的。这个是因为在命令行模式下,程序是默认顺序接收用户输入的,偶尔可以跳至同一行稍前些的位置。但是,由于蛇要到处爬,所以这就遇到一个问题,如何让输入光标跳至窗口下的任意位置成了开发的基础和前提。具体的我后面会讲到我的解决方案。
我的实现思路:
首先,我要创建一个游戏背景,具体指的是贪吃蛇的移动范围。这个呢,我用二维的数组来表示。每个单元格有几个参数---是否存在障碍物、是否存在食物,如果有的话,就用true,否则为false。
//这个是背景的单元格数据结构
const length = 40;
const width = 20;
struct square{
bool blocked; //是否有障碍物
bool food; //是否有食物
int x; //单元格在背景中的相对横坐标
int y; //单元格在背景中的相对纵坐标
}bg[length][width]; //直接创建游戏背景
//设置背景
void setBG(int length, int width){
HANDLE hOut;
COORD OutChar;
OutChar.X = 10;
OutChar.Y = 10;
int i = 0;
int j = 0;
for(i = 0; i < width; i++){
for(j = 0; j < length; j++){
bg[i][j].x = i;
bg[i][j].y = j;
bg[i][j].blocked = false;
bg[i][j].food = false;
OutChar.X = j+10;
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hOut,OutChar);
cout << col(BG_WHITE,true) << " ";
}
cout << endl;
OutChar.Y = i+10;
SetConsoleCursorPosition(hOut,OutChar);
}
}
接下来,就是要在背景上创建障碍物,在创建它们之前,首先得解决如何在指定的单元格式绘制单元。思路很简单,就是编写一个函数将光标定位到相应的坐标位置,然后输入一个空白的上色字符就解决了。然后就可以利用这个函数在真正的背景上相应的位置构建障碍物了。同时可以实现随机创建任意个、任意位置的障碍物了。
//构造障碍物
void createBlock(int x, int y, unsigned short color){
HANDLE hOut;
COORD OutChar;
OutChar.X = x;
OutChar.Y = y;
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hOut,OutChar); //定位光标输入
cout << col(color, true) << " "; //一个颜色为color的空白字符
}
//生成单个障碍物
void createWall(int x,int y){
createBlock(x+10,y+10,BG_GREEN);
bg[x][y].blocked = true;
}
//判断所指坐标是否被占用
bool checkExisted(int x,int y){
if(bg[x][y].blocked == true || bg[x][y].food == true){
return false;
}
return true;
}
//随机生成障碍物
void rand_createWall(void){
srand((unsigned)time(NULL));
int n = rand() % 70+10;
int pos_x = 0;
int pos_y = 0;
int i = 0;
for(i = 0; i < n; i++){
pos_x = rand() % length;
pos_y = rand() % (width-1);
if(checkExisted(pos_x,pos_y) == true){ //防止障碍物重叠
createWall(pos_x,pos_y);
}else{
n++;
}
//createWall(pos_x,pos_y);
}
}
同理,食物的创建也一样。
//创建食物
void createFood(int x,int y){
createBlock(x+10,y+10,BG_BLUE);
bg[x][y].food = true;
}
//随机创建食物
void rand_createFood(void){
srand((unsigned)time(NULL));
int n = 1;//rand() % 20;
int pos_x = 0;
int pos_y = 0;
int i = 0;
for(i = 0; i < n; i++){
pos_x = rand() % length;
pos_y = rand() % (width-1);
if(checkExisted(pos_x,pos_y) == true){ //防止在障碍物上生成食物
createFood(pos_x,pos_y);
}else{
n++;
}
}
}
背景、障碍物和食物都创建好了,接下来就要构建蛇的模型了。由于考虑到蛇在吃完食物后,身体会变长,所以我采用了顺序表的数据结构来记录蛇的信息。那如何来表现蛇的移动呢?我的思路是,将身体靠近头的信息传递到次靠近头的,同时将新的下一步要走的坐标信息传给头部,同时有擦除掉尾部信息即可。
//物体信息,这是蛇的单元模型
const objLen = 5;
struct obj{
int x;
int y;
}snake[objLen];
//创建蛇
LinList<struct obj> newSnake;
void createSnake(void){
int i = 0;
for(i = 0; i < objLen; i++){
snake[i].x = i;
snake[i].y = 0;
newSnake.Insert(snake[i],i);
}
}
//绘制蛇
void drawSnake(int len){
int i = 0;
struct obj t;
for(i = 0; i < len; i++){
t = newSnake.GetData(i);
createBlock(t.x,t.y,BG_RED);
}
}
//增长蛇的身体
void insreaseSnake(int x,int y){
struct obj t;
t.x = x;
t.y = y;
newSnake.Insert(t,0);
createBlock(x,y,BG_RED);
}
//传递蛇的信息
void transSnake(int x,int y,int len){
int i = 0;
struct obj t1,t2;
for(i = 0; i < len-1; i++){
t1 = newSnake.GetData(i);
t2 = newSnake.GetData(i+1);
newSnake.Delete(i);
t1.x = t2.x;
t1.y = t2.y;
newSnake.Insert(t1,i);
}
newSnake.Delete(newSnake.Size()-1);
t1.x = x;
t1.y = y;
newSnake.Insert(t1,newSnake.Size()-1);
}
这里的相对位置是指以背景左上方的点为原点即(0,0),右下方为(length-1,width-1)。
接着呢,就是要获取用户的方向控制操作,并执行它们。由于采用的二维数组的方式表示蛇的形状以及游戏背景,所以当接收到命令如果是‘上’时,横坐标不变,而纵坐标减1,同时擦除原形状,如此一来,蛇就向上爬了。擦除函数的原理很简单,就是将对应的背景单元格的信息全部还原为初始值,就可以了。
//清除物体移动轨迹
void removeTrack(int x, int y){
HANDLE hOut;
COORD OutChar;
OutChar.X = x;
OutChar.Y = y;
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hOut,OutChar);
cout << col(BG_WHITE,true) << " ";
}
//移动物体
int x = 10;
int y = 10;
int tail_x = 0;
int tail_y = 0;
void moveBlock(char direction){
HANDLE hOut2;
COORD OutChar2;
OutChar2.X = x;
OutChar2.Y = y;
struct obj t;
t = newSnake.GetData(0);
tail_x = t.x;
tail_y = t.y;
hOut2 = GetStdHandle(STD_OUTPUT_HANDLE);
removeTrack(t.x,t.y);
switch(direction){
case 'w':{
OutChar2.Y--;
y--;
SetConsoleCursorPosition(hOut2,OutChar2);
break;
}
case 's':{
OutChar2.Y++;
y++;
SetConsoleCursorPosition(hOut2,OutChar2);
break;
}
case 'a':{
OutChar2.X--;
x--;
SetConsoleCursorPosition(hOut2,OutChar2);
break;
}
case 'd':{
OutChar2.X++;
x++;
SetConsoleCursorPosition(hOut2,OutChar2);
break;
}
}
transSnake(x,y,newSnake.Size());
drawSnake(newSnake.Size());
}
做完这个,不要以为就这样结束了,因为我们还没对蛇的运动范围作出限制,而且还要实现蛇的触发事件即碰到食物后身体变长,食物数增加1。
//判断是否碰到障碍物或边界
bool checkView(char direction){
if(direction == 'w' && y >= 10){
if(y == 10 || bg[x-10][y-10-1].blocked == true){return false;}
}
else if(direction == 's' && y < 10+width){
if(y == 10+width-2 || bg[x-10][y-10+1].blocked == true){return false;}
}
else if(direction == 'a' && x >= 10){
if(x == 10 || bg[x-10-1][y-10].blocked == true){return false;}
}
else if(direction == 'd' && x < 10+length){
if(x == 10+length-1 || bg[x-10+1][y-10].blocked == true){return false;}
}
return true;
}
//判断是否吃到食物
bool checkFood(int x, int y){
if(bg[x-10][y-10].food == true){return true;}
return false;
}
下面就是游戏原型的主函数:
int main()
{
HANDLE hOut;
COORD OutChar;
OutChar.X = 0;
OutChar.Y = 0;
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hOut,OutChar);
/*
struct square **bgR = new square*[width];
struct square *bgC = new square[length];
for(int i = 0; i < width; i++){
bgR[i] = bgC;
}
*/
//设置背景
setBG(length,width);
//设置障碍物
rand_createWall();
//设置食物
rand_createFood();
//创建蛇
createSnake();
//移动物体
char direction;
int score = 0;
for(;;){
direction = getch();
if(checkView(direction) == true){//判断能否移动
moveBlock(direction);
if(checkFood(x,y) == true){//判断是否吃到食物
bg[x-10][y-10].food = false;
score++;
insreaseSnake(tail_x,tail_y);//增长身体
rand_createFood();//吃完后随机在创建一个食物
}
}
OutChar.X = 0;
OutChar.Y = 0;
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hOut,OutChar);
cout << col(BG_WHITE,true) << "Scores: " << score;
}
return 0;
}
这个贪吃蛇原型是我一时兴起弄的,考虑的也比较简单,况且是第一次写这种文章,所以哪里讲的不清楚或是程序有问题的,请大家多包涵。如果有建议或不清楚的地方,我会尽力解答的。谢谢。
分享到:
相关推荐
python实现自动贪吃蛇效果实现python实现自动贪吃蛇效果实现python实现自动贪吃蛇效果实现python实现自动贪吃蛇效果实现python实现自动贪吃蛇效果实现python实现自动贪吃蛇效果实现python实现自动贪吃蛇效果实现...
基于linux0.11内核 修改内核代码在控制台实现贪吃蛇游戏
贪吃蛇游戏 精简版 实现基本功能 贪吃蛇游戏 精简版 实现基本功能 贪吃蛇游戏 精简版 实现基本功能
以上是制作贪吃蛇游戏的基本思路和关键组件,实际开发中还需考虑更多的细节,如游戏的初始化、得分系统、游戏结束条件等。通过不断地完善和优化,我们可以构建出一个功能完整且有趣的贪吃蛇游戏。
在这个“AS3.0贪吃蛇”源码中,开发者已经实现了基本的贪吃蛇游戏功能。下面我们将深入探讨这个游戏的实现细节。 1. **基本结构** - 游戏通常由一个主循环(main loop)驱动,负责处理每一帧的游戏状态更新和渲染...
简单的实现了贪吃蛇的基本功能,没有别的华丽的功能,适合初学者看
Java实现贪吃蛇小游戏Java实现贪吃蛇小游戏Java实现贪吃蛇小游戏Java实现贪吃蛇小游戏 Java实现贪吃蛇小游戏Java实现贪吃蛇小游戏Java实现贪吃蛇小游戏Java实现贪吃蛇小游戏 Java实现贪吃蛇小游戏Java实现贪吃蛇小...
在本文中,我们将深入探讨如何使用Java技术实现一个简单的贪吃蛇游戏,主要涉及的类是`GameCanvas`和`SnakeGame`。贪吃蛇是一款经典的休闲游戏,玩家需要控制一条蛇吃食物,每次吃掉食物后蛇的身体会变长,而碰到...
这种实现方式适合初学者理解游戏的基本机制,并学习使用jQuery进行动态网页开发。同时,这也是一个很好的实践项目,可以在此基础上增加更多功能,如计分系统、多级难度、自定义皮肤等,提升游戏体验。
首先,我们需要理解贪吃蛇游戏的基本原理。游戏通常包含以下几个关键元素: 1. 蛇:由一系列连续的单元格组成,随着食物的吞噬,蛇的长度会增加。 2. 食物:随机生成在游戏区域内的一个点,蛇吃到食物后会增长。 3. ...
贪吃蛇是一款经典的游戏,它的设计思路和实现代码主要涉及编程语言C++和游戏理论。在本文中,我们将深入探讨如何使用C++来构建一个基本的贪吃蛇游戏。 首先,我们要理解贪吃蛇的基本机制。游戏的核心是蛇在二维网格...
本文将探讨如何使用HTML5来实现贪吃蛇游戏,包括游戏的实现思路、关键代码解析以及涉及的技术点。 首先,游戏的操作是通过键盘的上、下、左、右按键来控制贪吃蛇的移动。当贪吃蛇吃到食物后,它的长度会增加一个...
通过以上步骤,我们可以用Win32 API实现一个基本的贪吃蛇游戏。尽管这只是一个简单的示例,但这个过程涵盖了GUI编程的基础,对于理解Windows应用程序的工作原理非常有帮助。实际开发中,可以进一步优化游戏性能,...
《C语言版贪吃蛇设计思路及源代码》 贪吃蛇是一款经典的计算机游戏,它以其简单的规则和无限的游戏可能吸引了无数玩家。本教程将深入探讨如何使用C语言实现这样一个游戏,从底层逻辑到界面展示,我们将一步步揭示其...
首先,让我们深入了解贪吃蛇游戏的基本原理。贪吃蛇游戏的核心在于动态数组或链表的运用,用于存储蛇的身体位置。当蛇移动时,其头部位置会更新,而旧位置则成为新的身体部分。如果蛇吃到食物,它的长度会增加;如果...
这个简单的实现虽然可以运行基本的游戏逻辑,但可能还需要扩展和完善,比如添加碰撞检测、得分系统、游戏结束条件等。此外,为了提高用户体验,可以考虑添加音效、优化动画效果,甚至支持多人在线对战等功能。
该资源详细描述了如何利用C语言和win32API实现贪吃蛇的基本功能,包括源代码该资源详细描述了如何利用C语言和win32API实现贪吃蛇的基本功能,包括源代码该资源详细描述了如何利用C语言和win32API实现贪吃蛇的基本功能,...
经典贪吃蛇算法实现C#.rar经典贪吃蛇算法实现C#.rar经典贪吃蛇算法实现C#.rar经典贪吃蛇算法实现C#.rar经典贪吃蛇算法实现C#.rar经典贪吃蛇算法实现C#.rar经典贪吃蛇算法实现C#.rar
分享一个自己用C语言实现的贪吃蛇,在控制台中显示,实现了基本功能,没有美观的图形界面,仅供参考。