[vc++] Need Help für mein erstes snake-game auf consolenbasis

Scandle

Cadet 1st Year
Registriert
Jan. 2005
Beiträge
11
Hallo,
Das hier ist mein erster Beitrag in diesem Forum (was heißt in diesem??)
Mein erster Beitrag überhaupt in irgendeinem Forum :p

Naja, ich bräucht mal die hilfe von Leuten, die sich mit sowas auskennen...

Aaaalsooo:

(Bin ein ziemlicher NoOb in Sachen Vc++) :(

Ich hab angefangen mein erstes kleines Spiel zu schreiben. So....ja...äh ich werd hinten dran noch meinen Source hängen.

Zwar kann ich schon meine Schlange mittels "W A S D" bewegen und außerdem hab ich auch schon eine kleine "Kollisionsabfrage"...

...Aber!:

1. Die Schlange läuft nicht von allein, also nicht im alt bewährten Snake-Style, sondern ich hab volle Kontrolle über sie.....hört sich schön an....isses aber nich.... :D
Das Problem liegt an der Schleife....ich hab keine Ahnung wie ich diese mittels einer Tastenabfrage unterbrechen kann :lol:

2.Die Schlange besteht aus einem Kopf und der Schwanz aus kleinen o's. Aber wie schaff ich es, dass sich, sagen wir ab den dritten Glied der Schwanz wieder auflöst?
Also wer des mit meinem Code schafft....respekt.

3.Außerdem bräuchte ich noch eine Kollisionsabfrage, wenn der Kopf auf seinen eigenen Schwanz stößt....KA wie.

Ez seht ihr mal so nen richtig krassen Noob-code :D
Bitte viel Kritisieren und Verbesserungsvorschläge bringen.
Wird mir sicherlich helfen!!

Vielen dank schonmal im Voraus für eure Hilfe und nochmals ein herzliches HALLO an die Forum Gemeinschaft!!!

Code:
#include <iostream>
#include <conio.h>
#include <windows.h>
#include <conioex.h>

using namespace std;


int i,zahl; 
char taste;

int feld[20][20] = {0};

int posx, posy;

bool stat = TRUE;

const int d = 100;
const int a =  97;
const int w = 119;
const int s = 115;

Spielfeld();

	


Spielfeld() //Spielfeld eben
{
	
	
	cout<<"Zug :"<<zahl<<"\n"; //des haut noch nich so ganz hin
	cout<<" ----------------------------------------------------------------- \n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|-----------------------------------------------------------------|\n";
return 0;
}



 

main()
{
	posx=12; //Anfangsposition der Schlange X-Koordinate
	posy=12; //Anfangsposition der Schlange Y-Koordinate
	
	
	while(stat==TRUE) //Hauptschleife
	{
		Spielfeld();
		gotoxy(posx,posy);
		for(i=0;i<=500;i++) //Einfach so,..muss noch geänder werden
		{
			zahl=i;
			taste=getch();	
			if(taste==d) //Bewegung nach unten
			{
			
				if(posx>=66)
				{
					gotoxy(posx,posy); //Kollisionsabfrage
				}
				else
				{
				gotoxy((posx++),posy); //Bewegung bei Tastendruck "d"
				cout<<"o\2";
				zahl=i;
				}
			}
			else
			if(taste==s)
			{
				if(posy>=23)
				{
					gotoxy(posx,posy);
				}
				else
				{
					gotoxy(posx,posy);
					cout<<"o";
					gotoxy(posx,++posy);
					cout<<"o";
					gotoxy(posx,posy);
					cout<<"\2";
				}
			}
			else
			if(taste==w)
			{
				if(posy<=3)
				{
					gotoxy(posx,posy);
				}
				else
				{
					gotoxy(posx,posy);
					cout<<"o";
					gotoxy(posx,--posy);
					cout<<"o";
					gotoxy(posx,posy);
					cout<<"\2";
				}
			}
			else
			if(taste==a)
			{
				if(posx<=2)
				{
					gotoxy(posx,posy);
				}
				else
				{
					gotoxy(posx--,posy);
					cout<<"o";
					gotoxy(posx,posy);
					cout<<"\2";
				}
			}
		}	
	}
	return 0;
}
 
Zuletzt bearbeitet:
Re: [vc++] Need Held für mein erstes snake-game auf consolenbasis

Hallo,

Ich nehme mal an das getch() auf die Tastatur eingabe wartet.
Daher vorher abfragen ob ein Tastendruck da ist:

_kbhit
Checks the console for keyboard input.
int _kbhit( void );

Grob:

while( 1 )
{
if( kbhit() )
{
getch();
....
}

// let the snake run :-).

}


MfG

Arnd
 
Zuletzt bearbeitet:
Re: [vc++] Need Held für mein erstes snake-game auf consolenbasis

Hi Arnd,
Danke erst mal für deine Antwort!!
Aber ist des nich so, wenn in einer Schleife z.b. "getch()" vorkommt, dass die Schleife dann solange abgebrochen wird, bis ein Tastendruck für "getch()" ankommt? Das würde nähmlich die Bewegung der Schlange auch abbrechen .
 
Re: [vc++] Need Held für mein erstes snake-game auf consolenbasis

Hat doch geklappt mit "kbhit()" Danke !!
So...da warens nur noch zwei Probs. :-)
 
