Schulprojekt: Snake programmieren mit C#

Nymphalis

Mitglied
Hallo!
Ich gehe jetzt in die letzte Klasse Gymnasium und hab das 3te Jahr Informatik
wegem Lehrerwechsel und erst kürzlichem Umpolen zu Visual C# hab ich keine Ahnung wie überhaupt alles geht.
Jetzt in der 3. Informatikstunde haben wir den Auftrag bekommen, das Spiel "Snake" zu programmieren

Für die, die es nicht so gut kennen: da ist eine Schlange auf einem kleinen Feld, die das Futter fressen muss um länger zu werden.
Sie stirbt, wenn sie sich selbst frisst oder die Wand berührt.

Der Lehrer hat uns ins kalte Wasser geworfen und jetzt bewegt sich meine Schlange nur in eine Richtung, die Pfeiltasten sollten zwar funktionieren, tun es aber nicht.

bitte helft mir mit der Steuerung!
hier meine bisherige Missleistung:

(ich weiß leider nicht, ob das mit dem Anhängen geklappt hat, deshalb kopier ich es auch ins Fenster)

Code:
using System.Collections;

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

        ArrayList s = new ArrayList();  //Schlange, aus Segmenten (Pictureboxen)
        int l = 5;
        int ri = 1;  //1:W, 2:N, 3:O, 4:S

        private void timer1_Tick(object sender, EventArgs e)
        {
            for (int i = l - 1; i > 0; i--)
            {
                ((PictureBox)s[i]).Left = ((PictureBox)s[i - 1]).Left;
                ((PictureBox)s[i]).Top = ((PictureBox)s[i - 1]).Top;
                
            }
            switch (ri) //fallunterscheidung ohne if
            {
                case 1:  //links 
                    ((PictureBox)s[0]).Left = ((PictureBox)s[1]).Left - 10; //Kopf immer an stelle 0 jetzt an Stelle ? 1-10 
                    break;
                case 2: //oben
                    ((PictureBox)s[0]).Top = ((PictureBox)s[1]).Top + 10;
                    break;
                case 3: //rechts
                    ((PictureBox)s[0]).Left = ((PictureBox)s[1]).Left +10;
                    break;
                case 4: //unten
                    ((PictureBox)s[0]).Top = ((PictureBox)s[1]).Top - 10;
                    break;   
            }

        }

        private void Form1_Load(object sender, EventArgs e)
        {
            int x = 100;
            //---- Arraylist mit Pictureboxen füllen ----
            for (int i = 0; i < 5; i++)
            {
                PictureBox p = new PictureBox();  //neue Pictb  
                p.Image = Image.FromFile("segment.png");  //Bild zuweisen
                p.SizeMode = PictureBoxSizeMode.AutoSize;  //Größe einstellen
                p.Left = x + 10 * i;  //nach rechts, Kopf ist links
                p.Top = 100;
                panel1.Controls.Add(p);  //Anzeige auf Panel
                s.Add(p);  //zur Arraylist dazu
            }
        }

        private void button1_KeyDown(object sender, KeyEventArgs e) //e=taste die er drückt
        {
            switch (e.KeyCode)
            {
                case Keys.Left: ri = 1;
                    break;    //wenn man links klickt geht er nach Westen, siehe Timer
                case Keys.Up: ri = 2;
                    break;
                case Keys.Right: ri = 3;
                    break;
                case Keys.Down: ri=4;
                    break;
            }
        }

      



    }
}

