Seminarfacharbeit: Schriftliches Referat über die Elektrotechnik

Da es mich ärgert, wenn ich viel Zeit in Schularbeiten investiere, die lediglich einer Leistungsermittlung dienen, danach aber in Vergessenheit geraten, möchte ich mein schriftliches Referat für das Seminarfach "Berufsorientierung: MINT" hier öffentlich zur Verfügung stellen.
Im Folgenden findet sich das Vorwort, welches auf die Themen meiner Arbeit eingeht und ihre Schwerpunkte erläutert:

Diese Seminarfacharbeit befasst sich mit der Elektrotechnik, im umgangssprachlichen Alltagsgebrauch auch häufig als E.-Technik [i] bezeichnet, als Wissenschaft, den Ausbildungsmöglichkeiten zum Elektrotechniker sowie dem Studiengang Elektrotechnik, und dem Berufsfeld des Elektrotechnikers. Berücksichtigte Aspekte liegen dabei unter anderem in der Definition der Elektrotechnik, die eine sachliche Auskunft über die Inhalte und Aufgabenbereiche der Elektrotechnik gibt, in den erforderlichen Interessen und Fähigkeiten für die Berufsausbildung, Studieninhalten und reputablen Hochschulen für den Studiengang Elektrotechnik sowie in den Tätigkeits- und Anwendungsbereichen im Beruf.
Das primäre Ziel dieser Arbeit liegt in ihrer Bestrebung, dem Leser als auch dem Verfasser zu ermöglichen, den beruflichen Werdegang zu reflektieren und sich, basierend auf den eigenen Interessen und Kompetenzen, eine Vorstellung über die Elektrotechnik zu bilden.
Nicht zuletzt dient diese wissenschaftliche Arbeit als Grundlage für die Leistungsbewertung des Verfassers, der sich verpflichtet hat, die Arbeit selbständig ohne andere als angegebene Hilfsmittel zu verfassen.

Das Thema Elektrotechnik reizt durch eine Vielzahl persönlicher Gründe: Sie bildet die Grundlage unverzichtbarer elektronisch-technischer Erfindungen, darunter Computer, die den Alltag erheblich erleichtern und komfortabler machen. Gleichzeitig kommt der Mathematik in der Elektrotechnik eine nicht zu unterschätzende Rolle zu (vgl. Tabelle 3.4.1). Es kommt hinzu, dass sie in dadurch auch Grundlage für die Automatisierung elektronischer Systeme darstellt und folglich von wesentlicher Bedeutung für die elektronische Robotik ist.

 


[i] Online im Internet: URL: http://de.wikipedia.org/wiki/Elektrotechnik [Stand 28.11.2013]

Vielleicht kann sie dem ein oder anderen als Anregung für das Verfassen einer eigenen Arbeit dienen.
Das gesamte Dokument ist hier in meinem Schulordner zu finden.

Connecting an Arduino to an Android phone

Since I wanted to debug my Arduino using my mobile phone (Samsung Galaxy S2) using the Arduino's comfortable serial library, I bought a cheap USB-OTG adapter cable (male micro-USB-B to female USB-A) in order to connect the Arduino to my phone. The USB-A plug of the normal Arduino cable connecting an Arduino to the computer can be plugged into the above mentioned USB-A socket and again, the USB-B plug of that cable is connected to the phone.
After connecting it I had some difficulties to find a working app for my phone allowing to communicate with my Arduino using the serial interface. After some searching I found Slick USB 2 Serial Terminal which fulfilled its job fine for me. It is important to select "Prolific" mode in order to receive and send data from and to your Arduino. If your phone supports USB host mode, you can even use your phone to power the Arduino, so no external power supply is required.

Impressum vor Spam-Robotern schützen

Seit einiger Zeit erhalte ich auf einer meiner Webseiten Spam an eine im Impressum angegebene E-Mail-Adresse. Als diese Flut von 50 - 100 E-Mails pro Tag auch nach einer Woche nicht stoppen wollte, musste ich Maßnahmen gegen diese ergreifen. Zuerst habe ich natürlich die angegebene E-Mail-Adresse geändert. Um allerdings zukünftig auch Spam zu vermeiden, kamen folgende Maßnahmen infrage:

  1. Eine Einbindung der E-Mail-Adresse als Grafik. Diese erschwert das automatisierte Auslesen der Adresse, da Spammer im Besitz einer automatischen Texterkennungssoftware sein müssen, welche weitaus komplizierter und teurer zu implementieren ist, als lediglich das Auslesen einer E-Mail-Adresse im Klartext einer Seite.
  2. Ein 404-Not-Found Fehler. Dieser erlaubt es mir, an den Client, also normalerweise den Webbrowser eines Seitenbesuchers oder den Roboter eines Spammers, eine Fehlermeldung zu senden, die angibt, dass die angegebene Seite nicht aufrufbar sei (aufgrund einer Löschung oder Ähnlichem). Der normale Seitenbesucher bekommt von diesem Fehlercode am Anfang des HTTP-Headers nichts mit, für Spam- oder Suchmaschinenroboter ist dieser Code aber essenziell, da er angibt, ob eine Seite existiert. Da es für Spam- oder Suchmaschinenroboter jedoch unwirtschaftlich scheint, solche Seiten zu durchforsten, die mutmaßlich nicht existieren, bietet sich dies als Lösung für das Problem an, denn trotz des Fehlercodes kann ganz regulär im HTTP-Body Seiteninhalt an den Webbrowser übermittelt werden. Man gibt also an, dass das Impressum nicht existiert, dennoch sendet man es mit dem Seiteninhalt.
    Um dies zu realisieren, eignet sich folgender PHP-Code am Anfang der Seite:

    <?php
    header("HTTP/1.1 404 Not Found");
    ?>

Um sicherzustellen, dass ein Missbrauch meiner E-Mail-Adresse so schnell nicht wieder vorkommt, habe ich beide oben beschriebenen Maßnahmen ergriffen.

Linked list - Library for Arduino

As I was struggling with my HC-05 Bluetooth module which might return an unspecified count of lines when responding to a command in AT (attention) mode, I have written a small library for a single chained list. It is just a dynamic data structure supporting chronological pushing while it allows iterating through all its elements.

/*
  List.h - Linked List (single chain)
  Created by Birk Blechschmidt, 16 August 2013
  Released into the public domain.
*/
#ifndef List_h
#define List_h

#include "Arduino.h"

template <class T> class ListElement
{
	public:
		ListElement(T Element)
		{
			Content = Element;
			NextElement = NULL;
		}
		~ListElement()
		{
			delete NextElement;
		}
		T Content;
		ListElement<T> *NextElement;
};

template <class T> class List
{
  public:
	~List()
	{
		Clear();
		delete FirstElement;
		delete LastElement;
		delete CurrentElement;
	}
	List()
	{
		FirstElement = NULL;
		CurrentElement = NULL;
		LastElement = NULL;
		Length = 0;
	}
	void Clear()
	{
		ToBegin();
		delete CurrentElement;
		FirstElement = NULL;
		CurrentElement = NULL;
		LastElement = NULL;
		Length = 0;
	}
	void Push(T Element)
	{
		if(LastElement)
		{
			LastElement->NextElement = new ListElement<T>(Element);
			LastElement = LastElement->NextElement;
		}
		else
		{
			FirstElement = new ListElement<T>(Element);
			LastElement = FirstElement;
			CurrentElement = FirstElement;
		}
		Length++;
	}
	bool IsEnd()
	{
		if(CurrentElement)
		{
			return false;
		}
		else
		{
			return true;
		}
	}

	bool IsEmpty()
	{
		return FirstElement == NULL;
	}

	unsigned long Count()
	{
		return Length;
	}
	void ToBegin()
	{
		CurrentElement = FirstElement;
	}
	void Next()
	{
		if(CurrentElement)
		{
			CurrentElement = CurrentElement->NextElement;
		}
	}
	T GetValue()
	{
		return CurrentElement->Content;
	}
  private:
	  unsigned long Length;
	  ListElement<T> *FirstElement;
	  ListElement<T> *LastElement;
	  ListElement<T> *CurrentElement;
};

#endif

Usage:

#include <List.h>

void setup()
{
	List<String> StringList;
	StringList.Push("a");
	StringList.Push("b");
	StringList.Push("c");

	//Iterate through list
	bool ListEmpty = StringList.IsEmpty(); //false
	Serial.println("Count: "+String(StringList.GetCount()));
	StringList.ToBegin();
	while(!StringList.IsEnd())
	{
		Serial.println(StringList.GetValue());
		StringList.Next();
	}
	/*Output:
		Count: 3
		a
		b
		c
	*/
	StringList.Clear();
	ListEmpty = StringList.IsEmpty(); //true
}

void loop()
{
}

HiTechnic Infrared Seeker library for Arduino

Today I have created a class allowing you to connect a HiTechnic IR Seeker V2, which is originally designed for use with a LEGO Mindstorms NXT robot, to an Arduino Due board with a 9V battery. I struggled a bit with the the different sensor pins but I could finally manage to connect the sensor correctly.

  1. white -> battery +9V (Vcc)
  2. black -> Arduino GND
  3. red -> battery - (GND)
  4. green -> Arduino +3.3V (Vcc)
  5. yellow -> Arduino SCL
  6. blue -> Arduino SDA

The following code is executed by the Arduino:

#include <Wire.h>

/*
  IRSeeker.ino - A library/class for the HiTechnic IRSeeker V2 infrared sensor.
  Created by Birk Blechschmidt, August 1, 2013.
  Released into the public domain.
*/

struct InfraredResult
{
  byte Direction;
  byte Strength;
};

