|
| Författare | Meddelande |
|---|
Johan
Antal inlägg: 47 Join date: 08-09-03
 | Rubrik: Uppg 6 - Köapplikation fre okt 17, 2008 10:11 am | |
| Uppgift 6 – Köapplikation ------------------------------------ Nedan följer ett exempel på hur man kan göra ett kösystem. Jag har utgått helt från filerna till uppgift 3 (fightsimulatorn). Man kan lägga till nya bots längst bak i kön eller låta de två bots som är längst fram slåss. Vinnaren läggs sedan längst bak i kön igen och förloraren tas bort ur kön helt. Filerna ”globals.h”, Weapon.h” och ”Weapon.cpp” är exakt lika dana som tidigare. Vissa ändringar är gjorda i ”Fighter.h” och ”Fighter.cpp” och en helt ny klass ”FighterQueue” är ditlagd. ”main.cpp” är förståss helt omgjord. Som vanligt vill jag inte att ni bara kopierar min kod rakt upp och ned. Försök sätta er in i koden och förstå hur den är uppbyggd. Inlämningar som ser ruskigt likt min kod ut kommer att behöva extra genomgång muntligt. Jag tipsar också igen om att plocka in min kod i ett annat program som kan highlighta koden bättre. (tex. notepad++ eller CodeBlocks) Fel och buggar: --------------------- Jag har lagt in två medvetna fel. Svara nedan om du hittar ett fel och vinn äran. Den som hittar fel eller buggar som jag inte lagt dit medvetet förtjänar desto mer ära. Lycka till!
Senast ändrad av Johan den fre okt 17, 2008 10:52 am, ändrad totalt 1 gång |
|
 | |
Johan
Antal inlägg: 47 Join date: 08-09-03
 | Rubrik: Re: Uppg 6 - Köapplikation fre okt 17, 2008 10:15 am | |
| Jag börjar med de filer som är exakt lika dana som förut. globals.h är precis lika dant som tigigare. | Kod: | //ifndef och define gör det lättare att kompilera projektet om man har fler includes av denna fil #ifndef GLOBALS_H_INCLUDED #define GLOBALS_H_INCLUDED
//Includes #include <time.h>
//Om man skapar en onämnd namespace såhär, så kan man använda globala funktioner i alla andra filer som inkluderar "globals.h" namespace{
//Tärningsfunktionen. Returnerar en framslumpad siffra mellan min- och max-värdet. int dice(int min, int max){ int diceVal = rand() % (max - min +1) + min; return diceVal; } }
#endif //#ifndef GLOBALS_H_INCLUDED
|
|
|
 | |
Johan
Antal inlägg: 47 Join date: 08-09-03
 | Rubrik: Re: Uppg 6 - Köapplikation fre okt 17, 2008 10:17 am | |
| Weapon.h har inte fått någonting ändrat i sig. Den är precis som förut.' | Kod: | //Weapon.h //--------------
//Om man använder MS Visual Studio kan man bara skriva #pragma once istället för #ifndef osv. #pragma once
//Includes #include <iostream> #include <string>
using namespace std;
//Definition av klassen Weapon. Alla fighters ska bära ett vapen. class Weapon{ private: string name; //Vapnets namn int dam; //Vapnets skada string attackMess; //Meddelande som skrivs ut när vapnet används
public: Weapon(void); //Konstruktor //GET-funktioner string getAttack(void){return attackMess;} int getDam(void){return dam;} string getName(void){return name;} //Andra funktioner void print(void); // Skriver ut vapnets värden.
}; //Glöm inte ;
|
|
|
 | |
Johan
Antal inlägg: 47 Join date: 08-09-03
 | Rubrik: Re: Uppg 6 - Köapplikation fre okt 17, 2008 10:19 am | |