vielen Dank für jeden Versuch mir zu helfen
ich hab gehört, die Steuerung ist das schwierigste:(
 

Anhänge

  • Form1.cs
    2,7 KB · Aufrufe: 174
Zuletzt bearbeitet von einem Moderator:

sheel

I love Asm
Hi und Willkommen bei tutorials.de,

C# ist nicht C++. Verschoben.

Überprüf als Erstes mal, ob button1_KeyDown (warum Button)
bei einem Tastendruck überhaupt aufgerufen wird.
Irgendeinen Code rein, der sich äußerlich bemerkbar macht.
zB. eine Messagebox oder ein Biep (wie das geht findet man leicht über Google).

PS: Mein Beileid zum Lehrer (wenn er so ist wie ich denke), kenn selbst genug von der Sorte.
 

Nymphalis

Mitglied
Hi und Willkommen bei tutorials.de,

C# ist nicht C++. Verschoben.

Überprüf als Erstes mal, ob button1_KeyDown (warum Button)
bei einem Tastendruck überhaupt aufgerufen wird.

Danke für den Tipp, dass das wahrscheinlich nicht funktioniert:D
du hast mich damit so glücklich gemacht, da es jetzt endlich geht
ich weiß jetzt was das Problem war: bei der rechten Spalte unter Eigenschaften war der button1_KeyDown nicht angegeben, dass der bei KeyDown benutzt wird
das kommt daher, dass ich das Programm in der Schule einmal wiederherstellen musste und da nur den Code eingegeben habe

Weißt du wie ich es machen kann, dass die Schlange auf der anderen Seite wieder ins Feld kommt, wenn ich sie bei einem Rand rauslenke?:rolleyes: das funktioniert auch noch nicht, und ich hab mir gedacht, bevor ich die Sache mit dem Futter mache, sollte lieber die Steurung funktionieren
 

sheel

I love Asm
Schön, richtig geraten :D
Du hast/hattest wohl einen Button, für den das Klickereignis ursprünglich war
(also wenn er den Fokus hat bzw. "markiert" ist, dann ein Tastendruck).
Es muss aber eben für das ganze Fenster sein.


Die Sache mit dem Rand ist nicht so schwer:
Mit Size.Height und Size.Width bekomst du im Form die Abmessungen des ganzen Fensters.
Jetzt muss für die 4 Richtungen überprüft werden, ob die [0]-te PictureBox
(also der neu positionierte Kopf) drübersteht. Ggf. dann eben die Position neu berechnen.
Entweder jedesmal für alle 4 Richtungen nach dem switch prüfen, oder je nach Bewegungsrichtung einzeln im switch.

Also angenommen, das Fenster hat WxH 300x200 Pixel.
Bewegungsrichtung ist links: Wenn neue Position (x-Achse) kleiner 0, dann 300 dazurechnen.
-10 würde zu 290
Bewegungsrichtung rechts: Wenn neue Position (x-Achse) größer/gleich 300, dann minus 300.
Oben/Unten auch so, nur eben mit der Höhe.


Bevor das Futter dran ist hab ich dann noch einige fehlenden Funktionen ;-]
*Es darf nicht möglich sein, eine 180°-Drehung machen und in sich selbst zurückkriechen.
*Was ist, wenn die Schlange sich selbst in den Schwanz beißt...
*und für diese Verliersituation muss man die Schlange (das ganze Spiel) auch stoppen können.

Was als Nächstes? :D
 

Nymphalis

Mitglied
da es bei mir momentan nicht funktioniert, dass die Schlange am anderen Rand wieder rauskommt, hab ich doch mit dem futter angefangen
wie erzeugt man eine Picturebox an einem zufälligen Ort und vernichtet die die die Schlange berührt hat? das mit dem Wachsen ist ja fast schon leicht dagegen

