<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[8er-Puzzle]]></title><description><![CDATA[<p>Hallo!<br />
Ich habe ein Problem. Ich möchte ein sogenanntes 8er-Puzzle lösen.<br />
Ich habe zwar ein Programm das funktioniert, dieses verwendet aber eine eigene Klasse als queue. Nun möchte ich aber eine priority_queue der STL verwenden. Kann mir jemand helfen, wie ich das anstellen kann??<br />
Vielen Dank schon im Voraus!<br />
mfg</p>
<p>main:<br />
#include &lt;iostream&gt;<br />
#include &quot;puzzle.h&quot;<br />
#include &lt;queue&gt;<br />
#include &lt;deque&gt;<br />
#include &lt;functional&gt;</p>
<p>using namespace std;</p>
<p>int main()<br />
{</p>
<p>cout &lt;&lt; &quot;Programm zur Loesung des 8er-Puzzle&quot; &lt;&lt; endl;</p>
<p>bool flag = true;</p>
<p>//Heuristik waehlen<br />
cout &lt;&lt; &quot;Welche Heuristik?&quot; &lt;&lt; endl;<br />
cout &lt;&lt; &quot;1 fuer Spielsteine&quot; &lt;&lt; endl;<br />
cout &lt;&lt; &quot;2 fuer Manhattan&quot; &lt;&lt; endl;<br />
cout &lt;&lt; &quot;3 zum Beenden des Programms&quot; &lt;&lt; endl;<br />
int Eingabe;<br />
cin &gt;&gt; Eingabe;</p>
<p>if(Eingabe == 3)<br />
return 0;</p>
<p>//Startzustand<br />
//int arrStart[3][3] = {{1,0,3},{8,2,4},{7,6,5}};<br />
int arrStart[3][3];<br />
cout &lt;&lt; &quot;Geben Sie den Startzustand ein:&quot; &lt;&lt; endl;<br />
cout &lt;&lt; &quot;Zahlen von 0-8 in einer beliebigen Reihenfolge&quot; &lt;&lt; endl;</p>
<p>for (int i = 0; i &lt; 9; i++)<br />
cin &gt;&gt; arrStart[i/3][i%3];</p>
<p>//Endzustand<br />
int arrZiel[3][3] = {{1,2,3},{8,0,4},{7,6,5}};</p>
<p>cout &lt;&lt; &quot;Startzustand:&quot; &lt;&lt; endl;<br />
for(int x = 0; x&lt;3; x++){<br />
for(int y = 0; y&lt;3 ; y++)<br />
cout &lt;&lt; arrStart[x][y];<br />
cout &lt;&lt; endl;<br />
}<br />
cout &lt;&lt; endl;</p>
<p>//priority_queue&lt;int,deque&lt;int&gt; &gt; puzzle;<br />
<a href="//puzzle.push">//puzzle.push</a>(arrStart);<br />
<a href="//puzzle.push">//puzzle.push</a>(arrZiel);</p>
<p>expsortqueue puzzle(arrStart, arrZiel);<br />
knoten *best;</p>
<p>//priority_queue&lt;knoten *, deque&lt;int&gt; &gt; OPEN;<br />
list&lt;knoten *&gt; CLOSED;</p>
<p>best = puzzle.pop();</p>
<p>if(Eingabe == 2){<br />
while (best-&gt;manhattan() != 0 &amp;&amp; flag){<br />
puzzle.expand(best);<br />
best = puzzle.pop();<br />
best-&gt;printKnoten();<br />
//Aktuellen Stand drucken?<br />
flag = !puzzle.isemptyqueue();<br />
}<br />
}<br />
else{<br />
while (best-&gt;spielsteine() != 0 &amp;&amp; flag){<br />
puzzle.expand(best);<br />
best = puzzle.pop();<br />
best-&gt;printKnoten();<br />
//Aktuellen Stand drucken?<br />
flag = !puzzle.isemptyqueue();<br />
}</p>
<p>}</p>
<p>if (flag){<br />
cout &lt;&lt; &quot;Solution found!&quot; &lt;&lt; endl;<br />
cout &lt;&lt; &quot;The sequence to get to the goal is: &quot;;<br />
best-&gt;printWeg();<br />
cout &lt;&lt; &quot;Zielzustand:&quot; &lt;&lt; endl;<br />
best-&gt;printKnoten();<br />
}<br />
else<br />
cout &lt;&lt; &quot;Problem has no solution, search tree exausted. Expanded &quot; &lt;&lt; best-&gt;level() &lt;&lt; &quot; levels&quot; &lt;&lt; endl;</p>
<p>//cout &lt;&lt; puzzle.nodesexpanded &lt;&lt; &quot; nodes expanded&quot; &lt;&lt; endl;</p>
<p>delete [] best;</p>
<p>return 0;<br />
}</p>
<p>puzzle.h:<br />
#ifndef _PUZZLE_<br />
#define _PUZZLE_</p>
<p>#include &lt;list&gt;<br />
#include &lt;queue&gt;<br />
#include &lt;cmath&gt;<br />
using namespace std;</p>
<p>//moegliche Richtungen<br />
enum richtung{UP, RIGHT, DOWN, LEFT, CENTER};</p>
<p>//Zielzustand<br />
int ziel[9];</p>
<p>//ein Punkt auf dem Brett<br />
struct punkt{<br />
int x;<br />
int y;<br />
};</p>
<p>class knoten {<br />
private:<br />
//int * puzzle; //Puzzle des Knotens<br />
knoten *nextKnoten; //Nächster Knoten in der queue<br />
int h,g; //Schätzwert Heuristik und Pfadkosten<br />
punkt leer; //Position des leeren Steins (0)<br />
richtung weg[2020]; //Speichert die Schritte der Leerstelle<br />
//struct listenelement *wegende; //Zeiger auf letzten Wegknoten<br />
//struct listenelement *weg; //Zeiger auf ersten Wegknoten<br />
public:<br />
knoten(knoten *vorgaenger, richtung dir); //Konstruktor<br />
knoten(int brt[3][3]); //Konstruktor<br />
int brett[3][3]; //8-puzzle brett<br />
void insert(knoten *next); //Fügt knoten ein<br />
knoten *getNext(); //Gibt adresse des nächsten Knoten zurück<br />
int f(); //Gibt f(n) zurück<br />
int manhattan(); //Gibt Manhattan-Distanz oder Spielsteine zurück<br />
int spielsteine();<br />
bool schieben(richtung dir); //Gibt an ob die Leerstelle in diese Richtung verschoben werden kann<br />
int level(); //Gibt den Level zurück, basierend auf g(n)<br />
richtung letzteDir(); //Gibt die Richtung an, in welche die Leerstelle als letztes verschoben wurde<br />
void printWeg(); //Gibt den Loesungsweg des Puzzles aus<br />
void printKnoten();<br />
};</p>
<p>//Prototypen<br />
int position(knoten *square);<br />
void change(int &amp;n1, int &amp;n2); //switch two items of a matrix<br />
punkt copyboard(int src[3][3], int dest[3][3]); //copy a matrix representing a board and return the zero position<br />
richtung invers(richtung dir);</p>
<p>// Priority queue<br />
class expsortqueue {<br />
private:<br />
knoten *first; //pointer to first node in queue (biggest f(n))<br />
knoten *last; //pointer to last node in queue (smallest f(n))<br />
int initial[3][3]; //initial state<br />
char visits[45360]; //binary hash to store the states already used (positions = 9!/8bits)<br />
public:<br />
//int queuesize; //just for testing<br />
//int nodesexpanded; //just for testing<br />
expsortqueue(int init[3][3], int ending[3][3]); //constructor<br />
~expsortqueue(); //destructor<br />
knoten *pop(); //get node on top of the queue<br />
void pushnsort(knoten *newnode); //put a new node in the queue<br />
void expand(knoten *parent); //expands a node<br />
bool isemptyqueue(); //determines if there are more states left in the queue<br />
bool wasvisited(knoten *square);<br />
void dovisit(knoten *square);<br />
};</p>
<p>//struct liste {<br />
// struct listenelement *anfang;<br />
// struct listenelement *ende;<br />
//};</p>
<p>//struct knoten V[</p>
<p>//Implementation der Klasse knoten</p>
<p>//Konstruktor fuer Startknoten<br />
knoten::knoten(int brt[3][3])<br />
{<br />
g = 0;</p>
<p>//copy brd into this node's board<br />
leer = copyboard(brt, brett);</p>
<p>h = manhattan(); //get manhatan distance</p>
<p>//setup linked list<br />
weg[0]=CENTER;<br />
weg[1]=CENTER;<br />
nextKnoten = NULL;</p>
<p>}</p>
<p>//Konstruktor fuer weitere Knoten<br />
knoten::knoten(knoten *vorgaenger, richtung dir)<br />
{<br />
int i;<br />
punkt lastblank;<br />
g = vorgaenger-&gt;g + 1;</p>
<p>//make a copY of the parent's board into this node's board<br />
leer = copyboard(vorgaenger-&gt;brett, brett);</p>
<p>//move positions according to direction dir<br />
lastblank = leer;<br />
switch(dir){<br />
case UP: leer.y--; break;<br />
case RIGHT: leer.x++; break;<br />
case DOWN: leer.y++; break;<br />
case LEFT: leer.x--; break;<br />
}<br />
change(brett[lastblank.y][lastblank.x], brett[leer.y][leer.x]);</p>
<p>h = manhattan(); //get manhatan distance</p>
<p>//setup linked list<br />
for (i=1; vorgaenger-&gt;weg[i] != CENTER; i++)<br />
weg[i]=vorgaenger-&gt;weg[i];<br />
weg[i] = dir;<br />
weg[i+1] = CENTER;<br />
nextKnoten = NULL;<br />
}</p>
<p>bool knoten::schieben(richtung dir)<br />
{<br />
switch(dir){<br />
case UP: if (leer.y &gt; 0) return true; break;<br />
case RIGHT: if (leer.x &lt; 2) return true; break;<br />
case DOWN: if (leer.y &lt; 2) return true; break;<br />
case LEFT: if (leer.x &gt; 0) return true; break;<br />
}<br />
return false;<br />
}</p>
<p>int knoten::manhattan()<br />
{<br />
int i, pos;<br />
int result=0;<br />
int x, y;</p>
<p>//the goal is defined by putting the position (1 trhough 9)<br />
//of the square at the array item with index equal to the<br />
//face number of the square.<br />
//smallnum ending[9] = {4,0,1,2,5,8,7,6,3}; //bonus = {8,0,1,2,3,4,5,6,7}</p>
<p>for (i = 0; i &lt; 9; i++){<br />
y = i/3;<br />
x = i%3;<br />
pos = brett[y][x];<br />
result+=abs(x - ziel[pos]%3); //addiere x distanz<br />
result+=abs(y - ziel[pos]/3); //addiere y distanz<br />
}<br />
return result;<br />
}</p>
<p>int knoten::spielsteine()<br />
{<br />
int i, pos;<br />
int result=0;<br />
int x, y;</p>
<p>//the goal is defined by putting the position (1 trhough 9)<br />
//of the square at the array item with index equal to the<br />
//face number of the square.<br />
//smallnum ending[9] = {4,0,1,2,5,8,7,6,3}; //bonus = {8,0,1,2,3,4,5,6,7}</p>
<p>for (i = 0; i &lt; 9; i++){<br />
y = i/3;<br />
x = i%3;<br />
pos = brett[y][x];<br />
if((abs(x - ziel[pos]%3) + abs(y - ziel[pos]/3)) != 0)<br />
result++;<br />
//Addiere 1 fuer jeden Spielstein, der nicht an der richtigen Position liegt<br />
}<br />
return result;<br />
}</p>
<p>void knoten::printKnoten()<br />
{<br />
int i;</p>
<p>for (i = 0; i &lt; 9; i++){<br />
cout &lt;&lt; brett[i/3][i%3];<br />
if (i%3 == 2)<br />
cout &lt;&lt; endl;<br />
}<br />
cout &lt;&lt; endl;<br />
}</p>
<p>int knoten::level()<br />
{<br />
return g;<br />
}</p>
<p>richtung knoten::letzteDir()<br />
{<br />
return weg[g];<br />
}</p>
<p>void knoten::printWeg()<br />
{<br />
int i = 1;</p>
<p>//Print solution using the history<br />
while (weg[i] != CENTER){<br />
switch(weg[i]){<br />
case UP: cout &lt;&lt; &quot;up, &quot;; break;<br />
case DOWN: cout &lt;&lt; &quot;down, &quot;; break;<br />
case LEFT: cout &lt;&lt; &quot;left, &quot;; break;<br />
case RIGHT: cout &lt;&lt; &quot;right, &quot;; break;<br />
}<br />
i++;<br />
}<br />
cout &lt;&lt; endl;<br />
}</p>
<p>knoten *knoten::getNext()<br />
{<br />
return nextKnoten;<br />
}</p>
<p>void knoten::insert(knoten *next)<br />
{<br />
nextKnoten = next;<br />
}</p>
<p>int knoten::f()<br />
{<br />
return g + h;<br />
}</p>
<p>//Implementation der queue Klasse</p>
<p>expsortqueue::expsortqueue(int init[3][3], int ending[3][3]) //constructor<br />
{<br />
int i;</p>
<p>//copy starting and ending states<br />
for (i = 0; i &lt; 9; i++){<br />
ziel[ending[i/3][i%3&rsqb;&rsqb;=i;<br />
initial[i/3][i%3] = init[i/3][i%3];<br />
}</p>
<p>//initialize visited states to 0<br />
for (i = 0; i &lt; 45360; i++)<br />
visits[i] = 0;</p>
<p>//initialize linked list<br />
first = new knoten(initial);<br />
last = first;<br />
//queuesize = 1;<br />
//nodesexpanded = 0;<br />
}</p>
<p>expsortqueue::~expsortqueue(){<br />
knoten *i, *tmp;</p>
<p>for (i = pop(); i!=NULL; i = pop())<br />
delete [] i;<br />
}</p>
<p>// create the children for parent node<br />
void expsortqueue::expand(knoten *vorgaenger)<br />
{<br />
richtung i;<br />
knoten *newnode;<br />
int h, g; //heuristics and path cost<br />
int brett[3][3]; //8-puzzle board<br />
punkt leer; //position of blank space (0)</p>
<p>i = UP;<br />
//make just the necessary objects<br />
//avoid making imposible states and states coming from the state before de parent<br />
if (invers(vorgaenger-&gt;letzteDir())!=i &amp;&amp; vorgaenger-&gt;schieben(i)){<br />
newnode = new knoten(vorgaenger, i);<br />
//don't push new state if it was already used<br />
if (!wasvisited(newnode)){</p>
<p>//nodesexpanded++;<br />
pushnsort (newnode);<br />
}<br />
else{<br />
delete [] newnode;<br />
}<br />
}</p>
<p>i = RIGHT;<br />
//make just the necessary objects<br />
//avoid making imposible states and states coming from the state before de parent<br />
if (invers(vorgaenger-&gt;letzteDir())!=i &amp;&amp; vorgaenger-&gt;schieben(i)){<br />
newnode = new knoten(vorgaenger, i);<br />
//don't push new state if it was already used<br />
if (!wasvisited(newnode)){</p>
<p>//nodesexpanded++;<br />
pushnsort (newnode);<br />
}<br />
else{<br />
delete [] newnode;<br />
}<br />
}<br />
i = DOWN;<br />
//make just the necessary objects<br />
//avoid making imposible states and states coming from the state before de parent<br />
if (invers(vorgaenger-&gt;letzteDir())!=i &amp;&amp; vorgaenger-&gt;schieben(i)){<br />
newnode = new knoten(vorgaenger, i);<br />
//don't push new state if it was already used<br />
if (!wasvisited(newnode)){</p>
<p>//nodesexpanded++;<br />
pushnsort (newnode);<br />
}<br />
else{<br />
delete [] newnode;<br />
}<br />
}<br />
i = LEFT;<br />
//make just the necessary objects<br />
//avoid making imposible states and states coming from the state before de parent<br />
if (invers(vorgaenger-&gt;letzteDir())!=i &amp;&amp; vorgaenger-&gt;schieben(i)){<br />
newnode = new knoten(vorgaenger, i);<br />
//don't push new state if it was already used<br />
if (!wasvisited(newnode)){</p>
<p>//nodesexpanded++;<br />
pushnsort (newnode);<br />
}<br />
else{<br />
delete [] newnode;<br />
}<br />
}</p>
<p>//register use of state of parent node<br />
dovisit(vorgaenger);</p>
<p>delete [] vorgaenger;</p>
<p>}</p>
<p>void expsortqueue::dovisit(knoten *square)<br />
{<br />
int pos, i; //position number of a given configuration of the board<br />
int power;</p>
<p>//get position number of the board of state &quot;square&quot;<br />
pos = position(square);</p>
<p>//get 2^(pos%8)<br />
power = 1;<br />
power = ( pos%8 == 0)?power = 1:power &lt;&lt; (pos%8);</p>
<p>//mark position as visited<br />
visits[pos/8] = visits[pos/8] | power;</p>
<p>}</p>
<p>bool expsortqueue::wasvisited(knoten *square)<br />
{<br />
int pos; //position number of a given configuration of the board<br />
int power;</p>
<p>//get position number of the board of state &quot;square&quot;<br />
pos = position(square);</p>
<p>//get 2^(pos%8)<br />
power = 1;<br />
power = (pos%8 == 0)?power = 1:power &lt;&lt; (pos%8);</p>
<p>//determine if position has been visited<br />
return ((visits[pos/8] &amp; power) &gt; 0);<br />
}</p>
<p>//return first node in priority queue (delete it from queue)<br />
knoten *expsortqueue::pop()<br />
{<br />
knoten *oldfirst;</p>
<p>oldfirst = first;<br />
if (first != NULL){<br />
first = first-&gt;getNext();<br />
}</p>
<p>//queuesize--;<br />
return oldfirst;</p>
<p>}</p>
<p>//push node to queue<br />
void expsortqueue::pushnsort(knoten *newNode)<br />
{<br />
knoten *n, *prev;</p>
<p>//in case the node is the first one to be pushed<br />
if ((first == NULL) || (first-&gt;f() &gt; newNode-&gt;f())){<br />
newNode-&gt;insert(first);<br />
first = newNode;<br />
}<br />
else{<br />
//look for ordered place in queue<br />
for (n = first-&gt;getNext(), prev = first; n != NULL; prev = n, n = n-&gt;getNext()){<br />
if (newNode-&gt;f() &lt; n-&gt;f()){<br />
prev-&gt;insert(newNode);<br />
newNode-&gt;insert(n);<br />
n==NULL;<br />
}<br />
}<br />
}<br />
//in case the node is the last one to be pushed<br />
if (newNode-&gt;getNext() == NULL){<br />
last-&gt;insert(newNode);<br />
last = newNode;<br />
}<br />
//queuesize++;</p>
<p>}</p>
<p>bool expsortqueue::isemptyqueue()<br />
{<br />
return (first == NULL);<br />
}</p>
<p>//Hilfsfunktionen</p>
<p>punkt copyboard(int src[3][3], int dest[3][3])<br />
{<br />
int i;<br />
punkt zero;</p>
<p>//copy array src to dest<br />
for (i = 0; i &lt; 9; i++){<br />
dest[i/3][i%3] = src[i/3][i%3];<br />
if (src[i/3][i%3] == 0){<br />
zero.x = i%3;<br />
zero.y = i/3;<br />
}<br />
}</p>
<p>return zero;<br />
}</p>
<p>//switch operation<br />
void change(int &amp;n1, int &amp;n2)<br />
{<br />
int tmp;</p>
<p>tmp = n1;<br />
n1 = n2;<br />
n2 = tmp;</p>
<p>}</p>
<p>//return the opsosite direction to each possible direction<br />
richtung invers(richtung dir)<br />
{<br />
switch(dir){<br />
case UP: return DOWN;<br />
case DOWN: return UP;<br />
case LEFT: return RIGHT;<br />
case RIGHT: return LEFT;<br />
case CENTER: return CENTER;<br />
}<br />
}</p>
<p>int position(knoten *square)<br />
{<br />
char i, j; //loop counters<br />
char h=0; //unit count for a given position<br />
int pos = 0; //position number of a given configuration of the board<br />
int bases[] = {1, 9, 72, 504, 3024, 15120, 60480, 181440, 362880}; //bases to use to count number of possible positions in the board<br />
int power, reg = 0; //register for numbers already used</p>
<p>//for each position in the board<br />
for (i=0; i &lt; 9; i++){<br />
//check if each number is used in the corresponding order...<br />
for (j=0; j &lt; 9; j++){<br />
power = 1;<br />
power = (j == 0)?power = 1:power &lt;&lt; j;<br />
//...skiping numbers that were already used<br />
if ((reg &amp; power) == 0){<br />
if (square-&gt;brett[i/3][i%3] == j){<br />
pos += h*(bases[i]); //increment position number<br />
//reset counters<br />
reg = reg | power;<br />
h = 0;<br />
j = 9;<br />
}<br />
else<br />
h++; //increment to next usable number in sequence<br />
}<br />
}<br />
}</p>
<p>return pos;<br />
}</p>
<p>#endif</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/132809/8er-puzzle</link><generator>RSS for Node</generator><lastBuildDate>Thu, 27 Aug 2026 16:07:22 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/132809.rss" rel="self" type="application/rss+xml"/><pubDate>Fri, 13 Jan 2006 10:12:59 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to 8er-Puzzle on Fri, 13 Jan 2006 10:12:59 GMT]]></title><description><![CDATA[<p>Hallo!<br />
Ich habe ein Problem. Ich möchte ein sogenanntes 8er-Puzzle lösen.<br />
Ich habe zwar ein Programm das funktioniert, dieses verwendet aber eine eigene Klasse als queue. Nun möchte ich aber eine priority_queue der STL verwenden. Kann mir jemand helfen, wie ich das anstellen kann??<br />
Vielen Dank schon im Voraus!<br />
mfg</p>
<p>main:<br />
#include &lt;iostream&gt;<br />
#include &quot;puzzle.h&quot;<br />
#include &lt;queue&gt;<br />
#include &lt;deque&gt;<br />
#include &lt;functional&gt;</p>
<p>using namespace std;</p>
<p>int main()<br />
{</p>
<p>cout &lt;&lt; &quot;Programm zur Loesung des 8er-Puzzle&quot; &lt;&lt; endl;</p>
<p>bool flag = true;</p>
<p>//Heuristik waehlen<br />
cout &lt;&lt; &quot;Welche Heuristik?&quot; &lt;&lt; endl;<br />
cout &lt;&lt; &quot;1 fuer Spielsteine&quot; &lt;&lt; endl;<br />
cout &lt;&lt; &quot;2 fuer Manhattan&quot; &lt;&lt; endl;<br />
cout &lt;&lt; &quot;3 zum Beenden des Programms&quot; &lt;&lt; endl;<br />
int Eingabe;<br />
cin &gt;&gt; Eingabe;</p>
<p>if(Eingabe == 3)<br />
return 0;</p>
<p>//Startzustand<br />
//int arrStart[3][3] = {{1,0,3},{8,2,4},{7,6,5}};<br />
int arrStart[3][3];<br />
cout &lt;&lt; &quot;Geben Sie den Startzustand ein:&quot; &lt;&lt; endl;<br />
cout &lt;&lt; &quot;Zahlen von 0-8 in einer beliebigen Reihenfolge&quot; &lt;&lt; endl;</p>
<p>for (int i = 0; i &lt; 9; i++)<br />
cin &gt;&gt; arrStart[i/3][i%3];</p>
<p>//Endzustand<br />
int arrZiel[3][3] = {{1,2,3},{8,0,4},{7,6,5}};</p>
<p>cout &lt;&lt; &quot;Startzustand:&quot; &lt;&lt; endl;<br />
for(int x = 0; x&lt;3; x++){<br />
for(int y = 0; y&lt;3 ; y++)<br />
cout &lt;&lt; arrStart[x][y];<br />
cout &lt;&lt; endl;<br />
}<br />
cout &lt;&lt; endl;</p>
<p>//priority_queue&lt;int,deque&lt;int&gt; &gt; puzzle;<br />
<a href="//puzzle.push">//puzzle.push</a>(arrStart);<br />
<a href="//puzzle.push">//puzzle.push</a>(arrZiel);</p>
<p>expsortqueue puzzle(arrStart, arrZiel);<br />
knoten *best;</p>
<p>//priority_queue&lt;knoten *, deque&lt;int&gt; &gt; OPEN;<br />
list&lt;knoten *&gt; CLOSED;</p>
<p>best = puzzle.pop();</p>
<p>if(Eingabe == 2){<br />
while (best-&gt;manhattan() != 0 &amp;&amp; flag){<br />
puzzle.expand(best);<br />
best = puzzle.pop();<br />
best-&gt;printKnoten();<br />
//Aktuellen Stand drucken?<br />
flag = !puzzle.isemptyqueue();<br />
}<br />
}<br />
else{<br />
while (best-&gt;spielsteine() != 0 &amp;&amp; flag){<br />
puzzle.expand(best);<br />
best = puzzle.pop();<br />
best-&gt;printKnoten();<br />
//Aktuellen Stand drucken?<br />
flag = !puzzle.isemptyqueue();<br />
}</p>
<p>}</p>
<p>if (flag){<br />
cout &lt;&lt; &quot;Solution found!&quot; &lt;&lt; endl;<br />
cout &lt;&lt; &quot;The sequence to get to the goal is: &quot;;<br />
best-&gt;printWeg();<br />
cout &lt;&lt; &quot;Zielzustand:&quot; &lt;&lt; endl;<br />
best-&gt;printKnoten();<br />
}<br />
else<br />
cout &lt;&lt; &quot;Problem has no solution, search tree exausted. Expanded &quot; &lt;&lt; best-&gt;level() &lt;&lt; &quot; levels&quot; &lt;&lt; endl;</p>
<p>//cout &lt;&lt; puzzle.nodesexpanded &lt;&lt; &quot; nodes expanded&quot; &lt;&lt; endl;</p>
<p>delete [] best;</p>
<p>return 0;<br />
}</p>
<p>puzzle.h:<br />
#ifndef _PUZZLE_<br />
#define _PUZZLE_</p>
<p>#include &lt;list&gt;<br />
#include &lt;queue&gt;<br />
#include &lt;cmath&gt;<br />
using namespace std;</p>
<p>//moegliche Richtungen<br />
enum richtung{UP, RIGHT, DOWN, LEFT, CENTER};</p>
<p>//Zielzustand<br />
int ziel[9];</p>
<p>//ein Punkt auf dem Brett<br />
struct punkt{<br />
int x;<br />
int y;<br />
};</p>
<p>class knoten {<br />
private:<br />
//int * puzzle; //Puzzle des Knotens<br />
knoten *nextKnoten; //Nächster Knoten in der queue<br />
int h,g; //Schätzwert Heuristik und Pfadkosten<br />
punkt leer; //Position des leeren Steins (0)<br />
richtung weg[2020]; //Speichert die Schritte der Leerstelle<br />
//struct listenelement *wegende; //Zeiger auf letzten Wegknoten<br />
//struct listenelement *weg; //Zeiger auf ersten Wegknoten<br />
public:<br />
knoten(knoten *vorgaenger, richtung dir); //Konstruktor<br />
knoten(int brt[3][3]); //Konstruktor<br />
int brett[3][3]; //8-puzzle brett<br />
void insert(knoten *next); //Fügt knoten ein<br />
knoten *getNext(); //Gibt adresse des nächsten Knoten zurück<br />
int f(); //Gibt f(n) zurück<br />
int manhattan(); //Gibt Manhattan-Distanz oder Spielsteine zurück<br />
int spielsteine();<br />
bool schieben(richtung dir); //Gibt an ob die Leerstelle in diese Richtung verschoben werden kann<br />
int level(); //Gibt den Level zurück, basierend auf g(n)<br />
richtung letzteDir(); //Gibt die Richtung an, in welche die Leerstelle als letztes verschoben wurde<br />
void printWeg(); //Gibt den Loesungsweg des Puzzles aus<br />
void printKnoten();<br />
};</p>
<p>//Prototypen<br />
int position(knoten *square);<br />
void change(int &amp;n1, int &amp;n2); //switch two items of a matrix<br />
punkt copyboard(int src[3][3], int dest[3][3]); //copy a matrix representing a board and return the zero position<br />
richtung invers(richtung dir);</p>
<p>// Priority queue<br />
class expsortqueue {<br />
private:<br />
knoten *first; //pointer to first node in queue (biggest f(n))<br />
knoten *last; //pointer to last node in queue (smallest f(n))<br />
int initial[3][3]; //initial state<br />
char visits[45360]; //binary hash to store the states already used (positions = 9!/8bits)<br />
public:<br />
//int queuesize; //just for testing<br />
//int nodesexpanded; //just for testing<br />
expsortqueue(int init[3][3], int ending[3][3]); //constructor<br />
~expsortqueue(); //destructor<br />
knoten *pop(); //get node on top of the queue<br />
void pushnsort(knoten *newnode); //put a new node in the queue<br />
void expand(knoten *parent); //expands a node<br />
bool isemptyqueue(); //determines if there are more states left in the queue<br />
bool wasvisited(knoten *square);<br />
void dovisit(knoten *square);<br />
};</p>
<p>//struct liste {<br />
// struct listenelement *anfang;<br />
// struct listenelement *ende;<br />
//};</p>
<p>//struct knoten V[</p>
<p>//Implementation der Klasse knoten</p>
<p>//Konstruktor fuer Startknoten<br />
knoten::knoten(int brt[3][3])<br />
{<br />
g = 0;</p>
<p>//copy brd into this node's board<br />
leer = copyboard(brt, brett);</p>
<p>h = manhattan(); //get manhatan distance</p>
<p>//setup linked list<br />
weg[0]=CENTER;<br />
weg[1]=CENTER;<br />
nextKnoten = NULL;</p>
<p>}</p>
<p>//Konstruktor fuer weitere Knoten<br />
knoten::knoten(knoten *vorgaenger, richtung dir)<br />
{<br />
int i;<br />
punkt lastblank;<br />
g = vorgaenger-&gt;g + 1;</p>
<p>//make a copY of the parent's board into this node's board<br />
leer = copyboard(vorgaenger-&gt;brett, brett);</p>
<p>//move positions according to direction dir<br />
lastblank = leer;<br />
switch(dir){<br />
case UP: leer.y--; break;<br />
case RIGHT: leer.x++; break;<br />
case DOWN: leer.y++; break;<br />
case LEFT: leer.x--; break;<br />
}<br />
change(brett[lastblank.y][lastblank.x], brett[leer.y][leer.x]);</p>
<p>h = manhattan(); //get manhatan distance</p>
<p>//setup linked list<br />
for (i=1; vorgaenger-&gt;weg[i] != CENTER; i++)<br />
weg[i]=vorgaenger-&gt;weg[i];<br />
weg[i] = dir;<br />
weg[i+1] = CENTER;<br />
nextKnoten = NULL;<br />
}</p>
<p>bool knoten::schieben(richtung dir)<br />
{<br />
switch(dir){<br />
case UP: if (leer.y &gt; 0) return true; break;<br />
case RIGHT: if (leer.x &lt; 2) return true; break;<br />
case DOWN: if (leer.y &lt; 2) return true; break;<br />
case LEFT: if (leer.x &gt; 0) return true; break;<br />
}<br />
return false;<br />
}</p>
<p>int knoten::manhattan()<br />
{<br />
int i, pos;<br />
int result=0;<br />
int x, y;</p>
<p>//the goal is defined by putting the position (1 trhough 9)<br />
//of the square at the array item with index equal to the<br />
//face number of the square.<br />
//smallnum ending[9] = {4,0,1,2,5,8,7,6,3}; //bonus = {8,0,1,2,3,4,5,6,7}</p>
<p>for (i = 0; i &lt; 9; i++){<br />
y = i/3;<br />
x = i%3;<br />
pos = brett[y][x];<br />
result+=abs(x - ziel[pos]%3); //addiere x distanz<br />
result+=abs(y - ziel[pos]/3); //addiere y distanz<br />
}<br />
return result;<br />
}</p>
<p>int knoten::spielsteine()<br />
{<br />
int i, pos;<br />
int result=0;<br />
int x, y;</p>
<p>//the goal is defined by putting the position (1 trhough 9)<br />
//of the square at the array item with index equal to the<br />
//face number of the square.<br />
//smallnum ending[9] = {4,0,1,2,5,8,7,6,3}; //bonus = {8,0,1,2,3,4,5,6,7}</p>
<p>for (i = 0; i &lt; 9; i++){<br />
y = i/3;<br />
x = i%3;<br />
pos = brett[y][x];<br />
if((abs(x - ziel[pos]%3) + abs(y - ziel[pos]/3)) != 0)<br />
result++;<br />
//Addiere 1 fuer jeden Spielstein, der nicht an der richtigen Position liegt<br />
}<br />
return result;<br />
}</p>
<p>void knoten::printKnoten()<br />
{<br />
int i;</p>
<p>for (i = 0; i &lt; 9; i++){<br />
cout &lt;&lt; brett[i/3][i%3];<br />
if (i%3 == 2)<br />
cout &lt;&lt; endl;<br />
}<br />
cout &lt;&lt; endl;<br />
}</p>
<p>int knoten::level()<br />
{<br />
return g;<br />
}</p>
<p>richtung knoten::letzteDir()<br />
{<br />
return weg[g];<br />
}</p>
<p>void knoten::printWeg()<br />
{<br />
int i = 1;</p>
<p>//Print solution using the history<br />
while (weg[i] != CENTER){<br />
switch(weg[i]){<br />
case UP: cout &lt;&lt; &quot;up, &quot;; break;<br />
case DOWN: cout &lt;&lt; &quot;down, &quot;; break;<br />
case LEFT: cout &lt;&lt; &quot;left, &quot;; break;<br />
case RIGHT: cout &lt;&lt; &quot;right, &quot;; break;<br />
}<br />
i++;<br />
}<br />
cout &lt;&lt; endl;<br />
}</p>
<p>knoten *knoten::getNext()<br />
{<br />
return nextKnoten;<br />
}</p>
<p>void knoten::insert(knoten *next)<br />
{<br />
nextKnoten = next;<br />
}</p>
<p>int knoten::f()<br />
{<br />
return g + h;<br />
}</p>
<p>//Implementation der queue Klasse</p>
<p>expsortqueue::expsortqueue(int init[3][3], int ending[3][3]) //constructor<br />
{<br />
int i;</p>
<p>//copy starting and ending states<br />
for (i = 0; i &lt; 9; i++){<br />
ziel[ending[i/3][i%3&rsqb;&rsqb;=i;<br />
initial[i/3][i%3] = init[i/3][i%3];<br />
}</p>
<p>//initialize visited states to 0<br />
for (i = 0; i &lt; 45360; i++)<br />
visits[i] = 0;</p>
<p>//initialize linked list<br />
first = new knoten(initial);<br />
last = first;<br />
//queuesize = 1;<br />
//nodesexpanded = 0;<br />
}</p>
<p>expsortqueue::~expsortqueue(){<br />
knoten *i, *tmp;</p>
<p>for (i = pop(); i!=NULL; i = pop())<br />
delete [] i;<br />
}</p>
<p>// create the children for parent node<br />
void expsortqueue::expand(knoten *vorgaenger)<br />
{<br />
richtung i;<br />
knoten *newnode;<br />
int h, g; //heuristics and path cost<br />
int brett[3][3]; //8-puzzle board<br />
punkt leer; //position of blank space (0)</p>
<p>i = UP;<br />
//make just the necessary objects<br />
//avoid making imposible states and states coming from the state before de parent<br />
if (invers(vorgaenger-&gt;letzteDir())!=i &amp;&amp; vorgaenger-&gt;schieben(i)){<br />
newnode = new knoten(vorgaenger, i);<br />
//don't push new state if it was already used<br />
if (!wasvisited(newnode)){</p>
<p>//nodesexpanded++;<br />
pushnsort (newnode);<br />
}<br />
else{<br />
delete [] newnode;<br />
}<br />
}</p>
<p>i = RIGHT;<br />
//make just the necessary objects<br />
//avoid making imposible states and states coming from the state before de parent<br />
if (invers(vorgaenger-&gt;letzteDir())!=i &amp;&amp; vorgaenger-&gt;schieben(i)){<br />
newnode = new knoten(vorgaenger, i);<br />
//don't push new state if it was already used<br />
if (!wasvisited(newnode)){</p>
<p>//nodesexpanded++;<br />
pushnsort (newnode);<br />
}<br />
else{<br />
delete [] newnode;<br />
}<br />
}<br />
i = DOWN;<br />
//make just the necessary objects<br />
//avoid making imposible states and states coming from the state before de parent<br />
if (invers(vorgaenger-&gt;letzteDir())!=i &amp;&amp; vorgaenger-&gt;schieben(i)){<br />
newnode = new knoten(vorgaenger, i);<br />
//don't push new state if it was already used<br />
if (!wasvisited(newnode)){</p>
<p>//nodesexpanded++;<br />
pushnsort (newnode);<br />
}<br />
else{<br />
delete [] newnode;<br />
}<br />
}<br />
i = LEFT;<br />
//make just the necessary objects<br />
//avoid making imposible states and states coming from the state before de parent<br />
if (invers(vorgaenger-&gt;letzteDir())!=i &amp;&amp; vorgaenger-&gt;schieben(i)){<br />
newnode = new knoten(vorgaenger, i);<br />
//don't push new state if it was already used<br />
if (!wasvisited(newnode)){</p>
<p>//nodesexpanded++;<br />
pushnsort (newnode);<br />
}<br />
else{<br />
delete [] newnode;<br />
}<br />
}</p>
<p>//register use of state of parent node<br />
dovisit(vorgaenger);</p>
<p>delete [] vorgaenger;</p>
<p>}</p>
<p>void expsortqueue::dovisit(knoten *square)<br />
{<br />
int pos, i; //position number of a given configuration of the board<br />
int power;</p>
<p>//get position number of the board of state &quot;square&quot;<br />
pos = position(square);</p>
<p>//get 2^(pos%8)<br />
power = 1;<br />
power = ( pos%8 == 0)?power = 1:power &lt;&lt; (pos%8);</p>
<p>//mark position as visited<br />
visits[pos/8] = visits[pos/8] | power;</p>
<p>}</p>
<p>bool expsortqueue::wasvisited(knoten *square)<br />
{<br />
int pos; //position number of a given configuration of the board<br />
int power;</p>
<p>//get position number of the board of state &quot;square&quot;<br />
pos = position(square);</p>
<p>//get 2^(pos%8)<br />
power = 1;<br />
power = (pos%8 == 0)?power = 1:power &lt;&lt; (pos%8);</p>
<p>//determine if position has been visited<br />
return ((visits[pos/8] &amp; power) &gt; 0);<br />
}</p>
<p>//return first node in priority queue (delete it from queue)<br />
knoten *expsortqueue::pop()<br />
{<br />
knoten *oldfirst;</p>
<p>oldfirst = first;<br />
if (first != NULL){<br />
first = first-&gt;getNext();<br />
}</p>
<p>//queuesize--;<br />
return oldfirst;</p>
<p>}</p>
<p>//push node to queue<br />
void expsortqueue::pushnsort(knoten *newNode)<br />
{<br />
knoten *n, *prev;</p>
<p>//in case the node is the first one to be pushed<br />
if ((first == NULL) || (first-&gt;f() &gt; newNode-&gt;f())){<br />
newNode-&gt;insert(first);<br />
first = newNode;<br />
}<br />
else{<br />
//look for ordered place in queue<br />
for (n = first-&gt;getNext(), prev = first; n != NULL; prev = n, n = n-&gt;getNext()){<br />
if (newNode-&gt;f() &lt; n-&gt;f()){<br />
prev-&gt;insert(newNode);<br />
newNode-&gt;insert(n);<br />
n==NULL;<br />
}<br />
}<br />
}<br />
//in case the node is the last one to be pushed<br />
if (newNode-&gt;getNext() == NULL){<br />
last-&gt;insert(newNode);<br />
last = newNode;<br />
}<br />
//queuesize++;</p>
<p>}</p>
<p>bool expsortqueue::isemptyqueue()<br />
{<br />
return (first == NULL);<br />
}</p>
<p>//Hilfsfunktionen</p>
<p>punkt copyboard(int src[3][3], int dest[3][3])<br />
{<br />
int i;<br />
punkt zero;</p>
<p>//copy array src to dest<br />
for (i = 0; i &lt; 9; i++){<br />
dest[i/3][i%3] = src[i/3][i%3];<br />
if (src[i/3][i%3] == 0){<br />
zero.x = i%3;<br />
zero.y = i/3;<br />
}<br />
}</p>
<p>return zero;<br />
}</p>
<p>//switch operation<br />
void change(int &amp;n1, int &amp;n2)<br />
{<br />
int tmp;</p>
<p>tmp = n1;<br />
n1 = n2;<br />
n2 = tmp;</p>
<p>}</p>
<p>//return the opsosite direction to each possible direction<br />
richtung invers(richtung dir)<br />
{<br />
switch(dir){<br />
case UP: return DOWN;<br />
case DOWN: return UP;<br />
case LEFT: return RIGHT;<br />
case RIGHT: return LEFT;<br />
case CENTER: return CENTER;<br />
}<br />
}</p>
<p>int position(knoten *square)<br />
{<br />
char i, j; //loop counters<br />
char h=0; //unit count for a given position<br />
int pos = 0; //position number of a given configuration of the board<br />
int bases[] = {1, 9, 72, 504, 3024, 15120, 60480, 181440, 362880}; //bases to use to count number of possible positions in the board<br />
int power, reg = 0; //register for numbers already used</p>
<p>//for each position in the board<br />
for (i=0; i &lt; 9; i++){<br />
//check if each number is used in the corresponding order...<br />
for (j=0; j &lt; 9; j++){<br />
power = 1;<br />
power = (j == 0)?power = 1:power &lt;&lt; j;<br />
//...skiping numbers that were already used<br />
if ((reg &amp; power) == 0){<br />
if (square-&gt;brett[i/3][i%3] == j){<br />
pos += h*(bases[i]); //increment position number<br />
//reset counters<br />
reg = reg | power;<br />
h = 0;<br />
j = 9;<br />
}<br />
else<br />
h++; //increment to next usable number in sequence<br />
}<br />
}<br />
}</p>
<p>return pos;<br />
}</p>
<p>#endif</p>
]]></description><link>https://www.c-plusplus.net/forum/post/965280</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/965280</guid><dc:creator><![CDATA[sweetjona]]></dc:creator><pubDate>Fri, 13 Jan 2006 10:12:59 GMT</pubDate></item><item><title><![CDATA[Reply to 8er-Puzzle on Fri, 13 Jan 2006 10:28:09 GMT]]></title><description><![CDATA[<p>Kannst du das mal in cpp-Tags einrahmen, da blickt ja kein Schwein durch.<br />
Ansonsten solltest du deine Zwischenpositionen in eine struct kapseln und dieser eine Vergleichfunktion (operator&lt;) spendieren, danach kannst du sie in die priority_queue pushen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/965295</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/965295</guid><dc:creator><![CDATA[CStoll (off)]]></dc:creator><pubDate>Fri, 13 Jan 2006 10:28:09 GMT</pubDate></item></channel></rss>