Contest #2: Space Invaders
-
Shade Of Mine schrieb:
Oder vielleicht sollte der Code nicht so leicht abusebar sein.
Solange ich das hier nicht an einen Kunden verkaufen, kann es mir herzlichst egal sein!
bmario schrieb:
Hinweis am Rande, ein Lichtjahr (light year) ist keine Zeiteinheit
Es dient auch hier der Entfernung, die das Raumschiff im Astroidenfeld schon zurückgelegt hat
bmario schrieb:
*Edit: Wenn man der
computeNextMove()
dasSpaceField
alsconst
-Referenz übergibt, ist immerhin Volkard's Hack dahin. Dann sollte aber besserSpaceField::isAstroidHere()
auchconst
sein.Ja das stimmt. Aber waehrend des Programmierens kam irgendwann der Punkt, wo ich mir selbst gesagt habe: "Ach, ist doch egal. Es geht hier nur um den Spaß und ich bin gerade zu Faul, um es sauber zu machen" ...
-
Entweder du machst es sauber, oder du musst Lösungen zulassen, die die Implementierung ausnutzen
Das ist das einzig Kluge, sonst ist schwammig, was man darf und was nicht. Und statt dafür Regeln wie "man darf nur diese Methoden aufrufen" zu formulieren, kann man den Code gleich entsprechend gestalten. Worauf ich hingegen keine Rücksicht nehmen würde, sind tatsächliche Hacks mit U.B., const_cast, #define private public etc.
-
edit: Nagut, dann schreibe ich nicht, wie ich es machen würde. Kann ja nicht wissen, daß man das offensichtliche nicht sagen darf. Wobei ich eher denke, daß KasF kaum darüber nachgedacht hat, wie eine gute Lösung aussehen würde.
-
class ReallyOutsideTheBox: public SpaceShip { public: ReallyOutsideTheBox(size_t x, size_t y) : SpaceShip(20 + 1, 20 + 1) // könnte sich noch ein wenig ändern. { } void computeNextMove(SpaceField &field) { static long i = 0; i++; if(i == MAX_LONG - 3 ) // -3 Sicherheitsabstand und mir reicht der fünfte Platz :) destroy(); //ungetestet aber ungefähr so sollte es sein :) } };
Mal eine "Böse" Frage:
Wenn ich anstattx
undy
konstante Werte> 19
nehme, dann wird ja irgendwo Speicher ein Byte mit einem 'S' überschrieben (typischer Buffer Overflow), aber gibt es nach der KlasseSpaceField
einen definierten Bereich, der "problemlos" überschrieben / gelesen werden kann (d.h. nicht abstützt, aber Spieler außerhalb des Spielfeldes)? Sozusagen der "Subraum", um bei StarTrek zu bleiben.
-
Kleines Codeupdate für die Heulsusen unter uns.
-
Ich find das auch schade, dass ihr da so pedantisch wart. Statt da zu kritisieren oder euch lustig drüber zu machen, könntet ihr den Quelltext ja auch 100% perfekt refaktorisieren und als Beispiel für perfektes C++ den kommenden Jahrhunderten und Jahrtausenden übergeben als Mahnmal des menschlichen Intellekts!
-
volkard schrieb:
...
Du bist doch echt der tollste beschde und coolste Typ in diesem Forum und weißt auch echt alles besser als wir alle zusammen. Statt den Leuten lieber ihren Spaß zu lassen, musst du es ihnen kaputt machen, da du bei dieser für dich primitiven Aufgabe ja selbst kein Spaß hast und somit den anderen auch nicht das Vergnügen gönnen willst. Ich disqualifiziere dich jetzt schonmal. Ist immerhin mein Spiel und ich suche mir eben nun mal meine Mitspieler selbst aus ...
-
@Decimad: Leider ist dieses Verhalten ein Problem in diesem Forum und genau dieses Verhalten ist auch das Abbild des Informatikers in unserer Gesellschaft. Schade, wo ich doch auch auch ganz nette, normale und soziale Informatiker kenne ...
Aber genug Off-Topic
-
Taktik: Auf der Grundlinie bleiben. Asteroiden verglühen dann automatisch vor dem Aufprall.
void computeNextMove(const SpaceField &field) { if(getPosition().y<field.getSizeY()) moveDown(); }
Überlebt beliebig lange.
Vermutlich Programmierfehler.
-
Taktik: Loch suchen und reinfahren.
class TomParisShuttle : public SpaceShip { public: Point findSpace(const SpaceField &field) { for(size_t y=field.getSizeY()-1;y>=1;--y) for(size_t x=0;x<field.getSizeX();++x) if(!field.isAstroidHere(Point(x,y))) return Point(x,y); return Point(3,3); } void computeNextMove(const SpaceField &field) { Point space=findSpace(field); while(getPosition().y<space.y) moveDown(); while(getPosition().y>space.y) moveUp(); while(getPosition().x>space.x) moveLeft(); while(getPosition().x<space.x) moveRight(); } };
Überlebt extrem lange.
Vermutlich Regelfehler.
-
volkard schrieb:
Vermutlich Programmierfehler.
Behoben. Danke.
volkard schrieb:
Vermutlich Regelfehler.
Behoben. Danke.
Du bist echt unglaublich. Wieso kannst du mich nicht ganz normal - wie ein Erwachsener - schon in deinem ersten Post auf meine ganzen Fehler aufmerksam machen und zur Qualitaet dieses Threads beitragen. Wieso nicht!? Ehrlich, sags mir. Wieso musst du dich dermaßen arrogant profilieren? ... Ich weiß echt nicht, wie oft ich dich schon bzgl dieses kindische Verhalten hier im Forum angesprochen habe. Traurig
-
volkard schrieb:
Taktik: Loch suchen und reinfahren.
Das war auch die erste Lösung, die mir eingefallen ist. Eine Variante, die auch mit kaltem Kaffee funktioniert war mir dann aber lieber
-
KasF schrieb:
...
Der Unterschied ist nur, ob ich es gleich sage, oder ob ich warte, bis Du soweit bist, es aufzunehmen. Das sehe ich auch oft, gerade hier im Forum, daß eine Aussage auf der ersten Seite partout nicht zur Kenntnis genommen wird, aber dieselbe Aussage auf Seite 7 wird vom Threadersteller (nachdem er sich ein paar Seiten lang mit dem Problem beschäftigt hat) als "die Lösung" gefeiert.
-
Warum macht ihr nicht mal einen Contest bei dem man etwas mit mehr Taktik machen kann? Z.B. ein Feld auf dem Energie und Punkte Items leigen. Man kann dann einen Roboter über das Feld steuern und jede Bewegung kostet Energie, das Schauen, was z.B. in einer Reihe vor einem liegt kostet auch Energie. Außerdem könnte man auch zwei Roboter gegeneinander antreten lassen und die Roboter können Bomben legen und zünden. Wer in einem Zeitraum am meisten Punkte einsammelt oder den anderen zerstört, gewinnt. Die Rechenzeit für einen Roboter sollte auch begrenzt sein, wenn sie gegeneinander spielen.
-
KasF schrieb:
#include <iostream> #include <vector> #include <cstdlib> #include <ctime> using namespace std; struct Point { size_t x,y; }; class SpaceField; class SpaceShip { private: Point position; bool aLive, moveDone; public: SpaceShip() : position{8,15}, aLive(true), moveDone(false) { } void destroy() { aLive = false; } bool isAlive() const { return aLive; } void doMove(SpaceField &field); virtual void computeNextMove(const SpaceField &field) = 0; void moveRight() { if(moveDone) return; ++position.x; moveDone = true; } void moveLeft() { if(moveDone) return; --position.x; moveDone = true; } void moveUp() { if(moveDone) return; --position.y; moveDone = true; } void moveDown() { if(moveDone) return; ++position.y; moveDone = true; } Point getPosition() const { return position; } }; class Astroids { private: vector<Point> astroidsPosition; size_t difficulty; long seed; long randomy() { return (((seed = seed * 214013L + 2531011L) >> 16) & 0x7fff); } void generateNewAstroids() { if(randomy() % 2 == 0) return; int noOfAstroids = randomy() % (difficulty > 15 ? 15 : difficulty) +1; while(noOfAstroids--) { astroidsPosition.push_back({randomy() % 20,0}); } } public: Astroids() { difficulty = 1; seed = 1234; } void increaseDifficulty() { ++difficulty; } size_t getDifficulty() const { return difficulty; } void moveForward() { generateNewAstroids(); for(vector<Point>::iterator it = astroidsPosition.begin(); it != astroidsPosition.end();) { if(++it->y > 20) it = astroidsPosition.erase(it); else ++it; } } vector<Point> getAstroidPosition() const { return astroidsPosition; } }; class SpaceField { private: char spaceField[20][20]; SpaceShip *spaceShip; Astroids astroids; Point lastShipPosition; void init() { for(size_t y = 0; y < 20; ++y) for(size_t x = 0; x < 20; ++x) spaceField[x][y] = '_'; } void updateField() { init(); spaceField[lastShipPosition.y][lastShipPosition.x] = 'S'; vector<Point> astroPoints = astroids.getAstroidPosition(); for(size_t i = 0; i < astroPoints.size(); ++i) spaceField[astroPoints[i].y-1][astroPoints[i].x] = 'A'; } public: SpaceField() { init(); } void insertShip(SpaceShip *ship) { spaceShip = ship; spaceField[spaceShip->getPosition().y][spaceShip->getPosition().x] = 'S'; lastShipPosition = spaceShip->getPosition(); } void increaseLevel() { astroids.increaseDifficulty(); } bool isAstroidHere(Point checkPoint) const { return spaceField[checkPoint.y][checkPoint.x] == 'A'; } size_t getLevel() const { astroids.getDifficulty(); } size_t getSizeY() const { return 20-1; } size_t getSizeX() const { return 20-1; } void moveShip(Point to) { if(spaceField[lastShipPosition.y][lastShipPosition.x] != 'A') spaceField[lastShipPosition.y][lastShipPosition.x] = '_'; if(spaceField[to.y][to.x] == 'A') { spaceShip->destroy(); return; } spaceField[to.y][to.x] = 'S'; lastShipPosition = to; } void moveAstroidsForward() { astroids.moveForward(); updateField(); } void printField() const { cout << "\x1b[2J\x1b[H" << flush; // clears linux terminal for(size_t y = 0; y < 20; ++y) { for(size_t x = 0; x < 20; ++x) cout << spaceField[y][x]; cout << endl; } cout << endl; } }; void SpaceShip::doMove(SpaceField &field) { moveDone = false; computeNextMove(field); field.moveShip(position); } class KasFSpaceShip : public SpaceShip { public: void computeNextMove(const SpaceField &field) { Point checkPoint = getPosition(); --checkPoint.y; if(field.isAstroidHere(checkPoint)) if(field.getSizeX() > checkPoint.x) moveRight(); else moveLeft(); } }; int main() { SpaceField spaceField; SpaceShip *ship = new KasFSpaceShip(); spaceField.insertShip(ship); long cycles = 0; while(ship->isAlive()) { ++cycles; spaceField.printField(); spaceField.moveAstroidsForward(); ship->doMove(spaceField); if(cycles % 10 == false) spaceField.increaseLevel(); cout << cycles << " light years survived" << endl; cout << "Level" << spaceField.getLevel() << endl; sleep(1); } cout << "\nYou survived " << cycles << " light years far!" << endl; }
sagt mal: kann es sein, dass genau dieser code nicht in visual c++ 2010 funktioniert?
der kennt zum beispiel zeile 20 die initialisierung von der point struktur nicht als rechtmässig an, gleiches problem in zeile 80. sleep in zeile 257 ist auch unbekannt
soll ich den code mal ein wenig ifdeffen und dann nochmal reinstellen?
-
Skym0sh0 schrieb:
sagt mal: kann es sein, dass genau dieser code nicht in visual c++ 2010 funktioniert?
der kennt zum beispiel zeile 20 die initialisierung von der point struktur nicht als rechtmässig an, gleiches problem in zeile 80.Kann es sein das VS2010 noch nicht die neue Art der C++0x-Initialisierung unterstützt? Bei mir kompiliert g++ das fein durch:
g++ -std=c++0x contest2.cpp
Skym0sh0 schrieb:
soll ich den code mal ein wenig ifdeffen und dann nochmal reinstellen?
Ja, waere gut auch ne Windows-Version zu haben.
Edit: @Volkard: Habe deinen ("fehlerhaften") Post noch gesehen. Aber ist doch schön das du als Moderator deinen ganzen Post verschwinden lassen kannst, gell
-
KasF schrieb:
Edit: @Volkard: Habe deinen ("fehlerhaften") Post noch gesehen. Aber ist doch schön das du als Moderator deinen ganzen Post verschwinden lassen kannst, gell
Wie oben. Besser, Du kommst selber drauf.
-
Ach, ist doch egal. Es geht hier nur um den Spaß und ich bin gerade zu Faul, um es sauber zu machen
Diese Haltung ist das Problem. Es macht keinen Spass fehlerhaften und beschissenen Quelltext zu lesen. Entweder machst du es richtig, oder gar nicht. Bei spieleprogrammierer.de gibt es auch ab und an Wettbewerbe. Sie unterscheiden sich qualitativ enorm von "Space Invaders mit Asteroiden".
-
so, auf visual c++ portiert(so dass es läuft), aber hab keinen anderen compiler, daher kann ichd a nix sagen
#include <iostream> #include <vector> #include <cstdlib> #include <ctime> #ifdef WIN32 #include <Windows.h> #endif // WIN32 using namespace std; struct Point { size_t x, y; #ifdef _MSC_VER Point(size_t x_ = 0, size_t y_ = 0) : x(x_), y(y_) {} #endif // _MSC_VER }; class SpaceField; class SpaceShip { private: Point position; bool aLive, moveDone; public: SpaceShip() : #ifdef _MSC_VER position(8, 15) #else position{8,15} #endif // _MSC_VER , aLive(true), moveDone(false) { } void destroy() { aLive = false; } bool isAlive() const { return aLive; } void doMove(SpaceField &field); virtual void computeNextMove(const SpaceField &field) = 0; void moveRight() { if(moveDone) return; ++position.x; moveDone = true; } void moveLeft() { if(moveDone) return; --position.x; moveDone = true; } void moveUp() { if(moveDone) return; --position.y; moveDone = true; } void moveDown() { if(moveDone) return; ++position.y; moveDone = true; } Point getPosition() const { return position; } }; class Astroids { private: vector<Point> astroidsPosition; size_t difficulty; long seed; long randomy() { return (((seed = seed * 214013L + 2531011L) >> 16) & 0x7fff); } void generateNewAstroids() { if(randomy() % 2 == 0) return; int noOfAstroids = randomy() % (difficulty > 15 ? 15 : difficulty) +1; while(noOfAstroids--) { #ifdef _MSC_VER astroidsPosition.push_back(Point(randomy() % 20, 0)); #else astroidsPosition.push_back({randomy() % 20,0}); #endif // _MSC_VER } } public: Astroids() { difficulty = 1; seed = 1234; } void increaseDifficulty() { ++difficulty; } size_t getDifficulty() const { return difficulty; } void moveForward() { generateNewAstroids(); for(vector<Point>::iterator it = astroidsPosition.begin(); it != astroidsPosition.end();) { if(++it->y > 20) it = astroidsPosition.erase(it); else ++it; } } vector<Point> getAstroidPosition() const { return astroidsPosition; } }; class SpaceField { private: char spaceField[20][20]; SpaceShip *spaceShip; Astroids astroids; Point lastShipPosition; void init() { for(size_t y = 0; y < 20; ++y) for(size_t x = 0; x < 20; ++x) spaceField[x][y] = '_'; } void updateField() { init(); spaceField[lastShipPosition.y][lastShipPosition.x] = 'S'; vector<Point> astroPoints = astroids.getAstroidPosition(); for(size_t i = 0; i < astroPoints.size(); ++i) spaceField[astroPoints[i].y-1][astroPoints[i].x] = 'A'; } public: SpaceField() { init(); } void insertShip(SpaceShip *ship) { spaceShip = ship; spaceField[spaceShip->getPosition().y][spaceShip->getPosition().x] = 'S'; lastShipPosition = spaceShip->getPosition(); } void increaseLevel() { astroids.increaseDifficulty(); } bool isAstroidHere(Point checkPoint) const { return spaceField[checkPoint.y][checkPoint.x] == 'A'; } size_t getLevel() const { return astroids.getDifficulty(); } size_t getSizeY() const { return 20-1; } size_t getSizeX() const { return 20-1; } void moveShip(Point to) { if(spaceField[lastShipPosition.y][lastShipPosition.x] != 'A') spaceField[lastShipPosition.y][lastShipPosition.x] = '_'; if(spaceField[to.y][to.x] == 'A') { spaceShip->destroy(); return; } spaceField[to.y][to.x] = 'S'; lastShipPosition = to; } void moveAstroidsForward() { astroids.moveForward(); updateField(); } void printField() const { #ifdef WIN32 system("cls"); // clears windows console #else cout << "\x1b[2J\x1b[H" << flush; // clears linux terminal #endif // WIN32 for(size_t y = 0; y < 20; ++y) { for(size_t x = 0; x < 20; ++x) cout << spaceField[y][x]; cout << endl; } cout << endl; } }; void SpaceShip::doMove(SpaceField &field) { moveDone = false; computeNextMove(field); field.moveShip(position); } class CustomSpaceShip : public SpaceShip { public: void computeNextMove(const SpaceField &field) { Point checkPoint = this->getPosition(); --checkPoint.y; if(field.isAstroidHere(checkPoint)) if(field.getSizeX() > checkPoint.x) this->moveRight(); else this->moveLeft(); } }; int main() { SpaceField spaceField; std::shared_ptr<SpaceShip> ship(new CustomSpaceShip()); spaceField.insertShip(ship.get()); long cycles = 0; while(ship->isAlive()) { ++cycles; spaceField.printField(); spaceField.moveAstroidsForward(); ship->doMove(spaceField); if(cycles % 10 == false) spaceField.increaseLevel(); cout << cycles << " light years survived" << endl; cout << "Level" << spaceField.getLevel() << endl; #ifdef WIN32 Sleep(100); #else sleep(1); #endif // WIN32 } cout << "\nYou survived " << cycles << " light years far!" << endl; return 0; }
- memory leak geschlossen
-
Skym0sh0 schrieb:
so, auf visual c++ portiert(so dass es läuft), aber hab keinen anderen compiler, daher kann ichd a nix sagen
Hab Deinen Code umgefrickelt, daß die Plattformabhängigkeiten aus dem Haupt-Code raus sind.
Aber wieder mit gcc unter linux.
Gehts noch unter visual c++?#include <iostream> #include <vector> #include <cstdlib> #include <ctime> #include <memory> using namespace std; #ifdef WIN32 #include <Windows.h> void sleep(int seconds) { Sleep(1000*seconds); } void cls() { system("cls"); } #else #include <unistd.h> void cls() { cout << "\x1b[2J\x1b[H" << flush; } #endif // WIN32 struct Point { size_t x, y; Point(size_t x_ = 0, size_t y_ = 0) : x(x_), y(y_) {} }; class SpaceField; class SpaceShip { private: Point position; bool aLive, moveDone; public: SpaceShip() : position(8, 15) , aLive(true), moveDone(false) { } void destroy() { aLive = false; } bool isAlive() const { return aLive; } void doMove(SpaceField &field); virtual void computeNextMove(const SpaceField &field) = 0; void moveRight() { if(moveDone) return; ++position.x; moveDone = true; } void moveLeft() { if(moveDone) return; --position.x; moveDone = true; } void moveUp() { if(moveDone) return; --position.y; moveDone = true; } void moveDown() { if(moveDone) return; ++position.y; moveDone = true; } Point getPosition() const { return position; } }; class Astroids { private: vector<Point> astroidsPosition; size_t difficulty; long seed; long randomy() { return (((seed = seed * 214013L + 2531011L) >> 16) & 0x7fff); } void generateNewAstroids() { if(randomy() % 2 == 0) return; int noOfAstroids = randomy() % (difficulty > 15 ? 15 : difficulty) +1; while(noOfAstroids--) { astroidsPosition.push_back(Point(randomy() % 20, 0)); } } public: Astroids() { difficulty = 1; seed = 1234; } void increaseDifficulty() { ++difficulty; } size_t getDifficulty() const { return difficulty; } void moveForward() { generateNewAstroids(); for(vector<Point>::iterator it = astroidsPosition.begin(); it != astroidsPosition.end();) { if(++it->y > 20) it = astroidsPosition.erase(it); else ++it; } } vector<Point> getAstroidPosition() const { return astroidsPosition; } }; class SpaceField { private: char spaceField[20][20]; SpaceShip *spaceShip; Astroids astroids; Point lastShipPosition; void init() { for(size_t y = 0; y < 20; ++y) for(size_t x = 0; x < 20; ++x) spaceField[x][y] = '_'; } void updateField() { init(); spaceField[lastShipPosition.y][lastShipPosition.x] = 'S'; vector<Point> astroPoints = astroids.getAstroidPosition(); for(size_t i = 0; i < astroPoints.size(); ++i) spaceField[astroPoints[i].y-1][astroPoints[i].x] = 'A'; } public: SpaceField() { init(); } void insertShip(SpaceShip *ship) { spaceShip = ship; spaceField[spaceShip->getPosition().y][spaceShip->getPosition().x] = 'S'; lastShipPosition = spaceShip->getPosition(); } void increaseLevel() { astroids.increaseDifficulty(); } bool isAstroidHere(Point checkPoint) const { return spaceField[checkPoint.y][checkPoint.x] == 'A'; } size_t getLevel() const { return astroids.getDifficulty(); } size_t getSizeY() const { return 20-1; } size_t getSizeX() const { return 20-1; } void moveShip(Point to) { if(spaceField[lastShipPosition.y][lastShipPosition.x] != 'A') spaceField[lastShipPosition.y][lastShipPosition.x] = '_'; if(spaceField[to.y][to.x] == 'A') { spaceShip->destroy(); return; } spaceField[to.y][to.x] = 'S'; lastShipPosition = to; } void moveAstroidsForward() { astroids.moveForward(); updateField(); } void printField() const { cls(); for(size_t y = 0; y < 20; ++y) { for(size_t x = 0; x < 20; ++x) cout << spaceField[y][x]; cout << endl; } cout << endl; } }; void SpaceShip::doMove(SpaceField &field) { moveDone = false; computeNextMove(field); field.moveShip(position); } class CustomSpaceShip : public SpaceShip { public: void computeNextMove(const SpaceField &field) { Point checkPoint = this->getPosition(); --checkPoint.y; if(field.isAstroidHere(checkPoint)){ if(field.getSizeX() > checkPoint.x) this->moveRight(); else this->moveLeft(); } } }; int main() { SpaceField spaceField; std::shared_ptr<SpaceShip> ship(new CustomSpaceShip()); spaceField.insertShip(ship.get()); long cycles = 0; while(ship->isAlive()) { ++cycles; spaceField.printField(); spaceField.moveAstroidsForward(); ship->doMove(spaceField); if(cycles % 10 == false) spaceField.increaseLevel(); cout << cycles << " light years survived" << endl; cout << "Level" << spaceField.getLevel() << endl; sleep(1); } cout << "\nYou survived " << cycles << " light years far!" << endl; return 0; }