Schulprojekt: Snake programmieren mit C#

Nymphalis

Mitglied
Ist oben reineditiert.
Das if paar Zeile über dem Dispose und so ist klar? ;-]
@sheel Ja, das ist klar:D


Ach so ist das mit dem Invoke...
Das erklärt auch, wieso das eine bei meiner Fortsetzung vom Quadrat von der ersten info-Stunde genervt hat...
Aber nicht, dass ihr erwartet, dass ich das auch jetzt hier reinstelle.
Das ist nämlich für immer verloren am Test-Account vom Schulcomputer.
Danke nochmal für alles. Ihr seid super!;-)
Ich muss jetzt leider noch die Mathe-Aufgabe fertig machen, also
Gute Nacht
P.S.: ich schreib natürlich dann rein, wie er das Snake-Spiel fand...
die Konkurrenz wird eh hart sein:rolleyes:
 

Nymphalis

Mitglied
Ich schon wieder;)
Ich bringe gute und schlechte Nachrichten:
Die schlechten zuerst:
1.)
Dem Lehrer ist ebenso wie mir aufgefallen, dass der InitSnake() teil kompliziert ist und ich ihn nicht ganz erklären konnte.
Ich sagte dann, dass mir jemand geraten hatte, das so zu machen...
Das ist ja keine ganze Lüge, was?;)

Code:
private void InitSnake()
        {
            int x = this.panel1.Width / 2;
            int y = this.panel1.Height / 2;

            while (x % 10 != 0)
                x++;
            while (y % 10 != 0)
                y++;
Könnt ihr mir bitte genau erkären warum x : 10 dividiert wird und es dann wächst?

2.) schlechte Nachricht: Wir sollen das Projekt erst in zwei Wochen abgeben.
Das wiederum heißt, dass ich noch alle möglichen wichtigen und unwichtigen Sachen dazugeben sollte. In der Stunde habe noch einen MenuStrip mit Datei - Beenden und Neu, Pause und Highscore dazugefügt.
Beenden und Pause ist zwar einfach, aber zum einen weiß ich nicht, wie ich das Spiel neustarten soll.
Man muss dafür ja alle Variable auf Null bzw den Ausgangswert setzen, aber wie?
Bei mir steht da immer, "die Komponenten kommen da gar nicht vor" oder so. :(
Also wenn man auf "Neu" klickt, soll das passieren.
Zum anderen hab ich mir noch nicht mal Gedanken über den Highscore gemacht, aber dazu irgendwann später.

3.) Die Dokumentation soll ganz genau sein.
Also mit Screenshot, Deckblatt, Listing (!?) und den obligatorischen Notizen auf der Seite, was was ist sowie einer Auflistung aller Funktionen und Eigenscahften, die das Spiel hat.
Könnt ihr mir bitte sagen, was ein Listing sein soll?:rolleyes:



4.) Ihr werdet mich wohl nicht so schnell los und ich sollte mich wohl darüber informieren was delegate ist.
Wobei ich das auch als gute Nachricht zähle:p


Die gute Nachricht ist, dass:
1.) Ihr jetzt viel Zeit habt, mir das alles zu erklären ...:D

2.) ...und ich auch die Zeit habe, möglichst viel (mit ein bisschen Unterstützung!?) selbst zu machen.

3.) Außer Highscore, Punkte anzeigen, Neustarten und vielleicht noch Mauern fehlt nichts mehr.

Falls ich schon wieder unübersichtlich und schlampig schreibe, entschuldige ich mich hiermit dafür.
Schließlich bin ich gerade erst vom Unterricht heim gekommen und hab mir auch ein paar kleine Sportverletzungen zugezogen.:eek:

P.S.: Ist es eigentlich möglich, Handmuskelkater vom Speerwerfen zu bekommen?
 

sheel

I love Asm
Hi

1)
Also...dass da die Position der am Anfang vorhandenen Schlangenteile berechnet wird,
ist ja klar. Wenn man mal so tut, als ob die zwei while-Schleifen nicht existieren:

Höhe und Breite vom Panel halbieren ergbit als Koordinaten gesehen die Mitte.
Dort kommt dann (bei der for Schleife unten) als Erstes der Kopf hin).
Jedes weitere Teil ist dann 10 auf der y-Achse weiterverschoben, also vertikal stehende Schlange.

Jetzt muss sichergestellt werden, dass die Koordinaten immer nur Vielfache von 10 sind.
zB. wenn die Schlange oben/unten ausgerichtet ist, kann das Kopfkästchen auf der x-Achse
zB. zwischen 100 und 110 sein, oder 240-250 usw. Aber nicht sowas wie 123-133.
Grund: Das Futter wird auch auf 10-Vielfache ausgerichtet,
damit stellt man sicher, dass das Futter immer genau in der "Spur" der Schlange liegt.
Wenns nur irgendwie zufällig wäre könnte das Futter auch mal zwischen
zwei Schlangenspuren liegen. Schaut komisch aus und erschwert die Kollisionsberechnung.