*Nervenzusammenbruch krieg*
das mit der 180° Wendung ist momentan egal, auch wenn es nicht schön aussieht, aber das Spielende durch selbst in den Schwanz beißen, muss ich noch machen
das dumme ist, ich denke immer noch in java und php und so:(
das ist ech anstrengend versuchen umzudenken, wenn man nicht weiß wie
und das Internet gibt auch nicht viel her, weil die meisten Leute Snake nicht unter Forms sondern unter Game programmieren (oder gleich Visual Basic)


meine neueste Idee für das Futter, die noch nicht ganz funktioniert:

Code:
private void pictureBox1_Click(object sender, EventArgs e)
        {
            int y = 100;
            //---- Arraylist mit Pictureboxen füllen ----
            for (int a = 0; a < 1; a++)
            {
                PictureBox b = new PictureBox();  //Bild zuweisen
                Random zufall = new Random();
                b.SizeMode = PictureBoxSizeMode.AutoSize;  //Größe einstellen
                b.Left = y + 10 * a;  //nach rechts, Kopf ist links
                b.Top = 100;
                panel1.Controls.Add(b);  //Anzeige auf Panel
                s.Add(b);  //zur Arraylist dazu
                PictureBox p = new PictureBox();
                p.Image = Image.FromFile("segment.png");  //nach rechts, Kopf ist links
                if (p == b) b = new PictureBox(); //****? wie geht das bitte?
            }
        }

das dumme ist, ich muss bis Montag fertig werden oder zumindest das wichtigste haben -
das wäre dann: Schlange, Futter, Fressen und möglichst noch das Spielende durch selbst Fressen

und das ist noch die einfachste Version:(

ach ja, lass dich nicht von den // Kommentaren störren, ich hab es einfach reinkopiert
die Dokumentation kommt nämlich ganz am Schluss
 

sheel

I love Asm
Ich mach trotzdem mal noch bei dem Seitenwechsel am Bildschirm weiter:
Wie schaut denn der Code dazu aus?
Was genau passiert, statt dem Erwarteten?

Zu dem Code im letzten Beitrag: Bin gerade erst bei der ersten Zeile,
aber warum ein Click für eine Picturebox?
Du solltest die Events da machen, wo sie wirklich gebraucht werden,
sonst hast du wieder so ein Problem wie am Anfang :rolleyes:
 

Nymphalis

Mitglied
momentan sieht der code dazu nach gar nichts aus-.-#
und vorher ist eben genau nichts passiert, ich glaub, da hab ich es direkt nach dem switch oder so eingefügt

:( du hast mein Problem wohl erkannt
da ich mich überhaupt nicht auskenne, habe ich eben etwas genommen, was ich zumindest kenne
bei der Programmiersprache von c# weiß ich eben gar niiix und ähnliches kenn ich nicht wirklich
ein Spiel haben wir nie programmiert und letztes Jahr ist außer ein bisschen php auch nix Großes passiert, nur Indesign blablabla
also hab ich bei c# bis jetzt eigentlich nur dieses Spiel mit dem wir grad angefangen jhaben und vorher ne halbe Stunde programmiert

also Ende mit meiner traurigen Geschichte:
was kann ich statt dem Event machen, ohne, dass er sich über "Mehrdeutigkeiten" bei FormDesigner beschwert?
genau denselben Fehler wie am Anfang werd ich wohl nicht mehr machen, ich hab mir das jetzt schon gemerkt :D
wenn ich public nehmen, will er einen Rückgabewert. (Was ist das?-.-#)
aber brauche ich nicht eigentlich ein Event, wenn ich möchte, dass die Picturebox verschwindet um wo anders wieder auftaucht?

bitte verzweifelt um Hilfe!
Danke, dass du so geduldig bist!;)
 

sheel

I love Asm
Zeigst du den Versuch nach dem switch auch mal?

Wenn man Java schon kann sollte C# doch keine große Umgewöhnung sein...
Was hat (Adobe) Indesign mit PHP zu tun?

Welche Beschwerde hat der Formdesigner denn genau? Wenn was gemacht wird?
Wo nimmst du warum public? Wieso sollte ohne kein Rückgabewert nötig sein?

C#:
public int gibZahl() {
    return 0;
}
int ist der Rückgabetyp und 0 der Wert dazu
(das gibts aber in Java und PHP genauso).

Ob du ein Event für die Pictureboxsache brauchst:
Von welcher Art von Event reden wir jetzt? (ist so ein vielverwendetes Wort)
Beim Verändern einer Pictureboxposition (beim Bewegen der Schlange) geht eins vom Fenster
an Betriebssystem, dass die betroffenen Bereiche neu gezeichnet wurden/werden sollen.
Der Timer in deinem Programm ist ein Event, um regelmäßige Bewegung zu haben.
Welches "Event" willst du jetzt wo haben, um was zu erreichen?
Die Bewegung der Schlange geht doch ohne irgendwelche Spezialarbeit (geht doch, oder?).
Länger werden/Futter auftauchen/Futter verschwinden ist grafikmäßig auch nicht anders.

Das Hauptproblem hier ist wohl nicht die Sprache C#, sondern der Formdesigner :rolleyes:
Falls du C# dadrch lieber hast: Den muss man nicht verwenden, geht auch alles codemäßig :)

Bitte Netiquette 15 beachten.

(Mein Beitrag hat wohl mehr Fragen als Antworten :rolleyes:)
 

Nymphalis

Mitglied
Zeigst du den Versuch nach dem switch auch mal?

kann ich leider nicht... es hat ein bisschen sehr falsch ausgesehen, deshalb hab ich es gestern oder wann das war, sofort gelöscht.

Wenn man Java schon kann sollte C# doch keine große Umgewöhnung sein...
Was hat (Adobe) Indesign mit PHP zu tun?
Dass ich Java kann, ist leider übertrieben.
Außerdem habe ich es zuletzt am Anfang der 6ten Klasse benutzt (also eben am Anfang vom ganzen Informatik-Unterricht)
Indesign hat deshalb etwas mit Java zutun, weil wir in Informatik auch das, Photoshop, Excel, Word und vieles mehr durchgenommen haben.
Aber nichts haben wir mehr als 2 Monate lang gemacht und ich muss zugeben, dass ich im Programmieren nicht die beste bin...


Welche Beschwerde hat der Formdesigner denn genau? Wenn was gemacht wird?
Wo nimmst du warum public? Wieso sollte ohne kein Rückgabewert nötig sein?


Der Formdesigner hat sich vorher beschwert, dass es bei der picturebox "Mehrdeutigkeiten" gibt,
also picturebox1 doppelt da wäre oder so.
Dann hab ich das Neueste ausgeschnitten und woanders gespeichert und es hat wieder funktioniert.

Warum ich jetzt public genommen hab, weiß ich nicht.
wenn ich ehrlich bin, versteh ich die ganzen Begriffe nicht. Das weiß ich auch nicht;)
kannst du mir erklären was überhaupt der Unterschied zwischen public und private ist? Das es bei private wahrscheinlich mehr Einschränkungen gibt, ist mir klar, aber was benutzt man in welchem Gebiet?

C#:
public int gibZahl() {
    return 0;
}
int ist der Rückgabetyp und 0 der Wert dazu
(das gibts aber in Java und PHP genauso).


ach DAS ist damit gemeint. So etwas ähnliches mit int hatte ich wirklich schon einmal. unter dem Namen Rückgabewert/typ haben wir das nie kennengelernt, da der letzte Informatikprofessor zwar ein begeisterter Programmierer war, aber davon ausging, dass wir alles verstanden.
Wenn man dann mal gefragt hat, warum etwas so und so war, kam dann meistens eine Antwort, die nur ein Spezialist versteht.


Ob du ein Event für die Pictureboxsache brauchst:
Von welcher Art von Event reden wir jetzt? (ist so ein vielverwendetes Wort)
Beim Verändern einer Pictureboxposition (beim Bewegen der Schlange) geht eins vom Fenster
an Betriebssystem, dass die betroffenen Bereiche neu gezeichnet wurden/werden sollen.
Der Timer in deinem Programm ist ein Event, um regelmäßige Bewegung zu haben.
Welches "Event" willst du jetzt wo haben, um was zu erreichen?
Die Bewegung der Schlange geht doch ohne irgendwelche Spezialarbeit (geht doch, oder?).
Länger werden/Futter auftauchen/Futter verschwinden ist grafikmäßig auch nicht anders.

Das Hauptproblem hier ist wohl nicht die Sprache C#, sondern der Formdesigner :rolleyes:
Falls du C# dadrch lieber hast: Den muss man nicht verwenden, geht auch alles codemäßig :)

Bitte Netiquette 15 beachten.

(Mein Beitrag hat wohl mehr Fragen als Antworten :rolleyes:)




Ich weiß auch nicht, welche Art von Event ich brauche, aber danke für die Info, dass die Picturebox auch beim Timer hinein kommt, wenn ich es richtig verstanden hab.
ohne Spezialarbeit: ja, aber ich weiß nicht, welche Art von Event und Funktion ich wo brauche, also welche Vokabeln und so:eek:
Wie macht man also bei Forms eine Schleife oder jedenfalls so etwas ähnliches, was bei php while wäre? :rolleyes:
nicht, dass ich mich noch richtig erinnere, wie man das verwendet, aber zumindest zu wissen, was was ist, hilft ungemein weiter.
:Dja, ich gebe zu, dass C# besser zu verwenden ist, als Java, vor allem ist es übersichtlicher
aber hui, ich mochte Codes leider noch nie
ist aber nichts persönliches, mir hat es nur noch nie jemand erklärt, deshalb versuch ich jetzt die Chance zu nutzen, selbst wenn mir das bei Snake und damit bei meiner Note überhaupt nicht weiterhilft

ich versuche es, so gut wie möglich, die Netiquette zu befolgen, aber es ist schwer, wenn man soo viel schreiben muss, um richtig zu antworten
manchmal würde ich am liebsten nur denken müssen, damit alles am Bildschirm auftaucht (oder auch am Zettel)
Meine Finger sind einfach zu langsam für das Hirn und deshalb hetze ich um halbwegs nachzukommen.
bitte verzeih mir das;)
 

rd4eva

Erfahrenes Mitglied
Indesign hat deshalb etwas mit Java zutun, weil wir in Informatik auch das, Photoshop, Excel, Word und vieles mehr durchgenommen haben.
Von jemandem der nie Informatik Unterricht genossen hat: Ist das normal? Und in Mathe habt ihr dann ein bischen Rechtschreibung geübt oder wie?
Warum ich jetzt public genommen hab, weiß ich nicht.
wenn ich ehrlich bin, versteh ich die ganzen Begriffe nicht.
kannst du mir erklären was überhaupt der Unterschied zwischen public und private ist?
Das sind Access Modifier und die existieren ebenfalls in Java / PHP.
Hier die Kurzerklärung aus der Doku:
public: Der Zugriff ist nicht eingeschränkt.
protected: Der Zugriff ist auf die enthaltende Klasse oder die von der enthaltenden Klasse abgeleiteten Typen begrenzt.
private: Der Zugriff ist auf den enthaltenden Typ begrenzt.
Vielleicht hilft folgendes Beispiel
C#:
class A
    {
        public int publicVar = 0;
        private int privateVar = 0;
        protected int protectedVar = 0;

        private void TesteZugriff()
        {
            // Funktioniert alles da der Zugriff auf die Variablen von der eigenen Klasse erfolgt
            int x = publicVar;
            int y = privateVar;
            int z = protectedVar;
        }
    }

    class B
    {
        private void TesteZugriff()
        {
            A instanzVonA = new A();
            int x = instanzVonA.publicVar; // funktioniert da public von "überall" aus erreichbar sind
            int y = instanzVonA.privateVar; // funktioniert nicht da private Variablen nicht von "aussen" erreichbar sind
            int z = instanzVonA.protectedVar; // funktioniert nicht da diese Klasse (B) nicht von A abgeleitet ist
        }
    }

    // Klasse C ist eine Klasse die von A erbt
    class C : A
    {
        private void TesteZugriff()
        {            
            int x = publicVar; // funktioniert da public von "überall" aus erreichbar sind
            int y = privateVar; // funktioniert nicht da private Variablen auch nicht von erbenden Klassen aus erreichbar sind
            int z = protectedVar; // funktioniert da diese Klasse von A abgeleitet ist
        }
    }
ach DAS ist damit gemeint. So etwas ähnliches mit int hatte ich wirklich schon einmal. unter dem Namen Rückgabewert/typ haben wir das nie kennengelernt, da der letzte Informatikprofessor zwar ein begeisterter Programmierer war, aber davon ausging, dass wir alles verstanden.
Ich bin mir nicht sicher ob du das richtig verstanden hast.
Int ist zwar in diesem Fall der Rückgabewert der Funktion/Methode aber Grundsätzlich ist int ein Datentyp.
Die Signatur einer Methode besteht immer aus :
1. Access Modifier
2. (optional) Modifizierer wie abstract oder sealed
3. Rückgabewert (entweder ein Datentyp oder void wenn die Methode nichts zurück gibt)
4. Name der Methode
5. (optional) Parameter
Auch hier gibt es btw. kaum Unterschiede zu Java/PHP.
Hier ein paar Beispiele
C#:
class A
    {
        // Access Modifier = public
        // Keine Modifizierer
        // Rückgabewert = void
        // Name = MethodeA
        // Keine Parameter
        public void MethodeA() { }

        // Kein Access Modifier impliziert private als Access Modifier
        // Keine Modifizierer
        // Rückgabewert = void
        // Name = MethodeB
        // Keine Parameter
        void MethodeB() { }

        // Access Modifier = public
        // Modifizierer = sealed
        // Rückgabewert = void
        // Name = MethodeC
        // Keine Parameter
        public sealed void MethodeC() { }

        // Access Modifier = protected
        // Modifizierer = abstract
        // Rückgabewert = int
        // Name = MethodeD
        // Keine Parameter
        protected abstract int MethodeD()
        {
            return 0;
        }

        // Access Modifier = private
        // Modifizierer = virtual
        // Rückgabewert = string
        // Name = MethodeE
        // Ein parameter vom Typ int
        private virtual string MethodeE(int x)
        {
            return string.Empty;
        }

        // Access Modifier = public
        // Modifizierer = static
        // Rückgabewert = int
        // Name = Sum
        // 2 Parameter vom Typ int
        public static int Sum(int a, int b)
        {
            return a + b;
        }
    }
 
Zuletzt bearbeitet: