bDyds Posted May 10, 2012 Report Posted May 10, 2012 Salut, sunt in clasa a XII-a si pentru atestat trebuie sa fac un joc de spanzuratoarea in C++. Programul trebuie sa preia cuvintele dintr-un fisier in care pe fiecare linie este un cuvant. Eu n-am mai lucrat cu fisiere din clasa a IX-a, de acum 3 ani, iar atunci am facut foarte putin, asa ca am nevoie de putin ajutor. Trebuie deasemenea sa folosesc si functii. Mecanismul ar fi in felul urmator: se citeste un numar n de la tastatura si este ales cuvantul de pe pozitia n. Fac un vector care contine literele, calculez cate elemente are vectorul (literele cuvantului), afisez primul element din vector, ultimul, iar intre ele numarul de elemenete - 2 caractere de '_'. Fac o functie care verifica daca litera introdusa de la tastatura se afla in vector, iar daca da afisez litera respectiva pe pozitiile pe care aceasta se afla in vector. Fac o variabila logica "ok" care poate lua valorile 0 sau 1, iar cand toate literele sunt ghicite, ok ia valoarea 0 si programul se termina.Ce nu prea am idee cum sa fac:- sa citesc cuvantul de pe linia n din fisierul de cuvinte- sa pun intr-un vector fisierul (sa il despart in litere)- sa afisez literele ghiciteAs dori daca se poate un ajutor cat mai repede, va multumesc. Btw, urmaresc de mult timp acest forum, chiar daca nu postez.LE: Am uitat, trebuie sa fac in asa fel incat la 5 incercari gresite sa pierzi. Probabil ca la fiecare incercare o sa maresc o constanta (nr++), iar cand nr==5 programul se termina. Quote
nedo Posted May 10, 2012 Report Posted May 10, 2012 Daca fisierul nu este mare, poti sa stochezi fiecare linie intr-un vector de stringuri.Altfel ai putea sa stochezi intr-un map 2 int-uri, unul cu numarul linii, iar altul cu pozitia acesteia.Cel mai bun loc pentru referinta, dupa parerea mea, este aiciNu ai nevoie sa mai pui cuvantul respectiv intr-un vector. Clasa string are toate cele necesare pentru a iti face viata usoara. Poti sa verifici toti membrii clasei string pe acelasi site. Quote
bDyds Posted May 10, 2012 Author Report Posted May 10, 2012 Salut, multumesc pentru explicatiile tale si pentru ca ai raspuns rapid. Din pacate, trebuie neaparat sa preiau datele dintr-un fisier. Sirurile nu mi le mai amintesc foarte bine, daca ai putea da niste explicatii ti-as fii recunoscator. Quote
nedo Posted May 10, 2012 Report Posted May 10, 2012 presupunand ca nu sunt exagerat de multe cuvinte in fisier, adica nu sunt foarte multe linii poti sa faci ceva de genul.Partea urmatoare ar copia in vectorul linii fiecare linie(cuvant)vector<string> linii;ifstream fin;fin.open("adresa fisierului"); // poate sa fie fie un argv[x] in cazul in care executi programul cu parametriif(fin.is_open()){ while(fin.good()) { string linie; getline(fin, linie); linii.push_back(linie); }}Dupa care folosesti un random number generator - poate fi si rand din libraria standard pe un range intre 0 si numarul de elemente din vectorul linii. Sau poti sa alegi tu direct linia, dupa index, toate cuvintele fiind stocate in vector.Iar pentru a verifica daca acea litera exista in cuvant pur si simplu extragi din vector cuvantul ales dupa indexceva de genulstring cuvant = linii[x]; // x fiind indexul liniei din fisiersi dupa asta folosesti cuvant.find("litera"); Quote
bDyds Posted May 10, 2012 Author Report Posted May 10, 2012 Tot n-am reusit sa fac prolema. Astept in continuare solutii Quote
nedo Posted May 10, 2012 Report Posted May 10, 2012 Am facut eu ceva, pentru a avea un punct de plecare, trebuie doar sa verifici daca utilizatorul a castigat sau pierdut, poti modifica numarul maxim de incercari. Probabil trebuie sa verifici pentru a nu permite jucatorului sa aleaga aceeasi litera de mai multe ori.#include <iostream>#include <fstream>#include <string>#include <vector>#include <windows.h> // system("CLS")#include <stdio.h> // getchar()using namespace std;int main(int argc, char* argv[]){ /**if(argc < 2) { cout << "Folosire: " << argv[0] << " fisier_cuvinte\n"; return 0; }*/ vector<string> linii; // va tine toate randurile din fisier. ifstream fIn; fIn.open("cuvinte.txt"); // inlocuiesti cu adresa catre fisier sau schimbi cu argv[1] si decomentezi liniile de mai sus // preiei liniile din fisier si le salvezi in vectorul de stringuri if(fIn.is_open()) { while(fIn.good()) { string linie; getline(fIn, linie); linii.push_back(linie); } } else { cout << "Nu am putut deschide: " << argv[1]; return 0; } int incercari = 0; int rand = (linii.size() + 1); do { cout << "Alege numarul randului de unde sa fie selectat cuvantul, intre 0 si " << (linii.size() - 1); cin >> rand; if(cin.fail()) { cin.ignore(); cin.clear(); char asdf[255]; cin.getline(asdf, 255); // extragem continutul gresit pentru a putea continua executia } }while((rand < 0) || (rand > linii.size())); string temp; temp.clear(); // ne asiguram ca temp e gol string de_ghicit; // va retine cuvantul de ghicit de_ghicit = linii[rand]; string utilizate; cin.ignore(); cin.clear(); // creem string-ul in care se vor salva literele noastre atunci cand le nimerim for(int i = 0; i < de_ghicit.size(); i++) { temp.append("_"); } // loop-ul jocului do { system("CLS"); // nu e recomandat sa folosesti asta dar pentru ce avem noi aici e ok cout << "Litere utilizate: " << utilizate << endl; cout << "Incercari: " << incercari << endl; cout << "Cuvantul: " << temp; cout << "\nTe rog alege o litera de la a la z.\n"; char litera; litera = getchar(); utilizate += litera; bool found = 0; for(int i = 0; i < de_ghicit.size(); i++) { if(litera == de_ghicit[i]) { temp[i] = litera; found = 1; } } if(found == 0) // daca litera exista atunci nu adaugam la numarul de incecari { incercari++; } cin.ignore(); // golim buffer-ul cin.clear(); // ignoram resetam buffer-ul }while((incercari < 5) && (temp != de_ghicit)); // atat timp cat numarul de incercari e mai mic de 5 sau nu am nimerit cuvantul cout << "Felicitari ai reusit sa gasesti cuvantul: " << temp << endl; return 0;} Quote
zorro59 Posted May 10, 2012 Report Posted May 10, 2012 Citesti n linii cu getline, si obtii cuvantul.De exemplu:string word = "mamaie";string guess = "______";Dupa ce ai cuvantul, chemi o functie de genul (pentru primul si ultimul caracter, ca sa le inlocuiasca si in interior, apoi pentru ce introduce userul)bool Replace(char guess_char){if (guess.find(guess_char) != -1)return false;//a fost ghicit dejaif (word.find(guess_char) != -1)){int index = word.find(guess_char);//indexul la care se gaseste prima literado{guess.replace(index, 1, guess_char);//schimbi din '_' in guess_charindex = word.find(guess_char, index);}while (index != -1);//cauti caracterul in continuare, in cazul in care mai estepe undeva, il bagi din noureturn true;//a ghicit, afisezi stringul nou}return false;//scazi vietile, nu a ghicit}Ceva de genul iti trebuie...@nedo faster than me Quote
pr00f Posted May 10, 2012 Report Posted May 10, 2012 Probabil trebuie sa verifici pentru a nu permite jucatorului sa aleaga aceeasi litera de mai multe ori.Asta se face foarte u?or, fiecare liter? introdus? de utilizator este introdus? într-un ?ir de caractere ?i la introducerea altei litere se verific? dac? exist? sau nu în acel ?ir. Quote
bDyds Posted May 10, 2012 Author Report Posted May 10, 2012 (edited) Multumesc pentru toate replicile de pana acum, au fost folositoare, insa la informatica nu am invatat functiile enumerate de voi mai sus. Am incercat sa fac programul de unul singur, iar cuvantul este citit de la tastatura la inceput. Insa, din cate vad, programul nu functioneaza. Daca cineva poate sa il depaneze, as fi recunoscator.#include <iostream.h>#include <string.h>int gasire(char c, char s1[100]) { char *p; int t=0; p=strchr(s1,c); while(p!=NULL) { t++; p=strchr(s1,c); } if(t==0) return 0; else return 1; } void aratalitera(char c, char s1[100], char s2[100]) { char *p; p=strchr(s1,c); while(p!=NULL) {s2[*p]=s1[*p]; p=strchr(s1,c); } }int verifica(char s2[100]) {int n, ok=1; n=strlen(s2)-1; for(int i=1;i<=n;i++) {if(s2[i]!='X') ok=0; } if(ok==1) return 1; else return 0; }void main(){char s1[100], s2[100], c; int i, ok=1, v=0; cin.get(s1,100); strcpy(s2, s1); for(i=1;i<strlen(s2)-1;i++) s2[i]='X'; while(ok==1) { cout<<"Introduceti o litera"; cin>>c; if(gasire(c,s1)==1) {cout<<"Litera se afla in cuvant!"; aratalitera(c,s1,s2); cout<<s2; } else {v++; cout<<"Litera nu se afla in cuvant. Mai aveti"<<5-v<<" vieti."; cout<<s2; } if(v>=5) {cout<<"Ati pierdut!"<<endl; cout<<"Cuvantul era:"<<endl; cout<<s1; ok=0; } if(verifica(s2)==0) {cout<<"Felicitari! Ati ghicit cuvantul!"; ok=0; } } }Mecanismul este urmatorul: -sirul s1 este citit de la tastatura (cuvantul)-sirul s1 este copiat in sirul s2-sirul s2 este modificat sa arate de forma CXXXXXl (sa afiseze doar prima si ultima litera)-se verifica daca litera citita de la tastatura se afla in sirul s1, iar daca da, adresa caracterului la care este gasita ia valoarea literei citite in sirul s2-se verifica daca mai sunt 'X'-uri in sirul s2, iar daca nu, algoritmul se termina-v reprezinta numarul de vieti, daca v>5, atunci algoritmul iarasi se terminaChiar nu imi dau seama unde am gresit.. Multumesc pentru atentie. Edited May 10, 2012 by bDyds Quote
zorro59 Posted May 10, 2012 Report Posted May 10, 2012 (edited) Sau mai bine verifici in temp daca exista litera aceea, nu mai creezi o variabila noua.#include <iostream>#include <string.h>using namespace std;bool gasire(char c, char s1[100], char s2[100]){ bool found = false; for (int i=0; i<strlen(s1); i++) { if (s1[i] == c) { s2[i] = c; found= true; } } if(found) return true; return false;}bool verifica(char s2[100]){ int index=0; while (index < strlen(s2) && s2[index] != 'X') index++; if (index == strlen(s2))//toate caracterele nu sunt 'X' return true; return false;//mai exista 'X'}void main(){ char s1[100], s2[100], c; int i, v=0; do { cout<<"Introduceti cuvantul "<<endl; cin>>s1; } while (strlen(s1) < 3 && cout<<"Cuvantul trebuie sa contina cel putin 3 litere distincte"<<endl);//ne trebuie cel putin 3 litere for(i=0;i<strlen(s1);i++) //tu trebuie sa verifici primele 2, de exemplu in cuvantul abcdabc, a trebuie aratat 'a' de 2 ori la inceput s2[i]='X'; s2[strlen(s1)] = '\0';//terminatorul gasire(s1[0], s1, s2);//inlocuiesc primul caracter gasire(s1[strlen(s1)-1], s1, s2);//si ultimul cout<<s2<<endl; while(1) { cout<<"Introduceti o litera"<<endl; cin>>c; if(strchr(s2, (int)c) != NULL)//a mai fost introduc c in s2 { cout<<"Litera a mai fost introdusa odata, ati pierdut o viata"<<endl;//aici poti sa ii spui doar mesajul, sa nu ii scazi din vieti cout<<"Mai aveti "<<5-++v<<" vieti."<<endl; cout<<s2<<endl; } else if(gasire(c,s1, s2))//a fost modificat s2 { cout<<"Litera se afla in cuvant!"<<endl; cout<<s2<<endl; } else { cout<<"Litera nu se afla in cuvant. Mai aveti "<<5-++v<<" vieti."<<endl; cout<<s2<<endl; } if(v>=5) { cout<<"Ati pierdut!"<<endl; cout<<"Cuvantul era:"<<endl; cout<<s1<<endl; break; } if(verifica(s2)) { cout<<"Felicitari! Ati ghicit cuvantul!"<<endl; break; } } cin>>i;//pauza }Good enough?La tine greselile sunt destule, de exemplu strchr nu face ce crezi tu:Returns a pointer to the first occurrence of character in the C string str.The terminating null-character is considered part of the C string. Therefore, it can also be located to retrieve a pointer to the end of a string.Adica daca il gaseste odata in string pe pozitia 1 sa zicem, el si a doua oara va cauta tot de la inceput, si va gasit iar la pozitia 1 => infinite loop. Edited May 10, 2012 by zorro59 Quote
Starker Posted May 10, 2012 Report Posted May 10, 2012 Verifici daca e litera cu strchr... daca este atunci o afiseaza, daca nu atunci scade nr de incercari. Quote
bDyds Posted May 10, 2012 Author Report Posted May 10, 2012 Sau mai bine verifici in temp daca exista litera aceea, nu mai creezi o variabila noua.Poti fi mai explicit te rog?Verifici daca e litera cu strchr... daca este atunci o afiseaza, daca nu atunci scade nr de incercari.Asta am incercat si eu sa fac, insa probabil am gresit ceva si nu imi dau seama unde. Quote
zorro59 Posted May 10, 2012 Report Posted May 10, 2012 (edited) Ti-am explicat ce este gresit cu strchr.Uitate aici de exemplu:strchr() helpSa luam stringul abcabc, si sa zicem ca noi vrem de cate ori este gasit caracterul 'a'.El va fi gasit pe pozitia 0, apoi se va avansa o pozitie (stringul nostru va deveni bcabc), unde vom gasi din nou pe pozitia 2 caracterul, apoi va deveni bc, nu vom mai gasi caracterul si functia va returna null.La tine gaseste mereu pe o pozitie caracterul si se blocheaza. Edited May 10, 2012 by zorro59 Quote
Ellimist Posted May 10, 2012 Report Posted May 10, 2012 Uite cod complet explicat pentru oricine. Tot ce trebuie sa faci e sa modifici variabila user_word sa o preiei din fisier.Hangman C++ - Game Programming Tutorials | Dream.In.Code Quote
zeus21 Posted May 12, 2012 Report Posted May 12, 2012 poate te ajuta varianta mea, am pus si comentariu sa fie mai pe inteles, ti-am lasat si tie sa faci partea de citire cuvant din fiser...posibil sa fie si mici scapari la cod nu l-am testat foarte intens dar ideea de baza cam asta e dar se poate face in tzz metode diferite dar am considerat ca poate pe asta o intelegi mai bine. Succes!#include<iostream.h>#include<string.h>#include<windows.h>char a[50],propuse[30],lit;bool b[50],kill;int i,gasite=0,vit=5,j=0;bool verif_lit(char li) // functia care verifica daca a mai fost introdusa litera{ for(i=0;i<strlen(propuse);i++) { if (propuse[i]==li) return true; } return false;}void main(){ cout<<"Introduceti un cuvant:"; cin>>a; //citim cuvantul strlwr(a); // converteste toate literele in litere mici system("cls"); //curatam ecranul dupa citire cout<<a[0]<<" ";//afisam primul character din cuvant b[0]=true; // memoram in vectorul b starea de afisare a caracterului daca e true il afisam daca nu afisam "_" propuse[j]=a[0]; // memoram in vectorul propuse literele descoperite si propuse de la tastatura j++; // trecem la urmatorul element al vectorului propuse gasite++; // incrementam cu 1 numarul de litere gasite for(i=1;i<strlen(a)-1;i++)//parcurgem vectorul de la al 2 lea caracter pana la penultimul { if((a[i]==a[0])||(a[i]==a[strlen(a)-1])) // verificam daca characterul e identic cu primul sau ultimul { cout<<a[i]<<" "; // daca e il afisam, ii modificam starea de vizibilitate (true) b[i]=true; //si incrementam numarul de litere gasite gasite++; } else // altfel afisam in locul lui o liniuta " _ " { cout<<"_ "; b[i]=false; } } cout<<a[strlen(a)-1]<<endl; // afisam ultimul caracter b[strlen(a)-1]=true; // starea de vizibilitate propuse[j]=a[strlen(a)-1]; j++; gasite++; // in continuare citim litere de la tastatura pana se completeaza cuvantul //sau pana depasim numarul de 5 (vieti) incercari esuate while(vit!=0 && gasite!=strlen(a)) { kill=true; cout<<"\nIntroduceti o litera:"; cin>>lit; if (verif_lit(lit)) // verificam daca litera introdusa a mai fost propusa altfel trecem mai departe cout<<"\nAti mai introdus litera!"<<endl; else { propuse[j]=lit; //adaugam litera in sirul literelor propuse j++; for(i=0;i<strlen(a);i++) // reafisam cuvantul caracter cu caracter cu eventualele modificari { if ((b[i] == true) || (lit==a[i])) { cout<<a[i]<<" "; if (lit==a[i]) { kill=false; // daca regasim litera introdusa atunci nu pierdem viata kill devine false if (b[i]==false) { b[i]=true; gasite++; } } } else cout<<"_ "; } if (kill==true) // daca ramane true atunci am pierdut o viata si scadem numarul lor { vit-=1; cout<<"\nNumar de vieti ramase: "<<vit; } } } if (vit==0) cout<<"\n>>> Ai pierdut! <<<"<<endl; else cout<<"\n*** Felicitari! ***"<<endl; system("pause 0");} Quote