Jump to content
bDyds

Spanzuratoarea in C++

Recommended Posts

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 ghicite

As 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.

Link to comment
Share on other sites

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 aici

Nu 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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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 parametri
if(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 index

ceva de genul

string cuvant = linii[x]; // x fiind indexul liniei din fisier

si dupa asta folosesti cuvant.find("litera");

Link to comment
Share on other sites

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;
}

Link to comment
Share on other sites

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 deja

if (word.find(guess_char) != -1))

{

int index = word.find(guess_char);//indexul la care se gaseste prima litera

do

{

guess.replace(index, 1, guess_char);//schimbi din '_' in guess_char

index = word.find(guess_char, index);

}while (index != -1);//cauti caracterul in continuare, in cazul in care mai estepe undeva, il bagi din nou

return true;//a ghicit, afisezi stringul nou

}

return false;//scazi vietile, nu a ghicit

}

Ceva de genul iti trebuie...

@nedo faster than me :))

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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 termina

Chiar nu imi dau seama unde am gresit.. Multumesc pentru atentie.

Edited by bDyds
Link to comment
Share on other sites

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 by zorro59
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

Ti-am explicat ce este gresit cu strchr.

Uitate aici de exemplu:

strchr() help

Sa 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 by zorro59
Link to comment
Share on other sites

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");
}

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...