<html>

<head><script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- MyFirstUnitAd -->
<ins class="adsbygoogle"
     style="display:inline-block;width:970px;height:250px"
     data-ad-client="ca-pub-5778386704669218"
     data-ad-slot="1503492166"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>

<meta http-equiv="Content-Language" content="zh-cn">
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>labyrith</title>
</head>

<body>



<p align="left"><font size="6" color="#FF0000"><span lang="en-ca"><b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </b></span>
<b>&nbsp;<span lang="en-ca">&nbsp;&nbsp; </span></b></font><span lang="en-ca">
<font size="6" color="#FF0000"><b>Labyrinth-Revisited </b></font></span></p>

<div align="left">
  <pre><b><font color="#ff0000" size="5">A. <span lang="en-ca">Fourth?</span> Edition</font></b></pre>
</div>
<div align="left">
  <pre><b><font size="3">This is <span lang="en-ca">the intermediate version of my 15 puzzle. And it is not surprise to ask what is relation</span></font></b></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>between this labyrinth-finding question and 15 puzzle. I want to use a &quot;snake&quot; to represent my</b></font></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>path on board. This &quot;snake&quot; or &quot;Cluster&quot; can grow and move step by step. It is the path for &quot;space&quot;</b></font></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>to move. It can also be the body of a &quot;string of numbers&quot;, i.e. 1234. You will see that on 15 puzzle</b></font></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>your goal is to make a correct sequence of numbers. If you can see this, you will understand what</b></font></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>I want to do.</b></font></span></pre>
</div>
<div align="left">
  <pre><b><font color="#ff0000" size="5"><span lang="en-ca">B</span>.<span lang="en-ca"><a name="problem"></a>The problem</span></font></b></pre>
</div>
<div align="left">
  <p ALIGN="LEFT"><span lang="en-ca">The 15 puzzle? Or the path for a node to 
  move? Or the path for a cluster of number to move, like snake? Or the</span></div>
<div align="left">
  <p ALIGN="LEFT"><span lang="en-ca">number cluster itself?</span></div>
<div align="left">
  <p ALIGN="LEFT">　</div>
<div align="left">
  <b><font color="#ff0000" size="5"><span lang="en-ca"><a name="explain"></a>C</span>.<span lang="en-ca">The
  </span></font></b><span lang="en-ca"><font size="5" color="#FF0000"><b>idea of 
  program</b></font></span></div>
<div align="left">
  　</div>
<div align="left">
  <pre><span lang="en-ca">Since I have to memorize all coordinate I have been in the labyrinth, there is no better way than a simple DFS. I would not</span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca">bother to find any algorithm, as all algorithms require you to memorize the position you have been to.</span></pre>
</div>
<div align="left">
  <pre><b><font color="#ff0000" size="5">D.<span lang="en-ca"><a name="Method"></a>The </span>major functions</font></b></pre>
</div>
<div align="left">
  <pre>　</pre>
</div>
<div align="left">
  <pre><b><font color="#ff0000" size="5"><span lang="en-ca">E</span>.</font></b><span lang="en-ca"><font size="5" color="#FF0000"><b>Further improvement</b></font></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca">The next step is to implement the move a single node on board, then the whole cluster move.</span></pre>
</div>
<div align="left">
  <pre><b><font color="#ff0000" size="5"><span lang="en-ca">F</span>.</font></b><span lang="en-ca"><font size="5" color="#FF0000"><b>File listing</b></font></span></pre>