class InfraredSeeker
{
  public:
    static void Initialize();
    static boolean Test();
    static void ReadACRaw(byte* buffer);
    static void ReadDCRaw(byte* buffer);
    static InfraredResult ReadAC();
    static InfraredResult ReadDC();
    static int DirectionAngle(byte Direction);
  private:
    static InfraredResult PopulateValues(byte* buffer);
    static void ReadValues(byte OffsetAddress, byte* buffer);
    static const int Address = 0x10 / 2; //Divide by two as 8bit-I2C address is provided
};

void InfraredSeeker::Initialize()
{
  Wire.begin();
  Wire.beginTransmission(InfraredSeeker::Address);
  Wire.write(0x00);
  Wire.endTransmission();
  while(Wire.available() > 0)
    Wire.read();
}

boolean InfraredSeeker::Test()
{
  Wire.beginTransmission(InfraredSeeker::Address);
  Wire.write(0x08);
  Wire.endTransmission();
  Wire.requestFrom(InfraredSeeker::Address, 16);
  char Manufacturer_Model[16];
  while(Wire.available() < 16);
  for(byte i=0; i < 16; i++)
  {
    Manufacturer_Model[i] = Wire.read();
  }
  while(Wire.available() > 0)
    Wire.read();
  return strncmp(Manufacturer_Model, "HiTechncNewIRDir", 16)==0;
}

void InfraredSeeker::ReadValues(byte OffsetAddress, byte* buffer)
{
  Wire.beginTransmission(InfraredSeeker::Address);
  Wire.write(OffsetAddress);
  Wire.endTransmission();
  Wire.requestFrom(InfraredSeeker::Address, 6);
  while(Wire.available() < 6);
  for(byte i = 0; i < 6; i++)
  {
    buffer[i] = Wire.read();
  }
  while(Wire.available() > 0)
    Wire.read();
}

void InfraredSeeker::ReadACRaw(byte* buffer)
{
  ReadValues(0x49, buffer);
}

void InfraredSeeker::ReadDCRaw(byte* buffer)
{
  ReadValues(0x42, buffer);
}

InfraredResult InfraredSeeker::PopulateValues(byte* buffer)
{
  InfraredResult Data;
  Data.Direction = buffer[0];
  if(buffer[0] != 0)
  {
    if(buffer[0] % 2 == 0)
    {
      Data.Strength = (buffer[buffer[0] / 2] + buffer[buffer[0] / 2 + 1]) / 2;
    }
    else
    {
      Data.Strength = buffer[buffer[0] / 2 + 1];
    }
  }
  else
  {
    Data.Strength = 0;
  }
  return Data;
}

InfraredResult InfraredSeeker::ReadAC()
{
  byte buffer[6];
  ReadACRaw(buffer);
  return PopulateValues(buffer);
}

InfraredResult InfraredSeeker::ReadDC()
{
  byte buffer[6];
  ReadDCRaw(buffer);
  return PopulateValues(buffer);
}

int DirectionAngle(byte Direction)
{
  return Direction * 30 - 150;
}

void setup()
{
  Serial.begin(9600);
  Serial.println("HiTechnic IRSeeker V2");
  Serial.println();
  Serial.println();
  Serial.println("Dir\tAngle\tStrength");
  Serial.println();
  InfraredSeeker::Initialize();
}

void loop()
{   
  InfraredResult InfraredBall = InfraredSeeker::ReadAC();
  Serial.print(InfraredBall.Direction);
  Serial.print("\t");
  Serial.print(DirectionAngle(InfraredBall.Direction));
  Serial.print("\t");
  Serial.print(InfraredBall.Strength);
  Serial.println();
  delay(100); //optional
}

To download the compressed zip-archive of the library just go to http://birkb.eu/programming/Arduino/libraries/HTInfraredSeeker.zip. This archive can be imported using the "Sketch" menu of your Arduino IDE. Just click "Import library" and choose "Add library...". Then just #include <HTInfraredSeeker.h> and use it as shown above in the loop- and main function.

HC-SR04 Ultrasonic Sensor Library for Arduino

Some days ago my new HC-SR04 ultrasonic sensor for my new Arduino board arrived. In order to keep the overview of my programs, I have written a small library for the sensor which I want to share with you here. As the library is pretty much self-explicatory in my opinion, I will not further comment the following code at this point.

UltraSonic.h

/*
  UltraSonic.h - A library for the HC-SR04 UltraSonic sensor.
  Created by Birk Blechschmidt, May 25, 2013.
  Released into the public domain.
*/

#ifndef UltraSonic_h
	#define UltraSonic_h

	#include "Arduino.h"

	class UltraSonic
	{
	  public:
		byte TriggerPin, DataPin;
		UltraSonic(byte TriggerPort, byte DataPort, unsigned int MaximumRange = 400);
		unsigned int ReadCentimeters();
		void ReadCentimetersAsync(int &Centimeters);
	  private:
		unsigned long AsyncTime;
		byte AsyncState;
		unsigned long AsyncLength;
		unsigned int Timeout;
	};

#endif

UltraSonic.cpp

/*
  UltraSonic.cpp - A library for the HC-SR04 UltraSonic sensor.
  Created by Birk Blechschmidt, May 25, 2013.
  Released into the public domain.
*/

#include "Arduino.h"
#include "UltraSonic.h"

UltraSonic::UltraSonic(byte TriggerPort, byte DataPort, unsigned int MaximumRange)
{
  Timeout = MaximumRange * 58;
  TriggerPin = TriggerPort;
  DataPin = DataPort;
  pinMode(TriggerPin, OUTPUT);
  digitalWrite(TriggerPin, LOW);
  pinMode(DataPin, INPUT);
  AsyncState = 0;
}

unsigned int UltraSonic::ReadCentimeters()
{
      digitalWrite(TriggerPin, HIGH);
      delayMicroseconds(10);
      digitalWrite(TriggerPin, LOW);
      return pulseIn(DataPin, HIGH, Timeout)/58;
}

void UltraSonic::ReadCentimetersAsync(int &Centimeters)
{
  switch(AsyncState)
  {
    case 0:
    {
      Centimeters = -1;
      digitalWrite(TriggerPin, HIGH);
      AsyncTime = micros();
      AsyncState++;
      break;
    }
    case 1:
    {
      if(micros() >= AsyncTime + 10)
      {
        AsyncState++;
        digitalWrite(TriggerPin, LOW);
        AsyncTime = micros();
      }
      break;
    }
    case 2:
    {
      if(digitalRead(DataPin) == HIGH)
      {
        AsyncState++;
        AsyncTime = micros();

      }
      else if(micros() - AsyncTime > Timeout)
      {
        Centimeters = 0;
        AsyncState = 4; 
      }
      break;
    }
    case 3:
    {
      if(digitalRead(DataPin) == LOW)
      {
        Centimeters = (micros() - AsyncTime) / 58;
        AsyncState++;
      }
      else if(micros() - AsyncTime > Timeout)
      {
        Centimeters = 0;
        AsyncState++;
      }
      break;
    }
    case 4:
    {
      Centimeters = -1;
      AsyncState = 0;
      break;
    }
  }
}

Copy the above files to your Arduino libraries located at C:\Program Files\Arduino\libraries. Please be aware that you might need to create a new folder.

"Probots" gewinnen die RoboNight 2012

Alle Jahre wieder. So könnte das Motto für unsere Teilnahme beim saarländischen Robotik-Wettbewerb „RoboNight“ lauten. Wie auch bereits in den vergangenen Jahren, hat unsere Schule auch dieses Jahr wieder an dem von der Hochschule für Technik und Wirtschaft und T-Systems gesponserten Wettbewerb teilgenommen. Dieses Mal traten wir zwar mit einer neuen Konstellation an, dennoch wurde unsere Schule erfolgreich von unserem Team „Probots“, bestehend aus Jonas Kraemer (Klassenstufe 8) und Birk Blechschmidt (Klassenstufe 11), vertreten.

Wie jedes Jahr fanden an drei Samstagen Workshops in der HTW-Mensa statt. Dort galt es, diverse Übungsaufgaben zu lösen. Aufgrund der vielen Teams, 25 mit insgesamt über 100 Schülern an der Zahl, fand am 13. Oktober bereits ein Vorentscheid in der HTW statt, bei dem wir uns bereits als erstes Team mit großem Abstand zum Zweitplatzierten qualifiziert haben.
Der Ablauf sah bei jeder dieser Veranstaltungen ähnlich aus. Zuerst wurde der Roboter aus den verfügbaren Lego-Teilen zusammengebaut. (Diese umfassen unter anderem den programmierbaren NXT-Stein, Licht-, Ultraschall- und Berührungssensoren sowie drei Motoren.) Danach wurde der Roboter in NXC (Not eXactly C), einer Sprache mit C-ähnlicher Syntax, programmiert. Im Anschluss wurden die geschriebenen Programme getestet und auf Fehler überprüft. Beim Vorentscheid sowie im Finale wurde die Erfüllung der Aufgaben durch die Roboter schließlich noch präsentiert und mit Punkten nach klaren Regeln bewertet.

