| Autor |
Nachricht |
Modarek
Mitglied
Benutzerprofil
Anmeldungsdatum: 06.08.2012
Beiträge: 5
|
Modarek Mitglied
19:15:20 06.08.2012 Titel: |
Snake |
Zitieren |
Hallo,
Ich programmiere zur Zeit Snake für die Linux Konsole. Ich bin eigentlich schon fertig, bis auf ein kleines Problem. Die Frucht, die die Schlange fressen muss um länger zu werden taucht manchmal nicht irgendwo auf dem Spielfeld auf sondern mitten in der Schlange. Wenn die Schlange dann drüber gelaufen ist wird sie unsichtbar. Wie ihr euch denken könnt macht es mit einer unsichtbaren Frucht eher wenig Spaß
Ich vermute es liegt an meiner putFruit().
Meiner Meinung nach ist sie so korrekt und es dürfte nicht dazu kommen, aber irgendwas muss ja falsch sein...
| C++: | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | void Snake::putFruit() {
srand(time(0));
while (true) {
int tmpX = random()%_maxX + 1; // maxX und maxY sind die Spielfeldbegrenzungen. tmpX und tmpY sind zufällige Koordianten an denen die Frucht erscheint.
int tmpY = random()%_maxY + 1;
for (int i = 0; i <= S.size(); i++) // S ist die Schlange (Vektor); Hier wird doch ausgeschlossen,
if (S[i].x == tmpX && S[i].y == tmpY) // dass sie in die Schlange kommt.
continue; // Falls die zwei Zufallszahlen eine schon von der Schlange belegte Position ausspucken, startet die while-Schleife neu.
if (tmpX >= _maxY - 2 || tmpY >= _maxX - 3)
continue;
fruit.x = tmpX;
fruit.y = tmpY;
break;
}
move(fruit.y, fruit.x);
addch(fruitChar);
refresh();
} | |
Ich bedanke mich schon mal für eure Hilfe
LG Modarek |
Zuletzt bearbeitet von Modarek am 19:37:35 06.08.2012, insgesamt 5-mal bearbeitet |
|
 |
SeppJ
Moderator
Benutzerprofil
Anmeldungsdatum: 10.06.2008
Beiträge: 17930
|
SeppJ Moderator
19:42:48 06.08.2012 Titel: |
|
Zitieren |
Und woher weiß das continue in Zeile 8, dass du die while-Schleife meinst und nicht die for-Schleife?
Wenn du versuchst, etwas strukturierter zu programmieren, dann brauchst du auch nicht den Spaghetticode aus Endlosschleifen, continue, break & Co. Du siehtst, wohin so etwas führt. Der eigentliche Ablaufplan wäre doch, in einer Schleife so lange Werte zu würfeln, bis die beiden Bedingungen (was soll eigentlich die zweite?) für gültige Werte erfüllt sind. Der Code sollte dies widerspiegeln.
Das sieht falsch aus, denn das setzt den globalen Zufallsgeneratorzustand bei jedem Funktionsaufruf auf einen anderen Wert. |
_________________ Du brauchst Hilfe?, Buchempfehlungen für C++,
Wie man in Fragen den richtigen Code postet,
The Definitive C++ Book Guide and List
|
|
 |
Modarek
Mitglied
Benutzerprofil
Anmeldungsdatum: 06.08.2012
Beiträge: 5
|
Modarek Mitglied
19:52:15 06.08.2012 Titel: |
|
Zitieren |
Vielen Dank
Ich programmiere erst seit einem halben Jahr, deswegen geht es bei mir noch etwas drunter und drüber
Ich werde es gleich mal ausprobieren.
LG Modarek |
|
|
|
 |
