现在的位置: 首页 > 综合 > 正文

广度优先搜索算法的典型应用——消灭小星星游戏的核心代码实现与解析

2018年01月11日 ⁄ 综合 ⁄ 共 3002字 ⁄ 字号 评论关闭

        说明:本文的代码参考了网络上下载的源代码:《2013.3.25 游戏开发基地——孙广东 消灭小星星》,在此对原作者表示衷心感谢!

        这几天在看算法导论里面的BFS和DFS,于是发现消灭小星星这个游戏就用到了BFS算法,就自己试着写了一下消灭小星星游戏的主要代码。现在与大家分享,欢迎批评指正!

#include <stdlib.h>
//小星星的坐标
class point
{
public:
	int x;
	int y;
	point():x(0),y(0){}
};
//存储小星星的链表
class starListNode
{
public:
	point p;
	starListNode *next;
	starListNode()
	{
		p.x = 0;
		p.y = 0;
		next = NULL;
	}
};
//链表队列
class listQueue
{
public:
	starListNode *head;
	starListNode *tail;
	listQueue():head(NULL),tail(NULL){}
};
listQueue lq;
//初始化队列
bool initListQueue()
{
	lq.head = new starListNode();
	lq.tail = lq.head;
	if(lq.head == NULL)
		return false;
	lq.head->next == NULL;
	return true;
}
//入队
bool enQueue(point tp)
{
	starListNode *np = new starListNode();
	if(np == NULL)
		return false;
	np->p.x = tp.x;
	np->p.y = tp.y;
	np->next = NULL;
	lq.tail->next = np;
	lq.tail = np;
	return true;
}
//出队
bool deQueue(point &tq)
{
	if(lq.head == lq.tail)
		return false;
	starListNode *slnp;
	slnp = lq.head->next;
	tq.x = slnp->p.x;
	tq.y = slnp->p.y;
	lq.head->next = slnp->next;
	if(slnp == lq.tail)
		lq.tail = lq.head;
	delete slnp;
	return true;
}
//小星星类
class star
{
public:
	int x;//横坐标
	int y;//纵坐标
	int type;//取值为1到5,6表示背景色
	int state;//0表示未被选中,1表示被选中
};
star st[10][10];
//初始化所有星星
void initStar()
{
	for(int i = 0;i < 10;i++)
		for(int j = 0;j < 10;j++)
		{
			st[i][j].x = j;
			st[i][j].y = i;
			st[i][j].type = rand()%5 + 1;
			st[i][j].state = 0;
		}
}
//判断某一个星星的上方是否还有未消去的星星,如果还有未消去的星星则返回true,否则返回false
bool upExistStar(star s)
{
	int j = s.x;
	int i = s.y;
	for(;i > 0;--i)
	{
		if(st[i-1][j].type != 6)
			return true;
	}
	return false;
}
//处理空格,使星星下落
void dealBlank()
{
	int i,j,m;
	for(j = 0;j < 10;++j)
	{
		for(i = 9;i > 0;--i)
		{
			if(st[i][j].type == 6 && upExistStar(st[i][j]) == true)
			{
				for(m = i;m > 0;--m)
					st[m][j].type = st[m-1][j].type;
				st[m][j].type = 6;
			}	
		}
	}
}
//判断某一列是否为空白
bool isBlankColumn(int j)
{
	for(int i = 0;i < 10;i++)
	{
		if(st[i][j].type != 6)
			return false;
	}
	return true;
}
//消去出现的空白列
void dealBlankColumn()
{
	for(int j = 0;j < 10;j++)
	{
		if(isBlankColumn(j))
		{
			for(int m = j;m < 9;m++)
				for(int i = 0;i < 10;i++)
					st[i][m].type = st[i][m+1].type;
		}
	}
}
//当选中一颗小星星时,找到与它相邻的所有相同星星
void findAllSameStar(int sx,int sy)
{
	if(st[sx][sy].type == 6)
		return;
	st[sx][sy].state = 1;
	int starType = st[sx][sy].type;
	point tepo;
	tepo.x = st[sx][sy].x;
	tepo.y = st[sx][sy].y;
	initListQueue();
	enQueue(tepo);
	point tp;
	//用BFS算法,找到与选中的小星星相同的所有相邻小星星
	while(deQueue(tp))
	{
		if(tp.x > 0 && st[tp.x - 1][tp.y].type == starType && st[tp.x - 1][tp.y].state != 1)
		{
			st[tp.x - 1][tp.y].state = 1;
			tepo.x = tp.x - 1;
			tepo.y = tp.y;
			enQueue(tepo);
		}
		if(tp.x < 9 && st[tp.x + 1][tp.y].type == starType && st[tp.x + 1][tp.y].state != 1)
		{
			st[tp.x + 1][tp.y].state = 1;
			tepo.x = tp.x + 1;
			tepo.y = tp.y;
			enQueue(tepo);
		}
		if(tp.y > 0 && st[tp.x][tp.y - 1].type == starType && st[tp.x][tp.y - 1].state != 1)
		{
			st[tp.x][tp.y - 1].state = 1;
			tepo.x = tp.x;
			tepo.y = tp.y - 1;
			enQueue(tepo);
		}
		if(tp.y < 9 && st[tp.x][tp.y + 1].type == starType && st[tp.x][tp.y + 1].state != 1)
		{
			st[tp.x][tp.y + 1].state = 1;
			tepo.x = tp.x;
			tepo.y = tp.y + 1;
			enQueue(tepo);
		}
	}
}
int score = 0;
//当鼠标再次点击选中的小星星时,与它相邻的所有相同小星星均消失,并且悬空的小星星下降,空白列被消除
void wipeAllStar()
{
	for(int i = 0;i < 10;i++)
	{
		for(int j = 0;j < 10;j++)
		{
			if(st[i][j].state == 1 && st[i][j].type != 6)
			{
				st[i][j].type = 6;
				score += 200;//每消去一个星星得200分
				st[i][j].state = 0;//消去后状态改为未选中
			}
		}
	}
	//处理悬空的小星星,在这里要调用3次dealBlank()是因为如果第一行的一个小星星最大可能向下滑9格,但是在这种情况下调用一次dealBlank()后距离底部的单元格数是4,需要再调用两次dealBlank()才能使小星星坠落到底部
	dealBlank();
	dealBlank();
	dealBlank();
	//处理空白列
	dealBlankColumn();
}

抱歉!评论已关闭.