</div>
<div align="left" style="width: 898; height: 86">
  <pre><font size="3"><b><span lang="en-ca">1. node</span>.</b></font><span lang="en-ca"><font size="3"><b>h</b></font></span></pre>
  <pre><span lang="en-ca"><font size="3"><b>2</b></font></span><font size="3"><b><span lang="en-ca">. node</span>.cpp</b></font></pre>
  <pre><span lang="en-ca"><font size="3"><b>3</b></font></span><font size="3"><b><span lang="en-ca">. cluster</span>.<span lang="en-ca">h</span></b></font></pre>
  <pre><span lang="en-ca"><font size="3"><b>4</b></font></span><font size="3"><b><span lang="en-ca">. cluster</span>.cpp</b></font></pre>
  <pre><span lang="en-ca"><font size="3"><b>5</b></font></span><font size="3"><b><span lang="en-ca">. board</span>.<span lang="en-ca">h</span></b></font></pre>
  <pre><span lang="en-ca"><font size="3"><b>6</b></font></span><font size="3"><b><span lang="en-ca">. board</span>.</b></font><span lang="en-ca"><font size="3"><b>cpp</b></font></span></pre>
  <pre><font size="3"><b><span lang="en-ca">7. main</span>.<span lang="en-ca">cpp</span></b></font></pre>
  <pre>　</pre>
  <pre><font size="3" color="#FF0000"><b><span lang="en-ca">file name: node</span>.<span lang="en-ca">h</span></b></font></pre>
  <pre>#ifndef NODE_H
#define NODE_H

#include &lt;stdio.h&gt;
#include &lt;math.h&gt;

const int BoardSize=4;
const int MaxNodesLength=BoardSize*2-1;
const int MaxBoardSize=10;
const int MinimumRotateSize=2;

//#define abs(x) (x&gt;=0?x:-x)


enum Direction
{
	U, R , D , L, None 
};

enum Position
{
	Right, DownRight, Down, DownLeft, Left, UpLeft, Up, UpRight
};

//class Puzzle;

class Coord
{
	friend class Board;
private:
	int row;
	int col;	
public:
	const Coord&amp; operator=(const Coord&amp; rhs);
	bool operator==(const Coord&amp; rhs) const;
	bool operator!=(const Coord&amp; rhs) const ;
	bool neighbour(const Coord&amp; rhs) const;
	void move(Direction dir);
	Coord(int r=-1, int c=-1);
};



#endif</pre>
  <pre>　</pre>
  <pre><font size="3" color="#FF0000"><b><span lang="en-ca">file name: node</span>.</b></font><span lang="en-ca"><font size="3" color="#FF0000"><b>cpp</b></font></span></pre>
  <pre>#include &quot;cluster.h&quot;
#include &lt;math.h&gt;


const Coord Cluster::getHead()
{
	return nodes[head];
}


bool Cluster::removeHead()
{
	if (length==0)
	{
		return false;
	}
	else
	{
		length--;
		head=(head+1)%MaxNodesLength;	
	}
	return true;
}

void Cluster::clear()
{
	initialize();
}

bool Cluster::step(Direction dir)
{
	Coord dummy;
	dummy=nodes[head];
	dummy.move(dir);
	return step(dummy);
}

//valid for two meanings:
//1. not eat any node
//2. adjacent to head
bool Cluster::step(const Coord&amp; newPos)
{
	//don't bite your tail or body
	if (isNode(newPos))
	{
		return false;
	}
	//can you bite too far?
	if (!nodes[head].neighbour(newPos))
	{
		return false;
	}
	head--;
	if (head&lt;0)
	{
		head+=MaxNodesLength;
	}
	nodes[head]=newPos;
	return true;
}

bool Cluster::isNode(const Coord&amp; rhs)
{
	for (int i=0; i&lt;length; i++)
	{
		if (this-&gt;operator[](i)==rhs)
		{
			return true;
		}
	}
	return false;
}

void Cluster::initialize()
{
	head=-1;
	length=0;
}

Cluster::Cluster()
{
	initialize();
}


//unless it is first time or cleared, you cannot set head
//when it already has one
bool Cluster::setHead(const Coord&amp; first)
{
	if (head!=-1)
	{
		return false;
	}
	head=0;
	length=1;
	nodes[head]=first;
	return true;
}

bool Cluster::addTail(const Coord&amp; newTail)
{
	int tail=(head+length)%MaxNodesLength;
	if (length==MaxNodesLength)
	{
		return false;
	}
	if (isNode(newTail))
	{
		return false;
	}
	if (!nodes[tail].neighbour(newTail))
	{
		return false;
	}

	length++;
	tail=(head+length)%MaxNodesLength;
	nodes[tail]=newTail;
	return true;
}

int Cluster::index(const Coord&amp; pos) const
{
	for (int i=0; i&lt;length; i++)
	{
		if (this-&gt;operator [](i)==pos)
		{
			return i;
		}
	}
	return -1;
}