Modarek
Mitglied
Benutzerprofil
Anmeldungsdatum: 06.08.2012
Beiträge: 5
|
Modarek Mitglied
20:45:12 06.08.2012 Titel: |
|
Zitieren |
Hey,
Ich hab es jetzt versucht aber ohne großen Erfolg -.-
Könntest du mir nochmal kurz auf die Sprünge helfen wie das aussehen muss?
Ich kann ja schlecht so lange würfeln bis beide Bedingungen, die zweite ist dafür da, dass die Frucht nicht außerhalb vom Feld erscheint, erfüllt sind, wenn ich die Zufallszahl für die Bedingung noch gar nicht habe, die dann sagen würde ob die Bedingung erfüllt ist oder nicht. Wahrscheinlich stehe ich gerade auf dem Schlauch -.-
Nur einen Ansatz, oder irgendwie so was
LG Modarek |
Zuletzt bearbeitet von Modarek am 20:47:48 06.08.2012, insgesamt 1-mal bearbeitet |
|
 |
Clundsch
Mitglied
Benutzerprofil
Anmeldungsdatum: 31.05.2012
Beiträge: 50
|
Clundsch Mitglied
20:59:45 06.08.2012 Titel: |
|
Zitieren |
ich hab ebenfalls snake für die konsole programmiert ( ) und hab das problem folgendermaßen gelöst, indem ich eine Funktion geschrieben habe, die als Übergabeparameter die Position aller Schlangenglieder und die des Fressens hat. diese wird von der fressen-generieren-Funktion aufgerufen und überprüft durch eine schleife, ob das fressen auf der schlange liegt. wenn ja liefert sie false zurück und die fressen-generieren-Funktion wiederholt sich.
EDIT: allerdings war ich bisher zu blöd um das ganze von strukturiert in objektorientiert zu übersetzten |
Zuletzt bearbeitet von Clundsch am 21:02:19 06.08.2012, insgesamt 2-mal bearbeitet |
|
 |
Sone
Mitglied
Benutzerprofil
Anmeldungsdatum: 29.05.2012
Beiträge: 3157
|
Sone Mitglied
21:19:25 06.08.2012 Titel: |
|
Zitieren |
| Clundsch schrieb: | | die Position aller Schlangenglieder |
OUCH. Wieso nicht Klassen? Snake lässt sich wunderschön mit Klassen für Früchte, Glieder und er Schlange selbst und dem Feld lösen.
Edit: Edit übersehen ^^ |
_________________ You want to do X, and you think Y is the best way of doing so. Instead of asking about X, you ask about Y. | Wenn man was zum Lachen braucht: Why C++ Sucks
Zuletzt bearbeitet von Sone am 21:19:50 06.08.2012, insgesamt 1-mal bearbeitet |
|
 |
Clundsch
Mitglied
Benutzerprofil
Anmeldungsdatum: 31.05.2012
Beiträge: 50
|
Clundsch Mitglied
21:29:34 06.08.2012 Titel: |
|
Zitieren |
| Sone schrieb: |
OUCH. Wieso nicht Klassen? Snake lässt sich wunderschön mit Klassen für Früchte, Glieder und er Schlange selbst und dem Feld lösen.
|
Ich weiß. ich hab schon total viel dran rumgebastelt, aber irgendwie wollen die Klassen net zusammenarbeiten der wirft mir dann irgendeinem unverständlichen Mist raus.
sitze grad an nem anderen Projekt, aber Snake will ich auf jeden Fall nochmal versuchen umzuschreiben |
|
|
|
 |
SeppJ
Moderator
Benutzerprofil
Anmeldungsdatum: 10.06.2008
Beiträge: 17930
|
SeppJ Moderator
21:59:24 06.08.2012 Titel: |
|
Zitieren |
|
 |
