niejasny blad w dzialaniu programu

0

od niedawna zaczalem pisac w c++;
moje umiejetnosci sa na poziomie level 2 ~ noob
wiec prosze o wyrozumienie gdyby okazalo sie ze nie zauwazylem smiesznie prostego bledu;
program pokazany ponizej mial na celu wylosowac trzy niepowtarzalne pytania (z naciskiem na "niepowtarzalne"),
ale zamiast tego program wywala czesto w losowym momencie a dwa pierwsze pytania sie za kazdym razem powtarzaja;

#include <iostream>
#include <time.h>
#include <windows.h>

using namespace std;

short l0,l1[3],l2,l3;
string n0;
void pytania();
short los_bez_powt();

int main()
{
	srand(time(NULL));
	l0=los_bez_powt();
	pytania();
	l0=los_bez_powt();
	pytania();
	l0=los_bez_powt();
	pytania();
	cout <<"Zdobyles: "<<l3<<" puntkow";
	
}

short los_bez_powt()
{
	for (int i;i<=0;)
	{
		l2=rand()%3+1;
		if ((l2!=l1[0]&&l2!=l1[1]&&l2!=l1[2]))
		{
			i+=1;
			return l2;
		}
    }
}

void pytania()
{
	switch (l0)
	{
		case 1: cout << "Ile skrzydel ma ptak?: ";
		        cin>>n0;
		        if (n0=="2")
		        {
		        	cout<< "Poprawna odpowiedz - zdobywasz 1 punkt" <<endl;
		        	l1[0]+=1;
		        	l3+=1;
		        	break;
				}
				else
				{
					cout<< "bledna odpowiedz - brak puntku" <<endl;
					l1[0]+=1;
					break;
				}
		case 2: cout << "Ile jest palcow u jednej dloni czlowieka?: ";
		        cin>>n0;
		        if (n0=="5")
		        {
		        	cout<< "Poprawna odpowiedz - zdobywasz 1 punkt"<<endl;
		        	l1[1]+=2;
		        	l3+=1;
		        	break;
				}
				else
				{
					cout<< "bledna odpowiedz - brak puntku"<<endl;
					l1[1]+=2;
					break;
				}
		case 3: cout << "Ile nog ma pajak?: ";
		        cin>>n0;
		        if (n0=="8")
		        {
		        	cout << "Poprawna odpowiedz - zdobywasz 1 punkt"<<endl;
		        	l1[2]+=3;
		        	l3+=1;
		        	break;
				}
				else
				{
					cout<< "bledna odpowiedz - brak puntku"<<endl;
					l1[2]+=3;
					break;
				}
				default: break;	
	}
}

ale to ze nie dziala nie jest najciekawsze(...) najciekawszym jest za to to ze jesli usune void pytania(); oraz kod z void pytania(); wkleje do
int main() na miejsce pytania() (czyli wkleje ten sam kod 3 razy zamiast tworzyc void pytania) to w magiczny sposob program zaczyna dzialac jak nalezy...
prosze o wyedukowanie mnie jesli komus by sie chcialo

2

ogólnie to wiele rzeczy może tutaj źle działać ;)
Masz np. funkcję short los_bez_powt(), która na pewno nie działa poprawnie: w pętli używasz zmiennej "i" która nie ma podanej wartości początkowej. Dodatkowo jak warunek zostanie spełniony to inkrementujesz tę zmienną, ale zaraz później masz "return", więc nawet nigdzie nie wykorzystasz tej zmienionej wartości. Co do samego warunku, to porównujesz wynik losowania do tablicy, która też nie ma zdefiniowanych wartości, więc raczej też nie może działać dobrze. Może zrób tak: nazwij zmienne tak, żeby ich nazwy mówiły co one dokładnie przechowują i ustaw dla nich wartości początkowe. Następnie też przenieś je do wnętrza funkcji main (raczej nie powinno się używać zmiennych statycznych). Potem jeśli program nie będzie dalej działał to wklej nowy kod, to będziemy myśleć dalej.

2

Tak jak wspomniał @_dominik, nazwy zmiennych muszą mówić co reprezentują bo inaczej czytanie kodu przypomina czytanie hieroglifów.
Zamiast 'l0' to napisz nie wiem, np. 'question_id', albo 'numer_pytania' jeśli po polsku wolisz, czy coś podobnego.
Zacznij od tego.

1
Darek554 napisał(a):

Tak jak wspomniał @_dominik, nazwy zmiennych muszą mówić co reprezentują bo inaczej czytanie kodu przypomina czytanie hieroglifów.
Zamiast 'l0' to napisz nie wiem, np. 'question_id', albo 'numer_pytania' jeśli po polsku wolisz, czy coś podobnego.
Zacznij od tego.

Dodam: zmienne globalne, bleeee
Wystarczy żeby funkcje dostawały argument void pytania(int x), i globalsy mogą zniknąć.