Re: [vc++] Need Held für mein erstes snake-game auf consolenbasis

Hallo Scandle,

das formuliere ich jetzt auch mal allgemein.

Die Information wie die Schlange aussieht würde ich in einer Liste mit Koordinaten speichern.
Ändert sich das aussehen der Schlange, einfach einmal Bildschirm löschen und alles neu zeichnen. Das ist die einfache und unschöne Methode.

Schöner wäre es die Information der alten Schlange ebenfalls zu speichern und bei Änderung vorher nur die alte Schange löschen (z.B. mit Spaces) und dann die neue zeichnen.

z.B.

#include <list>

class CSnakePos
{
public:
CSnakePos();

int mX;
int mY;
}

list <CSnakePos> gListOfSnakePos;
list <CSnakePos> gListOfOldSnakePos;


Hinzufügen zur Liste:

gListOfSnakePos.push_back( CSnakePos( x,y) );

Iterieren der Liste:

list<CSnakePos>::iterator lItem = gListOfSnakePos.begin();

while( lItem != gListOfSnakePos.end() )
{
lx = (*lItem).mx;
ly = (*lItem).my;
// draw snake position
lItem++;
}


löschen eine Eintrages:

gListOfSnakePos.erase( ... )


Nur mal als Vorschlag und als Starthilfe. Um Doku lesen und selber probieren kommst Du damit nicht ganz herum :-).

Unter Windows kann es ein das vor das list ein _STD gehört.

Und als allgemeine Anmerkung noch. Globale Variablen sollte man vermeiden. Bei Programmen in Deiner jetzigen grössenordnung geht das ja noch. Aber je grösser das Programm desto unübersichtlicher.
Besser die Vars in eine Klasse packen und als Member nutzen.

Ausserdem liebe ich die Laufvariable i, vor allem in Kombination mit j und k. Das ist wieder so richtig schön lesbar. Variablennamen mit iRow, iCol, ... sind wesentlich besser nachzuvollziehen.

MfG

Arnd
 
Zuletzt bearbeitet:
Re: [vc++] Need Held für mein erstes snake-game auf consolenbasis

Arnd schrieb:
Nur mal als Vorschlag und als Starthilfe. Um Doku lesen und selber probieren kommst Du damit nicht ganz herum :-).

Arnd
Puh, da hast recht! Dann werd ich erst mal "<list.h>" genauer unter die Lupe nehmen.
Mal schaun wie weit ich komm...
 
Re: [vc++] Need Held für mein erstes snake-game auf consolenbasis

Die Online Hilfe vom VC++ ist da wesentlich hilfreicher. Die Header Dateien von Templates zu verstehen, kann kompliziert werden :-).

Im wesentlich brauchst Dur nur

- hinzufügen -> push_back
- löschen -> erase
- abfragen -> iterator mit while Schleife