| Weapon.cpp är precis som förut. | Kod: | //Weapon.cpp //----------------
//Includes systemfiler #include <iostream> #include <string>
//Includes egna filer #include "globals.h" #include "Weapon.h"
using namespace std;
//I konstruktorn slumpar vi fram ett fördefinierat vapen. //Dam-värdet slumpas ut mellan olika parametrar beroende på vilket vapen det blev. //Notera att jag använt en Switch, (en variant av en if-sats), och att dam-värdet bara slumpas ut i konstruktorn. I mitt spel är skadan ett konstant värde sedan det väl fått sin siffra. Weapon::Weapon(void){ switch (dice(0,10)) { case 1: this->name = "Tiny Knife"; this->dam = dice(10,20); this->attackMess = " carefully swings a "; break; case 2: this->name = "Hammer of Judgement"; this->dam = dice(50,200); this->attackMess = " uses the powerfull "; break; case 3: this->name = "Fire Ball"; this->dam = dice(100,300); this->attackMess = " magically steers a "; break; case 4: this->name = "Love Bite"; this->dam = dice(1,1000); this->attackMess = " has love in the eyes and gives out a "; break; case 5: this->name = "Wierd Thing"; this->dam = dice(50,750); this->attackMess = " swigingy swoops the shweetness with a "; break; case 6: this->name = "Sword of Lightning"; this->dam = dice(500,100); this->attackMess = " flashes with a "; break; case 7: this->name = "Massive Destruction"; this->dam = dice(1000,2000); this->attackMess = "unleashes the power of "; break; case 8: this->name = "Handy Mace"; this->dam = dice(30,100); this->attackMess = " swings the "; break; case 9: this->name = "Simple Sword"; this->dam = dice(40,150); this->attackMess = " is wishwasing around with a "; break; case 10: this->name = "Ice Bolt"; this->dam = dice(200,400); this->attackMess = " summons a freezing "; break; default: this->name = "Weaponless Fist"; this->dam = dice(5,20); this->attackMess = " gives a nice punch with a "; break; }
}
//Skriv ut vapnets namn och dam-värde. void Weapon::print(void){ cout << name << " (dam: " << dam << ")"; }
|
|
|
 | |
Johan
Antal inlägg: 47 Join date: 08-09-03
 | Rubrik: Re: Uppg 6 - Köapplikation fre okt 17, 2008 10:21 am | |
| -------------------------------------- Nedan följer filer som jag har gjort ändringar i. Jag har lagt in "//nytt" på de ställen i Fighter.h som jag gjort ändringar i. | Kod: | //Fighter.h //----------------
//ifndef och define gör det lättare att kompilera projektet om man har fler includes av denna fil #ifndef FIGHTER_H_INCLUDED #define FIGHTER_H_INCLUDED
//Includes #include <iostream> #include <string> #include "Weapon.h"
using namespace std;
//Fighter -definitionen. class Fighter{ private: string name; //Fighterns namn int hp; //Fighterns hälsa. Om hp blir noll så ska Fightern dö. int skill; //Färdighetsvärdet. Hur duktig Fightern är på att slåss. Weapon weapon; //Vapnet som Fightern "har". //nytt Fighter* next; //Pekar på nästa i listan
public: Fighter(string n); //konstruktor //GET-funktioner int getHp(void){return hp;} string getName(void){return this->name;} //nytt Fighter* getNext(void){return this->next;}
//SET-funktioner void death(void){hp=0;}//Dödar Fightern //nytt void setNext(Fighter* n){next = n;}
//Andra funktioner void print(void); //skriver ut alla fighterns värden void attack(Fighter * enemy); //attackerar en fiende void damage(int dam); //tar skada från fienden
//nytt void deleteQ(void); //Används när man vill tömma listan helt.
}; //glöm inte ;
//avsluta ifndef (glöm inte att tala om hur den såg ut i början på filen. Det anses vara snyggare kod.) #endif //#ifndef FIGHTER_H_INCLUDED
|
Senast ändrad av Johan den mån okt 20, 2008 3:53 am, ändrad totalt 1 gång |
|
 | |
Johan
Antal inlägg: 47 Join date: 08-09-03
 | Rubrik: Re: Uppg 6 - Köapplikation fre okt 17, 2008 10:23 am | |