Das Finale am 10. November begann bereits um 9.00 Uhr morgens in den Räumen der Telekom- Tochter auf dem Eschberg. Nachdem wir in die Aufgabenstellungen eingeführt und in unsere Arbeitsräume eingeteilt worden waren, konnten wir mit dem Programmieren loslegen. Wir mussten bis 16.30 Uhr drei Aufgaben mit verschiedenen Schwierigkeiten bewältigen, welche wir ab etwa
19.30 Uhr präsentierten.
Die erste Aufgabe bestand im Folgen einer schwarzen Linie, was einfach durch die Erkennung des Hell-Dunkel-Kontrasts mithilfe der Lichtsensoren zu realisieren war. Beim Folgen sollte der Roboter an zwei markierten Punkten die Höhe von zwei verschiedenen, neben der Fahrbahn platzierten Mauern messen und nach den Messungen die größere umstoßen. Zur Erkennung der Höhe nutzten wir den Ultraschallsensor. Diese Aufgabe löste unser Roboter mit einer Bestzeit von knapp zehn Sekunden und brachte uns somit 50 von 50 möglichen Punkten. Überraschend war, dass überhaupt nur zwei Teams diese Aufgabe komplett lösen konnte.
Die zweite Aufgabe war schon etwas anspruchsvoller. Auf dem Spielfeld befanden sich drei parallele schwarze Linien, wobei auf der vorderen Linie vier Blöcke positioniert waren. Eben dieser Grundlinie sollte unser Roboter folgen, sobald er auf einen Block stieß, musste dieser weggeschoben werden. Die Schwierigkeit bestand hier darin, dass der erste Block genau zwischen die beiden hinteren Markierungen geschoben werden musste, der zweite hinter diese, der dritte wieder dazwischen und der vierte erneut dahinter. Nach dem Verschieben der Blöcke musste der Roboter dann wieder zur Grundlinie zurückkehren. Leider verschob unser Roboter beim zweiten Versuch nur drei der vier Blöcke korrekt und kam dann aus ungeklärten Gründen nicht korrekt zurück auf die Grundlinie. Daher erhielten wir für diese Aufgabe nur 30 Punkte, allerdings gab es auch hier nur zwei Roboter, die den Parcours komplett bewältigten.
Bei der letzten und schwierigsten Aufgabe hatte sogar der Moderator Reinhard Karger vom DFKI (Deutsches Forschungsinstitut für Künstliche Intelligenz) Probleme, diese mit der Hand zu lösen. Auf drei Türmen war jeweils ein Ball positioniert, neben jedem Turm stand ein Korb, wobei jeder Korb zusätzlich mit einer anderen Orientierung zur Grundlinie, auf welcher der Roboter sich bewegen sollte, aufgestellt war. Mit sehr präzisem Geschick mussten die Bälle von den Türmen in die Körbe gestoßen werden, jedoch ohne dabei den jeweiligen Turm umzuwerfen. Trotzdem passierte es häufig, dass - aus Gründen der Ungenauigkeit oder wegen der federnden Wirkung des Materials – der Ball einfach aus dem Korb heraushüpfte oder gar nicht erst hineinfiel. Daher schaffte auch Herr Karger es nicht auf Anhieb, die Bälle mit der Hand in die Körbe zu stoßen. Beim ersten Versuch meisterte unser Roboter als einziger diese Aufgabe mit ein wenig Glück komplett. Der komplette Saal brach in Beifall aus und wir jubelten bereits, nachdem unser Roboter den ersten Ball in den zugehörigen Korb befördert hatte, da dies bereits den Sieg für uns entschied. So erhielten wir mit 50
Punkten für diese Aufgabe erneut die höchstmögliche Punktzahl, was eine Gesamtpunktzahl von 130
Punkten ergab, und uns einen Vorsprung von insgesamt 47 Punkten vor der zweitplatzierten
Mannschaft verschaffte.

Nach einer mehr oder weniger kurzen Pause, in der wir unter anderem einem Reporter ein Interview gaben, fand im Anschluss die Siegerehrung mitsamt der Preisverleihung und der symbolischen Übergabe des Wanderpokals an unsere Schule statt. Da unsere Schule bereits 2011 den ersten Preis mit dem Team „RoboGuards“ (bestehend aus Fabian Kunze, Sebastian Schumann und Birk Blechschmidt) gewonnen hatte, wanderte der Pokal zu unserer Freude dieses Jahr ausnahmsweise nicht.
Als glückliche Sieger erhielten wir beide die tragbare Spielekonsole „Nintendo 3DS“ und brachten außerdem je einen Rucksack mit nach Hause – ganz zu schweigen von den tollen Erinnerungen und Erfahrungen.

Lego Mindstorms NXT Flugzeugspiel

Da ich für den Tag der offenen Tür meiner Schule, welcher bereits im Januar stattfand, eine etwas abwechslungsreichere und anspruchsvollere Projektidee gesucht habe, habe ich eine Abwandlung des 2D-Spiels "Helicopter" für den PC geschrieben, welche jedoch mit dem NXT gesteuert wird. Allerdings bin ich kein guter Grafiker, daher habe ich mein Spiel auf ein statisches Flugzeugbild beschränkt. Das gesamte Spiel wurde in C# programmiert, die Steuerung des NXTs in NXC.

Video:

Die NXT-Steuerung:
NXT-Steuerungsroboter

Quelltext C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections;