Modarek
Mitglied
Benutzerprofil
Anmeldungsdatum: 06.08.2012
Beiträge: 5
|
Modarek Mitglied
12:08:44 07.08.2012 Titel: |
|
Zitieren |
So, ich hab ein bisschen was geschafft:
| C++: | 1 2 3 4 5 6 7 8 9 10 11 12 | void Snake::putFruit() {
do {
tmpX = random()%_maxX + 1; // tmpX und tmpY sind mit 0 initialisiert, damit putFruit von Anfang an funktioniert.
tmpY = random()%_maxY + 1;
} while ((S[0].x == tmpX && S[0].y == tmpY) && // Hier habe ich S[0] gesetzt, weil ich leider keine Ahnung hab, wie ich jetzt alle Teile der
(tmpX >= _maxY - 2 || tmpY >= _maxX - 3)); // Schlange überprüfen kann :(. Ich hab es ja mit "for (int i = 0; i <= S.size(); i++)" gemacht,
fruit.x = tmpX; // aber das kann ich da ja nicht in die while-Schleife einbauen.
fruit.y = tmpY;
move(fruit.y, fruit.x);
addch(fruitChar);
refresh();
} | |
Leider funktioniert das so auch nicht -.- Langsam blick ich nicht mehr durch -.-
Irgendwas mache ich falsch... Jetzt erscheint die Frucht ständig in der Schlange.
Kann vielleicht jemand noch mal drüber schauen? Wie ich das dann für alle Teile der Schlange mache weiß ich leider auch nicht.
LG Modarek |
Zuletzt bearbeitet von Modarek am 12:26:33 07.08.2012, insgesamt 3-mal bearbeitet |
|
 |
camper
Mitglied
Benutzerprofil
Anmeldungsdatum: 06.08.2004
Beiträge: 5774
|
camper Mitglied
12:23:11 07.08.2012 Titel: |
|
Zitieren |
| Modarek schrieb: | | Nur könnte mir vielleicht jemand sagen, wie ich das jetzt für die ganze Schlange mache? | Dafür würde sich eine eigene Funktion eignen.
bool Snake::isOccupying(int x, int y) const
oder so |
Zuletzt bearbeitet von camper am 12:23:23 07.08.2012, insgesamt 1-mal bearbeitet |
|
 |
Modarek
Mitglied
Benutzerprofil
Anmeldungsdatum: 06.08.2012
Beiträge: 5
|
Modarek Mitglied
13:14:33 07.08.2012 Titel: |
|
Zitieren |
So,
ich habe es endlich geschafft.
Wahrscheinlich ist es keine elegante Lösung, aber sie funktioniert. Anstatt mit "continue" zu arbeiten habe ich es mit einem "Label" und "goto" gemacht.
Hier der Code:
| C++: | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | void Snake::putFruit() {
putFruit:
while (true) {
int tmpX = random()%_maxX + 1;
int tmpY = random()%_maxY + 1;
for (int i = 0; i <= S.size(); i++)
if (S[i].x == tmpX && S[i].y == tmpY)
goto putFruit;
if (tmpX >= _maxY - 2 || tmpY >= _maxX - 3)
goto putFruit;
fruit.x = tmpX;
fruit.y = tmpY;
break;
}
move(fruit.y, fruit.x);
addch(fruitChar);
refresh();
} | |
Vielen Dank an alle die geholfen haben!
LG Modarek |
|
|
|
 |
C. elegans
Unregistrierter
|
C. elegans Unregistrierter
14:40:05 07.08.2012 Titel: |
|
Zitieren |
| Modarek schrieb: |
Wahrscheinlich ist es keine elegante Lösung [...]
|
Das ist richtig Und die Verwendung von goto macht es richtig schlimm. Die Vorposter haben es ja schon gesagt: Zerlege das in ein paar logische Methoden
| C++: | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | struct coord
{
int x;
int y;
coord(int x, int y) : x(x), y(y)
{
}
};
/*
* Ich nehme mal an, Deine Snake sei definiert als vector<coord> S
*/
bool isOnSnake(coord f)
{
for (int i = 0; i <= S.size(); i++)
{
if (f == S[i])
{
return true;
}
}
return false;
}
coord makeRandomCoordinate(coord min, coord max)
{
coord c;
do
{
c.x = random()%_maxX + 1;
c.y = random()%_maxY + 1;
} while ( (c.x >= max.x ) || (c.y >= max.y)
|| (c.x < min.x ) || (c.y < min.y));
return c;
}
void Snake::putFruit()
{
coord fruit;
do
{
fruit = makeRandomCoordinate(coord(0,0), coord(maxY-2, maxX-3));
} while (isOnSnake(fruit));
move(fruit.y, fruit.x);
addch(fruitChar);
refresh();
} | | |
|
|
|
 |