bool Cluster::addHead(const Coord&amp; newHead)
{
	if (length==MaxNodesLength)
	{
		return false;
	}
	if (isNode(newHead))
	{
		return false;
	}
	if (!nodes[head].neighbour(newHead))
	{
		return false;
	}
	length++;
	head--;
	if (head&lt;0)
	{
		head+=MaxNodesLength;
	}
	
	nodes[head]=newHead;
	return true;
}


Coord Cluster::operator [](int index) const
{
	return nodes[(head+index)%MaxNodesLength];
}</pre>
  <pre>　</pre>
  <pre><font size="3" color="#FF0000"><b><span lang="en-ca">file name: cluster</span>.<span lang="en-ca">h</span></b></font></pre>
  <pre>#include &lt;stdio.h&gt;
#include &quot;node.h&quot;


class Cluster
{
private:
	int length;
	Coord nodes[MaxNodesLength];
	//bool ascending;
	int head;//this is the head pos, as head is moving
	void initialize();
public:
	void clear();
	const Coord getHead();
	bool step(const Coord&amp; newPos);//must be a valid move
	bool step(Direction dir);
	bool addTail(const Coord&amp; newTail);
	bool isNode(const Coord&amp; rhs);
	bool addHead(const Coord&amp; newHead);
	bool removeHead();
	bool setHead(const Coord&amp; first);
	Coord operator[](int index) const;
	int index(const Coord&amp; pos) const;
	Cluster();
};


<font size="3" color="#FF0000"><b><span lang="en-ca">file name: cluster</span>.<span lang="en-ca">cpp</span></b></font></pre>
  <pre>#include &quot;cluster.h&quot;
#include &lt;math.h&gt;


const Coord Cluster::getHead()
{
	return nodes[head];
}


bool Cluster::removeHead()
{
	if (length==0)
	{
		return false;
	}
	else
	{
		length--;
		head=(head+1)%MaxNodesLength;	
	}
	return true;
}

void Cluster::clear()
{
	initialize();
}

bool Cluster::step(Direction dir)
{
	Coord dummy;
	dummy=nodes[head];
	dummy.move(dir);
	return step(dummy);
}

//valid for two meanings:
//1. not eat any node
//2. adjacent to head
bool Cluster::step(const Coord&amp; newPos)
{
	//don't bite your tail or body
	if (isNode(newPos))
	{
		return false;
	}
	//can you bite too far?
	if (!nodes[head].neighbour(newPos))
	{
		return false;
	}
	head--;
	if (head&lt;0)
	{
		head+=MaxNodesLength;
	}
	nodes[head]=newPos;
	return true;
}

bool Cluster::isNode(const Coord&amp; rhs)
{
	for (int i=0; i&lt;length; i++)
	{
		if (this-&gt;operator[](i)==rhs)
		{
			return true;
		}
	}
	return false;
}

void Cluster::initialize()
{
	head=-1;
	length=0;
}

Cluster::Cluster()
{
	initialize();
}


//unless it is first time or cleared, you cannot set head
//when it already has one
bool Cluster::setHead(const Coord&amp; first)
{
	if (head!=-1)
	{
		return false;
	}
	head=0;
	length=1;
	nodes[head]=first;
	return true;
}

bool Cluster::addTail(const Coord&amp; newTail)
{
	int tail=(head+length)%MaxNodesLength;
	if (length==MaxNodesLength)
	{
		return false;
	}
	if (isNode(newTail))
	{
		return false;
	}
	if (!nodes[tail].neighbour(newTail))
	{
		return false;
	}

	length++;
	tail=(head+length)%MaxNodesLength;
	nodes[tail]=newTail;
	return true;
}

int Cluster::index(const Coord&amp; pos) const
{
	for (int i=0; i&lt;length; i++)
	{
		if (this-&gt;operator [](i)==pos)
		{
			return i;
		}
	}
	return -1;
}