Natürlich musst Du keine Templates nehmen. Eine Listenverwaltung selber zu programmieren hat auch was. Die list Klasse spart aber einfach eine Menge Arbeit.

Die Liste an sich ist halt sinnvoll damit die Schlange eine variable Länge haben kann.
Ein fixes Array hat wie der Name sagt eine begrenzte Länge und dynamisch Speicher allokieren und den dann zu vergrössern, ist fehleranfällig und auch nicht besonder elegant.

Deswegen -> Templates :-).

Zwecks der Erkennung ob die Schlange sich selber trifft. Das ist ein simpler Vergleich ob die Koordinaten des ersten Elements der Liste identisch sind mit den Koordinaten eines anderen Elements der Schlange und die Liste eine Länge > 1 hat.
Das setzt natürlich voraus das die Schlange sich immer nur um einen Punkt bewegt, wenn Sie Sprünge machen kann, kommt ein bisschen Mathematik ins Spiel.

Das Auflösen ist ebenfalls simpel, wenn die Länger der Liste > n ist alle Elemente der Liste > n löschren und die Schlange neu zeichnen, oder besser die gelöschten einfach mit Space überschreiben.

Ein wesentliches Ziel bei der Bedienung sollte sein, das der komplette Bildschirm nicht zu oft neugezeichnet wird da es sonst dauernd flackert und dann macht das spielen keinen Spass mehr.

Als Vorgehensweise mal ein Vorschlag:

1. Überlegen was will ich machen
2. Welche Methoden und Klassen benötige ich dazu
3. Deklaration der Methoden und Klassen, d.h. noch kein Inhalt erst mal nur die Namen
4. Das Hauptprogramm schreiben das nur die Methoden aufruft
5. Wenn dann die Logik stimmt, die Methoden mit Inhalt füllen
6. Das hilft sehr die Übersicht zu behalten und sich nicht zu verzetteln.

MfG

Arnd

PS: Oben sind mir wie Du sicher feststellen wirst ein paar Schreibfehler unterlaufen.
 
Zuletzt bearbeitet:
Re: [vc++] Need Held für mein erstes snake-game auf consolenbasis

Hm ich wollte das auch mal ausprobieren allerdings bekomme ich eine Fehlermeldung. Die Datei conioex.h kann nicht gefunden werden. Weiß jemand woran das liegt ? Ach ja ich benutze den VC++
 
Re: [vc++] Need Held für mein erstes snake-game auf consolenbasis

Hallo daemon777,

ich glaube da kann nur Scandle weiterhelfen. Bei meiner Installation von VC++ 6.0 ist auch kein conioex.h dabei. Ebenso beim VS.NET 2003.
Auch die methode gotoxy ist in der Hilfe nicht enthalten.

Ich vermute mal das er eine extra Library benutzt.

MfG

Arnd
 
Re: [vc++] Need Held für mein erstes snake-game auf consolenbasis

Arnd schrieb:
ich glaube da kann nur Scandle weiterhelfen.

Was ist denn Scandle schon wieder ? :D

Ich hab irgendwie in letzter Zeit sehr viele Fragen wies aussieht :evillol:
 
Re: [vc++] Need Held für mein erstes snake-game auf consolenbasis

Arnd schrieb:
Bei meiner Installation von VC++ 6.0 ist auch kein conioex.h dabei. Ebenso beim VS.NET 2003.
Auch die methode gotoxy ist in der Hilfe nicht enthalten.

Ich vermute mal das er eine extra Library benutzt.


Die Library kann man sich downloaden, da sind diese Funktionen dabei.
Sind sehr hilfreich, wenn man Seinen Konsolentext farbig darstellen möchte.

http://www.tbkoenig.de/conioex.htm
 
daemon777 schrieb:
Was ist denn Scandle schon wieder ?
Sollte das ein scherz sein? :D Das ist nur der name!

Ich hatte es gestern auch mit Vc++ probiert und mich gewundert, da es bei mir ebenfals nicht funktioniert hat.