namespace NXT_Helicopter
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        System.Drawing.Bitmap Bitmap;
        System.Drawing.Image plane;
        int planesize = 200;
        double planediagonal;
        bool started = false;
        Point screenmiddle;
        double rotation;
        int Byte;
        int oldByte=-1;
        Size Formsize;
        string path = "";
        long score = 0;
        long scoretoreach;

        ArrayList condensation;
        ArrayList highscorepoints;
        ArrayList highscorenames;
        TextBox nameBox;
        Button submitButton;

        ArrayList blocktypes;

        double leftfraction = (double)100 / 1000;

        double blockXfraction = (double)150 / (double)1000;
        double blockYfraction = (double)150 / (double)1000;

        double planefraction=(double)100 / (double)1000;

        ArrayList collisionZone;
        ArrayList originalZone;

        Color background = System.Drawing.Color.DeepSkyBlue;

        ArrayList blocks;
        

        Point planeposition;
        

        int maxData = 45;
        int maxDegrees = 45;

        double XSpeed = (double)10/(double)1000;
        double startspeed;

        double maxupfraction = (double)40/(double)1000;

        Point rotatePoint(Point middle, Point point, double degrees)
        {

            //return new Point((int)(middle.X + Math.Sin(degrees * Math.PI / 180) * Math.Sqrt(Math.Pow(point.X - middle.X, 2) + Math.Pow(point.Y - middle.Y, 2))), (int)(middle.Y + Math.Cos(degrees * Math.PI / 180) * Math.Sqrt(Math.Pow(point.X - middle.X, 2) + Math.Pow(point.Y - middle.Y, 2))));
            //return point;
            return new Point((int)(Math.Cos(degrees * Math.PI / 180) * (point.X - middle.X) - Math.Sin(degrees * Math.PI / 180)*(point.Y-middle.Y) + middle.X), (int)(Math.Sin(degrees * Math.PI / 180) * (point.X - middle.X) + Math.Cos(degrees * Math.PI / 180)*(point.Y-middle.Y) + middle.Y));
            //return new Point((int)(middle.X + Math.Cos(degrees * Math.PI / 180) * Math.Sqrt(Math.Pow(point.X - middle.X, 2) + Math.Pow(point.Y - middle.Y, 2))), (int)(middle.Y + Math.Sin(degrees * Math.PI / 180) * Math.Sqrt(Math.Pow(point.X - middle.X, 2) + Math.Pow(point.Y - middle.Y, 2))));
        }

        void nameBox_GotFocus(object sender, EventArgs e)
        {
            ((TextBox)sender).Text = "";
            ((TextBox)sender).ForeColor = Color.Black;
        }

        private void rotatePlane(double degrees)
        {
            double olddegrees=-degrees;
            degrees+=90;
            Point[] destinationPoints =
            {
                new Point((int)(planeposition.X+Math.Sin((degrees+135)*Math.PI/180)*(planediagonal)), (int)(planeposition.Y+Math.Cos((degrees+135)*Math.PI/180)*(planediagonal))),
                new Point((int)(planeposition.X+Math.Sin((degrees+45)*Math.PI/180)*(planediagonal)), (int)(planeposition.Y+Math.Cos((degrees+45)*Math.PI/180)*(planediagonal))),
                new Point((int)(planeposition.X+Math.Sin((degrees+225)*Math.PI/180)*(planediagonal)), (int)(planeposition.Y+Math.Cos((degrees+225)*Math.PI/180)*(planediagonal)))
            };
            Point middle = new Point((destinationPoints[0].X + destinationPoints[2].X) / 2, (destinationPoints[0].Y + destinationPoints[2].Y) / 2);
            middle = planeposition;
            for (int i = 0; i < originalZone.Count; i++)
            {
                Point pt = (Point)originalZone[i];

                collisionZone[i] = rotatePoint(middle, pt, olddegrees);
                
            }
            
            Graphics.FromImage(pictureBox1.Image).DrawImage(plane, destinationPoints);
            /*for (int i = 0; i < collisionZone.Count; i++)
            {
                Graphics.FromImage(pictureBox1.Image).FillRectangle(new SolidBrush(Color.Red), new Rectangle((Point)collisionZone[i], new Size(1, 1)));
            }*/
        }

        void updateScore()
        {
            tableLayoutPanel1.Controls.Clear();
            tableLayoutPanel1.RowCount = 0;
            tableLayoutPanel1.RowCount++;
            Label titlelabel = new Label();
            titlelabel.Name = "titlelabel";
            titlelabel.Text = "Highscore";
            titlelabel.Dock = DockStyle.Top;
            titlelabel.AutoSize = true;
            titlelabel.Font = new Font("Arial", 25, FontStyle.Bold);
            titlelabel.ForeColor = Color.Black;
            titlelabel.TextAlign = ContentAlignment.TopCenter;
            tableLayoutPanel1.Controls.Add(titlelabel, 0, 0);
            tableLayoutPanel1.SetColumnSpan(titlelabel, 2);
            tableLayoutPanel1.Visible = true;
            if (!System.IO.File.Exists(path + "highscore.txt"))
            {
                System.IO.File.WriteAllText(path + "highscore.txt", "");
            }
            string Highscore = System.IO.File.ReadAllText(path + "highscore.txt", Encoding.UTF8);
            string[] scores=Highscore.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            for (int i = 0; i < scores.Length; i++)
            {
                tableLayoutPanel1.RowCount++;
                for (int j = 0; j < 2; j++)
                {
                    Label label = new Label();
                    label.Text = scores[i].Split(new string[] { "\t" }, StringSplitOptions.None)[j];
                    label.AutoSize = true;
                    label.Dock = DockStyle.Top;
                    label.TextAlign = ContentAlignment.MiddleLeft;
                    label.Font = new Font("Arial", 20, FontStyle.Bold);
                    tableLayoutPanel1.Controls.Add(label, j, tableLayoutPanel1.RowCount-1);
                }
                highscorepoints.Add(Convert.ToInt64(scores[i].Split(new string[] { "\t" }, StringSplitOptions.None)[1]));
                highscorenames.Add(scores[i].Split(new string[] { "\t" }, StringSplitOptions.None)[0]);
            }
            nameBox = new TextBox();
            nameBox.Text = "Dein Name";
            nameBox.Dock = DockStyle.Bottom;
            nameBox.GotFocus += new EventHandler(nameBox_GotFocus);
            nameBox.ForeColor = Color.Gray;
            nameBox.Font = new Font("Arial", 20, FontStyle.Bold);
            Button replay = new Button();
            replay.Text = "Erneut spielen";
            replay.Dock = DockStyle.Bottom;
            replay.BackColor = SystemColors.ButtonFace;
            replay.AutoSize = true;
            replay.TextAlign = ContentAlignment.MiddleCenter;
            replay.Font = new Font("Arial", 20, FontStyle.Bold);
            replay.Click += new EventHandler(replay_Click);
            tableLayoutPanel1.RowCount++;
            tableLayoutPanel1.Controls.Add(nameBox, 0, tableLayoutPanel1.RowCount - 1);
            submitButton = new Button();
            submitButton.Text = "Eintragen";
            submitButton.AutoSize = true;
            submitButton.Font = new Font("Arial", 20, FontStyle.Bold); ;
            submitButton.Dock = DockStyle.Bottom;
            submitButton.TextAlign = ContentAlignment.MiddleCenter;
            submitButton.Click += new EventHandler(submitButton_Click);
            submitButton.BackColor = SystemColors.ButtonFace;
            tableLayoutPanel1.Controls.Add(submitButton, 1, tableLayoutPanel1.RowCount - 1);
            tableLayoutPanel1.RowCount++;
            tableLayoutPanel1.Controls.Add(replay, 0, tableLayoutPanel1.RowCount - 1);
            tableLayoutPanel1.SetColumnSpan(replay, 2);
        }

        void draw()
        {
            if (started)
            {
                bool collision = false;
                Image image = pictureBox1.Image;
                string debug = "Punktzahl: " + score.ToString();
                System.Random random = new Random();
                Graphics.FromImage(image).Clear(background);
                //Graphics.FromImage(pictureBox1.Image).DrawLine(new Pen(Color.Red), random.Next(pictureBox1.Width), random.Next(pictureBox1.Height), random.Next(pictureBox1.Width), random.Next(pictureBox1.Width));
                //Graphics.FromImage(pictureBox1.Image).DrawImage(plane, 10, 20, 150, 150);
                int Ychange=(int)(((double)Byte / (double)maxData) * (double)maxupfraction * (double)Formsize.Height);
                planeposition.Y -= Ychange;
                if (random.Next(30) == 5 && score >= scoretoreach)
                {
                    int top = random.Next(this.Height);
                    int width = random.Next(Formsize.Width / 100, Formsize.Width / 8);
                    int height = random.Next((int)((double)Formsize.Height * blockYfraction) + planesize + planesize / 3, this.Height - (int)((double)Formsize.Height * blockYfraction) - planesize - planesize / 3);
                    blocks.Add(new Rectangle(Formsize.Width, top, width, height));
                    blocktypes.Add((byte)1);
                    scoretoreach = score+ (long)((double)height / (double)25);
                }
                for (int i = 0; i < condensation.Count; i++)
                {
                    Point blockrect = (Point)condensation[i];
                    if (blockrect.X < -50)
                    {
                        condensation.RemoveAt(i);
                        i--;
                    }
                    else
                    {
                        blockrect.X -= (int)XSpeed;
                        condensation[i] = blockrect;
                    }
                }
                condensation.Add(new Point(planeposition.X, planeposition.Y));
                if (condensation.Count > 1)
                {
                    Graphics.FromImage(image).DrawCurve(new Pen(Color.FromArgb(150, Color.White), 10), (Point[])condensation.ToArray(typeof(Point)));
                }
                int left = 0;
                int downleft = 0;
                for (int i = 0; i < originalZone.Count; i++)
                {
                    Point pt = (Point)originalZone[i];
                    pt.Y -= Ychange;
                    originalZone[i] = pt;
                }
                for (int i = 0; i < blocks.Count; i++)
                {
                    Graphics.FromImage(image).FillRectangle(new SolidBrush(Color.LightGray), (Rectangle)blocks[i]);
                    Rectangle blockrect = (Rectangle)blocks[i];
                    if (blockrect.X + blockrect.Width < 0)
                    {
                        blocks.RemoveAt(i);
                        blocktypes.RemoveAt(i);
                        i--;
                    }
                    else
                    {
                        blockrect.X -= (int)XSpeed;
                        blocks[i] = blockrect;
                        if ((byte)blocktypes[i] == 0)
                        {
                            if (blockrect.X + blockrect.Width > left)
                            {
                                left = blockrect.X + blockrect.Width;
                            }
                        }
                        if ((byte)blocktypes[i] == 2)
                        {
                            if (blockrect.X + blockrect.Width > downleft)
                            {
                                downleft = blockrect.X + blockrect.Width;
                            }
                        }
                    }
                }
                while (left < Formsize.Width)
                {
                    int width = random.Next(20, (int)(blockXfraction * (double)Formsize.Width));
                    blocks.Add(new Rectangle(left, 0, width, random.Next((int)((double)Formsize.Height * blockYfraction) / 10, (int)((double)Formsize.Height * blockYfraction))));
                    blocktypes.Add((byte)0);
                    left += width;
                }
                while (downleft < Formsize.Width)
                {
                    int width = random.Next(20, (int)(blockXfraction * (double)Formsize.Width));
                    int height = random.Next((int)((double)Formsize.Height * blockYfraction) / 10, (int)((double)Formsize.Height * blockYfraction));
                    blocks.Add(new Rectangle(downleft, Formsize.Height-height, width, height));
                    blocktypes.Add((byte)2);
                    downleft += width;
                }
                rotatePlane(rotation);
                Graphics.FromImage(image).DrawString(debug, new System.Drawing.Font("Arial", 15), new SolidBrush(Color.Black), new Point(10, 10));
                pictureBox1.Refresh();
                for (int i = 0; i < blocks.Count; i++)
                {
                    Rectangle blockrect = (Rectangle)blocks[i];
                    for (int j = 0; j < collisionZone.Count; j++)
                    {
                        if (((Point)collisionZone[i]).X > blockrect.X && ((Point)collisionZone[i]).X < blockrect.X + blockrect.Width && ((Point)collisionZone[i]).Y > blockrect.Y && ((Point)collisionZone[i]).Y < blockrect.Y + blockrect.Height && !collision)
                        {
                            timer1.Stop();
                            collision = true;
                            System.Windows.Forms.Cursor.Show();
                            System.Windows.Forms.DialogResult result=MessageBox.Show("Du bist mit einem unbekannten Objekt kollidiert, dein Flugzeug ist nur noch Schrott.\n\nImmerhin hast du "+score.ToString()+" Punkte erreicht.\n\nMöchtest du dich in die Highscore eintragen?", "GAME OVER", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                            if (result == System.Windows.Forms.DialogResult.Yes)
                            {
                                
                                updateScore();
                                
                            }
                            else
                            {
                                load();
                            }
                        }
                    }
                }
                score++;
                if (score % 100 == 0)
                {
                    XSpeed = startspeed + score / 100;
                }
            }
        }

        void replay_Click(object sender, EventArgs e)
        {
            load();
        }

        void submitButton_Click(object sender, EventArgs e)
        {
            string highscorestring = "";
            bool inserted = false;
            for (int i = 0; i < highscorepoints.Count; i++)
            {
                if (score > (long)highscorepoints[i] && !inserted)
                {
                    highscorestring += nameBox.Text + "\t" + score.ToString() + "\r\n";
                    inserted = true;
                }
                highscorestring += (string)highscorenames[i] + "\t" + (long)highscorepoints[i] + "\r\n";
            }
            if (!inserted)
            {
                highscorestring += nameBox.Text + "\t" + score.ToString() + "\r\n";
                inserted = true;
            }
            System.IO.File.WriteAllText(path + "highscore.txt", highscorestring, Encoding.UTF8);
            updateScore();
            submitButton.Enabled=false;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            draw();
           
        }

        private void drawThread()
        {
            while (true)
            {
                draw();
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
        }

        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            while (serialPort1.BytesToRead >= 3)
            {
                serialPort1.ReadByte();
                serialPort1.ReadByte();
                oldByte=Byte+maxData;
                Byte=serialPort1.ReadByte();
                
                //MessageBox.Show(Byte.ToString());
                if (!started && Byte != oldByte)
                {
                    started = true;
                }
                Byte -= maxData;
                rotation = (double)(Byte * maxDegrees / (double)maxData);
                //rotation = Byte;
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            serialPort1.Dispose();
            serialPort1.Close();
        }

        void load()
        {
            highscorenames = new ArrayList();
            highscorepoints = new ArrayList();
            tableLayoutPanel1.Visible = false;
            score = 0;
            scoretoreach = 0;
            started = false;
            oldByte = -1;
            XSpeed = (double)10 / (double)1000;
            rotation = 0;
            this.BackColor = background;
            System.Windows.Forms.Cursor.Hide();
            blocktypes = new ArrayList();
            condensation = new ArrayList();
            blocks = new ArrayList();
            Formsize = this.Size;
            XSpeed *= Formsize.Width;
            screenmiddle = new Point((int)((double)Formsize.Width * leftfraction), Formsize.Height / 2);
            collisionZone = new ArrayList();
            originalZone = new ArrayList();
            planeposition = screenmiddle;
            plane = System.Drawing.Image.FromFile(path + "falcon.png");
            plane = plane.GetThumbnailImage((int)((double)Formsize.Width * planefraction), (int)((double)Formsize.Width * planefraction), null, IntPtr.Zero);
            planesize = plane.Width;
            planediagonal = Math.Sqrt((double)(planesize * planesize + planesize * planesize)) / (double)2;
            System.Drawing.Bitmap planeMap = new Bitmap(plane);
            Bitmap = new System.Drawing.Bitmap(pictureBox1.Width, pictureBox1.Height);
            pictureBox1.Image = Bitmap;
            for (int y = 0; y < plane.Height; y++)
            {
                for (int x = 0; x < plane.Width; x++)
                {
                    if (planeMap.GetPixel(x, y).A > 1 && planeMap.GetPixel(x, y).A < 255)
                    {
                        collisionZone.Add(new Point(screenmiddle.X - planesize / 2 + x, screenmiddle.Y - planesize / 2 + y));
                        originalZone.Add(new Point(screenmiddle.X - planesize / 2 + x, screenmiddle.Y - planesize / 2 + y));
                    }
                }
            }
            //originalZone = collisionZone;
            plane = planeMap;

            startspeed = XSpeed;
            timer1.Start();
            rotatePlane(0);
        }

        private void Form1_Shown(object sender, EventArgs e)
        {
            load();
            System.Windows.Forms.Cursor.Show();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            serialPort1.PortName = textBox1.Text;
            serialPort1.Open();
            System.Windows.Forms.Cursor.Hide();
            textBox1.Dispose();
            button1.Dispose();
        }
    }
}