camper
Mitglied
Benutzerprofil
Anmeldungsdatum: 06.08.2004
Beiträge: 5774
|
camper Mitglied
14:59:27 07.08.2012 Titel: |
|
Zitieren |
EIn bisschen gekürzt wird daraus| C++: | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | struct coord
{
int x;
int y;
};
bool operator==(const coord& lhs, const coord& rhs) { return lhs.x == rhs.x && lhs.y == rhs.y; }
bool isOnSnake(const coord& f)
{
return find(begin(S), end(S), [&](const coord& s_pos){ return f == s_pos; }) != end(S);
}
coord makeRandomCoordinate(coord min, coord max)
{
return { random()%(max.x-min.x+1)+min.x, random()%(max.y-min.y+1)+min.y };
}
coord makeFreeRandomCoordinate(coord min, coord max)
{
for (;;)
{
coord pos = makeRandomCoordinate( min, max );
if ( !isOnSnake( pos ) )
return pos;
}
}
void Snake::putFruit()
{
coord fruit = makeFreeRandomCoordinate({0,0}, {maxY-2, maxX-3});
move(fruit.y, fruit.x);
addch(fruitChar);
refresh();
} | | |
Zuletzt bearbeitet von camper am 09:44:23 08.08.2012, insgesamt 2-mal bearbeitet |
|
 |
C. elegans
Unregistrierter
|
C. elegans Unregistrierter
09:39:08 08.08.2012 Titel: |
|
Zitieren |
@Camper: Ja, das ist noch mal kürzer. Wobei: Der operator== ist m.E. nicht nötig, da die struct Elementweise verglichen wird. Dann wäre es noch kürzer.
Ich hatte zuerst eine ähnliche Version, allerdings nicht mit dem schönen random Konstrukt von Dir. Dann habe ich mir aber überlegt, dass der TO bei der Version von mir gar nichts mehr von seinem Code wiederfindet. Ich denke, zum Lernen sind kleinere (Fort-)Schritte hilfreicher (wobei Deine Lösung die deutlich elegantere ist ) |
|
|
|
 |
zergleicher
Unregistrierter
|
zergleicher Unregistrierter
08:08:17 09.08.2012 Titel: |
|
Zitieren |
Ne, operator== ist immer nötig, wenn es sich um benutzerdefinierte Typen handelt. Klassen werden nicht automatisch memberweise verglichen. |
|
|
|
 |
cazubi
Unregistrierter
|
cazubi Unregistrierter
11:05:56 23.10.2012 Titel: |
|
Zitieren |
Da ihr jetzt ja schon alle so schön über Snake redet und voll im Thema drinne seit habe ich auch eine Frage.
Um C zu lernen hab ich jetzt auch Snake programmiert und es eigentlich komplett fertig, das einzige was mir noch fehlt ist das die Schlange sich nicht von alleine bewegen kann.
Ich lasse die Richtung in die sich die Schlange bewegen soll von einem getchar() auslesen welches nicht mit <ENTER> bestätigt werden muss. Der nächste Schritt wäre dem programm zu sagen nach einer bestimmten zeit geh in die letzt gegangene Richtung aber wie ?? |
|
|
|
 |
Belli
Mitglied
Benutzerprofil
Anmeldungsdatum: 29.08.2009
Beiträge: 1772
|
Belli Mitglied
11:23:36 23.10.2012 Titel: |
|
Zitieren |
| zergleicher schrieb: | | Ne, operator== ist immer nötig, wenn es sich um benutzerdefinierte Typen handelt. Klassen werden nicht automatisch memberweise verglichen. |
Das ist falsch!
Edit:
Doch nicht falsch - ich habs mit dem operator= verwechselt, der standardmäßig erzeugt wird. |
Zuletzt bearbeitet von Belli am 11:30:10 23.10.2012, insgesamt 1-mal bearbeitet |
|
 |
SeppJ
Moderator
Benutzerprofil
Anmeldungsdatum: 10.06.2008
Beiträge: 17930
|
SeppJ Moderator
11:31:04 23.10.2012 Titel: |
|
Zitieren |
|
 |