| "//NYTT" indikerar ändringar som är gjorda i Fighter.cpp | Kod: | //Fighter.cpp //----------------
//Includes systemfiler #include <iostream> #include <string>
//Includes egna filer #include "globals.h" #include "Fighter.h" #include "Weapon.h"
using namespace std;
//Konstruktor Fighter::Fighter(string n){ this->name = n; this->hp = dice(3000,5000); //Slumpa fram Fighterns hp this->skill = dice(20,80); //Slumpa fram Fighterns färdighetsvärde
//NYTT i konstruktorn //------------------ this->next = NULL; //Sätt nästa till NULL
cout << "Creating fighter:\n"; print(); cout << endl; //------------------ }
//Andra metoder //-----------------
//Skriver ut fighterns alla värden void Fighter::print(void){ cout << name << endl; cout << "HP: " << hp << endl; cout << "Skill:" << skill << endl; cout << "Weapon: "; weapon.print(); //Anropa vapnets print() funktion. dvs. skriv ut vilket vapen Fightern har }
//Attackerar en fiende. Notera att enemy är en penkare och att vi i main skickat med en adress. void Fighter::attack(Fighter * enemy){ //Kolla ifall resultatet på en D100 (framslumpat tal mellan 1-100) är mindre än färdighetsvärdet if(dice(1,100) <= skill){ //I så fall: Skriv ut attacken.. cout << name << " " << weapon.getAttack() << " " << weapon.getName() << ".\n"; cout << enemy->getName() << " looses " << weapon.getDam() << " HP.\n"; enemy->damage(enemy.getDam()); // ..och dra av Fighterns vapens dam-värde på fiendens hp. }else{ //Om D100 bler högre än färdighetsvärdet: Skriv ut att han har missat. cout << name << " misses.\n"; } }
//Låter fightern ta skada från fiendens attack void Fighter::damage(int dam){ hp -= dam; }
//NYTT //Rekurserar igenom kön och tar bort alla Fighters void Fighter::deleteQ(void){ cout << "\nDeleting " << name;
//Kontrollera att next inte är NULL if (this->next){ //Om det finns en next: rekursera funktionen dit, så att den tas bort. this->next->deleteQ(); }else{ //Om det inte finns så är vi längst bak i listan. cout << "\nEnd of list."; } delete this; }
|
|
|
 | |
Johan
Antal inlägg: 47 Join date: 08-09-03
 | Rubrik: Re: Uppg 6 - Köapplikation fre okt 17, 2008 10:26 am | |