Quelltext NXC

#define motor OUT_C
#define touch S4
#define BT 0

/*
Zuordnungen:
 45° -> 100%
  0° ->   0%
*/

byte buffer[1];
byte number;
int rotation;

int max=45;

task main()
{
   SetLongAbort(true);
   TextOut(0, LCD_LINE1, "Game Joystick");
   TextOut(0, LCD_LINE2, "(Motor C)");
   TextOut(0, LCD_LINE4, "Kalibrieren...");
   until(ButtonPressed(BTNCENTER, true));
   ResetRotationCount(motor);
   //PlayTone(440, 200);
   TextOut(0, LCD_LINE5, "OK");
   while(true)
   {
       rotation=MotorRotationCount(motor)%360;
       if(rotation > max)
       {
          rotation=max;
       }
       if(rotation < -max)
       {
          rotation=-max;
       }
       number=max+rotation;
       buffer[0]=number;
       BluetoothWrite(0, buffer);
       NumOut(0, LCD_LINE7, number);
       Wait(50);
   }
}

Downloads

Einfache, ausführbare Version oder Version mit Quelltext

Spambog.com Sicherheitslücke (XSS-Injection)

Seit einiger Zeit verwende ich den Dienst Spambog.com, welcher Wegwerf-E-Mail-Adressen zur Verfügung stellt. Dort habe ich eine Sicherheitslücke entdeckt (XSS-Injection), die das Sperren fremder Konten möglich machte und dem Angreifer Zugriff zu passwortgeschützten Mailboxen verschaffen konnte. Nachdem die Sicherheitslücke mittlerweile behoben wurde, folgt hier ein Video mit näheren Informationen:

Das Affenpuzzle-Problem

Da wir vor einiger Zeit im Informatikunterricht mit Backtracking-Algorithmen befasst und uns auch das Affenpuzzle angesehen haben, hatte ich mich entschlossen, ein kleines C++-Programm zu schreiben, welches selbiges löst.
Unter http://www.swisseduc.ch/informatik/120-lektionen/principles/computation/kara/docs/affenpuzzle_bastelbogen_unprotected.pdf kann man sich die Bastelvorlage des Affenpuzzles herunterladen.

Das Affenrätsel ist ein Puzzle, welches aus einem Quadrat aus mit einer bestimmten Kantenlänge (2, 3, 4, 5 oder mehr) Karten besteht. Jede Karte muss passend an die andere angelegt werden, sodass ein beispielsweise gelber Affenkopf nur an einem gelben Affenkörper anliegt. Dabei gibt es nur eine begrenzte Anzahl an Lösungen, welche ausschließlich durch ein sogenanntes Backtracking-Verfahren herauszufinden sind.

// Affenpuzzle.cpp: Birk Blechschmidt, 14 November 2011
// Dieser Kommentar muss erhalten bleiben.

#include "iostream"
#include "string"
#include "time.h"
using namespace std;

const char greenhead=1;
const char greenbody=2;
const char redhead=4;
const char redbody=5;
const char bluehead=7;
const char bluebody=8;
const char yellowhead=10;
const char yellowbody=11;
time_t beginning, ending;
double timespan;

long solutioncount=0;

long iterationcount=0;

const char rowcount=4;

const char fieldcount=rowcount*rowcount;
char cards[fieldcount][4];
char rotations[fieldcount];
char table[fieldcount];
bool set[fieldcount];
char* solutions=new char[0];

char modulus(char input)
{
	char output=input;
	if(output < 0)
	{
		output*=-1;
	}
	return output;
}

string getReadableName(char input)
{
	string name="";
	if(input==greenhead)
	{
		name="gh";
	}
	if(input==greenbody)
	{
		name="gb";
	}
	if(input==redhead)
	{
		name="rh";
	}
	if(input==redbody)
	{
		name="rb";
	}
	if(input==bluehead)
	{
		name="bh";
	}
	if(input==bluebody)
	{
		name="bb";
	}
	if(input==yellowhead)
	{
		name="yh";
	}
	if(input==yellowbody)
	{
		name="yb";
	}
	return name;
}

void rotateCard(char cardnumber, char rotationcount) //Uhrzeigersinn
{
	if(rotationcount !=0)
	{
		char tempCard[4];
		for(char i=0; i < 4; i++)
		{
			tempCard[i]=cards[cardnumber][i];
		}
		for(char i=0; i < 4; i++)
		{
			char newindex=i-rotationcount;
			while(newindex < 0)
			{
				newindex+=4;
			}
			while(newindex > 3)
			{
				newindex-=4;
			}
			cards[cardnumber][i]=tempCard[newindex];
		}
		rotations[cardnumber]+=rotationcount;
		while(rotations[cardnumber] < 0)
		{
			rotations[cardnumber]+=4;
		}
		while(rotations[cardnumber] > 3)
		{
			rotations[cardnumber]-=4;
		}
	}
}

bool validNeighbours(char cardnumber, bool debug=false)
{
	bool valid=true;
	if(cardnumber % rowcount > 0)
	{
		if(table[cardnumber-1]!=-1)
		{
			if(modulus(cards[table[cardnumber]][3]-cards[table[cardnumber-1]][1])!=1)
			{
				valid=false;
			}
		}
	}

	if(cardnumber % rowcount < rowcount-1)
	{
		if(modulus(cards[table[cardnumber]][1]-cards[table[cardnumber+1]][3])!=1)
		{
			if(table[cardnumber+1]!=-1)
			{
				valid=false;
			}
		}
	}

	if(cardnumber >= rowcount)
	{
		if(modulus(cards[table[cardnumber]][0]-cards[table[cardnumber-rowcount]][2])!=1)
		{
			if(table[cardnumber-rowcount]!=-1)
			{
				valid=false;
			}
		}
	}

	if(cardnumber < fieldcount-rowcount)
	{
		if(modulus(cards[table[cardnumber]][2]-cards[table[cardnumber+rowcount]][0])!=1)
		{
			if(table[cardnumber+rowcount]!=-1)
			{
				valid=false;
			}
		}
	}

	return valid;
}

void printCards()
{
	for(char yC=0; yC < rowcount; yC++)
	{
		for(char xC=0; xC < rowcount; xC++)
		{
			cout << " |";
			cout << getReadableName(cards[table[yC*rowcount+xC]][0]) << "| ";
		}
		cout << endl;
		for(char xC=0; xC < rowcount; xC++)
		{
			cout << getReadableName(cards[table[yC*rowcount+xC]][3]) << "| |";
			cout << getReadableName(cards[table[yC*rowcount+xC]][1]) <<" ";
		}
		cout << endl;
		for(char xC=0; xC < rowcount; xC++)
		{

			cout << " |";
			cout << getReadableName(cards[table[yC*rowcount+xC]][2]) << "| ";
		}
		cout << endl<<endl;
	}
}

