`
bilipan
  • 浏览: 10941 次
  • 性别: 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实现自动贪吃蛇效果实现...

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

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

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

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

    贪吃蛇 C# 实现基本功能

    实现了贪吃蛇的一般功能,可以吃不同的果子得到不同的分数,碰撞后可以自动减长减分等,得到一定分数即可通关

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

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

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

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

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

    as3.0贪吃蛇源码 实现了基本功能 希望大家多提建议,美术很粗糙,多多忍受!

    原生JavaScript贪吃蛇完美实现

    原生JavaScript贪吃蛇完美实现 思路绝对让你眼前一亮!

    贪吃蛇的基本实现

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

    j2me贪吃蛇的制作思路

    j2me贪吃蛇的制作思路 j2me贪吃蛇的制作思路

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

    一款简单的通过java实现的贪吃蛇的小游戏,只实现了一关,后面的关数可以通过修改时间和障碍物难度来实现。。。

    Java实现贪吃蛇小游戏.zip

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

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

    这是在大学暑假实训中 对设计简单贪吃蛇的思路 代码分为几个部分一步一步实现

    C#做的贪吃蛇 源码加注释 思路很清楚

    很不错 C#做的贪吃蛇 源码加注释 思路很清楚

    贪吃蛇游戏(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语言实现的贪吃蛇,在控制台中显示,实现了基本功能,没有美观的图形界面,仅供参考。

    贪吃蛇游戏(c++实现)

    基于c++实现的经典贪吃蛇游戏,适合学生下载学习,但是不准倒卖

    (深信息)用python实现贪吃蛇小游戏毕业设计报告 .docx

    (深信息)用python实现贪吃蛇小游戏毕业设计报告 .docx(深信息)用python实现贪吃蛇小游戏毕业设计报告 .docx(深信息)用python实现贪吃蛇小游戏毕业设计报告 .docx(深信息)用python实现贪吃蛇小游戏毕业设计报告 .docx...

Global site tag (gtag.js) - Google Analytics