So, also immer Vielfache von 10 Pixeln bei den Koordinaten.
Der Kopf beginnt in der Panelmitte.
Was ist aber, wenn das Panel zB. 344x266 groß ist?
Jeweils die Hälfte, der Kopf wäre an 172x133.
Mit den zwei while-Schleifen wird das jetzt auf 10er aufgerundet, in dem Fall 180x140

% ist keine normale Division wie / sondern der Rest
(Grundschule/Volkschule: 172 durch 10 ist 17 und 2 Rest. Dieser Rest).
172/10 bei float/double wäre korrekt 17.2,
bei ints (die ja keine Kommastellen können) 17 und mit % (genannt Modulo) Rest 2.
Die Schleifen addieren jetzt solange 1, bis der Rest 0 ist, also ein voller Zehner erreicht ist.
Die (etwas umständliche) Vorgehensweise passt dienem Lehrer hier wohl nicht,
das könnte man mit einer gezielten Addition auch lösen. Statt eine Schleife +1, +1, +1...
C#:
x = x - x%10 + 10;
y = y - y%10 + 10;
statt der zwei while-Schleifen hat den selben Effekt, auf die nächste volle 10 aufrunden
(zuerst abrunden, indem alles subtrahiert wird, was über 10 raussteht,
dann +10 ist man beim höheren Rundungsende).

Bei der Futterpositionierung sind übrigens auch zwei solche while-Schleifen,
können auch so gemacht werden.


2) Ist doch schön, mehr Zeit.
Der Lehrer hat die Ranzerei hier wohl gelesen :D

Beenden: Beide Timer beenden (wie beim Gameover)
und Form.Close (so irgendwie, Google :))
Das Form-closen könnte man übrigens auch beim Gameover noch einbauen.

Pause: Eine Variable, die bei den Menüpunkten umstellen,
und beim Timer jedesmal fragen, ob die Variable auf "An" steht, sonst nichts machen.
C#:
if(inBetrieb == 1) {alles machen}

Neu:
Schlange: Die snakeSegments vom panel nehmen, löschen (List leeren)
(so wie bei den Fruitpoints beim Fressen:
C#:
this.panel1.Controls.Remove(fp);
this.fruitPoints.Remove(fp);
fp.Dispose();
Sowas in der Art für alle Schlangenteile, dann InitSnake ausführen,
das erstellt die Grundschlange wieder.

Neu: Futter: Auch entsprechend alle vorhandenen Futterteile weg.

Highscore: In einer Variable mitzählen, wie oft etwas gefressen wurde.
Beim Menüpunkt eine Messagebox mit der Zahl ausgeben.

(Aufpassen, dass die Events der Menüpunkte nicht durcheinanderkommen ;-])

3)
Mit Listing wird er den Code meinen.

Delegate...später :)
Muss leider auch noch was tun heut.
 

Nymphalis

Mitglied
Ich hoffe, du hältst mich nicht für völig unfähig:rolleyes:
Das Beenden und die Pause hab ich nämlich sogar schon;-)
aber bei der Pause hab ich offensichtlich doch nicht an alles gedacht.
Danke für die Erklärung der while-Schleife

Der Lehrer hat die Ranzerei hier wohl gelesen
hoffentlich nicht;)

ich kann mich leider erst morgen wieder richtig drum kümmern, also kein Problem, wenn du auch keine Zeit hast.
Jetzt stehen eben ein paar Tests an...
 

Nymphalis