void solve(char fieldnumber)
{
	for(char card=0; card < fieldcount; card++)
	{
		if(!set[card])
		{
			table[fieldnumber]=card;
			set[card]=true;
			for(char r=0; r<4; r++)
			{
				iterationcount++;
				if(validNeighbours(fieldnumber))
				{
					if(fieldnumber == fieldcount-1)
					{

						if(rotations[0]==0)
						{
							solutioncount++;
							cout << "Solution:"<<endl<<endl;
							char* temparr=new char[solutioncount*fieldcount*2];
							for(int i=0; i < solutioncount-1; i++)
							{
								for(int j=0; j < fieldcount; j++)
								{
									temparr[i*fieldcount*2+j*2]=solutions[i*fieldcount*2+j*2];
									temparr[i*fieldcount*2+j*2+1]=solutions[i*fieldcount*2+j*2+1];
								}
							}
							for(int i=0; i < fieldcount; i++)
							{
								temparr[(solutioncount-1)*fieldcount*2+i*2]=table[i];
								temparr[(solutioncount-1)*fieldcount*2+i*2+1]=rotations[table[i]];
							}
							solutions=new char[solutioncount*fieldcount*2];
							for(int i=0; i < solutioncount; i++)
							{
								for(int j=0; j < fieldcount; j++)
								{
									solutions[i*fieldcount*2+j*2]=temparr[i*fieldcount*2+j*2];
									solutions[i*fieldcount*2+j*2+1]=temparr[i*fieldcount*2+j*2+1];
								}
							}

								printCards();

							cout << endl<<endl;
						}
					}

					solve(fieldnumber+1);
				}
				rotateCard(card, 1);
			}
			table[fieldnumber]=-1;
			set[card]=false;
		}
	}
}

int main()
{

	//Kartendefinition 2*2
	/*cards[0][0]=greenbody;
 cards[0][1]=redhead;
 cards[0][2]=greenbody;
 cards[0][3]=bluehead;

 cards[1][0]=bluebody;
 cards[1][1]=greenhead;
 cards[1][2]=yellowhead;
 cards[1][3]=redbody;

 cards[2][0]=yellowbody;
 cards[2][1]=bluebody;
 cards[2][2]=redbody;
 cards[2][3]=bluehead;

 cards[3][0]=greenhead;
 cards[3][1]=bluebody;
 cards[3][2]=bluehead;
 cards[3][3]=yellowbody;*/

	//Kartendefinition 4*4
	cards[0][0]=redhead;
	cards[0][1]=bluehead;
	cards[0][2]=yellowhead;
	cards[0][3]=yellowhead;

	cards[1][0]=yellowbody;
	cards[1][1]=redhead;
	cards[1][2]=greenhead;
	cards[1][3]=redhead;

	cards[2][0]=redbody;
	cards[2][1]=bluehead;
	cards[2][2]=yellowbody;
	cards[2][3]=bluebody;

	cards[3][0]=bluebody;
	cards[3][1]=bluehead;
	cards[3][2]=yellowbody;
	cards[3][3]=greenhead;

	cards[4][0]=redbody;
	cards[4][1]=bluebody;
	cards[4][2]=greenhead;
	cards[4][3]=yellowhead;

	cards[5][0]=bluebody;
	cards[5][1]=redbody;
	cards[5][2]=bluehead;
	cards[5][3]=redbody;

	cards[6][0]=bluehead;
	cards[6][1]=bluehead;
	cards[6][2]=yellowbody;
	cards[6][3]=greenbody;

	cards[7][0]=redhead;
	cards[7][1]=greenhead;
	cards[7][2]=yellowhead;
	cards[7][3]=greenhead;

	cards[8][0]=redhead;
	cards[8][1]=greenbody;
	cards[8][2]=bluehead;
	cards[8][3]=greenbody;

	cards[9][0]=bluebody;
	cards[9][1]=greenhead;
	cards[9][2]=yellowbody;
	cards[9][3]=yellowbody;

	cards[10][0]=greenbody;
	cards[10][1]=bluehead;
	cards[10][2]=yellowhead;
	cards[10][3]=redbody;

	cards[11][0]=yellowbody;
	cards[11][1]=greenhead;
	cards[11][2]=greenbody;
	cards[11][3]=bluebody;

	cards[12][0]=greenbody;
	cards[12][1]=yellowhead;
	cards[12][2]=bluehead;
	cards[12][3]=bluehead;

	cards[13][0]=greenbody;
	cards[13][1]=yellowhead;
	cards[13][2]=redhead;
	cards[13][3]=redhead;

	cards[14][0]=yellowbody;
	cards[14][1]=greenhead;
	cards[14][2]=redhead;
	cards[14][3]=bluebody;

	cards[15][0]=redbody;
	cards[15][1]=yellowhead;
	cards[15][2]=redbody;
	cards[15][3]=greenhead;

	//Kartendefinition 6*6
	/*cards[0][0]=redbody;
 cards[0][1]=redhead;
 cards[0][2]=yellowhead;
 cards[0][3]=bluebody;

 cards[1][0]=redhead;
 cards[1][1]=redbody;
 cards[1][2]=yellowbody;
 cards[1][3]=bluehead;

 cards[2][0]=yellowhead;
 cards[2][1]=greenbody;
 cards[2][2]=greenbody;
 cards[2][3]=bluehead;

 cards[3][0]=greenhead;
 cards[3][1]=bluebody;
 cards[3][2]=yellowhead;
 cards[3][3]=yellowbody;

 cards[4][0]=redhead;
 cards[4][1]=greenhead;
 cards[4][2]=bluebody;
 cards[4][3]=bluebody;

 cards[5][0]=yellowhead,
 cards[5][1]=yellowhead;
 cards[5][2]=redbody;
 cards[5][3]=greenbody;

 cards[6][0]=redbody;
 cards[6][1]=redbody;
 cards[6][2]=redhead;
 cards[6][3]=bluehead;

 cards[7][0]=bluebody;
 cards[7][1]=redbody;
 cards[7][2]=redhead;
 cards[7][3]=bluehead;

 cards[8][0]=yellowbody;
 cards[8][1]=redhead;
 cards[8][2]=bluehead;
 cards[8][3]=greenbody;

 cards[9][0]=redhead;
 cards[9][1]=yellowbody;
 cards[9][2]=redhead;
 cards[9][3]=greenhead;

 cards[10][0]=bluehead;
 cards[10][1]=bluebody;
 cards[10][2]=redhead;
 cards[10][3]=redhead;

 cards[11][0]=greenhead;
 cards[11][1]=bluebody;
 cards[11][2]=bluebody;
 cards[11][3]=greenhead;

 cards[12][0]=greenhead;
 cards[12][1]=greenhead;
 cards[12][2]=bluehead;
 cards[12][3]=yellowbody;

 cards[13][0]=yellowbody;
 cards[13][1]=greenbody;
 cards[13][2]=redbody;
 cards[13][3]=greenbody;

 cards[14][0]=yellowhead;
 cards[14][1]=redhead;
 cards[14][2]=greenhead;
 cards[14][3]=bluebody;

 cards[15][0]=bluehead;
 cards[15][1]=yellowbody;
 cards[15][2]=greenbody;
 cards[15][3]=redhead;

 cards[16][0]=yellowbody;
 cards[16][1]=greenhead;
 cards[16][2]=redhead;
 cards[16][3]=redbody;

 cards[17][0]=yellowhead;
 cards[17][1]=bluehead;
 cards[17][2]=yellowhead;
 cards[17][3]=redhead;

 cards[18][0]=bluehead;
 cards[18][1]=bluebody;
 cards[18][2]=greenbody;
 cards[18][3]=greenhead;

 cards[19][0]=bluebody;
 cards[19][1]=yellowhead;
 cards[19][2]=greenhead;
 cards[19][3]=redhead;

 cards[20][0]=redbody;
 cards[20][1]=greenhead;
 cards[20][2]=yellowhead;
 cards[20][3]=bluebody;

 cards[21][0]=greenhead;
 cards[21][1]=greenhead;
 cards[21][2]=bluehead;
 cards[21][3]=redhead;

 cards[22][0]=redhead;
 cards[22][1]=redhead;
 cards[22][2]=bluebody;
 cards[22][3]=yellowhead;

 cards[23][0]=greenhead;
 cards[23][1]=yellowbody;
 cards[23][2]=redhead;
 cards[23][3]=yellowhead;

 cards[24][0]=redbody;
 cards[24][1]=yellowhead;
 cards[24][2]=bluehead;
 cards[24][3]=yellowbody;

 cards[25][0]=redhead;
 cards[25][1]=redbody;
 cards[25][2]=bluebody;
 cards[25][3]=bluehead;

 cards[26][0]=greenhead;
 cards[26][1]=redbody;
 cards[26][2]=yellowbody;
 cards[26][3]=yellowhead;

 cards[27][0]=greenbody;
 cards[27][1]=bluehead;
 cards[27][2]=greenhead;
 cards[27][3]=greenhead;

 cards[28][0]=bluehead;
 cards[28][1]=bluebody;
 cards[28][2]=bluehead;
 cards[28][3]=greenbody;

 cards[29][0]=yellowbody;
 cards[29][1]=bluehead;
 cards[29][2]=redbody;
 cards[29][3]=redbody;

 cards[30][0]=yellowhead;
 cards[30][1]=redbody;
 cards[30][2]=greenbody;
 cards[30][3]=redhead;

 cards[31][0]=redbody;
 cards[31][1]=bluehead;
 cards[31][2]=redbody;
 cards[31][3]=yellowhead;

 cards[32][0]=redhead;
 cards[32][1]=bluehead;
 cards[32][2]=yellowbody;
 cards[32][3]=yellowhead;

 cards[33][0]=bluehead;
 cards[33][1]=yellowhead;
 cards[33][2]=redhead;
 cards[33][3]=yellowbody;

 cards[34][0]=bluehead;
 cards[34][1]=yellowhead;
 cards[34][2]=yellowbody;
 cards[34][3]=redhead;

 cards[35][0]=greenbody;
 cards[35][1]=yellowhead;
 cards[35][2]=bluebody;
 cards[35][3]=bluehead;*/

	cout << "Monkey Puzzle Solver by Birk Blechschmidt, 14 November 2011"<<endl<<endl;
	cout << "Puzzle size: "<<(short)rowcount<<"*"<<(short)rowcount<<"="<<(short)fieldcount<<endl<<endl;
	cout << "Initial cards: "<<endl<<endl;
	for(int i=0; i < fieldcount; i++)
	{
		table[i]=i;
	}
	printCards();
	cout << endl<<endl;
	for(int i=0; i < fieldcount; i++)
	{
		rotations[i]=0;
		table[i]=-1;
		set[i]=false;
	}
	cout << "Press ENTER key to start..."<<endl<<endl;
	fflush(stdin);
	getchar();
	time(&beginning);
	solve(0);
	time(&ending);
	timespan=difftime(ending, beginning);
	cout << "In total "<<solutioncount<<" solutions were found in "<<timespan<<" seconds and "<<iterationcount<<" iterations."<<endl << endl;
	cout << endl << "Press ENTER key to quit..."<<endl<<endl;
	fflush(stdin);
	getchar();
	return 0;
}

