Was der Mathematiker Gauß
nicht konnte, das können wir
16.01.2003 Prof. R. Zavodnik/C++ Vorlesung/Kapitel IX 2
friend
Klassenmethoden können friend -Funktionen anderer Klassen werden
Ganze Klassen können friend s von anderen Klassen werden.
Dadurch erhalten sie Zugriff auf alle Methodenfunktionen, z.B.
Konstruktoren
class deineKlasse;
class meineKlasse{
...
public:
meineKlasse copy(deineKlasse &);
...
};
class deineKlasse{
friend meineKlasse& meineKlasse::copy(deineKlasse &);
public:
...
16.01.2003 Prof. R. Zavodnik/C++ Vorlesung/Kapitel IX 4
Man achte auf die
Vorwärtsdeklaration von
deineKlasse , um copy() als friend dieser Klasse zu erklären Falls sich zwei Klassen
gegenseitig die Mitgliedsfunktionen der anderen als friend erklären wollen, muss eine Klasse ein
friend der anderen werden
"collaboration"
class deineKlasse;
class meineKlasse{
friend class deineKlasse;
...
};
class deineKlasse{
friend class meineKlasse;
...
};
16.01.2003 Prof. R. Zavodnik/C++ Vorlesung/Kapitel IX 6
Beispiel von backtracking
Am besten mit Rekursion
Alle Möglichkeiten werden
systematisch erzeugt
Beim Versagen bei Erzeugung des i -ten Elements einer Lösung kehre man zurück zum ( i-1 )-ten
Element
Dort ein neues passendes Element bestimmen
Kehre dann wieder zum i -ten
Element zurück
16.01.2003 Prof. R. Zavodnik/C++ Vorlesung/Kapitel IX 8
Und das rekursiv!
Man fange am Anfang mit
irgendeinem möglichen ersten
Element an
Man betrachte ein 8 x 8 Schachbrett
Man versuche 8 Damen auf dem
Schachbrett so zu plazieren, dass
sich keine zwei bedrohen können
16.01.2003 Prof. R. Zavodnik/C++ Vorlesung/Kapitel IX 10
Zunächst eine globale Funktion advance(i) schreiben, die
versucht die i -te Königin zu plazieren
Falls advance(i) keinen Erfolg meldet, kehrt sie zu
advance(i-1) zurück und inkrementiert die aktuelle
Reihenposition mit 1 und ruft
advance(i) erneut wieder auf
advance(i){
next: plaziere ite Koenigin bei naechsten Reihe;
if (OK){
markiere all Felder die Koenigin bedrohen kann;
notiere Position dieser i-ten Koenigin if (i == 8) return mit Erfolg
else{
advance(i+1);
if (!Erfolg) entferne Koenigin;
go to next;
} }
else{
if (keineLoesung mehr) return Misserfolg;
16.01.2003 Prof. R. Zavodnik/C++ Vorlesung/Kapitel IX 12
Jede Königin ist ein Objekt der
Klasse queen. Gespeichert wird:
die konstante Spaltennummer die aktuelle Reihennummer
Das Schachbrett ist eine
zweidimensionale static
bool'sche Reihung
Die i -te Königin wird auf der i -ten Spalte plaziert
Eine Lösung besteht aus einer
gültigen Reihennummer für jede
Königin
16.01.2003 Prof. R. Zavodnik/C++ Vorlesung/Kapitel IX 14
! queen.h
#include <ostream.h>
#define BOARDSIZE 8 class Queen{
private:
const int column;
int row;
static bool board[BOARDSIZE][BOARDSIZE];
public:
Queen(int col): column(col){row = -1;}
bool canAttack(int, int);
bool isVulnerable();
void setPosition(int);
void undoPosition();
void dumpBoard();
};
" # $ %
#include "queens.h"
bool Queen::board[BOARDSIZE][BOARDSIZE] =
{{false, false, false, false, false, false, false, false}, {false, false, false, false, false, false, false, false}, {false, false, false, false, false, false, false, false}, {false, false, false, false, false, false, false, false}, {false, false, false, false, false, false, false, false}, {false, false, false, false, false, false, false, false}, {false, false, false, false, false, false, false, false}, {false, false, false, false, false, false, false, false}
};
16.01.2003 Prof. R. Zavodnik/C++ Vorlesung/Kapitel IX 16
$ % &' ( )
bool Queen::canAttack(int i, int j) { if (row == i) return true;
else if ((j-i) == (column - row)) return true;
else if ((j+i) == (column + row)) return true;
return false;}
bool Queen::isVulnerable(int m) {
for (int i = 0; i < BOARDSIZE; i++) for (int j = 0; j < BOARDSIZE; j++)
if (board[i][j]) if (m == i) return true;
else if (column == j) return true;
else if ((i+j) == (m + column)) return true;
else if ((j-i) == (column - m)) return true;
return false;
}
$ % &' ( )
void Queen::setPosition(int j) {
board[j][column] = true;
}
void Queen::setRow(int i) { row = i;
}
void Queen::undoPosition() {
board[row][column] = false;
row = -1;
16.01.2003 Prof. R. Zavodnik/C++ Vorlesung/Kapitel IX 18
$ % &' ( )
void Queen::dumpBoard() {
for(int i = 0; i < BOARDSIZE; i++)
for (int j = 0; j < BOARDSIZE; j++)
if (board[i][j]) cout << i << "," << j << endl;
}
' advance(i)
#include "queens.h"
Queen *Queens[BOARDSIZE];
bool advance (int i) {
for (int j=0; j < BOARDSIZE; j++){
if ((!Queens[i]->isVulnerable(j)))[
Queens[i]->setPosition(j);
Queens[i]->setRow(j);
if (i < 7) {if (!advance(i+1))
Queens[i]->undoPosition();
else
return true;} } else return true;}
}
16.01.2003 Prof. R. Zavodnik/C++ Vorlesung/Kapitel IX 20
*
void printSolution() {
for (int i=0; i < BOARDSIZE; i++) Queens[i]->print();
}
int main() {
for(int i = 0; i < BOARDSIZE; i++) Queens[i] = new Queen(i);
if (advance(0)) printSolution();
for(int i = 0; i < BOARDSIZE; i++) delete Queens[i];
return 0;
}
Das Schachbrett muss ausserhalb der Klasse Queen definiert und
initialisiert werden. Also static Definition
advance() ist keine
Elementfunktion der Klasse Queen
16.01.2003 Prof. R. Zavodnik/C++ Vorlesung/Kapitel IX 22