bool Cluster::addHead(const Coord&amp; newHead)
{
	if (length==MaxNodesLength)
	{
		return false;
	}
	if (isNode(newHead))
	{
		return false;
	}
	if (!nodes[head].neighbour(newHead))
	{
		return false;
	}
	length++;
	head--;
	if (head&lt;0)
	{
		head+=MaxNodesLength;
	}
	
	nodes[head]=newHead;
	return true;
}


Coord Cluster::operator [](int index) const
{
	return nodes[(head+index)%MaxNodesLength];
}</pre>
  <pre>　</pre>
  <pre><font size="3" color="#FF0000"><b><span lang="en-ca">file name: board</span>.<span lang="en-ca">h</span></b></font></pre>
  <pre>#include &quot;cluster.h&quot;
#include &quot;node.h&quot;


class Board
{
	friend class Cluster;
private:
	int board [BoardSize][BoardSize];
	bool map[BoardSize][BoardSize];
	bool restrict[BoardSize][BoardSize];
	Cluster path;
	int size;
	void initialize();
	bool valid(const Coord&amp; pos);
	Direction findDir(const Coord&amp; start, const Coord&amp; end);
	Direction findNextDir(const Coord&amp; curr, Direction dir);
	bool impasse(const Coord&amp; curr, Direction dir);
	bool doPathFinding(const Coord&amp; curr, const Coord&amp; end, Direction dir);
public:
	Board(int theSize=BoardSize);
	void display();
	void displayPath(bool showPath=true);
	bool pathFinding(const Coord&amp; start, const Coord&amp; end);
	bool pathFinding(const Coord&amp; end);
	bool pathFinding2(const Coord&amp; start, const Coord&amp; end);
	void setRestrict(const Coord&amp; pos);
	void resetRestrict(const Coord&amp; pos);
};


</pre>
  <pre><font size="3" color="#FF0000"><b><span lang="en-ca">file name: board</span>.<span lang="en-ca">cpp</span></b></font></pre>
  <pre>#include &quot;board.h&quot;



int settings[BoardSize][BoardSize]=
{
	{1, 5,   2,  3 },
	{4, 10,   0,  7 }, 
	{8, 9,    6, 11},
	{12, 13, 14,  15}
};

void Board::displayPath(bool showPath)
{
	Coord curr;
	int index;
	for (int i=0; i&lt;size; i++)
	{
		for (int j=0; j&lt;size; j++)
		{
			curr.row=i;
			curr.col=j;
			index=path.index(curr);
			if (index!=-1)
			{
				if (showPath)
				{
					printf(&quot;%2d\t&quot;, index);
				}
				else
				{
					printf(&quot;%2d\t&quot;, board[i][j]);
				}
			}
			else
			{
				printf(&quot;%c%c\t&quot;, '*', '*');
			}			
		}
		printf(&quot;\n&quot;);
	}
}

//this is the rather direct path
bool Board::pathFinding(const Coord&amp; start, const Coord&amp; end)
{
	Coord curr;
	Direction dir;
	path.clear();
	path.setHead(start);
	curr=path.getHead();
	while (curr!=end)
	{
		dir=findDir(curr, end);
		curr.move(dir);
		if (valid(curr))
		{
			path.addHead(curr);
			curr=path.getHead();//??not necessary
		}
		else
		{
			//it must be something restricted and it is a 
			//a more generate way of finding path
			for (int i=0; i&lt;size; i++)
			{
				for (int j=0; j&lt;size; j++)
				{
					map[i][j]=false;
				}
			}
			map[start.row][start.col]=true;//I am here!!!
			path.clear();//restart!!
			path.setHead(start);
			return pathFinding2(start, end);
		}
	}
	return true;
}





bool Board::pathFinding2(const Coord&amp; start, const Coord&amp; end)
{
	Coord curr;
	if (start==end)
	{
		return true;
	}
	for (int dir=0; dir&lt;4; dir++)
	{
		curr=start;
		curr.move((Direction)dir);
		if (valid(curr))
		{
			if (!map[curr.row][curr.col])
			{
				path.addHead(curr);
				map[curr.row][curr.col]=true;
				if (pathFinding2(curr, end))
				{
					return true;
				}
				else
				{
					path.removeHead();
					//anyway, I have been here before
					//map[curr.row][curr.col]=false;
				}
			}
		}	
	}
	return false;
}