| Klassen FighterQueue är helt ny. Läs och begrunda. Jag har lagt FighterQueue's metod-definitioner i samma fil, så det blir ingen FighterQueue.cpp sen. Det blir ganska massivt med kod på en gång. Så, här kan det ha varit smartare att dela upp klassen i fler filer. | Kod: | //FighterQueue.h //----------------------
#pragma once //gör så att h.filen bara kan inkluderas en gång
//Includes #include <iostream> #include <string> #include "Fighter.h" //Eftersom FighterQueue har en fighterpekare måste vi inkludera Fighter.h
using namespace std;
//Klassen FighterQueue blir som en "paraplyklass" eller vad man vill kalla det. Den innehåller en pekare till den som är först i kön, men även appendfunktionen och lite annat. //Andra saker som man kan tänka sig att man skulle vilja att denna klass höll reda på, även om jag inte gör det i detta exempel, kan t.ex. vara en pekare som pekar på sista fightern i kön eller hur många fighters som finns i kön. class FighterQueue{ private: Fighter* firstFighter; //Ska peka på den första Fightern i kön. (Ändras när en duell är avklarad)
public: FighterQueue(){this->firstFighter = NULL;} //Konstruktor, sätter firstFighter till NULL.. dvs.. vi har inga fighters i kön till at börja med. void printQueue(void); //Skriver ut hela kön på skärmen void deleteQueue(void); //Tar bort alla Fighters i kön void append(Fighter* newFighter); //Lägg till en ny Fighter längst bak i kön void fight(void); //Låter de två främsta Fighters duellera varandra och slåss tills en eller båda har dött. };
//deleteQueue() //Tar bort alla Fighters i kön. //Eftersom vi vill kunna ta bort enstaka objekt efter en duell, vill vi inte använda den rekursiva destruktorn som vi använt tidigare. En egen metod för at ta rensa upp listan innan avslut av programmet får användas. void FighterQueue::deleteQueue(void){ cout << "\nDeleting Queue:"
//Kontrollera att listan inte är tom if (this->firstFighter){ //Om det finns nåt i listan: Loopa igenom listan och ta bort det. firstFighter->deleteQ(); //Notera här att jag lagt till en deleteQ metod i Fighter-klassen }else{ //Om det inte finns så är vi längst bak i listan. cout << "\nQueue is empty."; }//if }
//append() //Lägger till en ny Fighter längst bak i kön void FighterQueue::append(Fighter* newFighter){ //Kontrollera ifall det finns nåt i listan eller om den är tom if (firstFighter == NULL){ //Om listan är tom: Låt den nya, medskickade, fightern bli den första i listan. firstFighter = newFighter; }else{ //Annars(dvs. om listan redan innehåller något): Fighter* marker = firstFighter; //Skapa en markör(en pekare som kan "markera" objekt i minnet) //Loopa igenom listan while(marker->getNext()){ marker = marker->getNext(); } //När marker är längst bak i listan lägger vi den nya, medskickade, Fightern efter marker i kön. marker->setNext(newFighter); }//if }
//printQueue() //Skriver ut hela kön på skärmen void FighterQueue::printQueue(void){ //Kontrollera ifall det finns nåt i listan eller om den är tom if (firstFighter == NULL){ //Om listan är tom: tala om för användaren att så är läget. cout << "\nNo Fighters in queue.\n"; }else{ //Annars(dvs. om listan redan innehåller något): Loopa igenom listan och skriv ut alla Fighters. cout << "\nQueue of Fighters:\n"; int i = 1;//en liten variabel håller koll på hur många loopar som görs //Loopa igenom listan, den här gången med en for-loop (gämför med en while-loop) for(Fighter* marker = firstFighter ; marker != NULL ; marker = marker->getNext()){ //skriv ut den markerade Fightern cout << "\nNr " << i << ":\n"; marker->print(); cout << endl; i++;//öka på variabeln som håller koll på hur många loopar som görs. }//for }//if }
//fight() //Låter de två främsta Fighters duellera varandra och slåss tills en eller båda har dött. void FighterQueue::fight(void){ //Kontrollera ifall det finns nåt i listan if (firstFighter == NULL){ //Om listan är tom: Skriv ut felmeddelande cout << "\nNo Fighters in queue.\n"; }else if (firstFighter->getNext() == NULL){ //Om listan bara innehåller EN Fighter: Skriv ut felmeddelande cout << "\nNot enough Fighters in the queue. There needs to be two of them you know.\n"; }else{ //Om listan inte är tom:
//Här har jag koperat in den gammla fight-loopen från Fight-bot-uppgiften och gjort om den lite :)
//Skapa två Fighterpekare och ställ in dem på att peka på de två första Fighters i listan. Fighter* bot1 = firstFighter; Fighter* bot2 = firstFighter->getNext();
//Fight-loop bool fight=1; while(fight){ //Skriv ut bottarnas hp-värden cout << bot1->getName() << endl << "HP: " << bot1->getHp() << "\n\n"; cout << bot2->getName() << endl << "HP: " << bot2->getHp() << "\n\n"; Sleep(1000); //Stanna upp programmet i 1 sekund //Låt bottarna attakera varandra. bot1->attack(bot2); Sleep(500); bot2->attack(bot1); Sleep(1000); cout << endl; //Kontrollera ifall BÅDA har dött. if (bot1->getHp() < 0 && bot2->getHp() < 0){ //I så fall: Nollställ hp-värdena.. bot1->death(); bot2->death(); //.. skriv ut bottarnas hp... cout << bot1->getName() << endl << "HP: " << bot1->getHp() << "\n\n"; cout << bot2->getName() << endl << "HP: " << bot2->getHp() << "\n\n"; Sleep(4000); //.. och rapportera resultat. cout << "\n\nBoth fighters are dead."; Sleep(2000);
firstFighter = bot2->getNext(); //Ställ om firtsFighter så att den pekar på rätt Fighter i listan. Den som stod efter bot2 ska nu bli först i kön. //Ta bort båda Fighterena. delete bot1; delete bot2; //Stäng till sist av loopen. fight=0;
//Om inte båda har dött, kanske bara en av dem har dött. //Har bot1 dött? }else if (bot1->getHp() < 0){ bot1->death(); cout << bot1->getName() << endl << "HP: " << bot1->getHp() << "\n\n"; cout << bot2->getName() << endl << "HP: " << bot2->getHp() << "\n\n"; Sleep(2000); cout << "\n\n" << bot1->getName() << " is dead. " << bot2->getName() << " wins the fight and is put in the back of the queue.\n"; //Ställ om firtsFighter så att den pekar på rätt Fighter i listan. Den som stod efter bot2 ska nu bli först i kön. firstFighter = bot2->getNext(); //Ta bort bot1 som dog delete bot1; //Lägg bot2 längts bak i litsan igen. bot2->setNext(NULL); //Glöm inte att den nu ska ha sin next satt till NULL. Den ska ju vara längst bak. this->append(bot2);
Sleep(2000); fight=0; //Har bot2 dött? }else if (bot2->getHp() < 0){ bot2->death(); cout << bot1->getName() << endl << "HP: " << bot1->getHp() << "\n\n"; cout << bot2->getName() << endl << "HP: " << bot2->getHp() << "\n\n"; Sleep(4000); cout << "\n\n" << bot2->getName() << " is dead. " << bot1->getName() << " wins the fight and is put in the back of the queue.\n"; firstFighter = bot2->getNext(); delete bot2; bot1->setNext(NULL); this->append(bot1); Sleep(2000); fight=0; }//if }//while }//if }
|
Senast ändrad av Johan den mån okt 20, 2008 3:54 am, ändrad totalt 2 gånger |
|
 | |