Mitglied
Ich bin wieder da;)
Leider gibt es noch mehr Tests, aber die Zeitwird langsam knapp.
Ich flehe dich an sheel, erklär mir bitte, was delegate ist!:rolleyes:
das ist wirklich wichtig, dass ich jedes Fitzelchen verstehe, damit ich es bei meiner Doku schreiben kann.
Wenn ich das nicht da stehen hab, was es bedeutet, dann gilt der Teil wo es steht nicht. :(
Morgen mach ich in der Schule mit dem Programmierteil weiter.
Das wird sicher nicht lustig, weil mir der Lehrer sicher die ganze Zeit über die Schulter schaut, aber hier zu Hause lass ich mich zu leicht ablenken. :eek:
Danach kommen also noch ein paar Fragen.

P.S.: ...Falls wir nicht mit einem neuen Thema anfangen. Jedenfalls: Danke für alles!
 

Shakie

Erfahrenes Mitglied
(Ich habe den Thread nicht vollständig gelesen. Es könnte daher sein, dass ich ein bisschen am Thema vorbei rede.)

Hi Nymphalis,

kennst du die MSDN? Da ist alles drin dokumentiert.
Beispielsweise Delegates: http://msdn.microsoft.com/de-de/library/vstudio/ms173171.aspx

Beispiel:
C#:
public delegate double TolleFunktion(int x, int y);
Das sagt ungefähr aus, dass es irgendwo eine Funktion geben könnte, die zwei Integers als Argument erwartet und ein Double zurück gibt. Der Delegat macht keine Aussage über den Namen der Funktion. Vielmehr ist "TolleFunktion" nun ein Typ, so wie "Integer" oder "Form".
Du kannst jetzt eine Variable vom Typ "TolleFunktion" erstellen und dieser Variable die Adresse einer Funktion zuweisen.
Dann kannst du die Funktion über die Variable mittels der Invoke-Methode aufrufen, anstatt die Funktion direkt aufzurufen.
Das kann vorteilhaft sein, wenn du die Adresse einer Funktion an eine andere Funktion weitergeben möchtest.

Hier ein Beispiel, das hoffentlich hilfreich ist:
C#:
using System;

namespace NeuesProgramm1
{
    class Program
    {
        delegate String MeinFunktionsDelegatTyp(int x);

        static void Main(string[] args)
        {
            MeinFunktionsDelegatTyp f1 = Funktion1;
            MachWasMitDelegat(f1);           
            Console.ReadKey();
        }

        static void MachWasMitDelegat(MeinFunktionsDelegatTyp d)
        {
            String Funktionsergebnis = d.Invoke(42);
            Console.WriteLine(Funktionsergebnis);
        }

        static String Funktion1(int x)
        {
            return "Funktion 1 wurde mit x=" + x.ToString() + " aufgerufen.";
        }       

    }
}
 

Nymphalis

Mitglied
Ich glaube, ich hab noch eine Frage:
gestern war ich mir bei dieser Stelle noch sicher, was sie bedeutet, aber jetzt komme ich mir irgendwie ahnungslos vor.
Könnt ihr mir da helfen?

Code:
switch (ri)  
                {
                    case -1:
                    case 1:
                        head.Left += 10 * ri;
                        break;
                    case -2:
                    case 2:
                        head.Top -= 5 * ri;
                        break;
                }

Meiner Meinung nach geht es da darum, wenn man eine der Richtungstasten drückt,- jeweils die horizontalen und die vertikalen- es, dass der Kopf sich jeweils 10 bzw 5 in die eine oder andere Richtung bewegt, aber warum sind die Werte unterschiedlich?(Abgesehen davon, dass ich mich wahrscheinlich irre...)
Hängt das damit zusammen, dass das Spielfeld Hochformat ist?
 

sheel

I love Asm
Wenn die Richtung 1/-1/2/-2 ist Rechts/Links/Oben/Unten

1 bedeutet also, Die X-Koordinate (Left) um 10 erhöhen = x plus 10
-1 -> x minus 10
2 -> y minus 10
-2 -> y plus 10

Im Fall Rechts/Links kann man die Richtung ja gleich mit 10 Pixeln multiplizieren,
um den X-Unterschied zu erhalten.
+1*10=+10
-1*10=-10

Bei Oben/Unten würde die Multiplikation aber nicht +/-10, sondern 20 ergeben. 2 mal eben.
Deshalb nur 5, 5*2 ist wieder 10
 

Nymphalis

Mitglied
Ach ja:rolleyes:
dankeschön für die schnelle Antwort;)
Das ist so klar, wenn man nur hinguckt. Offensichtlich sitze ich schon zu lange vor dem PC, sodass mir sowas nicht mehr auffällt.
 

Nymphalis

Mitglied
wie mach ich das, wenn eine bestimmte Anzahl von Futter, sagen wir mal 5 auftaucht, dass dann das Spiel beendet wird?
Das Spiel beenden kann ich, aber wie mach ich das mit der Bedingung und den 5 Stück?

Mein genaues Problem ist eigentlich: wie bestimme ich das Futter bzw das Größer-Zeichen?
Das das da unten nicht geht, weiß ich auch...
Das kommt davon, wenn man nicht alles alleine schafft und Hilfe von anderen animmt:
Man ist zwar überglücklich darüber, kommt aber nicht mehr los:rolleyes:

Code:
if (this.fp > 3) 
                    {this.fruitTimer.Stop();  
                    this.timer.Stop();
                    MessageBox.Show("Game over!");
                    this.Close();
                   }