Affenpuzzle
Aus ProgrammingWiki
Wiki-Quelltext dieser Seite.
<language>Javascript</language>
Das Affenpuzzle ist ein kombinatorisches Rätsel. Es besteht aus 9, 16, 25 oder mehr Karten die in einer Matrix angeordnet werden. Ziel des Spiels ist es die Karten so zu legen und zu drehen, das alle Teile (hier der Hexen) zusammenpassen.
[[Bild:Admin_Hexenpuzzle.png]]
== Lösung mit dem Computer ==
Würde man alle möglichen Kombinationen durchprobieren, wären das bei 3x3 bereits 95126814720 Kartenstellungen. Auch mit einem leistungsstarken Computer dauert das mehrere Stunden, diese alle durchzuprobieren.
Zum Glück müssen wir aber nicht alle Kombinationen ausprobieren. Sollte schon die erste zur zweiten Karte nicht passen, müssen wir die restlichen Kombinationen mit diesem Anfang ja gar nicht weiterverfolgen. Der nachfolgende Algorithmus nutzt das aus und legt zunächst eine Karte aufs Feld. Bei der zweiten Karte wird bereits geprüft, ob diese zur ersten passt und nur dann mit der Suche fortgesetzt.
<run id="595f4420a170d">
var KopfRot = 1, BauchRot = 2;
var KopfGelb = 4, BauchGelb = 5;
var KopfBlau = 7, BauchBlau = 8;
var KopfGruen = 10, BauchGruen = 11;
var Karten = [];
Karten[0] = [KopfRot,BauchGruen,BauchGelb,KopfBlau];
Karten[1] = [KopfGruen,BauchRot,BauchBlau,KopfBlau];
Karten[2] = [BauchRot,BauchBlau,KopfGruen,KopfBlau];
Karten[3] = [KopfGelb,BauchRot,BauchGelb,KopfGruen];
Karten[4] = [KopfGelb,BauchGruen,BauchRot,KopfBlau];
Karten[5] = [BauchRot,KopfGruen,KopfBlau,BauchGelb];
Karten[6] = [BauchBlau,BauchGelb,KopfGruen,KopfRot];
Karten[7] = [KopfRot,BauchGruen,BauchGelb,KopfGruen];
Karten[8] = [BauchBlau,BauchRot,KopfBlau,KopfGelb];
function spielfeldAusgeben(Kartenfeld){
function lesbar(n){
if(n == KopfRot) return "KR";
if(n == BauchRot) return "BR";
if(n == KopfGelb) return "KG";
if(n == BauchGelb) return "BG";
if(n == KopfBlau) return "KB";
if(n == BauchBlau) return "BB";
if(n == KopfGruen) return "KG";
if(n == BauchGruen) return "BG";
}
var s = "";
var zeilen = Math.round(Math.sqrt(Kartenfeld.length));
for(var i=0; i < Kartenfeld.length; i++){
s += "["+lesbar(Karten[Kartenfeld[i]][0])+" "+
lesbar(Karten[Kartenfeld[i]][1])+" "+
lesbar(Karten[Kartenfeld[i]][2])+" "+
lesbar(Karten[Kartenfeld[i]][3])+"]";
if(i % zeilen == zeilen-1) s += "\n";
}
return (s);
}
function kartePruefen(nummer, feld){
if(nummer == 0){
if(feld[1] != -1 && Math.abs(Karten[feld[0]][1] - Karten[feld[1]][3]) != 1) return false;
if(feld[3] != -1 && Math.abs(Karten[feld[0]][2] - Karten[feld[3]][0]) != 1) return false;
return true;
}
if(nummer == 1){
if(feld[2] != -1 && Math.abs(Karten[feld[1]][1] - Karten[feld[2]][3]) != 1) return false;
if(feld[4] != -1 && Math.abs(Karten[feld[1]][2] - Karten[feld[4]][0]) != 1) return false;
if(feld[0] != -1 && Math.abs(Karten[feld[1]][3] - Karten[feld[0]][1]) != 1) return false;
return true;
}
if(nummer == 2){
if(feld[5] != -1 && Math.abs(Karten[feld[2]][2] - Karten[feld[5]][0]) != 1) return false;
if(feld[2] != -1 && Math.abs(Karten[feld[2]][3] - Karten[feld[2]][1]) != 1) return false;
return true;
}
if(nummer == 3){
if(feld[0] != -1 && Math.abs(Karten[feld[3]][0] - Karten[feld[0]][2]) != 1) return false;
if(feld[4] != -1 && Math.abs(Karten[feld[3]][1] - Karten[feld[4]][3]) != 1) return false;
if(feld[6] != -1 && Math.abs(Karten[feld[3]][2] - Karten[feld[6]][0]) != 1) return false;
return true;
}
if(nummer == 4){
if(feld[1] != -1 && Math.abs(Karten[feld[4]][0] - Karten[feld[1]][2]) != 1) return false;
if(feld[5] != -1 && Math.abs(Karten[feld[4]][1] - Karten[feld[5]][3]) != 1) return false;
if(feld[7] != -1 && Math.abs(Karten[feld[4]][2] - Karten[feld[7]][0]) != 1) return false;
if(feld[3] != -1 && Math.abs(Karten[feld[4]][3] - Karten[feld[3]][1]) != 1) return false;
return true;
}
if(nummer == 5){
if(feld[2] != -1 && Math.abs(Karten[feld[5]][0] - Karten[feld[2]][2]) != 1) return false;
if(feld[8] != -1 && Math.abs(Karten[feld[5]][2] - Karten[feld[8]][0]) != 1) return false;
if(feld[4] != -1 && Math.abs(Karten[feld[5]][3] - Karten[feld[4]][1]) != 1) return false;
return true;
}
if(nummer == 6){
if(feld[3] != -1 && Math.abs(Karten[feld[6]][0] - Karten[feld[3]][2]) != 1) return false;
if(feld[7] != -1 && Math.abs(Karten[feld[6]][1] - Karten[feld[7]][3]) != 1) return false;
return true;
}
if(nummer == 7){
if(feld[4] != -1 && Math.abs(Karten[feld[7]][0] - Karten[feld[4]][2]) != 1) return false;
if(feld[8] != -1 && Math.abs(Karten[feld[7]][1] - Karten[feld[8]][3]) != 1) return false;
if(feld[6] != -1 && Math.abs(Karten[feld[7]][3] - Karten[feld[6]][1]) != 1) return false;
return true;
}
if(nummer == 8){
if(feld[5] != -1 && Math.abs(Karten[feld[8]][0] - Karten[feld[5]][2]) != 1) return false;
if(feld[7] != -1 && Math.abs(Karten[feld[8]][3] - Karten[feld[7]][1]) != 1) return false;
return true;
}
}
function karteDrehen(k){
var p = k.shift(); // erstes Element wegnehmen
k.push(p); // hinten wieder einfügen
}
var loesungen = 0;
var tests = 0;
var Kartenfeld = [];
var gesetzt = [];
for(var i=0; i < 9; i++){
Kartenfeld[i] = -1;
gesetzt[i] = false;
}
function suchen(Feld){
for(var k=0; k < Karten.length; k++){
if(!gesetzt[k]){
Kartenfeld[Feld] = k;
gesetzt[k] = true;
for(var r=0; r<4; r++){
tests++;
if(kartePruefen(Feld,Kartenfeld)){
if(Feld == Karten.length-1){
loesungen++;
console.log("Lösung:\n"+spielfeldAusgeben(Kartenfeld));
}
suchen(Feld+1);
}
karteDrehen(Karten[k]);
}
Kartenfeld[Feld] = -1;
gesetzt[k]=false;
}
}
}
suchen(0);
console.log("Es wurden "+tests+" Tests gemacht und "+loesungen+" Lösungen gefunden.");
</run>