Permalänk
Medlem

C++ slumpade tal fungerar inte.

Jag är väldigt ny till c++ (började för en vecka sedan) och jag försöker just nu göra en enkel "stridssimulator" dvs att man har människor och zombies med olika mycket attack och liv och i början får man skriva in hur många människor man vill ha och hur många zombies man vill ha. Sedan kommer programmet att räkna ut vilka som vinner och skriva ut hur många människor och hur många zombies som finns kvar när någon av parterna har "dött".

Men problemet är att jag försöker använda slumpade tal för att människorna eller zombierna bara ska träffa ibland men det verkar inte fungera som det ska.

Om jag till exempel skriver in 500 människor och 2500 zombies så kommer den bara att säga varje gång att zombierna vann och att det finns 2000 zombies kvar när det egentligen borde vara olika resultat varje gång. Med andra ord struntar den i attack och liknande och tar bara antalet zombies - antalet människor.

Det är möjligt att jag missar något enkelt här men jag lyckades inte hitta någon bra förklaring på internet och jag har som sagt bara hållit på i en vecka.

Här är koden. (Förlåt om den är svår att läsa men jag försökte i alla fall göra det enklare genom att lägga till kommentarer).

#include <iostream> #include <random> #include <ctime> using namespace std; int main() { //Anger variablerna för hur många dem är och deras attack och liv. int Humans; int Zombies; int HumanAtack = 100; int HumanHealth = 200; int ZombieAtack = 20; int ZombieHealth = 40; //Anger de slumpmässiga variablerna. mt19937 randomgenerator(time(0)); uniform_int_distribution<int> hitpercenthuman(1, 10); uniform_int_distribution<int> hitpercentzombie(1, 10); //Låter användaren säga hur många människor och zombier det ska vara. cout << "How many humans do you want?" << endl << endl; cin >> Humans; cout << "How many zombies do you want?" << endl << endl; cin >> Zombies; cout << endl; cout << "Battlenoises" << endl << endl; //Loop som går medans människorna eller zombisarna lever. while (Humans && Zombies > 0) { //Väljer ett slumpmässigt tal mellan 1 och 10 och atackerar zombisarna om det blir 5 eller lägre. hitpercenthuman(randomgenerator); if (hitpercenthuman(randomgenerator) <= 5) { HumanAtack - ZombieHealth; } //Väljer ett slumpmässigt tal mellan 1 och 10 och atackerar människorna om det blir 3 eller lägre. hitpercentzombie(randomgenerator); if (hitpercentzombie(randomgenerator) <= 3) { ZombieAtack - HumanHealth; } //Om zombisarnas liv går ner till 0 minskas de med en. if (ZombieHealth == 0); { Zombies--; } //Om människornas liv går ner till 0 minskas de med en. if (HumanHealth == 0); { Humans--; } } //Säger hur många människor och zombies det finns kvar när en av variablerna har dött ut. cout << Humans << endl << endl; cout << Zombies << endl; system("PAUSE"); return(0); }

Jag använder visual studio 2017 community om ni vill veta det.

Permalänk
Medlem

Du kan använda code-taggen för att posta kod.

Det är inget fel i slumptalen så vitt jag kan se, däremot i if-satserna så skriver du enbart ut en sats utan sidoeffekt. Exempel:

if (hitpercenthuman(randomgenerator) <= 5) { HumanAtack - ZombieHealth; // Korrekt syntaktiskt, fast inget händer }

Permalänk
Medlem

@Kotra25:

Här kommer en radda med tips

Tips 1:
Din while loop kör så länge (tal1 && tal2 > 0). Om vi låsas att tal1 är 17 och tal2 är 42 så får vi följande uttryck: 17 och 42 > 0. Detta kanske i svenska låter som det du menar men där lurar man sig, men en dator komma göra såhär: Först kolla om 17 är sant, sen kolla om 42 > 0 är sant. Båda dessa är "sanna" (alla heltal som inte är 0 är sanna i c++).

I det här fallet funkar det dock också att skriva såhär men jag tror du menar tal1 > 0 && tal2 > 0

Tips 2:
Jag tror du har blandat ihop -- operatorn med -. När du tar human-- så är det shorthand för human = human - 1. Om man bara skriver human - 1 så kommer inte antalet människor minska, eller hur? Så när du tar HumanAtack - ZombieHealth; så ändras inget tal, det är faktiskt samma sak som att skriva 60;.

Tips 3:
if (*sant eller falskt uttryck*);{
}
Ska vara:

if (*sant eller falskt uttryck*){
}
Alltså inget semikolon där.

Tips 4:
Variabelnamn brukar man skriva med små bokstäver

Kul program!

Mvh

Permalänk
Medlem
Skrivet av MrDoggo:

Det är inget fel i slumptalen så vitt jag kan se, däremot i if-satserna så skriver du enbart ut en sats utan sidoeffekt.

Ursäkta men vad är en sidoeffekt?

Skrivet av Sensed:

@Kotra25:

Här kommer en radda med tips

Tips 1:
Din while loop kör så länge (tal1 && tal2 > 0). Om vi låsas att tal1 är 17 och tal2 är 42 så får vi följande uttryck: 17 och 42 > 0. Detta kanske i svenska låter som det du menar men där lurar man sig, men en dator komma göra såhär: Först kolla om 17 är sant, sen kolla om 42 > 0 är sant. Båda dessa är "sanna" (alla heltal som inte är 0 är sanna i c++).

I det här fallet funkar det dock också att skriva såhär men jag tror du menar tal1 > 0 && tal2 > 0

Tack jag ska tänka på det nästa gång.

Skrivet av Sensed:

Tips 2:
Jag tror du har blandat ihop -- operatorn med -. När du tar human-- så är det shorthand för human = human - 1. Om man bara skriver human - 1 så kommer inte antalet människor minska, eller hur? Så när du tar HumanAtack - ZombieHealth; så ändras inget tal, det är faktiskt samma sak som att skriva 60;.

Nu förstår jag fortfarande inte riktigt, ska jag skriva HumanAtack = ZombieHealth - HumanAtack;?

Skrivet av Sensed:

Tips 3:
if (*sant eller falskt uttryck*);{
}
Ska vara:

if (*sant eller falskt uttryck*){
}
Alltså inget semikolon där.

Spelar det någon roll eller är det bara för att göra koden snygg?

Skrivet av Sensed:

Tips 4:
Variabelnamn brukar man skriva med små bokstäver

Kul program!

Då vet jag det till nästa gång, och tyvär var det inte jag som kom på idén med programmet.

Men tack för all hjälp, mycket uppskattat

Permalänk
Medlem
Skrivet av Kotra25:

Ursäkta men vad är en sidoeffekt?

Tack jag ska tänka på det nästa gång.

Nu förstår jag fortfarande inte riktigt, ska jag skriva HumanAtack = ZombieHealth - HumanAtack;?

Spelar det någon roll eller är det bara för att göra koden snygg?

Då vet jag det till nästa gång, och tyvär var det inte jag som kom på idén med programmet.

Men tack för all hjälp, mycket uppskattat

Det spelar roll då du avslutar if-satsen utan någon åtgärd.

Visa signatur

OS: MacOS/ Windows 10 Pro 64-bit MB: ASUS-Z97-A CPU: i7 4790k
NÄTAGG: EVGA SUPERNOVA G2
RAM: 32768 MiB GPU: 1070 FTW Chassi: Fractal Design R4
MBP 13" i5 | 256GB | 16GB RAM | MID 2014

Permalänk
Medlem

@N0iZE så med andra ord så går variabeln aldrig -1 för att jag avslutar innan den gör någonting?

Permalänk
Medlem
Skrivet av Kotra25:

@N0iZE så med andra ord så går variabeln aldrig -1 för att jag avslutar innan den gör någonting?

Såsom du har kodat, kommer uttrycket inom if-satsen kollas om den är sann och sedan avslutas. Det betyder att kodblocket efter kommer exekveras oavsett om villkoret var uppfyllt. Skriver du som på "rätt" sätt (föreslaget i tråden innan), kommer kodblocket efter if-satsen endast exekveras om villkoret är uppfyllt.

Visa signatur

OS: MacOS/ Windows 10 Pro 64-bit MB: ASUS-Z97-A CPU: i7 4790k
NÄTAGG: EVGA SUPERNOVA G2
RAM: 32768 MiB GPU: 1070 FTW Chassi: Fractal Design R4
MBP 13" i5 | 256GB | 16GB RAM | MID 2014

Permalänk
Medlem

Nu har jag ändrat koden så att den ser ut i alla fall som jag tror att ni menade men jag märkte att så fort jag tog bort mina semikolon i if satsen så slutade den skriva någonting alls. Nu stannar den bara på "battlenoises" och sedan gör den inget mer.

Detta förstår jag mig inte på, den borde väl bara utföra if satsen nu istället för att frysa. Jag provade att använda all kod som den var förut och bara ta bort de två semikolonen i slutet, så jag vet att det är dem som är problemet.

Min kod ser u så här nu i alla fall:

#include <iostream> #include <random> #include <ctime> using namespace std; int main() { //Anger variablerna för hur många dem är och deras atack och liv. int Humans; int Zombies; int HumanAtack = 100; int HumanHealth = 200; int ZombieAtack = 20; int ZombieHealth = 40; //Anger de slumpmässiga variablerna. mt19937 randomgenerator(time(0)); uniform_int_distribution<int> hitpercenthuman(1, 10); uniform_int_distribution<int> hitpercentzombie(1, 10); //Låter användaren säga hur många människor och zombier det ska vara. cout << "How many humans do you want?" << endl << endl; cin >> Humans; cout << "How many zombies do you want?" << endl << endl; cin >> Zombies; cout << endl; cout << "Battlenoises" << endl << endl; //Loop som går medans människorna eller zombisarna lever. while (Humans && Zombies > 0) { //Väljer ett slumpmässigt tal mellan 1 och 10 och atackerar zombisarna om det blir 5 eller lägre. hitpercenthuman(randomgenerator); if (hitpercenthuman(randomgenerator) <= 5) { ZombieHealth = HumanAtack - ZombieHealth; } //Väljer ett slumpmässigt tal mellan 1 och 10 och atackerar människorna om det blir 3 eller lägre. hitpercentzombie(randomgenerator); if (hitpercentzombie(randomgenerator) <= 3) { HumanHealth = ZombieAtack - HumanHealth; } //Om zombisarnas liv går ner till 0 minskas de med en. if (ZombieHealth == 0) { Zombies--; } //Om människornas liv går ner till 0 minskas de med en. if (HumanHealth == 0) { Humans--; } } //Säger hur många människor och zombies det finns kvar när en av variablerna har dött ut. cout << Humans << endl << endl; cout << Zombies << endl; system("PAUSE"); return(0); }

Permalänk
Medlem

@Kotra25: Här är lite kommentarer på din huvudloop, se kommentarer i koden:

// Detta borde som sagt vara: // while (Humans > 0 && Zombies > 0) // Det råkar fungera ändå i detta fall, men du bör lära dig att använda && korrekt. while (Humans && Zombies > 0) { // Detta slumpar fram ett tal, men gör ingenting med det. hitpercenthuman(randomgenerator); // Detta slumpar fram *ett nytt* tal, så raden ovan kan tas bort om du inte av någon anledning // bara vill använda vartannat slumptal. if (hitpercenthuman(randomgenerator) <= 5) { // Jag antar att du egentligen vill dra bort HumanAtack från ZombieHealth, då borde det vara: // ZombieHealth = ZombieHealth - HumanAtack; // Eller kortformen: // ZombieHealth -= HumanAtack; ZombieHealth = HumanAtack - ZombieHealth; } // Samma som ovan. hitpercentzombie(randomgenerator); if (hitpercentzombie(randomgenerator) <= 3) { HumanHealth = ZombieAtack - HumanHealth; } // Detta kommer bara trigga om ZombieHealth är *exakt* 0. // ZombieHealth är 40 och HumanAtack är 100, så ZombieHealth kommer aldrig bli exakt 0. // Använd <= 0 istället för att även trigga när ZombieHealth blir negativ. if (ZombieHealth == 0) { Zombies--; } // Samma som ovan. if (HumanHealth == 0) { Humans--; } }

Sen vet jag inte hur du tänkt hantera "overkill". En människoattack är just nu nog för att döda 2.5 zombies, men enligt koden kan aldrig mer än en zombie i taget dö. Men det är väl något du får fundera på när du fått koden att fungera som den är nu.

Permalänk
Medlem
Skrivet av perost:

@Kotra25: Här är lite kommentarer på din huvudloop, se kommentarer i koden:

// Detta borde som sagt vara: // while (Humans > 0 && Zombies > 0) // Det råkar fungera ändå i detta fall, men du bör lära dig att använda && korrekt. while (Humans && Zombies > 0) { // Detta slumpar fram ett tal, men gör ingenting med det. hitpercenthuman(randomgenerator); // Detta slumpar fram *ett nytt* tal, så raden ovan kan tas bort om du inte av någon anledning // bara vill använda vartannat slumptal. if (hitpercenthuman(randomgenerator) <= 5) { // Jag antar att du egentligen vill dra bort HumanAtack från ZombieHealth, då borde det vara: // ZombieHealth = ZombieHealth - HumanAtack; // Eller kortformen: // ZombieHealth -= HumanAtack; ZombieHealth = HumanAtack - ZombieHealth; } // Samma som ovan. hitpercentzombie(randomgenerator); if (hitpercentzombie(randomgenerator) <= 3) { HumanHealth = ZombieAtack - HumanHealth; } // Detta kommer bara trigga om ZombieHealth är *exakt* 0. // ZombieHealth är 40 och HumanAtack är 100, så ZombieHealth kommer aldrig bli exakt 0. // Använd <= 0 istället för att även trigga när ZombieHealth blir negativ. if (ZombieHealth == 0) { Zombies--; } // Samma som ovan. if (HumanHealth == 0) { Humans--; } }

Sen vet jag inte hur du tänkt hantera "overkill". En människoattack är just nu nog för att döda 2.5 zombies, men enligt koden kan aldrig mer än en zombie i taget dö. Men det är väl något du får fundera på när du fått koden att fungera som den är nu.

Tack! Jag fick programmet att fungera nu.

Och angående overkill så var planen från början att ha någon form av en defense så att man ibland ska kunna blocka en attack men att människorna ändå ska kunna attackera så jag antar att det blir det jag gör näst på tur.