Wenn ihr so Aufgabenstellung in der Prüfung kriegen würdet
Aufgabe 3:
Auf einem Schachbrett kann man nicht nur Schach, sondern auch andere
Spiele wie z.B. Dame spielen. Allgemein soll ein Feld mit einer Figur
vom Typ T belegbar sein, wobei auch ein Leerfeld durch einen Wert dieses
Typs gekennzeichnet wird. Das Schach-brett wird demzufolge als
Template-Klasse realisiert. Jedes Feld wird wie in nebenstehendem Bild
als String aus zwei Zeichen adressiert, also z.B. "g5".
Vereinbaren Sie in einem Modul die Klasse Schach-brett mit folgenden
Eigenschaften:
- Attribute sind die Feldermatrix und der Wert des Leerfeldes. Der
Konstruktor hat als Parameter dWert des Leerfeldes. Dieser Wert wird
gespei-chert, da er später noch benötigt wird; außerdem werden alle
Felder mit diesem Wert initialisiert.
- Die Methode void set(const char *pfeld, T figur) platziert eine Figur.
- Die Methode T get(const char *pfeld) const liefert die Belegung eines
Feldes.
- Die Methode T ziehe(const char *pquelle, const char *pziel) zieht eine
Fi-gur. Der alte Wert des Zielfeldes wird als Funktionswert
zurückgeliefert. Das Quellfeld muss hinterher leer sein. Die Klasse
Schachbrett kümmert sich nicht um Spielregeln.
Hinweis: Vereinbaren Sie eine private Hilfsfunktion, die den
Feldbezeichnungsstring analysiert und daraus Zeilen- und Spaltenindex
berechnet, und benutzen sie diese bei set(), get() und ziehe(). Es darf
davon ausgegangen werden, dass die Feldbezeichnung immer im zulässigen
Wertebereich ist!
Was würdet ihr da machen also ne main usw ist doch da nicht verlangt
oder?
ich hätte blos das geschrieben
c
template <class T> class Schachbrett{
public:
Schachbrett(T leerwert){
initialwert = leerwert;
for (int i=0; i<65; i++){
matrix[i] = leerwert;
}
void set(const char *pfeld, T figur){
hilfsfunktion(pfeld) = figur;
};
T get(const char *pfeld) const {
return hilfsfunktion(pfeld);
};
T ziehe(const char *pquelle, const char *pziel){
T temp = get(pziel);
set(pziel, get(pquelle));
set(pquelle, initialwert);
return temp;
};
private:
T hilfsfunktion(const char * a)
{
//aus zeitgründen berechne den Wetrt der Matrix und gut is
//und geb den passenden index zurück
return matrix[index];
T initialwert;
T matrix[64];
};
/c
das war zwar so verlangt
return matrix[(a[1] - '1')*8 + a[0]-'a']
aber das bekomme ich in Prüfung bestimmt nicht hin
da hätte ich auch garnicht versucht etwas zu entwickeln
@oslo
Hast Du verstanden, was da genau gemacht wird?
Die Matrix ist ja ein Array mit 64 Elementen. Diese werden dort nach
folgendem Muster gespeichert:
Name: a1, b1, c1, d1, e1, f1, g1, h1, a2, b2, c2, ...
Index: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...
D.h. der Buchstabe wird bei jedem Element erhöht und springt an den
Anfang, sobald er über 'h' läuft. Die Zahl wird nur bei jedem 8-ten
Element erhöht. Wenn der Buchstabe z.b. a ist, dann wird bei Zahl=1 auf
Element 0 zugegriffen, bei Zahl=2 auf element 8, bei Zahl=3 auf Element
12 usw. Es ist leicht ersichtlich, dass die Element-Nr. bei Buchstabe=a
(Zahl-1)*8 sein muss. Bei Buchstabe=b muss es jeweils das nachfolgende
Element sein, also (Zahl-1)*8 + 1, bei Buchstabe=c (Zahl-1)*8 + 2 usw.
Auf alle möglichen Buchstaben und Zahlen verallgemeinert lautet der
Index (Zahl-1)*8 + Buchstabe, wobei a den Wert 0 hätte, b den Wert 1
usw.
Was noch übrig bleibt, ist die Zahl und den Buchstaben aus dem String zu
bekommen. Es ist vorgegeben, dass das erste Zeichen, also pfeld[0] den
Buchstababen enthält und das zweite Zeichen pfeld[1] die Zahl. Da beide
im ASCII-Code sind, muss man von dem Buchstaben 'a' abziehen, um zu der
Zuordnung a=0, b=1, ... zu kommen und von der Zahl '0', damit '1'=1,
'2'=2, ... wird. Der Code würde dann so aussehen:
1
intbuchstabe=pfeld[0]-'a';
2
intzahl=pfeld[1]-'0';
3
intindex=(zahl-1)*8+buchstabe;
4
returnmatrix[index];
und ohne den Umweg über die Zwischenvariablen
1
returnmatrix[(pfeld[1]-'0'-1)*8+pfeld[0]-'a']
"pfeld[1] - '0' - 1" ist nichts anderes als "pfeld[1] - ('0' + 1)" =
"pfeld[1] - '1'", sodass man letzendlich zu
1
returnmatrix[(pfeld[1]-'1')*8+pfeld[0]-'a']
kommt.
>da hätte ich auch garnicht versucht etwas zu entwickeln
Ein Tip von mir: beschäftige dich viel intensiver mit der
Programmierung. Fange mit kleinen Programmen an, die nur auf eine
bestimmte Sache spezialisiert sind. Wenn Du z.B. eine Datei hast, in der
eine Zeichenfolge durch eine andere ersetzt werden soll, dann erledige
das nicht mit dem Texteditor, sondern schreib dein eigenes Programm
dafür. Je mehr du programmierst, desto weniger Zeit wirst du brauchen,
um verschiedene Aufgaben zu lösen und desto komplexer können die
Programme werden.
MfG Mark
ich sehe es jetzt mal unter Prüfungsbedingung
und da ist keine Zeit für sowas
wir haben 90 minuten zeit
und es gibt meistens mehr punkte
es gibt 100 Punkte und 90 werden nur benötigts usw
deshalb hätte ich es weg gelassen
warum einfach, wenn es auch umständlich geht?
Soweit ich mich entsinne, gibt es in C auch mehrdimensionale Felder.
[8][8] hat auch 64 Elemente und ist wohl etwas einfacher was
den Zugriff angeht.
Dann wäre es aber einfacher, eine std::map<std::string, int> zu
verwenden statt jedesmal mühsam die Berechnung auszuführen. Die Map kann
dann bereits im Konstruktor vorbelegt werden und die Prüfung der Eingabe
ist ein einfaches find().
Ingo Elsen schrieb:
> Dann wäre es aber einfacher, eine std::map<std::string, int> zu> verwenden statt jedesmal mühsam die Berechnung auszuführen. Die Map kann> dann bereits im Konstruktor vorbelegt werden und die Prüfung der Eingabe> ist ein einfaches find().
Und in Summe ist das mehr Aufwand, als diese simple Berechnung.
Klar, man kann in einem Programm auch eine Mutliplkationstabelle
hinterlegen. Man kann aber auch ganz einfach multiplizieren :-)
Nein, Aufwand ist O(log(n)). Bei der simplen Berechung O(n). Leichter
wartbar ist es außerdem (weil weniger Fehleranfälliger Code)
Man kann natürlich auch ganz einfach multiplizieren.
Ingo Elsen schrieb:
> Nein, Aufwand ist O(log(n)). Bei der simplen Berechung O(n).
Äh, ist er nicht.
Da ist er O(1)
Du willst mir jetzt hoffentlich nicht weiß machen, dass dein find
ein
1
(a[1]-'1')*8+a[0]-'a'
schlagen kann. Das hier ist ausgerechnet, noch ehe der find den
Stackframe aufgesetzt hat.
Hier eine map und find einzusetzen ist ganz einfach mit Kanonen auf
Spatzen geschossen ...
> weil weniger Fehleranfälliger Code
und ob in der Initialisierungsphase ...
1
map["a1"]=0;
2
map["a2"]=1;
3
map["a3"]=2;
4
map["a4"]=3;
5
map["a5"]=4;
6
map["a6"]=5;
7
map["a7"]=6;
8
map["a8"]=7;
9
map["b1"]=8;
10
map["b2"]=9;
11
map["b3"]=10;
12
map["b4"]=11;
13
...
14
map["h8"]=64;
... wartbarer, lesbarer und weniger fehleranfälllig ist, wage ich
gelinde gesagt zu bezweifeln.
Du hast recht. Er ist O(1). Mein Fehler.
>Du willst mir jetzt hoffentlich nicht weiß machen, dass dein find>ein>> (a[1] - '1')*8 + a[0]-'a'>>schlagen kann. Das hier ist ausgerechnet, noch ehe der find den>Stackframe aufgesetzt hat.
Du wirst aber zugeben, dass
Ingo Elsen schrieb:
> Du wirst aber zugeben, dass>>
1
>wert=brett["a3"];
2
>
>> einfacher ist als obiger code.
Kommt drauf an, was du als einfach definierst.
Du Alternative dazu lautet zur Zeit
1
wert=get("a3");
und das sieht mir nicht wesentlich umständlicher oder verwirrender aus.
Es ist anders, ja, aber einfacher ....
Und wenn ich drauf stehe, dass ich ausserhalb der Klasse mit
Array-Indizierungssyntax zu Werke gehe, kann ich immer noch machen:
>Kommt drauf an, was du als einfach definierst.>Du Alternative dazu lautet zur Zeit>> wert = get( "a3" );>>und das sieht mir nicht wesentlich umständlicher oder verwirrender aus.>Es ist anders, ja, aber einfacher ....
Doch, weil get(string& s) muss noch geschrieben werden. Den
Indexoperator liefert mir schon std::map
Ingo Elsen schrieb:
> Doch, weil get(string& s) muss noch geschrieben werden. Den> Indexoperator liefert mir schon std::map
Du mögest bitte die Aufgabenstellung studieren.
Die Funktion get wurde dort explizit gefordert (und ist dort auch
sinnvoll, weil du mit Sicherheit niemanden ausserhalb der Klasse an
deinen internen Speicher ranlassen willst).
So gesehen ist es sogar einfacher, wenn innerhalb der Klasse alle
Zugriffe auf das eigentliche Brett ausschliesslich über get() und set()
geführt werden und das Wissen, wie die Daten gespeichert sind, nicht
über die komplette Klasse (in Form einer Indizierungsoperation hier und
einer dort) verstreut ist. Ändert sich die Speicherform, muss nur get
und set angepasst werden. Die Funktion ziehe() kann zb schon wieder
exakt so bleiben wie sie zur Zeit ist.
:-) Du läufst im Moment gegen Windmühlen an :-)
> Dann wäre es aber einfacher, eine std::map<std::string, int> zu
verwenden statt jedesmal mühsam die Berechnung auszuführen.
Wie schön, daß C++ den Rechenaufwand so schön verdeckt.
Da kommen dann so perfomante Programme wie Windows Vista bei raus.
Mit unserem Bildungsfortschritt gegenüber China sehe ich schwarz.
MaWin schrieb:
>> Dann wäre es aber einfacher, eine std::map<std::string, int> zu> verwenden statt jedesmal mühsam die Berechnung auszuführen.>> Wie schön, daß C++ den Rechenaufwand so schön verdeckt.
Du übertreibst :-)
So schlimm ist es auch wieder nicht.
Der Denkfehler ist passiert, als er die Berechnung als O(n) ansah.
Wenn dem so wäre (Konjunktiv) hat er recht. Aber da dem nicht so ist,
ist der Vorschlag nicht zu verteidigen.
Es war einfach nur ein Missverständnis.
>> Wie schön, daß C++ den Rechenaufwand so schön verdeckt.>> Du übertreibst :-)> So schlimm ist es auch wieder nicht
Vor allem könnte ich in C oder so ziemlich jeder anderen Sprache auch
beliebig viel Rechenaufwand hinter einer Funktion verstecken.