`
bilipan
  • 浏览: 11108 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
文章分类
社区版块
存档分类
最新评论

贪吃蛇原型实现基本思路

阅读更多
贪吃蛇的原型是在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;
}


这个贪吃蛇原型是我一时兴起弄的,考虑的也比较简单,况且是第一次写这种文章,所以哪里讲的不清楚或是程序有问题的,请大家多包涵。如果有建议或不清楚的地方,我会尽力解答的。谢谢。
9
2
分享到:
评论
1 楼 Max_1106 2010-07-20  
多年之前在学校的时候用delphi做过

相关推荐

    python实现自动贪吃蛇效果实现

    python实现自动贪吃蛇效果实现python实现自动贪吃蛇效果实现python实现自动贪吃蛇效果实现python实现自动贪吃蛇效果实现python实现自动贪吃蛇效果实现python实现自动贪吃蛇效果实现python实现自动贪吃蛇效果实现...

    操作系统课设-贪吃蛇游戏实现

    基于linux0.11内核 修改内核代码在控制台实现贪吃蛇游戏

    贪吃蛇游戏 精简版 实现基本功能

    贪吃蛇游戏 精简版 实现基本功能 贪吃蛇游戏 精简版 实现基本功能 贪吃蛇游戏 精简版 实现基本功能

    贪吃蛇制作思路.docx

    以上是制作贪吃蛇游戏的基本思路和关键组件,实际开发中还需考虑更多的细节,如游戏的初始化、得分系统、游戏结束条件等。通过不断地完善和优化,我们可以构建出一个功能完整且有趣的贪吃蛇游戏。

    as3.0贪吃蛇源码 实现了基本功能

    在这个“AS3.0贪吃蛇”源码中,开发者已经实现了基本的贪吃蛇游戏功能。下面我们将深入探讨这个游戏的实现细节。 1. **基本结构** - 游戏通常由一个主循环(main loop)驱动,负责处理每一帧的游戏状态更新和渲染...

    贪吃蛇的基本实现

    简单的实现了贪吃蛇的基本功能,没有别的华丽的功能,适合初学者看

    Java实现贪吃蛇小游戏.zip

    Java实现贪吃蛇小游戏Java实现贪吃蛇小游戏Java实现贪吃蛇小游戏Java实现贪吃蛇小游戏 Java实现贪吃蛇小游戏Java实现贪吃蛇小游戏Java实现贪吃蛇小游戏Java实现贪吃蛇小游戏 Java实现贪吃蛇小游戏Java实现贪吃蛇小...

    通过java技术简单贪吃蛇的实现 事件监听

    在本文中,我们将深入探讨如何使用Java技术实现一个简单的贪吃蛇游戏,主要涉及的类是`GameCanvas`和`SnakeGame`。贪吃蛇是一款经典的休闲游戏,玩家需要控制一条蛇吃食物,每次吃掉食物后蛇的身体会变长,而碰到...

    基于 jquery 的 html 贪吃蛇 简单实现

    这种实现方式适合初学者理解游戏的基本机制,并学习使用jQuery进行动态网页开发。同时,这也是一个很好的实践项目,可以在此基础上增加更多功能,如计分系统、多级难度、自定义皮肤等,提升游戏体验。

    三菱PLC用ST语言实现贪吃蛇游戏

    首先,我们需要理解贪吃蛇游戏的基本原理。游戏通常包含以下几个关键元素: 1. 蛇:由一系列连续的单元格组成,随着食物的吞噬,蛇的长度会增加。 2. 食物:随机生成在游戏区域内的一个点,蛇吃到食物后会增长。 3. ...

    贪吃蛇设计思路及具体实现代码

    贪吃蛇是一款经典的游戏,它的设计思路和实现代码主要涉及编程语言C++和游戏理论。在本文中,我们将深入探讨如何使用C++来构建一个基本的贪吃蛇游戏。 首先,我们要理解贪吃蛇的基本机制。游戏的核心是蛇在二维网格...

    贪吃蛇游戏实现思路及源代码.pdf

    本文将探讨如何使用HTML5来实现贪吃蛇游戏,包括游戏的实现思路、关键代码解析以及涉及的技术点。 首先,游戏的操作是通过键盘的上、下、左、右按键来控制贪吃蛇的移动。当贪吃蛇吃到食物后,它的长度会增加一个...

    win32 API实现贪吃蛇

    通过以上步骤,我们可以用Win32 API实现一个基本的贪吃蛇游戏。尽管这只是一个简单的示例,但这个过程涵盖了GUI编程的基础,对于理解Windows应用程序的工作原理非常有帮助。实际开发中,可以进一步优化游戏性能,...

    C语言版贪吃蛇设计思路及源代码

    《C语言版贪吃蛇设计思路及源代码》 贪吃蛇是一款经典的计算机游戏,它以其简单的规则和无限的游戏可能吸引了无数玩家。本教程将深入探讨如何使用C语言实现这样一个游戏,从底层逻辑到界面展示,我们将一步步揭示其...

    vc实现 控制台贪吃蛇

    首先,让我们深入了解贪吃蛇游戏的基本原理。贪吃蛇游戏的核心在于动态数组或链表的运用,用于存储蛇的身体位置。当蛇移动时,其头部位置会更新,而旧位置则成为新的身体部分。如果蛇吃到食物,它的长度会增加;如果...

    贪吃蛇游戏实现思路及源代码.docx

    这个简单的实现虽然可以运行基本的游戏逻辑,但可能还需要扩展和完善,比如添加碰撞检测、得分系统、游戏结束条件等。此外,为了提高用户体验,可以考虑添加音效、优化动画效果,甚至支持多人在线对战等功能。

    贪吃蛇游戏(C语言实现)

    该资源详细描述了如何利用C语言和win32API实现贪吃蛇的基本功能,包括源代码该资源详细描述了如何利用C语言和win32API实现贪吃蛇的基本功能,包括源代码该资源详细描述了如何利用C语言和win32API实现贪吃蛇的基本功能,...

    经典贪吃蛇算法实现C#.rar

    经典贪吃蛇算法实现C#.rar经典贪吃蛇算法实现C#.rar经典贪吃蛇算法实现C#.rar经典贪吃蛇算法实现C#.rar经典贪吃蛇算法实现C#.rar经典贪吃蛇算法实现C#.rar经典贪吃蛇算法实现C#.rar

    C语言实现贪吃蛇vs源码

    分享一个自己用C语言实现的贪吃蛇,在控制台中显示,实现了基本功能,没有美观的图形界面,仅供参考。

Global site tag (gtag.js) - Google Analytics