Forum: PC-Programmierung Prüfung c++ was hättet ihr da gemacht


von olso (Gast)


Lesenswert?

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?

von olso (Gast)


Lesenswert?

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

von Mark .. (mork)


Lesenswert?

@olso

Im Prinzip richtig, aber da sind noch ein paar Fehler drin:
1
(int i=0; i<65; i++)
 muss
1
(int i=0; i<64; i++)
 heißen, da matrix nur 64 Elemente hat.
1
T hilfsfunktion(const char * a)
 ->
1
T& hilfsfunktion(const char * a)
 um sie später in set verwenden zu können.

Die Hilfsfunktion könnte so aussehen:
1
return matrix[(a[1] - '1')*8 + a[0]-'a']

MfG Mark

von olso (Gast)


Lesenswert?

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

von Mark .. (mork)


Lesenswert?

@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
int buchstabe = pfeld[0] - 'a';
2
int zahl = pfeld[1] - '0';
3
int index = (zahl - 1) * 8 + buchstabe;
4
return matrix[index];
und ohne den Umweg über die Zwischenvariablen
1
return matrix[(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
return matrix[(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

von olso (Gast)


Lesenswert?

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

von olso (Gast)


Lesenswert?

ich bin momentan so aufgeregt das ich glaube das ich gar nichts mehr 
kann

von Klaus W. (mfgkw)


Lesenswert?

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.

von olso (Gast)


Lesenswert?

naja wurde aber von Prof
so empfohlen das ganze in ner hilfsfunktion eindimensional zu machen

so kann man dann auf den rest noch gute punkte geben

von Ingo E. (ogni42)


Lesenswert?

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().

von Karl H. (kbuchegg)


Lesenswert?

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 :-)

von Ingo E. (ogni42)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Ingo E. (ogni42)


Lesenswert?

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
1
wert = brett["a3"];

einfacher ist als obiger code.

von Karl H. (kbuchegg)


Lesenswert?

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:
1
class ...
2
3
   T operator[] ( const char* address ) const { return get( address ); }

von Ingo E. (ogni42)


Lesenswert?

>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

von Karl H. (kbuchegg)


Lesenswert?

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 :-)

von Ingo E. (ogni42)


Lesenswert?

stimmt, ich geb' mich geschlagen :-)

von MaWin (Gast)


Lesenswert?

> 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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Rolf Magnus (Gast)


Lesenswert?

>> 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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.