Snake Programmieren



  • Hallo zusammen,

    bin neu hier, aber habe schon öfters das Forum durchgestöbert 😉

    Ich bin gerade dabei Snake zu programmieren und habe einige Probleme dabei.......

    1.) Ich kriege es nicht hin die Schlange nach einer bestimmten länge zu löschen, damit sie auch wie ein richtiges Snake läuft.
    2.) Wie kann ich es am besten machen das die Schlange weiß wann sie mit sich selber zusammenstößt....Soll ich die einzlenen Punkten in Variablen speichern oder wie???

    Das wars erst mal für heute 😃

    #include <iostream.h>
    #include <conio.h>
    #include <dos.h>
    #include <stdlib.h>
    #include <graphics.h>
    
    void feld()   // Erzeugt das Spielfeld
    {
    
    	int  graphdriver = DETECT , graphmode=  VGAHI ;
    	initgraph( &graphdriver, &graphmode , "" ) ;
    
    	cout <<"\t\t***Snake V. 0.6.2***";
    	setcolor(20);
    	line(50,20,580,20);
    	line(580,20,580,400);
    	line(580,400,50,400);
    	line(50,400,50,20);
    
    }
    void snake(int x,int y)
    {
    	line(x,y,x,y);
    }
    void main(void)
    {
    clrscr();
    feld();
    
    		int y_achse=50,x_achse=100;
    		char eingabe,lastenter;
    		int snaketempo=3;
    
    		do
    		{
    
    				line(x_achse,y_achse,x_achse,y_achse);
    				eingabe=getch();
    				setcolor(9);
    
    				switch(eingabe)
    				{
    
    					case 75:
    
    					while (!kbhit() && lastenter!='d')
    					{
    
    						setcolor(9);
    						a:
    						lastenter='a';
    						delay(snaketempo);
    						snake(x_achse,y_achse);
    						if (x_achse==51) x_achse=570;
    						x_achse--;
    
    					}
    					if (lastenter=='d') goto d;
    
    					break;
    
    					case 77:
    
    					while (!kbhit() && lastenter!='a') 
    					{
    						d:
    						lastenter='d';
    						delay(snaketempo);
    						snake(x_achse,y_achse);
    						if(x_achse==569) x_achse=51;
    						x_achse++;
    					}
    					if (lastenter=='a') goto a;
    
    					break;
    
    					case 72:
    				 	while (!kbhit() && lastenter!='s') 
    					{					
    						w:
    						lastenter='w';
    						delay(snaketempo);
    						snake(x_achse,y_achse);
    						if (y_achse==21) y_achse=399;
    						y_achse--;
    					}
    					if (lastenter=='s') goto s;
    
    				 	break;
    
    					case 80:
    
    				 	while (!kbhit() && lastenter!='w') 
    					{
    
    						s:
    						lastenter='s';
    						delay(snaketempo);
    						snake(x_achse,y_achse);
    						if (y_achse==399) y_achse=20;
    						y_achse++;
    					}
    				 	if (lastenter=='w') goto w;
    
    					break;
    
    				}
    
    		}  while (eingabe !='q' && eingabe !='Q');
    
    closegraph();
    cout <<"\t\t\n\n\n !!! SPIEL BEENDET !!! ";
    
    getch();
    }
    

    Wie ihr sehen könnt verwende ich noch einen alten Compiler (Turbo C++), weil wir den auch in der
    Schule vorerst zum Einstieg benutzen.....

    Und bitte nur meine Probleme beantworten und keine zusätzlichen TIPP's geben, weil ich den Rest ja selber finden will 😉 Und kann es sein das ich es zu kompliziert gemacht habe oder es einen besseren Weg gibt????

    -->* Freak_Coder *<--



  • Ich habe sowas in der Art auch irgendwann mal gemacht.
    Geht vielleicht auch einfacher, aber da war meine Grundidee:

    Du hast ein Spielfeld mir x=0 bis xmax, y = 0 bis ymax.

    Nun nimmst Du Dir ein Array mit "Schlangenpunkten", will heissen, alle Koordinaten, in denen Deine Schlange sich befindet, werden hier gespeichert.

    Angenommen Deine Schlange hat gerade die Länge 3, dann sieht das etwas so aus:

    x[0]=x0; x[1]=x1; x[2]=x2;
    analog y

    wenn sich jetzt Deine Schlange bewegt ohne zu wachsen, shiftest Du alle x[] nach rechts:

    for(i=max; i>0; i--) //max ist die Laenge der Schlange
      x[i] = x[i-1];
    x[0] = xneu;
    

    analog y

    wächst Deine Schlange, erhöst Du max um eins und shiftest analog wie oben.

    Um nun abzufragen, ob Du eine Kollision hast, fragst Du nacheinander alle x[],y[]-Paare ab und schaust ob ein Paar Deinen momentanen Koordinaten entspricht.
    In etwa so:

    for(i=1;i<=max;i++)
      if((x[i]==x[0])&&(y[i]==y[0])) KOLLISSION;
    

    Hoffe, ich habs noch richtig zusammenbekommen.

    Hab mir Deinen Code jetzt leder nicht angeschaut, zumal das Rahmenkonzept ja passen muss um das einzubauen, aber kannst das ja als Anregung nehmen.

    MfG M



  • Arg! Hab grad doch mal in Deinen Code geschaut: GOTOS ?!
    Ist ja legitim, bin ich persänlich aber gar kein Fan von.

    Vesuch doch mal den Grunaufbau:

    while(spiel)
    {
      dx=0; dy=0;
      eingabe = getch();
      if(eingabe=='a') dx=-1;
      if(eingabe=='d') dx=1;
      if(eingabe=='w') dy=-1;
      if(eingabe=='s') dy=1;
      //hier dann die Abfrage ob innerhalb des Feldes und so.
    
      //und dann sowas wie
      xneu = xalt + dx;
      yneu = yalt + dy;  
      //und hier dann das Shiften vom letzten Beitrag
    
      //hier dann die Kollisionserkennung, wenn Kollision, dann spiel = false; oder sowas
    }
    

    So in der Art sollte das etwas einfacher gehen, aber wie gesagt, ist nur das Grundgerüst.



  • Hi MG80S,

    ich weiß selber das Goto's nicht schön sind, aber mir fällt da nichts anderes ein....... Ich mache das ja nur, weil wenn die Schlange nach rechts geht, dann bei links betätigung nicht direkt nach links laufen darf..... 😉

    Deswegen speichere ich die letzteeingabe in einer Variable und prüfe ob bei links klick die schalnge nicht vorher rechts lief und wenn das der Fall sein sollte dann soll die Schlange in die richtung der letzteneingabe laufen.......
    Genau das selber spiel auch bei oben und unten.

    Deswegen die GOTO'S also !!!!

    Ich wusste nicht wie ich das Problem einfacher lösen könnte 😉

    Ach und danke für die Antwort werde es so versuchen 😉

    -->* Freak_Coder *<--



  • Freak_Coder schrieb:

    Ich wusste nicht wie ich das Problem einfacher lösen könnte 😉

    weisst du, was eine Funktion ist, und wie man die verwendet? wenn nein: unbedingt lernen! wenn ja: damit kannst du's besser loesen 🙂

    Ein Tipp fuer Fortgeschrittenere:
    Ansonsten: eine andere Idee waer es, die Schlangenpunkte in einer Queue (zu deutsch treffend als "Schlange" uebersetzt - also wortwoertlich das, was du brauchst 😃 ) zu speichern: der aelteste Punkt fliegt bei jedem neuen Frame hinten raus, und vorne kommt ein neuer dazu 🙂
    Eine Queue ist eine Datenstruktur so aehnlich wie ein Array, aber mit variabler Groesse: d.h. du kannst Elemente rausloeschen oder neue hinzufuegen. Allerdings kann man nur "hinten" Elemente dranhaengen und nur "Vorne" welche rausnehmen, aehnlich wei bei einer Warteschlange z. B. an der Supermarktkassa: hinten kommen neue Leute dazu, und vorne gehen welche raus. in der STL (das ist die Standardbibliothek von C++, da kommen auch die <iostream> & co her) gibts eine solche queue, vielleicht kannst du damit was anfangen (Eine kurze Uebersicht ueber die Klasse gibts z.B. unter www.cppreference.com , aber auch an vielen anderen Stellen im Netz, musst nur danach googlen).... Aber ich fuercht, wenn du erst am Anfang mit dem Programmieren stehst, wird das evtl. eine Spur "zu hoch" fuer dich sein. In dem Fall: don't worry, am Anfang gings mir genauso 😉



  • Eine verkettete Liste wäre für so etwas wirklich genial.
    Sollte man zwar in der Spieleprogrammierung wegen der Performance nicht verwenden, aber wenn man nur sehr wenige Elemente ändern muss ist eine Liste perfekt.



  • Natülich weiß ich was Funktionen sind 😉 und wie man sie benutzt.........

    Werde mir dann mal überlegen wie ich das Goto Problem lösen kann (Die armen Goto's, immer hat jemand was gegen sie 😞 )

    Werde dann mal weiter coden 😃



  • Auch Carmack benutzt GOTOs!! Also nevermind!! 😋 👍



  • Sgt. Nukem schrieb:

    Auch Carmack benutzt GOTOs!! Also nevermind!! 😋 👍

    GOTT darf das! :p

    hehe, ne im Ernst die Doom3 Engine ist die beste. Warum, weil selbst in HL2 ( Source ) ne menge bugs sind! Doom3 lief bis jetzt bugfrei! hammer



  • Hab "meins" nochmal abgeändert, damit Deine "von rechts nicht nach links etc." Problematik mit drin ist. Probier mal das:

    dx=0; dy=0;
    while(spiel) 
    { 
      eingabe = getch(); 
      if(dx==0){
        if(eingabe=='a'){ dx=-1; dy=0; }
        if(eingabe=='d'){ dx=1; dy:=0; }
      }
      else{
        if(dy==0){
          if(eingabe=='w'){ dy=-1; dx=0; }
          if(eingabe=='s'){ dy=1; dx=0; }
        }
      }
      //hier dann die Abfrage ob innerhalb des Feldes und so. 
    
      //und dann sowas wie 
      xneu = xalt + dx; 
      yneu = yalt + dy;   
      //und hier dann das Shiften vom letzten Beitrag 
    
      //hier dann die Kollisionserkennung, wenn Kollision, dann spiel = false; oder sowas 
    }
    

    Habs jetzt nicht getestet, aber der Grundgedanke war der:

    dx, dy geben die relative Positionsveränderung in x- und y-Richtung an (also -1,0 oder 1).
    Nur wenn dx=0, also weder links noch rechts, kann nach links oder rechts bewegt werden. Wenn hier allerdings dx z.B. schon links ist, bleibt es das auch.
    Das selbe Spiel mit y.
    Wenn nun die Bewegung nach links oder rechts geändert wird, muss natürlich die oben/unten-Bewegung gestoppt werden, daher dy=0;
    analog oben/unten Bewegung

    Etwas komisch erklärt? 😕
    Ich finds logisch! 😉



  • Aha, Dankesehr habs schon verstanden 😉 werde es mal versuchen....


Anmelden zum Antworten