Die Ausgabe:

Monkey Puzzle Solver by Birk Blechschmidt, 14 November 2011

Puzzle size: 4*4=16

Initial cards:

  |rh|      |yb|      |rb|      |bb|
yh|  |bh  rh|  |rh  bb|  |bh  gh|  |bh
  |yh|      |gh|      |yb|      |yb|

  |rb|      |bb|      |bh|      |rh|
yh|  |bb  rb|  |rb  gb|  |bh  gh|  |gh
  |gh|      |bh|      |yb|      |yh|

  |rh|      |bb|      |gb|      |yb|
gb|  |gb  yb|  |gh  rb|  |bh  bb|  |gh
  |bh|      |yb|      |yh|      |gb|

  |gb|      |gb|      |yb|      |rb|
bh|  |yh  rh|  |yh  bb|  |gh  gh|  |yh
  |bh|      |rh|      |rh|      |rb|

Press ENTER key to start...

Solution:

  |rh|      |gh|      |gh|      |gb|
yh|  |bh  bb|  |yb  yh|  |rh  rb|  |bh
  |yh|      |yb|      |gh|      |yh|

  |yb|      |yh|      |gb|      |yb|
rh|  |rh  rb|  |rb  rh|  |bh  bb|  |gh
  |gh|      |gh|      |gb|      |gb|

  |gb|      |gb|      |gh|      |gh|
bh|  |yh  yb|  |bh  bb|  |yh  yb|  |bb
  |bh|      |bh|      |rb|      |bh|

  |bb|      |bb|      |rh|      |bb|
yb|  |rb  rh|  |yb  yh|  |rh  rb|  |rb
  |bh|      |gh|      |gb|      |bh|

Solution:

  |rh|      |yb|      |bh|      |yb|
yh|  |bh  bb|  |gh  gb|  |bh  bb|  |gh
  |yh|      |rh|      |yb|      |gb|

  |yb|      |rb|      |yh|      |gh|
gh|  |yb  yh|  |bb  bh|  |rb  rh|  |yh
  |bb|      |gh|      |gb|      |gh|

  |bh|      |gb|      |gh|      |gb|
rb|  |rb  rh|  |yh  yb|  |bb  bh|  |rh
  |bb|      |rh|      |bh|      |gb|

  |bh|      |rb|      |bb|      |gh|
bh|  |gb  gh|  |yh  yb|  |rb  rh|  |rh
  |yh|      |rb|      |bh|      |yb|

Solution:

  |gh|      |yh|      |gb|      |rb|
rh|  |rh  rb|  |rb  rh|  |bh  bb|  |bh
  |yb|      |gh|      |gb|      |yb|

  |yh|      |gb|      |gh|      |yh|
bh|  |rb  rh|  |yh  yb|  |gb  gh|  |rb
  |gb|      |rh|      |bb|      |bb|

  |gh|      |rb|      |bh|      |bh|
yb|  |bb  bh|  |bb  bh|  |yb  yh|  |bh
  |bh|      |rb|      |gb|      |gb|

  |bb|      |rh|      |gh|      |gh|
rh|  |yb  yh|  |bh  bb|  |yb  yh|  |rh
  |gh|      |yh|      |yb|      |gh|

Solution:

  |rb|      |bh|      |rh|      |gh|
bb|  |bh  bb|  |yb  yh|  |bh  bb|  |yb
  |yb|      |gh|      |yh|      |yb|

  |yh|      |gb|      |yb|      |yh|
bh|  |rb  rh|  |bh  bb|  |gh  gb|  |bh
  |gb|      |gb|      |gb|      |bh|

  |gh|      |gh|      |gh|      |bb|
yh|  |rh  rb|  |rb  rh|  |rh  rb|  |rb
  |gh|      |yh|      |yb|      |bh|

  |gb|      |yb|      |yh|      |bb|
yb|  |bh  bb|  |gh  gb|  |rh  rb|  |gh
  |bh|      |rh|      |rh|      |yh|

Solution:

  |rb|      |gh|      |rh|      |bh|
bb|  |bh  bb|  |yb  yh|  |bh  bb|  |yb
  |yb|      |yb|      |yh|      |gh|

  |yh|      |yh|      |yb|      |gb|
gb|  |rh  rb|  |rb  rh|  |rh  rb|  |bh
  |rh|      |gh|      |gh|      |yh|

  |rb|      |gb|      |gb|      |yb|
yh|  |bb  bh|  |yh  yb|  |bh  bb|  |gh
  |gh|      |bh|      |bh|      |gb|

  |gb|      |bb|      |bb|      |gh|
bh|  |rh  rb|  |rb  rh|  |yb  yh|  |rh
  |gb|      |bh|      |gh|      |gh|

Solution:

  |yb|      |yb|      |bh|      |rh|
bh|  |bb  bh|  |gh  gb|  |gb  gh|  |gh
  |rb|      |bb|      |rh|      |yh|

  |rh|      |bh|      |rb|      |yb|
yb|  |gh  gb|  |bh  bb|  |bh  bb|  |gh
  |rh|      |yb|      |rb|      |rh|

  |rb|      |yh|      |rh|      |rb|
yh|  |bb  bh|  |rb  rh|  |gb  gh|  |yh
  |gh|      |gb|      |yh|      |rb|

  |gb|      |gh|      |yb|      |rh|
bh|  |yh  yb|  |gb  gh|  |yb  yh|  |bh
  |bh|      |bb|      |bb|      |yh|

Solution:

  |bh|      |rh|      |gh|      |gb|
rb|  |yb  yh|  |bh  bb|  |yh  yb|  |bh
  |bb|      |yh|      |rb|      |bh|

  |bh|      |yb|      |rh|      |bb|
bh|  |gb  gh|  |yb  yh|  |rh  rb|  |rb
  |yh|      |bb|      |gb|      |bh|

  |yb|      |bh|      |gh|      |bb|
bb|  |gh  gb|  |yh  yb|  |gb  gh|  |bh
  |rh|      |rb|      |bb|      |yb|

  |rb|      |rh|      |bh|      |yh|
gh|  |yh  yb|  |gh  gb|  |gb  gh|  |gh
  |rb|      |rh|      |rh|      |rh|

Solution:

  |bh|      |rh|      |rb|      |rb|
bb|  |yb  yh|  |bh  bb|  |bh  bb|  |bh
  |gh|      |yh|      |rb|      |yb|

  |gb|      |yb|      |rh|      |yh|
rb|  |bh  bb|  |gh  gb|  |gb  gh|  |gh
  |yh|      |gb|      |bh|      |rh|

  |yb|      |gh|      |bb|      |rb|
rh|  |rh  rb|  |rb  rh|  |yb  yh|  |bb
  |gh|      |yh|      |gh|      |gh|

  |gb|      |yb|      |gb|      |gb|
rh|  |yh  yb|  |bb  bh|  |yh  yb|  |bh
  |rh|      |gh|      |bh|      |bh|

Solution:

  |rh|      |rh|      |rb|      |rh|
gh|  |gh  gb|  |gb  gh|  |yh  yb|  |gh
  |yh|      |bh|      |rb|      |rh|

  |yb|      |bb|      |rh|      |rb|
bh|  |gh  gb|  |yb  yh|  |bh  bb|  |bh
  |bb|      |gh|      |yh|      |yb|

  |bh|      |gb|      |yb|      |yh|
rb|  |rb  rh|  |yh  yb|  |bb  bh|  |rb
  |bb|      |rh|      |gh|      |gb|

  |bh|      |rb|      |gb|      |gh|
bh|  |yb  yh|  |bb  bh|  |yh  yb|  |rh
  |gb|      |gh|      |bh|      |bb|

Solution:

  |rh|      |yh|      |gh|      |rh|
gh|  |gh  gb|  |bh  bb|  |yh  yb|  |gh
  |yh|      |bh|      |rb|      |rh|

  |yb|      |bb|      |rh|      |rb|
bh|  |gh  gb|  |yb  yh|  |bh  bb|  |bh
  |bb|      |gh|      |yh|      |yb|

  |bh|      |gb|      |yb|      |yh|
rb|  |rb  rh|  |bh  bb|  |gh  gb|  |rh
  |bb|      |gb|      |rh|      |rh|

  |bh|      |gh|      |rb|      |rb|
gb|  |bh  bb|  |yb  yh|  |gb  gh|  |yh
  |yb|      |yb|      |bh|      |rb|

Solution:

  |rh|      |yh|      |bh|      |bh|
gh|  |gh  gb|  |rh  rb|  |yb  yh|  |bh
  |yh|      |rh|      |bb|      |gb|

  |yb|      |rb|      |bh|      |gh|
gh|  |yb  yh|  |gh  gb|  |yh  yb|  |rh
  |bb|      |rb|      |rb|      |bb|

  |bh|      |rh|      |rh|      |bh|
gb|  |gb  gh|  |yb  yh|  |bh  bb|  |yb
  |rh|      |rh|      |yh|      |gh|

  |rb|      |rb|      |yb|      |gb|
yh|  |bb  bh|  |bb  bh|  |gb  gh|  |bb
  |gh|      |rb|      |bh|      |yb|

Solution:

  |gb|      |rb|      |gh|      |rh|
rh|  |bh  bb|  |bh  bb|  |yb  yh|  |bh
  |gb|      |rb|      |yb|      |yh|

  |gh|      |rh|      |yh|      |yb|
rb|  |rb  rh|  |gb  gh|  |rb  rh|  |rh
  |yh|      |yh|      |bb|      |gh|

  |yb|      |yb|      |bh|      |gb|
bh|  |bb  bh|  |gh  gb|  |yh  yb|  |bh
  |rb|      |bb|      |rb|      |bh|

  |rh|      |bh|      |rh|      |bb|
gh|  |bb  bh|  |gb  gh|  |gh  gb|  |yb
  |yb|      |yh|      |yh|      |gh|

Solution:

  |gh|      |rh|      |bh|      |rh|
bb|  |yb  yh|  |bh  bb|  |yb  yh|  |rh
  |yb|      |yh|      |gh|      |gb|

  |yh|      |yb|      |gb|      |gh|
rb|  |rb  rh|  |rh  rb|  |bh  bb|  |yh
  |gh|      |gh|      |yh|      |rb|

  |gb|      |gb|      |yb|      |rh|
bh|  |yh  yb|  |bh  bb|  |gh  gb|  |gb
  |bh|      |bh|      |gb|      |bh|

  |bb|      |bb|      |gh|      |bb|
yb|  |rb  rh|  |yb  yh|  |rh  rb|  |rb
  |bh|      |gh|      |gh|      |bh|

Solution:

  |rb|      |rh|      |rh|      |rb|
yh|  |gb  gh|  |yb  yh|  |bh  bb|  |bh
  |bh|      |rh|      |yh|      |yb|

  |bb|      |rb|      |yb|      |yh|
gh|  |bh  bb|  |bh  bb|  |gh  gb|  |bh
  |yb|      |rb|      |rh|      |bh|

  |yh|      |rh|      |rb|      |bb|
gh|  |rb  rh|  |gb  gh|  |yh  yb|  |gh
  |bb|      |yh|      |rb|      |yb|

  |bh|      |yb|      |rh|      |yh|
gb|  |bh  bb|  |gh  gb|  |gb  gh|  |gh
  |yb|      |gb|      |bh|      |rh|

Solution:

  |bh|      |yh|      |gb|      |yb|
bh|  |gb  gh|  |rb  rh|  |bh  bb|  |gh
  |yh|      |bb|      |gb|      |rh|

  |yb|      |bh|      |gh|      |rb|
bh|  |gh  gb|  |yh  yb|  |gb  gh|  |yh
  |bb|      |rb|      |bb|      |rb|

  |bh|      |rh|      |bh|      |rh|
bh|  |yb  yh|  |rh  rb|  |yb  yh|  |bh
  |gb|      |gb|      |bb|      |yh|

  |gh|      |gh|      |bh|      |yb|
bb|  |yb  yh|  |rh  rb|  |rb  rh|  |rh
  |yb|      |gh|      |bb|      |gh|

Solution:

  |bh|      |yh|      |bh|      |bb|
bh|  |gb  gh|  |gh  gb|  |yh  yb|  |gh
  |yh|      |rh|      |rb|      |yb|

  |yb|      |rb|      |rh|      |yh|
bh|  |gb  gh|  |yh  yb|  |gh  gb|  |rh
  |bh|      |rb|      |rh|      |rh|

  |bb|      |rh|      |rb|      |rb|
rh|  |yb  yh|  |bh  bb|  |bh  bb|  |bh
  |gh|      |yh|      |rb|      |yb|

  |gb|      |yb|      |rh|      |yh|
gh|  |bb  bh|  |gh  gb|  |gb  gh|  |rb
  |yb|      |bb|      |bh|      |bb|

Solution:

  |bh|      |rb|      |gh|      |rh|
yh|  |bh  bb|  |bh  bb|  |yb  yh|  |bh
  |gb|      |rb|      |yb|      |yh|

  |gh|      |rh|      |yh|      |yb|
rb|  |rb  rh|  |gb  gh|  |rb  rh|  |rh
  |yh|      |yh|      |bb|      |gh|

  |yb|      |yb|      |bh|      |gb|
bh|  |bb  bh|  |gh  gb|  |gb  gh|  |bb
  |rb|      |bb|      |rh|      |yb|

  |rh|      |bh|      |rb|      |yh|
gh|  |bb  bh|  |yb  yh|  |gb  gh|  |gh
  |yb|      |gb|      |bh|      |rh|

Solution:

  |rh|      |rb|      |gh|      |bh|
rh|  |gb  gh|  |yh  yb|  |rh  rb|  |yb
  |yh|      |rb|      |bb|      |bb|

  |yb|      |rh|      |bh|      |bh|
gh|  |yb  yh|  |bh  bb|  |yb  yh|  |bh
  |bb|      |yh|      |gh|      |gb|

  |bh|      |yb|      |gb|      |gh|
rb|  |rb  rh|  |rh  rb|  |bh  bb|  |yh
  |bb|      |gh|      |yh|      |rb|

  |bh|      |gb|      |yb|      |rh|
gb|  |gb  gh|  |bb  bh|  |gb  gh|  |gh
  |rh|      |yb|      |bh|      |yh|

Solution:

  |yb|      |rh|      |rh|      |rh|
bb|  |gh  gb|  |gb  gh|  |yb  yh|  |bh
  |rh|      |bh|      |rh|      |yh|

  |rb|      |bb|      |rb|      |yb|
yh|  |gb  gh|  |bh  bb|  |bh  bb|  |gh
  |bh|      |yb|      |yb|      |gb|

  |bb|      |yh|      |yh|      |gh|
rb|  |gh  gb|  |rh  rb|  |rb  rh|  |yh
  |yh|      |rh|      |gh|      |gh|

  |yb|      |rb|      |gb|      |gb|
yb|  |bb  bh|  |bb  bh|  |yh  yb|  |bh
  |gh|      |rb|      |bh|      |bh|

Solution:

  |rh|      |yb|      |bh|      |rh|
gh|  |bb  bh|  |gh  gb|  |yh  yb|  |gh
  |yb|      |bb|      |rb|      |rh|

  |yh|      |bh|      |rh|      |rb|
gb|  |rh  rb|  |yb  yh|  |bh  bb|  |bh
  |rh|      |bb|      |yh|      |rb|

  |rb|      |bh|      |yb|      |rh|
yh|  |gh  gb|  |bh  bb|  |gh  gb|  |gb
  |rb|      |yb|      |gb|      |bh|

  |rh|      |yh|      |gh|      |bb|
gh|  |gh  gb|  |bh  bb|  |yh  yb|  |gh
  |yh|      |bh|      |rb|      |yb|

Solution:

  |rh|      |yb|      |rb|      |rh|
gh|  |bb  bh|  |gb  gh|  |yh  yb|  |gh
  |yb|      |bh|      |rb|      |rh|

  |yh|      |bb|      |rh|      |rb|
gh|  |gh  gb|  |yb  yh|  |bh  bb|  |bh
  |rh|      |gh|      |yh|      |yb|

  |rb|      |gb|      |yb|      |yh|
yh|  |bb  bh|  |yh  yb|  |bb  bh|  |rb
  |gh|      |bh|      |gh|      |gb|

  |gb|      |bb|      |gb|      |gh|
bh|  |rh  rb|  |rb  rh|  |yh  yb|  |bb
  |gb|      |bh|      |rh|      |bh|

Solution:

  |gh|      |gb|      |bh|      |rh|
rb|  |rb  rh|  |bh  bb|  |yb  yh|  |bh
  |yh|      |gb|      |gh|      |yh|

  |yb|      |gh|      |gb|      |yb|
gh|  |yb  yh|  |rh  rb|  |bh  bb|  |gh
  |bb|      |gh|      |yh|      |rh|

  |bh|      |gb|      |yb|      |rb|
bh|  |gb  gh|  |bb  bh|  |bb  bh|  |bb
  |yh|      |yb|      |rb|      |rb|

  |yb|      |yh|      |rh|      |rh|
bh|  |gb  gh|  |rb  rh|  |gb  gh|  |yb
  |bh|      |bb|      |yh|      |rh|

Solution:

  |gh|      |rh|      |yb|      |rh|
rb|  |rb  rh|  |gb  gh|  |yb  yh|  |bh
  |yh|      |yh|      |bb|      |yh|

  |yb|      |yb|      |bh|      |yb|
bh|  |bb  bh|  |gh  gb|  |bh  bb|  |gh
  |rb|      |bb|      |yb|      |gb|

  |rh|      |bh|      |yh|      |gh|
gh|  |bb  bh|  |gb  gh|  |rb  rh|  |yh
  |yb|      |yh|      |bb|      |gh|

  |yh|      |yb|      |bh|      |gb|
bh|  |rb  rh|  |rh  rb|  |rb  rh|  |bh
  |gb|      |gh|      |bb|      |gb|

In total 23 solutions were found in 1 seconds and 26026288 iterations.

Press ENTER key to quit...

Mein Programm löst das Puzzle rekursiv, daher kann es zu Stapelüberläufen (Stackoverflows) kommen. Es empfiehlt sich daher das Heraufsetzen der maximalen Stapelgröße.