Johan
Antal inlägg: 47 Join date: 08-09-03
 | Rubrik: Re: Uppg 6 - Köapplikation fre okt 17, 2008 10:31 am | |
| Sist men inte minst... | Kod: | //main.cpp //-------------------
//Includes systemfiler #include <iostream> //för cout, cin, mm. #include <string> //för string #include <conio.h> //för getch() #include <time.h> //för srand() och rand() #include <windows.h> //för sleep() och system()
//Includes egna filer #include "Fighter.h" #include "FighterQueue.h"
using namespace std;
//MAIN //------------- int main(){ // Hämta en seed från datorns klocka. //(Behövs för att vi ska kunna slumpa nya tal varje gång programmet körs.) srand ((unsigned)time(NULL) );
FighterQueue queue; //kö-objektet. Från detta objket kan vi nå elementen i kön. string command; //Spelarens kommando //INTRO cout << "Welcome to the Great Arena of Fighters!\n" << "-----------------------------------------\n\n";
cout << "Available commands:\n"; cout << "new - to add a new fighter to the queue\n"; cout << "fight - to let the 2 first fighters fight to the death\n"; cout << "print - to see the entire queue\n"; cout << "help - to see a list of the available commands\n"; cout << "quit - to exit the game\n"; //GAME-LOOP bool game = 1; while (game){ //Hämta in kommando cout << "\nWhat is your command?\n>"; cin >> command; //Kontrollera vilket kommando som spelaren angivit if (command == "new"){ //Om spelaren vill lägga till en ny Fighter i kön: //Hämta in namn på den nya fightern cout << "What is the new fighter's name?\n>"; cin >> command; //Lägg till den längst bak i kön. queue.append(new Fighter(command));
}else if (command == "fight"){ //Om spelaren vill att de två första i kön ska slåss:
//Anropa queue's funktion för det queue.fight();
}else if (command == "print"){ //Om spelaren vill skriva ut hela kön på skärmen:
//Anropa queue's funktion för det queue.printQueue();
}else if (command == "help"){ //Om spelaren vill veta vilka kommandon den kan använda: cout << "Available commands:\n"; cout << "new - to add a new fighter to the queue\n"; cout << "fight - to let the 2 first fighters fight to the death\n"; cout << "print - to see the entire queue\n"; cout << "help - to see a list of the available commands\n"; cout << "quit - to exit the game\n"; }else if (command == "quit"){ //Om spelaren vill stänga av spelet:
cout << "\nThank you for playing!\n"; game=0; //Avbryt loopen
}else{ //Om spelaren skriver in någonting annat obegripligt: cout << "No such command. Type \"help\" to get a list of available commands.\n"; } } //AVSLUT queue.deleteQueue(); //Ta bort alla objekt som vi lagt i kön. cout << "\nPress any button to quit."; _getch();
return 0; }
|
|
|
 | |
Becca
Antal inlägg: 10 Join date: 08-09-01
 | Rubrik: Re: Uppg 6 - Köapplikation tor okt 30, 2008 3:50 pm | |
| I fighter.h filen: void setNext(Fighter* n){next=n;} borde det inte vara this->next = n? |
|
 | |
eliasandersen
Antal inlägg: 5 Join date: 08-09-01 Age: 18
 | Rubrik: Re: Uppg 6 - Köapplikation tor okt 30, 2008 9:43 pm | |
| | Becca skrev: | I fighter.h filen:
void setNext(Fighter* n){next=n;}
borde det inte vara this->next = n? |
Borde inte spela nån roll |
|
 | |
Becca
Antal inlägg: 10 Join date: 08-09-01
 | Rubrik: Re: Uppg 6 - Köapplikation fre okt 31, 2008 3:05 pm | |
| | Kod: | void FighterQueue::deleteQueue(void){ cout << "\nDeleting Queue:" |
Fel 1. Inget semikolon eller endl + semikolon efter den här couten i FighterQueue.h |
|
 | |
Johan
Antal inlägg: 47 Join date: 08-09-03
 | Rubrik: Re: Uppg 6 - Köapplikation mån nov 03, 2008 3:41 pm | |
| | Becca skrev: | | Kod: | void FighterQueue::deleteQueue(void){ cout << "\nDeleting Queue:" |
Fel 1. Inget semikolon eller endl + semikolon efter den här couten i FighterQueue.h |
Yesss! .. Becca var först med att hitta ett av mina medvetna fel. Ära går till Becca! 
...
Nu är frågan: Vem kommer att hitta det andra felet? |
|
 | |
|