void Board::setRestrict(const Coord&amp; pos)
{
	restrict[pos.row][pos.col]=true;
}

void Board::resetRestrict(const Coord&amp; pos)
{
	restrict[pos.row][pos.col]=false;
}

bool Board::impasse(const Coord&amp; curr, Direction dir)
{
	Coord dummy;
	dummy=curr;
	dummy.move(dir);
	return valid(dummy);
}

//this way has a fatal problem of circling
Direction Board::findNextDir(const Coord&amp; curr, Direction dir)
{
	Direction result=dir, turnLeft;
	//first try old direction,
	while (impasse(curr, result))
	{
		//cannot advance, so turn right, or next dir
		result=(Direction)((result+1)%4);
	}
	if (result!=dir)//means we already turned to right, so, return
	{
		return result;
	}
	else
	{
		//we must turn to left BEFORE we run into wall
		turnLeft=result;//initialize
		do 
		{
			result=turnLeft;//must!!!
			turnLeft=(Direction)(result-1&lt;0?3:result-1);
		}while (!impasse(curr, turnLeft));
		return result;//result is the dir before turning left
	}
}
	


bool Board::pathFinding(const Coord&amp; end)
{
	Coord curr;
	Direction dir;
	curr=path.getHead();
	//in what case, should I return false? a dead end?
	dir=findDir(curr, end);
	while (curr!=end)
	{
		dir=findNextDir(curr, dir);
		curr.move(dir);
		path.addHead(curr);
		curr=path.getHead();
	}
	return true;
}



Direction Board::findDir(const Coord&amp; start, const Coord&amp; end)
{
	int rOff, cOff;
	rOff=end.row-start.row;
	cOff=end.col-start.col;
	if (abs(rOff)&gt;abs(cOff))
	{
		return rOff&gt;0?D:U;
	}
	else
	{
		return cOff&gt;0?R:L;
	}
}

Board::Board(int theSize)
{
	size=theSize;
	initialize();

}

bool Board::valid(const Coord&amp; pos)
{
	if (pos.col&lt;0||pos.row&lt;0||pos.col&gt;=size||pos.row&gt;=size)
	{
		return false;
	}
	return !restrict[pos.row][pos.col];
}


void Board::display()
{
	printf(&quot;the size of board is %d\n&quot;, size);
	for (int i=0; i&lt;size; i++)
	{
		for(int j=0; j&lt;size; j++)
		{
			printf(&quot;%2d\t&quot;, board[i][j]);
		}
		printf(&quot;\n&quot;);
	}
}

void Board::initialize()
{
	for (int i=0; i&lt;size; i++)
	{
		for (int j=0; j&lt;size; j++)
		{
			board[i][j]=settings[i][j];
			restrict[i][j]=false;
		}
	}
}
	
</pre>
  <pre><font size="3" color="#FF0000"><b><span lang="en-ca">file name: main</span>.<span lang="en-ca">cpp</span></b></font></pre>
  <pre>#include &lt;stdio.h&gt;
#include &quot;board.h&quot;
#include &quot;node.h&quot;



int main()
{
	Board B;
	Coord start(0,3), end(3,1), temp(2,2), temp1(3,3);
	B.setRestrict(temp);
	B.setRestrict(temp1);
	B.pathFinding(start, end);
	B.displayPath();
	return 0;
}</pre>
  <pre>　</pre>
</div>
<pre></pre>
<pre><b><font color="#0000FF"><span lang="en-ca"><a name="result"></a>The result is like following:</span></font></b></pre>

<pre>** 2 3 6
** 1 4 5
** 0 ** **
** ** ** **
Press any key to continue</pre>

<pre><span lang="en-ca">				</span> <a href="game24.htm"><img src="picture/back.gif" style="border: medium none" alt="back.gif (341 bytes)" width="32" height="35"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="index.htm"><img src="picture/up.gif" style="border: medium none" alt="up.gif (335 bytes)" width="35" height="32"></a> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img src="picture/next.gif" style="border: medium none" alt="next.gif (337 bytes)" width="32" height="35"> </pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;                                   
&nbsp;&nbsp;&nbsp;</p>

</body>

</html>