Finde ich ja sehr interessant diese Libraries. Ich wusste garnicht das man sich soetwas runterladen kann. Gibt es davon noch mehr?

Hm ich bekomme trotzdem 2 Fehler angezeigt! :(
 
Zuletzt bearbeitet:
Lol. Stimmt der Name :D

War gestern dabei eine Bibliothek nach der anderen nach der datei pc.h zu durch suchen. Und dann sagt der "da kann nur scandle weiterhelfen" :D Da dachte ich schon iweder an ne bib ;D
 
Ach ja und hier is nochmal der aktuelle Source, hat sich noch nich soo viel getan aber is schon deutlich besser...

Code:
#include <iostream>
#include <conio.h>
#include <windows.h>
#include <conioex.h>
#include <time.h>


using namespace std;


int i,zahl; 
char taste;



int posx, posy;

bool stat = TRUE;

const int d = 100;
const int a =  97;
const int w = 119;
const int s = 115;

Spielfeld();

	


Spielfeld() //Spielfeld eben
{
	
	
	
	
	cout<<"\n"; //des haut noch nich so ganz hin
	cout<<" _________________________________________________________________ \n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|-----------------------------------------------------------------|\n";
	gotoxy(posx,posy);
return 0;
}





main()
{
	srand(GetTickCount());
	int zufallX;
	int zufallY;
	posx=12; //Anfangsposition der Schlange X-Koordinate
	posy=12; //Anfangsposition der Schlange Y-Koordinate
	
	
	

	
	Spielfeld();
	
	while(stat==TRUE) //Hauptschleife
	{
		zufallX=rand()%80+3;
		zufallY=rand()%80+3;
		
		gotoxy(posx,posy);
		for(i=0;i<=500;i++) //Einfach so,..muss noch geänder werden
		{
			
			
				
			if(kbhit())
			{
				
				taste=getch();
			}
				if(taste==d)
				{
					if(posx>=66)
					{
						gotoxy(posx,posy); //Kollisionsabfrage
						cout<<"\1";
					}
					else
					{
						gotoxy((posx++),posy); //Bewegung bei Tastendruck "d"
						cout<<"o\2";
						Sleep(100);
						zahl=i++;
						
						
					}
			
				}
			
				else
				if(taste==s)
				{
				
					if(posy>=23)
					{
						gotoxy(posx,posy);
						cout<<"\1";
					}
					else
					{
						gotoxy(posx,posy);
						cout<<"o";
						gotoxy(posx,++posy);
						cout<<"o";
						gotoxy(posx,posy);
						cout<<"\2";
						zahl=i++;
						Sleep(100);
					
					}
				}
				else
				if(taste==w)
				{
					if(posy<=3)
					{
						gotoxy(posx,posy);
						cout<<"\1";
					}
					else
					{
						gotoxy(posx,posy);
						cout<<"o";
						gotoxy(posx,--posy);
						cout<<"o";
						gotoxy(posx,posy);
						cout<<"\2";
						zahl=i++;
						Sleep(100);
					
					}
				}
				else
				if(taste==a)
				{
					if(posx<=2)
					{
						gotoxy(posx,posy);
						cout<<"\1";
					}
					else
					{
						gotoxy(posx--,posy);
						cout<<"o";
						gotoxy(posx,posy);
						cout<<"\2";
						zahl=i++;
						Sleep(100);
					
					}
				}

		}
			
	}
	return 0;
}
 
Hallo Scandle,

ich habe mal ein bisschen pretty printing betrieben. Wie ich mir das nur von der Optik her vorstellen würde.

Code:
#include <iostream>
#include <conio.h>
#include <windows.h>
#include <conioex.h>
#include <time.h>

using namespace std;

int         i = 0;
int      zahl = 0; 
int   zufallX = 0;
int   zufallY = 0;
char    taste = 0;
int      posx = 12; //Anfangsposition der Schlange X-Koordinate;
int      posy = 12; //Anfangsposition der Schlange Y-Koordinate;
bool     stat = TRUE;

#define KEY_D   100;
#define KEY_A     97;
#define KEY_W  119;
#define KEY_S   115;

void Spielfeld();


void Spielfeld() //Spielfeld eben
{
	cout<<"\n"; //des haut noch nich so ganz hin
	cout<<" _________________________________________________________________ \n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|                                                                 |\n";
	cout<<"|-----------------------------------------------------------------|\n";
	gotoxy(posx,posy);
	return 0;
}

int main()
{
	srand(GetTickCount());
	
	Spielfeld();
	
	while(stat==TRUE) //Hauptschleife
	{
		zufallX=rand()%80+3;
		zufallY=rand()%80+3;
		
		gotoxy(posx,posy);
		for(i=0;i<=500;i++) //Einfach so,..muss noch geänder werden
		{
			taste = 0;
			if(kbhit())
			{				
				taste=getch();
			}
			
			switch( taste )
			{
			case KEY_D:
				if(posx>=66)
				{
					gotoxy(posx,posy); //Kollisionsabfrage
					cout<<"\1";
				} else
				{
					gotoxy((posx++),posy); //Bewegung bei Tastendruck "d"
					cout<<"o\2";
					Sleep(100);
					zahl=i++;			
				}
				break;
			case KEY_S:
				if(posy>=23)
				{
					gotoxy(posx,posy);
					cout<<"\1";
				} else
				{
					gotoxy(posx,posy);
					cout<<"o";
					gotoxy(posx,++posy);
					cout<<"o";
					gotoxy(posx,posy);
					cout<<"\2";
					zahl=i++;
					Sleep(100);	
				}
				break;
			case KEY_W:
				if(posy<=3)
				{
					gotoxy(posx,posy);
					cout<<"\1";
				} else
				{
					gotoxy(posx,posy);
					cout<<"o";
					gotoxy(posx,--posy);
					cout<<"o";
					gotoxy(posx,posy);
					cout<<"\2";
					zahl=i++;
					Sleep(100);
					
				}
				break;
			case KEY_A:
				if(posx<=2)
				{
					gotoxy(posx,posy);
					cout<<"\1";
				} else
				{
					gotoxy(posx--,posy);
					cout<<"o";
					gotoxy(posx,posy);
					cout<<"\2";
					zahl=i++;
					Sleep(100);						
				}
				break;
			}
		}	
	}
	return 0;
}

Kompiliert habe ich es nicht.

Beachte bitte das setzen von taste auf 0. Da jetzt ein kbhit drin ist, würde deine Schlange sonst einen Dauerlauf betreiben, da nach einmal Taste drücken der Werte von taste immer auf dem letzten Wert stehen bleibt.

MfG

Arnd
 
Zuletzt bearbeitet:
Hi,

Ich würde hier nicht
if(kbhit());​
benutzen sondern
while(kbhit())​

sonst "verpasst" du Benutzereingaben.
Desweiteren würde ich die Eingaben puffern, weil getch() etwas langsam ist.
Ich würde hier sowieso direkt über das BIOS gehen.
BSP:
#include<bios.h>
.
.
.
#define LEFT 19200
#define RIGHT 19712
#define UP 18432
#define DOWN 20480
.
.
.
while(bioskey(1))
{
key=bioskey(0);
switch(key)
{
case UP: {
....
}break;
case DOWN:{
....
}break;
.
.
.​
PS:
Wieso machst du das eigentlich mit einer Konsolenanwendung?
Eine SDI-Anwendung mit DDRAW oder GDI, wäre doch besser oder?
Wenn du dich da nicht rantraust, versuchs mit dem Borland Builder mit der BGI(hier hab ich mein erstes snake programmiert).
Wenn du es mal sehen willst, einfach mail an mich.
 
Hallo,

Biosaufrufe sind sicher effektiver aber dafür dann nicht portabel.

Aber es ist sicher sinnvoll solange Tasten da sind diese auch abzufragen.

Ein weiterer Nachteil der momentanen Lösung ist sicher auch noch die hohe CPU Last auf Grund der Schleife.

MfG

Arnd
 
Zuletzt bearbeitet:
Zurück
Oben