Faktycznie, tego się czytać nie chce.

Edit:
użycie zmiennej indeksowanej ze stałymi jak l1[2]+=3; zwykle oznacza, że powinna być struktura struct z dobrze nazwanymi polami. proponuję powrót do książki, gdzieś blisko pcozątku.
Ta dwójka to w zamyśle autora coś jest, niestety my nie wiemy co

_dominik napisał(a):

ogólnie to wiele rzeczy może tutaj źle działać ;)

Dokładnie.

Edit2: mam takie swoje porzekadło: kod, który jest nieczytelny, jest praktycznie na pewno (wielokrotnie w tym przypadku) błędny

0

Wersja prymitywna:

#include <iostream>
#include <ctime>
using namespace std;

struct data { unsigned answer; const char *ask; }
Data[]=
{
	{ 2,   "Ile skrzydel ma ptak" },
	{ 5,   "Ile jest palcow u jednej dloni czlowieka" },
	{ 8,   "Ile nog ma pajak" },
	{ 101, "Ile programistow treba aby napisac ten program" },
};
const size_t DataSize=sizeof(Data)/sizeof(*Data);
const char *BadGood[]={"Bledna odpowiedz - brak puntku","Poprawna odpowiedz - zdobywasz 1 punkt"};

int main()
{
	srand(time(NULL));
	const size_t count=3;
	size_t ord[DataSize];
	for(size_t i=0;i<DataSize;++i) ord[i]=i;
	size_t goodcount=0;
	for(size_t i=0;i<count;++i)
	{
		size_t p=i+rand()%(DataSize-i);
		size_t swp=ord[i];
		ord[i]=ord[p];
		ord[p]=swp;
		size_t k=ord[i];
		cout<<Data[k].ask<<": ";
		unsigned answer;
        cin>>answer;
        bool goodanswer=(answer==Data[k].answer);
        goodcount+=goodanswer;
		cout<<BadGood[goodanswer]<<endl;
	}
	cout<<"Zdobyles: "<<goodcount<<" puntkow"<<endl;
	return 0;
}

Wersja bardziej sensowna:

#include <iostream>
#include <algorithm>
#include <array>
#include <random>
#include <chrono>
using namespace std;

const struct data { unsigned answer; const string ask; }
Data[]=
{
	{ 2,   "Ile skrzydel ma ptak" },
	{ 5,   "Ile jest palcow u jednej dloni czlowieka" },
	{ 8,   "Ile nog ma pajak" },
	{ 101, "Ile programistow treba aby napisac ten program" },
};
constexpr size_t DataSize=sizeof(Data)/sizeof(*Data);
const string BadGood[]={"Bledna odpowiedz - brak puntku","Poprawna odpowiedz - zdobywasz 1 punkt"};

int main()
{
	unsigned seed=chrono::system_clock::now().time_since_epoch().count();
	constexpr size_t count=3;
	array<size_t,count> ord;
	for(size_t i=0;i<DataSize;++i) ord[i]=i;
  	shuffle(ord.begin(),ord.end(),default_random_engine(seed));
	size_t goodcount=0;
	for(size_t i=0;i<count;++i)
	{
		size_t k=ord[i];
		cout<<Data[k].ask<<": ";
		unsigned answer;
        cin>>answer;
        bool goodanswer=(answer==Data[k].answer);
        goodcount+=goodanswer;
		cout<<BadGood[goodanswer]<<endl;
	}
	cout<<"Zdobyles: "<<goodcount<<" puntkow"<<endl;
	return 0;
}
1

Zobacz jak można napisać podobny przykład nie używając

  • zmienny globalnych
  • dziwnych nazw typu l0, które bardziej przypominają liczbę 10
  • losowania w którym prawdziwie losowe wartości przyjmuje tylko zmienna i w pętli for
  • wielokrotnie tego samego kodu w odpowiedziach
#include <iostream>
#include <algorithm>
#include <map>
#include <numeric>
#include <random>
#include <chrono>
#include <vector>

using namespace std;

struct Question
{
    string text;
    int answer {0};
};

const map<int,Question> question { {1,{"2+2 = ? ",4}} , {2,{"7-4 = ? ",3}} , {3,{"5*5 = ? ",25}} };

bool ask_question( int choise )
{
    int answer {0};
    cout << question.at(choise).text;
    cin >> answer;
    return ( answer == question.at(choise).answer ) ? true : false;
}


int main()
{
    int points {0};
    vector<int> question_order(question.size());

    default_random_engine random(chrono::system_clock::now().time_since_epoch().count());
    iota(question_order.begin(),question_order.end(),1);
    shuffle(question_order.begin(),question_order.end(),random);

    for( const auto& order : question_order )
    {
        if( ask_question(order) )
        {
            cout << "Correct!\n"; ++points;
        }
        else cout << "Wrong!\n";
    }

    cout <<"\nYou score " << points << " points";
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1