Last active
August 23, 2017 19:14
-
-
Save unrevised6419/d4ed4f08343bb3a59f8d84a8bf1a84fe to your computer and use it in GitHub Desktop.
2nd year at Univeristy. Minesweeper in terminal. Made on windows, might work on *nix
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//============================================================================= | |
// ----- Inceputul Programului | |
//============================================================================= | |
/* | |
Name: Genistul | |
Copyright: Luca 2012 | |
Author: Luca Andrei | |
Date: 26/05/12 17:15 | |
Date: 25/06/12 00:34 | |
Description: Un joc de inteligenta artificiala | |
*/ | |
//============================================================================= | |
// ----- Directive | |
//============================================================================= | |
#include <stdio.h> | |
#include <conio2.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <ctype.h> | |
#include <windows.h> | |
#include <time.h> | |
//============================================================================= | |
// ----- Structuri | |
//============================================================================= | |
// in aceastra structura se salveaza informatia ce se vede si cea ascunsa | |
typedef struct cell{ | |
char celula, vizual; | |
} CELL; | |
// structura pentru punctaj de salvare nume si timpul jocului | |
typedef struct scor{ | |
char nume[15]; | |
float timp; | |
} PUNCTAJ; | |
//============================================================================= | |
// ----- Prototipuri | |
//============================================================================= | |
int meniu(); | |
void deseana_meniu(int items, int length1, int length2); | |
int alege_itemi(int items, int counts); | |
void pune_mina(); | |
void curata_mina(); | |
void in_sus(); | |
void in_jos(); | |
void dute_jos(int items); | |
void dute_sus(int items); | |
void sunet(int n); | |
int joc_nou(); | |
int continua_joc(); | |
void punctaj(); | |
void setari(); | |
void ajutor(); | |
void ajutor_taste(); | |
void genereaza_teren(); | |
void verifica_teren(); | |
void mineaza_teren(); | |
void planteaza_mine(); | |
void curata_teren(); | |
void afisare_teren(); | |
void adauga_numere(); | |
void creaza_numere(int i, int j); | |
void arata_cursor(bool show); | |
void setari_incepator(); | |
void setari_intermediar(); | |
void setari_avansat(); | |
void setari_proprii(); | |
void stinga(); | |
void sus(); | |
void dreapta(); | |
void jos(); | |
void cursor_stinga(); | |
void cursor_sus(); | |
void cursor_dreapta(); | |
void cursor_jos(); | |
int enter(); | |
int spatiu(); | |
void salvare_joc(); | |
void timp(); | |
int pierdere(); | |
int victorie(int x); | |
void retine_punctaj(); | |
void deschide_zone_libere(int i, int j); | |
int alege_culoare(int i, int j); | |
void culoare_celula_fundal(int i); | |
void mine_ramase(); | |
void marimi_fereastra(int *x, int *y); | |
int meniu_la_final(int x); | |
int deschide_zonele_din_jur(); | |
int deschide_cel(int i, int j); | |
void adauga_scor(PUNCTAJ *scor_curent); | |
void citeste_scoruri(); | |
void scrie_scoruri(); | |
void sorteaza_scor(); | |
void swap(PUNCTAJ *x, PUNCTAJ *y); | |
//============================================================================= | |
// ----- Variabile globale | |
//============================================================================= | |
// variabila pentru alocarea memoriei pentru teren | |
CELL **teren = NULL; | |
// nr de zone x si y, nr de mine, cordonatele x si y, nr de mine ramase | |
int xzone = 9, yzone = 9, mines = 10, xcord = 0, ycord = 0, mine_au_ramas; | |
// variabile pentru determinarea timpului curent | |
time_t timp_start, timp_sfirsit; | |
// variabila pentru pastrarea timpului de la inceputul jocului | |
float timp_curent, timp_salvat = 0; | |
// variabile pentru verificare de repetare si continuare a jocului | |
int repetam_jocul = 0, continua_jocul = 0; | |
// un tablou de tip "PUNCTAJ" pentru salvare scor | |
PUNCTAJ scoruri[5]; | |
// o simpla functie de simulare a victoriei | |
// victoria este valida atunci cind | |
// toate zonele au partea ascunsa egala cu cea vizuala | |
void simulare_victorie(){ | |
for(int i = 0; i < xzone; i++){ | |
for(int j = 0; j < yzone; j++){ | |
teren[i][j].vizual = teren[i][j].celula; | |
} | |
} | |
} | |
//============================================================================= | |
// ----- Functia principala | |
//============================================================================= | |
int main(void){ | |
clrscr(); | |
// setare titul consolei | |
SetConsoleTitle("Genistul"); | |
// citeste scoruri precedente din fisier | |
citeste_scoruri(); | |
start1: | |
// functie pentru a ascunde cursorul | |
arata_cursor(false); | |
// functia meniu afiseaza un meniu si returneaza nr itemului din meniu ales | |
int alege = meniu(); | |
start2: | |
switch( alege ){ | |
case 1 :{ | |
// joc_nou returneaza valaorea 1 daca vrem sa jucam un joc nou | |
// si returneaza 2 daca vrem sa repetam jocul curent | |
int k = joc_nou(); | |
if ( k == 2 ){ | |
alege = 1; | |
goto start2; | |
}else if ( k == 3 ){ | |
repetam_jocul = 1; | |
alege = 1; | |
goto start2; | |
} | |
goto start1; | |
} | |
case 2 :{ | |
// functia continua_joc incarca din fisier datele salvate anterior | |
// pentru a prelua jocul in continuare | |
if ( continua_joc() ){ | |
alege = 1; | |
goto start2; | |
}else goto start1; | |
} | |
// punctajele au fost citite din fisier la executia programului | |
case 3 : punctaj(); goto start1; // functia punctaj doar le afiseaza | |
case 4 : setari(); goto start1; // setarile terenului si a minelor | |
case 5 : ajutor(); goto start1; // ajutorul jocului | |
// in caz ca parasim programul | |
// mai intii salvam punctajul curent inapoi in fisier | |
// si iesim fortat din program | |
case 6 : scrie_scoruri(); exit(1); | |
} | |
return 0; | |
} | |
//============================================================================= | |
// ----- Joc nou | |
//============================================================================= | |
int joc_nou(){ | |
char ch = 0; | |
// daca continua_jocul e adevarata atunci plecam la eticheta continua | |
// in cazul acesta nu riscam de a curata terenul | |
// doar continuam jocul incarcat | |
if(continua_jocul){ | |
continua_jocul = 0; | |
goto continua; | |
} | |
clrscr(); | |
// daca repetam_jocul este 0 atunci eliberam memorie | |
if (!repetam_jocul){ | |
// verificam daca teren nu este null | |
if ( teren ) curata_teren(); | |
// si generam terenul pentru o noua joaca | |
mineaza_teren(); | |
timp_salvat = 0; | |
}else{ | |
// daca repetam_jocul este 1 atunci nu e necesar de eliberare a memorie | |
// doar nivelam terenul | |
// indicind ca zonele vizuale sunt goale | |
verifica_teren(); | |
repetam_jocul = 0; | |
} | |
// afisare_teren deseneaaza terenul nostru de joc | |
afisare_teren(); | |
// oprim cursorul | |
arata_cursor(false); | |
// indicam ca mine au ramas cite sunt initial | |
mine_au_ramas = mines; | |
// cordonatele sunt 0, 0 | |
xcord = ycord = 0; | |
// daca ajungem la eticheta aceasta toate functiile anterioare | |
// pina la declaratie goto nu au fost executate | |
continua: | |
// mine_ramase afiseaza pe teren numarul minelor ramasae | |
mine_ramase(); | |
// startam timpul jocului | |
timp_start = time(NULL); | |
// setam culoare de fundal | |
textbackground(8); | |
// afisam celula initiala | |
gotoxy(wherex()-1, wherey()); | |
printf(" "); | |
gotoxy(wherex()-2, wherey()); | |
// cit timp ch e diferit de 27(Esc) repetam ciclul | |
while( ch != 27 ){ | |
ch = 0; | |
// kbhit returneaza 1 daca a fost tastat un buton | |
if( kbhit() ){ | |
// in caz ca sa tastat executam urmatoarele | |
// ch preia butonul tastat | |
ch = getch(); | |
// in dependenta de ce sa tastat avem | |
switch( ch ){ | |
// butonul Home | |
// functia cursor_stinga returneaza cursorul celulei | |
// la inceputul liniei | |
case 71 :{ | |
cursor_stinga(); | |
break; | |
} | |
// butonul End | |
// returneaza cursorul la sfirsitul liniei | |
case 79 :{ | |
cursor_dreapta(); | |
break; | |
} | |
// butonul PageUp | |
// returneaza cursorul la inceputul coloanei | |
case 73 :{ | |
cursor_sus(); | |
break; | |
} | |
// butonul PageDown | |
// returneaza cursorul la sfirsitul coloanei | |
case 81 :{ | |
cursor_jos(); | |
break; | |
} | |
// butonul sageata stinga | |
// returneaza cursorul cu o celula la stinga | |
// in caz ca e limita trece cursorul in partea opusa | |
case 75 :{ | |
stinga(); | |
break; | |
} | |
// butonul sageata sus | |
// returneaza cursorul cu o celula in sus | |
// in caz ca e limita trece cursorul in partea opusa | |
case 72 :{ | |
sus(); | |
break; | |
} | |
// butonul sageata dreapta | |
// returneaza cursorul cu o celula la dreapta | |
// in caz ca e limita trece cursorul in partea opusa | |
case 77 :{ | |
dreapta(); | |
break; | |
} | |
// butonul sageata jos | |
// returneaza cursorul cu o celula in jos | |
// in caz ca e limita trece cursorul in partea opusa | |
case 80 :{ | |
jos(); | |
break; | |
} | |
// butonul Enter | |
// functia enter deschide celula verificind continutul ei | |
// in caz ca functia returneaza nenul atunci | |
// 1 - iesire in meniu | |
// 2 - joc nou | |
// 3 - repeta jocul | |
case 13 :{ | |
//simulare_victorie(); | |
switch( enter() ){ | |
case 1 : return 1; | |
case 2 : return 2; | |
case 3 : return 3; | |
} | |
break; | |
} | |
// butonul Space | |
// functia space bifeaza celula curenta daca nu este deschisa | |
// ca si in cazul functiei enter returneaza aceleasi valori | |
// 1 - iesire in meniu | |
// 2 - joc nou | |
// 3 - repeta jocul | |
case 32 :{ | |
switch( spatiu() ){ | |
case 1 : return 1; | |
case 2 : return 2; | |
case 3 : return 3; | |
} | |
break; | |
} | |
} | |
} | |
// fucntia timp afiseaza timpul petrecu de la inceputul jocului | |
// daca nu se va apasa nici un buton ea se va apela foarte rapid | |
timp(); | |
} | |
// in cazul ca sa tastat 27(Esc) | |
// jocul automat se salveaza | |
salvare_joc(); | |
// si elibereaza memoria de pe teren | |
curata_teren(); | |
} | |
//============================================================================= | |
// ----- Joc Nou -> Enter | |
//============================================================================= | |
int enter(){ | |
int done = 1, dx, dy; | |
// daca partea vizuala e mina inseamna ca e bifata | |
// si returnam 0 nimic nu se intimpla | |
if ( teren[xcord][ycord].vizual == 15){ | |
return 0; | |
} | |
// daca partea ascunsa este mina atunci returnam functia pierdere | |
// care stopeaza programul | |
// si insasi returneaza | |
// 1 - iesire in meniu | |
// 2 - joc nou | |
// 3 - repeta jocul | |
if ( teren[xcord][ycord].celula == 15){ | |
return pierdere(); | |
} | |
// daca celula curenta este o cifra si in partea vizuala inca nu a fost afisata | |
// atunci ea este afisata | |
if ( (teren[xcord][ycord].celula >= '1') && (teren[xcord][ycord].celula <= '8')\ | |
&& (teren[xcord][ycord].vizual == '#') ){ | |
// egalam partea ascunsa cu cea vizuala | |
teren[xcord][ycord].vizual = teren[xcord][ycord].celula; | |
// alegem culoarea cifrei | |
// functia alege_culoare returneaza culoarea necesara | |
// pentru cifra cu cordonatele xcord, ycord | |
textcolor(alege_culoare(xcord, ycord)); | |
textbackground(8); | |
gotoxy(wherex()-1, wherey()); | |
printf(" %c ", teren[xcord][ycord].vizual); | |
gotoxy(wherex()-2, wherey()); | |
// done este pentru a anula urmatoarele conditii | |
done = 0; | |
} | |
// in cazul ca celula curenta este spatiu si partea vizuala nu a fost deschisa | |
if ( (teren[xcord][ycord].celula == ' ') && (teren[xcord][ycord].vizual == '#') && done ){ | |
// preluam cordonatele curente | |
dx = wherex(), dy = wherey(); | |
textbackground(15); | |
// deschide_zone_libere este o functie recursiva care deschide toate zonele | |
// din jurul ei in afara de mine | |
// si daca celulele din jur sunt spatii libere | |
// atunci functia este apelata recursiv si pentru ele | |
deschide_zone_libere(xcord, ycord); | |
// ne reintoarcem la cordonatele noastre initiale | |
gotoxy(dx, dy); | |
// afisam celula curenta cu setarile necesare | |
textbackground(8); | |
gotoxy(wherex()-1, wherey()); | |
printf(" "); | |
gotoxy(wherex()-2, wherey()); | |
arata_cursor(false); | |
done = 0; | |
} | |
// in caz ca celula curenta este deja deschisa atunci | |
// atunci verificam daca in jurul ei sau deschis numarul necesar de mine | |
// daca sau deschis minele necesare atunci deschidem si celulele ramase | |
if ( (teren[xcord][ycord].vizual >= '1') && (teren[xcord][ycord].vizual <= '8') && done ){ | |
// preluam cordonatele curente | |
dx = wherex(), dy = wherey(); | |
// functia deschide_zonele_din_jur deschide zonele din jurul celulei | |
// dar daca minele initiale nu au fost gasite corect in jurul celulei | |
// si la deschidere sau dat peste alte mine, atunci sa deschis o mina ascunsa | |
// jocul este pierdut. functia iarasi returneaza | |
// 1 - iesire in meniu | |
// 2 - joc nou | |
// 3 - repeta jocul | |
int val = deschide_zonele_din_jur(); | |
// revenim la cordonatele precedente | |
gotoxy(dx, dy); | |
// afisam celula curenta cu setarile ei | |
textcolor(alege_culoare(xcord, ycord)); | |
textbackground(8); | |
gotoxy(wherex()-1, wherey()); | |
printf(" %c ", teren[xcord][ycord].vizual); | |
gotoxy(wherex()-2, wherey()); | |
// returnam val | |
// 1 - iesire in meniu | |
// 2 - joc nou | |
// 3 - repeta jocul | |
return val; | |
} | |
// daca sa ajuns la acest pas verificam daca jocul nu este cistigat | |
// daca se salveaza datele necesare si | |
// functia iarasi returneaza chiar daca sa cistigat | |
// 1 - iesire in meniu | |
// 2 - joc nou | |
// 3 - repeta jocul | |
return victorie(0); | |
} | |
//============================================================================= | |
// ----- Joc Nou -> Enter -> Deschide zonele din jur | |
//============================================================================= | |
// functia deschide celulele din jurul uneia celule | |
int deschide_zonele_din_jur(){ | |
int val, k = 0; | |
// urmatoarele conditii sunt pentru a verifica | |
// cite mine sunt in jurul celulei | |
if ( (xcord-1 >= 0) && (ycord-1 >= 0) && (teren[xcord-1][ycord-1].vizual == 15) ) k++; | |
if ( (xcord-1 >= 0) && (teren[xcord-1][ycord].vizual == 15) ) k++; | |
if ( (xcord-1 >= 0) && (ycord+1 < yzone) && (teren[xcord-1][ycord+1].vizual == 15) ) k++; | |
if ( (ycord-1 >= 0) && (teren[xcord][ycord-1].vizual == 15) ) k++; | |
if ( (ycord+1 < yzone) && (teren[xcord][ycord+1].vizual == 15) ) k++; | |
if ( (xcord+1 < xzone) && (ycord-1 >= 0) && (teren[xcord+1][ycord-1].vizual == 15) ) k++; | |
if ( (xcord+1 < xzone) && (teren[xcord+1][ycord].vizual == 15) ) k++; | |
if ( (xcord+1 < xzone) && (ycord+1 < yzone) && (teren[xcord+1][ycord+1].vizual == 15) ) k++; | |
// in caz ca numarul de mine deschise nu este coincident cu cifra din celula | |
// atunci se returneaza 0, nu se face nimic | |
if ( k != teren[xcord][ycord].vizual-48) return 0; | |
// daca conditia de mai sus e adevarata atunci verificam pentru fiecare celula din jurul ei | |
// ne adresam catre celula doar daca nu este marcata ca mina | |
// si nu este iesita din zonele terenului | |
// conditiile de mai sus se adeveresc pentru toate zonele din jurul celulei | |
if ( (xcord-1 >= 0) && (ycord-1 >= 0) && (teren[xcord-1][ycord-1].vizual != 15) ){ | |
// deschide_cel returneaza 0 daca celula sa deschis cu succes | |
// in caz contrar acolo este o mina | |
// si jocul se stopeaza | |
// returnind | |
// 1 - iesire in meniu | |
// 2 - joc nou | |
// 3 - repeta jocul | |
val = deschide_cel(xcord-1, ycord-1); | |
// daca val este nenul atunci returnam val | |
if ( val != 0 ) return val; | |
} | |
// conditiile de mai sus se adeveresc pentru toate zonele din jurul celulei | |
if ( (xcord-1 >= 0) && (teren[xcord-1][ycord].vizual != 15) ){ | |
val = deschide_cel(xcord-1, ycord); | |
if ( val != 0 ) return val; | |
} | |
if ( (xcord-1 >= 0) && (ycord+1 < yzone) && (teren[xcord-1][ycord+1].vizual != 15) ){ | |
val = deschide_cel(xcord-1, ycord+1); | |
if ( val != 0 ) return val; | |
} | |
if ( (ycord-1 >= 0) && (teren[xcord][ycord-1].vizual != 15) ){ | |
val = deschide_cel(xcord, ycord-1); | |
if ( val != 0 ) return val; | |
} | |
if ( (ycord+1 < yzone) && (teren[xcord][ycord+1].vizual != 15) ){ | |
val = deschide_cel(xcord, ycord+1); | |
if ( val != 0 ) return val; | |
} | |
if ( (xcord+1 < xzone) && (ycord-1 >= 0) && (teren[xcord+1][ycord-1].vizual != 15) ){ | |
val = deschide_cel(xcord+1, ycord-1); | |
if ( val != 0 ) return val; | |
} | |
if ( (xcord+1 < xzone) && (teren[xcord+1][ycord].vizual != 15) ){ | |
val = deschide_cel(xcord+1, ycord); | |
if ( val != 0 ) return val; | |
} | |
if ( (xcord+1 < xzone) && (ycord+1 < yzone) && (teren[xcord+1][ycord+1].vizual != 15) ){ | |
val = deschide_cel(xcord+1, ycord+1); | |
if ( val != 0 ) return val; | |
} | |
// in caz ca toate celulele sau deschis cu succes returnam 0 | |
return 0; | |
} | |
//============================================================================= | |
// ----- Joc Nou -> Enter -> Deschide o celula | |
//============================================================================= | |
// functia verifica daca nu este mina si deschide celula | |
int deschide_cel(int i, int j){ | |
// daca e mina returneaza pierdere | |
if ( teren[i][j].celula == 15 ) return pierdere(); | |
// daca e loc liber atunci se apeleaza recursiv functia deschide_zone_libere | |
// acest tip de recursie se numeste indirect | |
// direct este atunci cind functia se apeleaza pe ea insasi | |
if ( teren[i][j].celula == ' ' ) deschide_zone_libere(i, j); | |
// indicam ca celula a fost deschisa | |
teren[i][j].vizual = teren[i][j].celula; | |
// afisam celula cu setarile ei | |
gotoxy( 5+j*4, 3+i*2 ); | |
textcolor( alege_culoare(i, j) ); | |
textbackground(15); | |
gotoxy(wherex()-1, wherey()); | |
printf(" %c ", teren[i][j].vizual); | |
return 0; | |
} | |
//============================================================================= | |
// ----- Joc Nou -> Enter -> Deschide zone libere | |
//============================================================================= | |
// functia deschide recursiv toate celulele cu numere si cu locuri libere | |
// din jurul unei celule indicate initial | |
void deschide_zone_libere(int i, int j){ | |
// verificam mai intii daca celula nu este mina ascunsa sau vizuala | |
if ( (teren[i][j].celula != 15) && (teren[i][j].vizual != 15) ){ | |
// verificam daca celula nu a fost deschisa | |
// "#" indica ca aceasta celula este neatinsa inca | |
if ( teren[i][j].vizual == '#'){ | |
gotoxy( 5+j*4, 3+i*2 ); | |
teren[i][j].vizual = teren[i][j].celula; | |
// verificam daca celula este spatiu liber | |
// daca da apelam recursiv toate celulele din jurul ei | |
if ( teren[i][j].celula == ' ' ){ | |
gotoxy(wherex()-1, wherey()); | |
printf(" "); | |
gotoxy(wherex()-2, wherey()); | |
// stinga sus | |
if ( (i-1 >= 0) && (j-1 >= 0) ) deschide_zone_libere(i-1, j-1); | |
// sus | |
if ( (i-1 >= 0) ) deschide_zone_libere(i-1, j); | |
// dreapta sus | |
if ( (i-1 >= 0) && (j+1 < yzone) ) deschide_zone_libere(i-1, j+1); | |
// stinga | |
if ( (j-1 >= 0) ) deschide_zone_libere(i, j-1); | |
// dreapta | |
if ( (j+1 < yzone) ) deschide_zone_libere(i, j+1); | |
// stinga jos | |
if ( (i+1 < xzone) && (j-1 >= 0) ) deschide_zone_libere(i+1, j-1); | |
// jos | |
if ( (i+1 < xzone) ) deschide_zone_libere(i+1, j); | |
// dreapta jos | |
if ( (i+1 < xzone) && (j+1 < yzone) ) deschide_zone_libere(i+1, j+1); | |
}else{ | |
// in caz ca zona nu e spatiu deci e cifra | |
// afiseaza doar cifra in mod normal | |
textcolor(alege_culoare(i, j)); | |
gotoxy(wherex()-1, wherey()); | |
printf(" %c ", teren[i][j].vizual); | |
gotoxy(wherex()-2, wherey()); | |
} | |
} | |
} | |
} | |
//============================================================================= | |
// ----- Joc Nou -> Spatiu | |
//============================================================================= | |
// functia bifeaza sau debifeaza celula | |
int spatiu(){ | |
// verificam daca celula nu a fost deschisa | |
if ( teren[xcord][ycord].vizual == '#' ){ | |
// functia mine_ramase decrementeaza numarul de mine si afiseaza la ecran | |
mine_ramase(); | |
// indicam ca celula vizual este mina(bifata) | |
teren[xcord][ycord].vizual = 15; | |
// bifam celula corespunzatoare la ecran | |
textcolor(15); | |
textbackground(4); | |
gotoxy(wherex()-1, wherey()); | |
printf(" %c ", 15); | |
gotoxy(wherex()-2, wherey()); | |
// verificam de victorie | |
return victorie(1); | |
// daca mina e deja bifata trebuie de debifat | |
// verificam daca celula vizual este bifata | |
}else if ( teren[xcord][ycord].vizual == 15 ){ | |
// marimnumarul de mine ramasa cu 2 deoarece mine_ramase decrementeaza cu 1 | |
// si va fi nevoie de ajuns la numarul de mine necesar | |
mine_au_ramas += 2; | |
mine_ramase(); | |
// debifam la ecran celula corespunzatoare | |
teren[xcord][ycord].vizual = '#'; | |
textbackground(8); | |
gotoxy(wherex()-1, wherey()); | |
printf(" "); | |
gotoxy(wherex()-2, wherey()); | |
return victorie(1); // !!!!! modificare curenta return 0;///////////////////////////////////////////////// | |
} | |
} | |
//============================================================================= | |
// ----- Joc Nou -> Alege Culoare | |
//============================================================================= | |
// functia alege o culaore in dependenta de parametrii trimisi | |
// verificind pe teren ce se afla acolo | |
int alege_culoare(int i, int j){ | |
if ( teren[i][j].vizual == '1' ) return 9; | |
if ( teren[i][j].vizual == '2' ) return 2; | |
if ( teren[i][j].vizual == '3' ) return 4; | |
if ( teren[i][j].vizual == '4' ) return 1; | |
if ( teren[i][j].vizual == '5' ) return 4; | |
if ( teren[i][j].vizual == '6' ) return 2; | |
if ( teren[i][j].vizual == '7' ) return 4; | |
if ( teren[i][j].vizual == '8' ) return 4; | |
if ( teren[i][j].vizual == 15 ) return 15; | |
return 0; | |
} | |
//============================================================================= | |
// ----- Joc Nou -> Culoare Celula Fundal | |
//============================================================================= | |
// functia verifica parametrul si in dependenta de i | |
// executa setarile pentru celula cind pleaca de la ea | |
// sau cind vine la o celula | |
void culoare_celula_fundal(int i){ | |
// daca in celula exista ceva | |
if ( teren[xcord][ycord].vizual != '#' ){ | |
// verifica parapentru i si seteaza fundal in dependenta de el | |
if (i){ | |
textbackground(15); | |
if ( teren[xcord][ycord].vizual == 15 ) textbackground(4); | |
} | |
// afisare celula curenta cu setarile ei | |
textcolor(alege_culoare(xcord, ycord)); | |
gotoxy(wherex()-1, wherey()); | |
printf(" %c ", teren[xcord][ycord].vizual); | |
gotoxy(wherex()-2, wherey()); | |
// in caz ca celula vizual inca nu a fost deschisa | |
// afiseaza doar spatiu liber cu fundalul necesar | |
}else{ | |
gotoxy(wherex()-1, wherey()); | |
printf(" "); | |
gotoxy(wherex()-2, wherey()); | |
} | |
} | |
//============================================================================= | |
// ----- Joc Nou -> Cursor la inceputul liniei | |
//============================================================================= | |
// functia seteaza cursorul celulei la inceputul liniei | |
void cursor_stinga(){ | |
textbackground(7); | |
culoare_celula_fundal(1); | |
gotoxy(5, wherey()); | |
ycord = 0; | |
textbackground(8); | |
culoare_celula_fundal(0); | |
} | |
//============================================================================= | |
// ----- Joc Nou -> Cursor la sfirsitul iniei | |
//============================================================================= | |
// functia seteaza cursorul celulei la sfirsitul liniei | |
void cursor_dreapta(){ | |
textbackground(7); | |
culoare_celula_fundal(1); | |
gotoxy(yzone*4+1, wherey()); | |
ycord = yzone - 1; | |
textbackground(8); | |
culoare_celula_fundal(0); | |
} | |
//============================================================================= | |
// ----- Joc Nou -> Cursor la inceputul coloanei | |
//============================================================================= | |
// functia seteaza cursorul celulei la inceputul coloanei | |
void cursor_sus(){ | |
textbackground(7); | |
culoare_celula_fundal(1); | |
gotoxy(wherex(), 3); | |
xcord = 0; | |
textbackground(8); | |
culoare_celula_fundal(0); | |
} | |
//============================================================================= | |
// ----- Joc Nou -> Cursor la sfirsitul coloanei | |
//============================================================================= | |
// functia seteaza cursorul celulei la sfirsitul coloanei | |
void cursor_jos(){ | |
textbackground(7); | |
culoare_celula_fundal(1); | |
gotoxy(wherex(), xzone*2+1); | |
xcord = xzone - 1; | |
textbackground(8); | |
culoare_celula_fundal(0); | |
} | |
//============================================================================= | |
// ----- Joc Nou -> Stinga | |
//============================================================================= | |
// muta celula cu o pozitie la stinga iar daca e la limita o duce in partea opusa | |
void stinga(){ | |
//if ( ycord-1 < 0) return; | |
textbackground(7); | |
culoare_celula_fundal(1); | |
if ( ycord == 0 ){ | |
gotoxy(wherex()+(yzone-1)*4, wherey()); | |
ycord += yzone - 1; | |
}else{ | |
gotoxy(wherex()-4, wherey()); | |
ycord--; | |
} | |
textbackground(8); | |
culoare_celula_fundal(0); | |
} | |
//============================================================================= | |
// ----- Joc Nou -> Sus | |
//============================================================================= | |
// muta celula cu o pozitie in sus iar daca e la limita o duce in partea opusa | |
void sus(){ | |
//if ( xcord-1 < 0 ) return; | |
textbackground(7); | |
culoare_celula_fundal(1); | |
if ( xcord == 0 ){ | |
gotoxy(wherex(), wherey()+(xzone-1)*2); | |
xcord += xzone - 1; | |
}else{ | |
gotoxy(wherex(), wherey()-2); | |
xcord--; | |
} | |
textbackground(8); | |
culoare_celula_fundal(0); | |
} | |
//============================================================================= | |
// ----- Joc Nou -> Dreapta | |
//============================================================================= | |
// muta celula cu o pozitie la dreapta iar daca e la limita o duce in partea opusa | |
void dreapta(){ | |
//if ( ycord+1 >= yzone ) return; | |
textbackground(7); | |
culoare_celula_fundal(1); | |
if ( ycord == yzone-1 ){ | |
gotoxy(wherex()-(yzone-1)*4, wherey()); | |
ycord = 0; | |
}else{ | |
gotoxy(wherex()+4, wherey()); | |
ycord++; | |
} | |
textbackground(8); | |
culoare_celula_fundal(0); | |
} | |
//============================================================================= | |
// ----- Joc Nou -> Jos | |
//============================================================================= | |
// muta celula cu o pozitie in jos iar daca e la limita o duce in partea opusa | |
void jos(){ | |
//if ( xcord+1 >= xzone ) return; | |
textbackground(7); | |
culoare_celula_fundal(1); | |
if ( xcord == xzone-1 ){ | |
gotoxy(wherex(), wherey()-(xzone-1)*2); | |
xcord = 0; | |
}else{ | |
gotoxy(wherex(), wherey()+2); | |
xcord++; | |
} | |
textbackground(8); | |
culoare_celula_fundal(0); | |
} | |
//============================================================================= | |
// ----- Joc Nou -> Salvare Joc | |
//============================================================================= | |
// functia salveaza toate datele necesare pentru a continua pe viitor jocul | |
void salvare_joc(){ | |
// deschidem fisierul de scriere in mod binar | |
FILE *f = fopen("bin\\lastsave.bin", "wb"); | |
// salvam numarul de zone | |
fwrite(&xzone, sizeof(xzone), 1, f); | |
fwrite(&yzone, sizeof(yzone), 1, f); | |
// salva numarul de mine | |
fwrite(&mines, sizeof(mines), 1, f); | |
// salvam cordonatele cerente ale celulei | |
fwrite(&xcord, sizeof(xcord), 1, f); | |
fwrite(&ycord, sizeof(ycord), 1, f); | |
// salvam cite mine au ramas nebifate | |
fwrite(&mine_au_ramas, sizeof(mine_au_ramas), 1, f); | |
// salva timpul curent | |
fwrite(&timp_curent, sizeof(timp_curent), 1, f); | |
// salvam ternul, fiecare celula in parte | |
for(int i = 0; i < xzone; i++){ | |
for(int j = 0; j < yzone; j++){ | |
fwrite(&teren[i][j], sizeof(teren[i][j]), 1, f); | |
} | |
} | |
// inchidem fisier | |
fclose(f); | |
} | |
//============================================================================= | |
// ----- Continua joc | |
//============================================================================= | |
// citeste din fisier datele necesare pentru a continua jocul | |
int continua_joc(){ | |
FILE *f; | |
// deschidem fisierul | |
// daca fiserul nu exista inseamna ca nu exista o joaca salvata | |
if ( (f = fopen("bin\\lastsave.bin", "rb")) == NULL){ | |
printf("\n Nu este o joaca\n salvata."); | |
getch(); | |
return 0; | |
} | |
// continuam jocul | |
continua_jocul = 1; | |
// citim din fiser numarul de zone | |
fread(&xzone, sizeof(xzone), 1, f); | |
fread(&yzone, sizeof(yzone), 1, f); | |
// citim din fiser numarul de mine | |
fread(&mines, sizeof(mines), 1, f); | |
// citim din fiser cordonatele ramase | |
fread(&xcord, sizeof(xcord), 1, f); | |
fread(&ycord, sizeof(ycord), 1, f); | |
// citim din fiser numarul de mine nebifate | |
fread(&mine_au_ramas, sizeof(mine_au_ramas), 1, f); | |
// marim numarul de mine ramase pentru a le afisa corect | |
mine_au_ramas++; | |
// citim timpul salvat | |
// care va fi sumat la timpul care va fi pe parcursul jocului continuat | |
fread(&timp_salvat, sizeof(timp_salvat), 1, f); | |
// generam ternul de xzone X yzone | |
genereaza_teren(); | |
// nivelam terenul | |
verifica_teren(); | |
// citim din fisier inapoi in matrice fiecare celula | |
for(int i = 0; i < xzone; i++){ | |
for(int j = 0; j < yzone; j++){ | |
fread(&teren[i][j], sizeof(teren[i][j]), 1, f); | |
} | |
} | |
// toate variabilele au fost citite in oridnea scrierii in fisier | |
// inchidem fisier | |
fclose(f); | |
// afisam teren | |
afisare_teren(); | |
// afisam terenul cum a ramas la ultima vizita | |
for(int i = 0; i < xzone; i++){ | |
for(int j = 0; j < yzone; j++){ | |
if (teren[i][j].vizual != '#'){ | |
gotoxy(5+j*4, 3+i*2); | |
textcolor(alege_culoare(i,j)); | |
if (teren[i][j].vizual == 15) textbackground(4); | |
else textbackground(15); | |
gotoxy(wherex()-1, wherey()); | |
printf(" %c ", teren[i][j].vizual); | |
gotoxy(wherex()-2, wherey()); | |
} | |
} | |
} | |
gotoxy(5+ycord*4, 3+xcord*2); | |
return 1; | |
} | |
//============================================================================= | |
// ----- Joc Nou -> Timp | |
//============================================================================= | |
// functia afiseaza la ecran timpul de la inceputul jocului | |
void timp(){ | |
// salveaza cordonatele curente | |
int dx = wherex(), dy = wherey(); | |
// salveaza timpul curent | |
timp_sfirsit = time(NULL); | |
// pleaca la cordonatele cronometrului | |
gotoxy(21, xzone * 2 + 3); | |
textbackground(7); | |
textcolor(10); | |
// facem diferenta de timp | |
timp_curent = difftime(timp_sfirsit, timp_start); | |
// afisam timpul curent + timpul de la ultima joaca | |
printf("%4.0f", timp_curent + timp_salvat); | |
// plecam iarasi la cordonatele noastre | |
gotoxy(dx, dy); | |
textbackground(8); | |
culoare_celula_fundal(0); | |
} | |
//============================================================================= | |
// ----- Joc Nou -> Mine Ramasa | |
//============================================================================= | |
// functie ce afiseaza la ecran numarul minelor ramase nebifate | |
// aceasta e o functie derivata a timpului | |
// este asemanatoare ei | |
void mine_ramase(){ | |
// savalm cordonatele | |
int dx = wherex(), dy = wherey(); | |
// plecam la zona de afisare a minelor | |
gotoxy(10, xzone * 2 + 3); | |
textbackground(7); | |
textcolor(10); | |
// afisam numarul de mine | |
printf("%3d", (mine_au_ramas == -mines)? mine_au_ramas : mine_au_ramas--); | |
gotoxy(dx, dy); | |
textbackground(8); | |
culoare_celula_fundal(0); | |
} | |
//============================================================================= | |
// ----- Joc Nou -> Pierdere | |
//============================================================================= | |
// functia este apelata atunci cind sa deschis o mina | |
// ea deschide toate minele ramase | |
// minele indicate gresit vor avea culaore neagra | |
// cele bifate corect vor avea culaore rosu inchis | |
// cele nebifate rosu deschis | |
int pierdere(){ | |
textcolor(15); | |
textbackground(12); | |
for (int i = 0; i < xzone; i++){ | |
for (int j = 0; j < yzone; j++){ | |
// daca celula ascunsa e mina dar bifata nu e mina atunci o afiseaza | |
if ( (teren[i][j].celula == 15) && (teren[i][j].vizual != 15) ){ | |
gotoxy( 5+j*4, 3+i*2 ); | |
gotoxy(wherex()-1, wherey()); | |
printf(" %c ", teren[xcord][ycord].celula); | |
gotoxy(wherex()-2, wherey()); | |
} | |
// daca celula e bifata gresit atunci ea va fi afisata cu un fundal negru | |
if ( (teren[i][j].vizual == 15) && (teren[i][j].celula != 15) ){ | |
gotoxy( 5+j*4, 3+i*2 ); | |
gotoxy(wherex()-1, wherey()); | |
textbackground(0); | |
printf(" %c ", teren[xcord][ycord].vizual); | |
textbackground(12); | |
gotoxy(wherex()-2, wherey()); | |
} | |
} | |
} | |
// functia meniu_la_final afiseaza un meniu si returneaza | |
// 1 - iesire in meniu | |
// 2 - joc nou | |
// 3 - repeta jocul | |
return meniu_la_final(1); | |
} | |
//============================================================================= | |
// ----- Joc Nou -> Victorie | |
//============================================================================= | |
// functia verifica da nu sa cistiga jocul | |
// sunt doua moduri de a verifica daca sa cistigat jocul | |
// 1. daca sau bifat toate minele corect | |
// 2. daca sau deschis toate zonele fara mine | |
int victorie(int x){ | |
// cind parametrul este 1 atunci verificam in modul 1 | |
// cind parametru leste 1 atunci functia se foloseste atunci cind se bifeaza | |
if (!x){ | |
for(int i = 0; i < xzone; i++){ | |
for(int j = 0; j < yzone; j++){ | |
// daca conditia este indplinita automat se returnoeaza | |
if ( (teren[i][j].celula != 15) && (teren[i][j].celula != teren[i][j].vizual) ){ | |
return 0; | |
} | |
} | |
} | |
// cind parametrul este 0 atunci verificam in modul 2 | |
// cind parametru leste 0 atunci functia se foloseste atunci cind se deschide mina | |
}else{ | |
for(int i = 0; i < xzone; i++){ | |
for(int j = 0; j < yzone; j++){ | |
// daca conditia este indplinita automat se returnoeaza | |
if ( (teren[i][j].celula == 15) && (teren[i][j].celula != teren[i][j].vizual) ){ | |
return 0; | |
} | |
} | |
} | |
} | |
// daca se ajunge aici inseamna ca victoria exista | |
// funtia meniu_la_final se foloseste si in cazul victoriei | |
return meniu_la_final(0); | |
} | |
//============================================================================= | |
// ----- Joc Nou -> Meniu la final de joc | |
//============================================================================= | |
// functia afiseaza un meniu pe mijlocul ferestrei | |
int meniu_la_final(int x){ | |
textcolor(15); | |
textbackground(4); | |
int marime_fereastra_x, marime_fereastra_y; | |
// functia marimi_fereastra determina marimea ferestrei | |
// valorile sunt schimbate deoarece sunt trimse adresele variabilelor | |
marimi_fereastra(&marime_fereastra_x, &marime_fereastra_y); | |
int dx = marime_fereastra_x, dy = marime_fereastra_y; | |
gotoxy(dx/2-8, dy/2-5); | |
// afisam un patrat rosu inchis | |
for (int i = 0; i < 10; i++){ | |
for(int j = 0; j < 20 ; j++){ | |
printf(" "); | |
} | |
gotoxy(dx/2-8, wherey()+1); | |
} | |
gotoxy(marime_fereastra_x/2-7, marime_fereastra_y/2-4); | |
// in dependenta de parametru | |
// afiseaza ca am cistigat sau pierdut | |
if ( x ){ | |
printf("Ati pierdut: "); | |
sunet(1); | |
}else{ | |
// daca am cistigat | |
printf("Ati cistigat: "); | |
sunet(3); | |
// functia retine_punctaj cere numele utilizatorului | |
// si il introduce in punctaje in dependenta de timpul jucat | |
retine_punctaj(); | |
} | |
// afisam meniul | |
// acesta este meniul care ne returneaza de fiecare data | |
// daca iesim in meniu, jucam din nou sau repetam jocul | |
gotoxy(dx/2-8, wherey()+3); | |
printf(" ESC -> Meniu "); | |
gotoxy(dx/2-8, wherey()+2); | |
printf(" ENTER -> Joc Nou "); | |
gotoxy(dx/2-8, wherey()+2); | |
printf(" SPACE -> Repeta "); | |
char ch; | |
do{ | |
ch = getch(); | |
switch( ch ){ | |
case 27 : return 1; | |
case 13 : return 2; | |
case 32 : return 3; | |
} | |
} while(1); | |
} | |
//============================================================================= | |
// ----- Joc Nou -> Retine Puctaj | |
//============================================================================= | |
// functia retine punctajul de la utilizator | |
void retine_punctaj(){ | |
PUNCTAJ scor_curent; | |
int dx = wherex(), dy = wherey(); | |
arata_cursor(true); | |
gotoxy(wherex()-20, wherey()+2); | |
printf(" Nickname: "); | |
gotoxy(wherex()-11, wherey()+2); | |
printf(" >> "); | |
// citim numele utilizatorului | |
scanf("%s", &scor_curent.nume); | |
// atribuim timpul curent | |
scor_curent.timp = timp_curent + timp_salvat; // modificare curenta + timp salvat ////////////////////////////////////////////// | |
// functia adauga_scor ia ca parametru adresa variabilei ce retine scorul | |
// si adauga in tabloul de scoruri inforamtia | |
adauga_scor(&scor_curent); | |
arata_cursor(false); | |
gotoxy(dx-20, dy+2); | |
for(int i = 0; i < 20; i++) printf(" "); | |
gotoxy(dx-20, dy+4); | |
for(int i = 0; i < 20; i++) printf(" "); | |
gotoxy(dx, dy); | |
} | |
//============================================================================= | |
// ----- Joc Nou -> Retine Puctaj -> Adauga scor in lista | |
//============================================================================= | |
// functia adauga scorul primit ca parametru in vector | |
void adauga_scor(PUNCTAJ *scor_curent){ | |
// mai intii sortam vectorul | |
sorteaza_scor(); | |
// dupa care verificam daca scorul curent e mai bun ca ultimul scor din tablou | |
// daca da atunci il punem la sfirsit | |
if ((*scor_curent).timp < scoruri[4].timp) scoruri[4] = *scor_curent; | |
// si sortam iar tabloul pentru a avea datele corect | |
sorteaza_scor(); | |
} | |
//============================================================================= | |
// ----- Joc Nou -> Retine Puctaj -> Sorteaza Scor | |
//============================================================================= | |
// functia sorteaza un tablou ascendent | |
void sorteaza_scor(){ | |
for(int i = 0; i < 4; i++){ | |
for(int j = i+1; j < 5; j++){ | |
if (scoruri[j].timp <= scoruri[i].timp) | |
// schimba valorile a 2 variabile | |
swap(&scoruri[j], &scoruri[i]); | |
} | |
} | |
} | |
//============================================================================= | |
// ----- Schimbarea continutului a 2 variabile | |
//============================================================================= | |
// functia schimba valorile variabilelor | |
void swap(PUNCTAJ *x, PUNCTAJ *y){ | |
PUNCTAJ aux; | |
aux = *x; | |
*x = *y; | |
*y = aux; | |
} | |
//============================================================================= | |
// ----- Joc Nou -> Retine Puctaj -> Scrie scor in fisier | |
//============================================================================= | |
// functia scrie in fisier tabloul nostru cu scoruri | |
void scrie_scoruri(){ | |
// deschidem fisier pentru scriere in mod binar | |
FILE *f = fopen("bin\\highscore.bin", "wb"); | |
for(int i = 0; i < 5; i++){ | |
fwrite(&scoruri[i], sizeof(scoruri[i]), 1, f); | |
} | |
fclose(f); | |
} | |
//============================================================================= | |
// ----- Joc Nou -> Retine Puctaj -> Citeste scor din fisier | |
//============================================================================= | |
// functia citeste din fisier scorurile | |
void citeste_scoruri(){ | |
// deschidem fiser pentru citire in mod binar | |
FILE *f = fopen("bin\\highscore.bin", "rb"); | |
// citim din fisier fiecare scor | |
for(int i = 0; i < 5; i++){ | |
fread(&scoruri[i], sizeof(scoruri[i]), 1, f); | |
} | |
fclose(f); | |
} | |
//============================================================================= | |
// ----- Punctaje | |
//============================================================================= | |
// functia deseana un simplu tabel in care se indica punctajele | |
void punctaj(){ | |
clrscr(); | |
deseana_meniu(5, 17, 6); | |
for(int i = 0; i < 5; i++){ | |
gotoxy(5, 3+i*2); | |
printf("%s", scoruri[i].nume); | |
gotoxy(23, 3+i*2); | |
printf("%4.0f", scoruri[i].timp); | |
} | |
getch(); | |
} | |
//============================================================================= | |
// ----- Optiuni | |
//============================================================================= | |
// functia permite de a seta optiunile standarte sau personale | |
void setari(){ | |
clrscr(); | |
// afisare un meniu | |
deseana_meniu(5, 3, 14); | |
gotoxy(9, 3); | |
textcolor(15); | |
printf("Incepator"); | |
gotoxy(9, 5); | |
printf("Intermediar"); | |
gotoxy(9, 7); | |
printf("Avansat"); | |
gotoxy(9, 9); | |
printf("Personal"); | |
gotoxy(9, 11); | |
printf("Meniu"); | |
textcolor(7); | |
gotoxy(5, 3); | |
// functia alege_itemi returneaza un numar din 5 incepind cu 1 | |
int n = alege_itemi(5, 1); | |
// in dependenta de ce am ales avem | |
switch (n){ | |
// setarile pentru incepatori | |
case 1 : setari_incepator(); return; | |
// setarile pentru intermediari | |
case 2 : setari_intermediar(); return; | |
// setarile pentru avansati | |
case 3 : setari_avansat(); return; | |
// setarile personale | |
case 4 : setari_proprii(); return; | |
// nre reintoarcem in meniu | |
case 5 : return; | |
} | |
} | |
//============================================================================= | |
// ----- Optiuni >> Setari incepator | |
//============================================================================= | |
void setari_incepator(){ | |
xzone = 9; | |
yzone = 9; | |
mines = 10; | |
} | |
//============================================================================= | |
// ----- Optiuni >> Setari intermediar | |
//============================================================================= | |
void setari_intermediar(){ | |
xzone = 16; | |
yzone = 16; | |
mines = 40; | |
} | |
//============================================================================= | |
// ----- Optiuni >> Setari avansat | |
//============================================================================= | |
void setari_avansat(){ | |
xzone = 16; | |
yzone = 30; | |
mines = 90; | |
} | |
//============================================================================= | |
// ----- Optiuni >> Setari proprii | |
//============================================================================= | |
// setam marimil personale | |
void setari_proprii(){ | |
// deseana meniu | |
deseana_meniu(4, 20, 3); | |
gotoxy(5,3); | |
textcolor(15); | |
printf("Inaltime 9 >> 24 "); | |
gotoxy(5,5); | |
printf("Latime 9 >> 30 "); | |
gotoxy(5,7); | |
printf("Bombe 10 >> 360"); | |
gotoxy(5,9); | |
printf("Meniu"); | |
int count = 1; | |
gotoxy(26,3); | |
punct1: | |
// alegem un item din 4 | |
int n = alege_itemi(4, count); | |
arata_cursor(true); | |
switch(n){ | |
case 1 : | |
gotoxy(5, wherey()); | |
printf(" "); | |
gotoxy(5, wherey()); | |
textcolor(10); | |
// citim numarul de zone pe vertiacala | |
scanf("%d", &xzone); | |
gotoxy(5, wherey()-1); | |
printf(" "); | |
gotoxy(5, wherey()); | |
cprintf("Inaltime >> "); | |
// in cazul ca se depasesc anumite limite setarile vor fi implicite | |
if (xzone < 9 || xzone > 24){ | |
if (xzone < 9){ | |
cprintf("9"); | |
xzone = 9; | |
}else{ | |
cprintf("24"); | |
xzone = 24; | |
} | |
}else{ | |
cprintf("%d", xzone); | |
} | |
count = 1; | |
gotoxy(26,3); | |
arata_cursor(false); | |
goto punct1; | |
case 2 : | |
gotoxy(5, wherey()); | |
printf(" "); | |
gotoxy(5, wherey()); | |
textcolor(10); | |
// citim numarul de zone pe orizontala | |
scanf("%d", &yzone); | |
gotoxy(5, wherey()-1); | |
printf(" "); | |
gotoxy(5, wherey()); | |
cprintf("Latime >> "); | |
// in cazul ca se depasesc anumite limite setarile vor fi implicite | |
if (yzone < 9 || yzone > 30){ | |
if (yzone < 9){ | |
cprintf("9"); | |
yzone = 9; | |
}else{ | |
cprintf("30"); | |
yzone = 30; | |
} | |
}else{ | |
cprintf("%d", yzone); | |
} | |
count = 2; | |
gotoxy(26,5); | |
arata_cursor(false); | |
goto punct1; | |
case 3 : | |
gotoxy(5, wherey()); | |
printf(" "); | |
gotoxy(5, wherey()); | |
textcolor(10); | |
// citim numarul de mine dorite | |
scanf("%d", &mines); | |
gotoxy(5, wherey()-1); | |
printf(" "); | |
gotoxy(5, wherey()); | |
cprintf("Bombe >> "); | |
// in cazul ca se depasesc anumite limite setarile vor fi implicite | |
// nu putem seta mine mai mult ca jumatate din celule | |
if ( mines < 10 || mines > (xzone * yzone * 0.5) ){ | |
if (mines < 10){ | |
cprintf("10"); | |
mines = 10; | |
}else{ | |
cprintf("%.0f", xzone * yzone * 0.5); | |
mines = xzone * yzone * 0.5; | |
} | |
}else{ | |
cprintf("%d", mines); | |
} | |
count = 3; | |
gotoxy(26,7); | |
arata_cursor(false); | |
goto punct1; | |
case 4 : return; | |
} | |
} | |
//============================================================================= | |
// ----- Ajutor | |
//============================================================================= | |
void ajutor(){ | |
int n; | |
clrscr(); | |
// deseana meniu | |
deseana_meniu(3, 3, 14); | |
textcolor(15); | |
gotoxy(9, 3); | |
printf("Taste"); | |
gotoxy(9, 5); | |
printf("Instructiuni"); | |
gotoxy(9,7); | |
printf("Meniu"); | |
gotoxy(5,3); | |
int count = 1; | |
eticheta: | |
// alegem un item din 3 incepind cu "count" | |
n = alege_itemi(3, count); | |
switch(n){ | |
case 1 : ajutor_taste(); break; | |
// functia system executa comenzi ce le poate executa si consola | |
case 2 : system("notepad ReadMe.txt"); count = 2; goto eticheta; | |
case 3 : return; | |
} | |
} | |
//============================================================================= | |
// ----- Ajutor > Taste folosite | |
//============================================================================= | |
void ajutor_taste(){ | |
char ch; | |
clrscr(); | |
// afisam toate tastele foliste si functiile lor | |
deseana_meniu(7, 13, 7); | |
textcolor(15); | |
gotoxy(5,3); printf("Sus"); | |
gotoxy(19, wherey()); printf("%c", 30); | |
gotoxy(5,wherey()+2); printf("Jos"); | |
gotoxy(19, wherey()); printf("%c", 31); | |
gotoxy(5,wherey()+2); printf("Stinga"); | |
gotoxy(19, wherey()); printf("%c", 17); | |
gotoxy(5,wherey()+2); printf("Dreapta"); | |
gotoxy(19, wherey()); printf("%c", 16); | |
gotoxy(5,wherey()+2); printf("Dezamorsare"); | |
gotoxy(19, wherey()); printf("Enter"); | |
gotoxy(5,wherey()+2); printf("Bifeaza"); | |
gotoxy(19, wherey()); printf("Space"); | |
gotoxy(5,wherey()+2); printf("Meniu"); | |
gotoxy(19, wherey()); printf("ESC"); | |
do{ | |
ch = getch(); | |
}while(ch != 27); | |
return; | |
} | |
//============================================================================= | |
// ----- Meniu principal | |
//============================================================================= | |
int meniu(){ | |
clrscr(); | |
int items = 6; | |
// deseana meniu | |
deseana_meniu(items, 3, 14); | |
gotoxy(9, 3); | |
textcolor(15); | |
printf("Joc Nou "); | |
gotoxy(wherex()-12, wherey()+2); | |
printf("Continua Joc"); | |
gotoxy(wherex()-12, wherey()+2); | |
printf("Punctaj "); | |
gotoxy(wherex()-12, wherey()+2); | |
printf("Optiuni "); | |
gotoxy(wherex()-12, wherey()+2); | |
printf("Ajutor "); | |
gotoxy(wherex()-12, wherey()+2); | |
printf("Iesire "); | |
textcolor(7); | |
gotoxy(5, 3); | |
// alege un item din items incepind cu 1 | |
int n = alege_itemi(items, 1); | |
return n; | |
} | |
//============================================================================= | |
// ----- Mineaza terenul | |
//============================================================================= | |
// functia pregateste terenul pentru joc | |
void mineaza_teren(){ | |
// genereaza matricea de structuri | |
genereaza_teren(); | |
// ii atribuie careva valori standarte | |
verifica_teren(); | |
// plantam minele pe teren | |
planteaza_mine(); | |
// adaugam numerele pe teren | |
adauga_numere(); | |
} | |
//============================================================================= | |
// ----- Genereaza terenul | |
//============================================================================= | |
// functia aloca memorie pentru teren | |
void genereaza_teren(){ | |
// daca teren deja exista il eliberam | |
if (teren) curata_teren(); | |
// alocam un vector de pointeri | |
teren = (CELL **)malloc(xzone * sizeof(CELL *)); | |
// pentru fiecare pointer creat alocam un vector de structuri | |
for(int i = 0; i < xzone; i++){ | |
teren[i] = (CELL *)malloc(yzone * sizeof(CELL)); | |
} | |
} | |
//============================================================================= | |
// ----- Verificarea terenului si nivelarea lui | |
//============================================================================= | |
// functia verifica terenul de denivelari | |
void verifica_teren(){ | |
for(int i = 0; i < xzone; i++){ | |
for(int j = 0; j < yzone; j++){ | |
// setam valorile standart pentru teren | |
// teren celula nu va fi setat in cazul cind vom repeta jocul | |
if (!repetam_jocul) teren[i][j].celula = ' '; | |
// com reseta doar vizual | |
teren[i][j].vizual = '#'; | |
} | |
} | |
} | |
//============================================================================= | |
// ----- Planteaza Mine | |
//============================================================================= | |
// functia data planteaza mine pe o matrice | |
void planteaza_mine(){ | |
int Zcnt = xzone * yzone, someRandom, tmpIndex; | |
// X si Y vor fi cordonatele unde plantam mina | |
// Z este un vector cu valorile de la 0 la Zcnt | |
int X, Y, *Z = (int *)malloc(Zcnt * sizeof(int)); | |
for (int i = 0; i < Zcnt; i++) Z[i] = i; | |
srand(time(NULL)); | |
// vom repeta ciclul de atitea ori de cite mine avem nevoie | |
// folosim vectorul Z pentru a nu primi de fiecare data aceleasi valori | |
// cu ajutorul lui randomizarea se face si mai eficienta | |
for (int i = 0; i < mines; i++){ | |
someRandom = rand() % Zcnt; | |
X = Z[someRandom] % yzone; | |
Y = Z[someRandom] / yzone; | |
teren[Y][X].celula = 15; | |
tmpIndex = Z[someRandom]; | |
Z[someRandom] = Z[Zcnt-1]; | |
Z[Zcnt-1] = tmpIndex; | |
Zcnt--; | |
} | |
// eliberare vectorul Z | |
free(Z); | |
} | |
//============================================================================= | |
// ----- Adauga numere | |
//============================================================================= | |
// functia adauga numere pe matrice | |
void adauga_numere(){ | |
// verificam pentru fiecare celula in parte | |
for (int i = 0; i < xzone; i++){ | |
for (int j = 0; j < yzone; j++){ | |
// daca e spatiu liber atunci cream numar pentru celula | |
if (teren[i][j].celula == ' ') creaza_numere(i,j); | |
} | |
} | |
} | |
//============================================================================= | |
// ----- Creaza numere | |
//============================================================================= | |
// functia urmatoare creaza un numar pe o zona anumita | |
void creaza_numere(int i, int j){ | |
int k = 0; | |
// verificam toate celulele din jurul celulei curente | |
// si daca sunt mine sumam in k cite sunt | |
if ( (i-1 >= 0) && (j-1 >= 0) && (teren[i-1][j-1].celula == 15) ) k++; | |
if ( (i-1 >= 0) && (teren[i-1][j].celula == 15) ) k++; | |
if ( (i-1 >= 0) && (j+1 < yzone) && (teren[i-1][j+1].celula == 15) ) k++; | |
if ( (j-1 >= 0) && (teren[i][j-1].celula == 15) ) k++; | |
if ( (j+1 < yzone) && (teren[i][j+1].celula == 15)) k++; | |
if ( (i+1 < xzone) && (j-1 >= 0) && (teren[i+1][j-1].celula == 15)) k++; | |
if ( (i+1 < xzone) && (teren[i+1][j].celula == 15)) k++; | |
if ( (i+1 < xzone) && (j+1 < yzone) && (teren[i+1][j+1].celula == 15)) k++; | |
// daca k e diferit de 0 atunci celulei ii atribuim cifra corespunzatoare lui k | |
if (k) teren[i][j].celula = '0' + k; | |
} | |
//============================================================================= | |
// ----- Curata terenul | |
//============================================================================= | |
// functia eliereaza memoria ocupata de teren | |
void curata_teren(){ | |
// mai intii verificam daca el exista | |
if (teren){ | |
// eliberam fiecare pointer de structuri in parte | |
for(int i = 0; i < xzone; i++) free(teren[i]); | |
// dupa care eliberam pointerul final | |
free(teren); | |
// ii atribuim NULL pentru a nu fi careva erori | |
teren = NULL; | |
} | |
} | |
//============================================================================= | |
// ----- Alegere un punct din meniu | |
//============================================================================= | |
// functia returneaza un numar din items | |
int alege_itemi(int items, int count){ | |
char ch; | |
// afiseaza o mina in meniu | |
pune_mina(); | |
do{ | |
ch = getch(); | |
switch(ch){ | |
// tasta Esc | |
case 27 : | |
return 6; | |
// tasta Enter | |
case 13 : | |
// la tastare enter se returneaza valoare unmarata | |
return count; | |
// cinta un sunet | |
sunet(2); | |
// tasta sageata in sus | |
case 72 : | |
// daca count inca nu a ajuns la 1 | |
if(count > 1 ){ | |
// misca punctul din meniu in sus | |
in_sus(); | |
sunet(2); | |
count--; | |
}else{ | |
// misca punctul din meniu la sfirsitul meniului | |
dute_jos(items); | |
sunet(2); | |
count = count + items - 1; | |
} | |
break; | |
// tasta sageata in jos | |
case 80 : | |
// daca count inca nu a ajuns la numarul de itemi | |
if(count < items){ | |
// misca punctul din meniu in jos | |
in_jos(); | |
sunet(2); | |
count++; | |
}else{ | |
// misca punctul din meniu in top | |
dute_sus(items); | |
sunet(2); | |
count = count - items + 1; | |
} | |
break; | |
} | |
}while(1); | |
} | |
//============================================================================= | |
// ----- Pornim un sunet | |
//============================================================================= | |
// functia cinta un sunet in dependenta de parametru primit | |
void sunet(int n){ | |
// PlaySound este o functie din biblioteca windows.h | |
switch(n){ | |
case 1 : PlaySound("sounds\\mine.wav", NULL, SND_FILENAME); break; | |
case 2 : PlaySound("sounds\\keys.wav", NULL, SND_FILENAME); break; | |
case 3 : PlaySound("sounds\\win.wav", NULL, SND_FILENAME); break; | |
} | |
} | |
//============================================================================= | |
// ----- Lasam mina la ultimul element din lista | |
//============================================================================= | |
void dute_jos(int items){ | |
curata_mina(); | |
gotoxy(wherex(),wherey()+(items-1)*2); | |
pune_mina(); | |
} | |
//============================================================================= | |
// ----- Ridicam mina la primul element din lista | |
//============================================================================= | |
void dute_sus(int items){ | |
curata_mina(); | |
gotoxy(wherex(),wherey()-(items-1)*2); | |
pune_mina(); | |
} | |
//============================================================================= | |
// ----- Ridicam mina din meniu in sus | |
//============================================================================= | |
void in_sus(){ | |
curata_mina(); | |
gotoxy(wherex(),wherey()-2); | |
pune_mina(); | |
} | |
//============================================================================= | |
// ----- lasam mina din meniu in jos | |
//============================================================================= | |
void in_jos(){ | |
curata_mina(); | |
gotoxy(wherex(),wherey()+2); | |
pune_mina(); | |
} | |
//============================================================================= | |
// ----- Afisare mina | |
//============================================================================= | |
void pune_mina(){ | |
textcolor(12); | |
cprintf("%c\b", 15); | |
textcolor(7); | |
} | |
//============================================================================= | |
// ----- Stergem mina | |
//============================================================================= | |
void curata_mina(){ | |
cprintf(" \b"); | |
} | |
//============================================================================= | |
// ----- Afisare teren | |
//============================================================================= | |
void afisare_teren(){ | |
char command[100]; | |
// functia system primeste ca parametru doar siruri de caractere | |
// de aia salvez comenzile intr-un sir de caractere | |
// setez marimea ferestrei | |
sprintf(command, "mode %d,%d", yzone * 4 + 5, xzone * 2 + 5); | |
// si apelez comdanda | |
system(command); | |
// setam culorile de desenare | |
system("color 70"); | |
textbackground(7); | |
textcolor(0); | |
// desenam terenul stiind codurile ASCII ale caracterelor necesare | |
printf("\n "); | |
putchar(201); | |
for(int i = 0; i < yzone - 1; i++){ | |
putchar(205); | |
putchar(205); | |
putchar(205); | |
putchar(203); | |
} | |
putchar(205); | |
putchar(205); | |
putchar(205); | |
putchar(187); | |
printf("\n "); | |
for(int i = 0; i < xzone - 1; i++){ | |
for(int j = 0; j < yzone; j++){ | |
putchar(186); | |
putchar(32); | |
putchar(32); | |
putchar(32); | |
} | |
putchar(186); | |
printf("\n "); | |
putchar(204); | |
for(int j = 0; j < yzone - 1; j++){ | |
putchar(205); | |
putchar(205); | |
putchar(205); | |
putchar(206); | |
} | |
putchar(205); | |
putchar(205); | |
putchar(205); | |
putchar(185); | |
printf("\n "); | |
} | |
for(int j = 0; j < yzone; j++){ | |
putchar(186); | |
putchar(32); | |
putchar(32); | |
putchar(32); | |
} | |
putchar(186); | |
printf("\n "); | |
putchar(204); | |
for(int j = 0; j < 2; j++){ | |
putchar(205); | |
putchar(205); | |
putchar(205); | |
putchar(202); | |
} | |
putchar(205); | |
putchar(205); | |
putchar(203); | |
for(int j = 0; j < 2; j++){ | |
putchar(202); | |
putchar(205); | |
putchar(205); | |
putchar(205); | |
} | |
putchar(202); | |
putchar(205); | |
putchar(205); | |
putchar(203); | |
for(int j = 0; j < yzone-6; j++){ | |
putchar(202); | |
putchar(205); | |
putchar(205); | |
putchar(205); | |
} | |
putchar(185); | |
printf("\n "); | |
putchar(186); | |
textcolor(12); | |
cprintf(" Mine "); | |
textcolor(0); | |
putchar(186); | |
textcolor(12); | |
cprintf(" Timp "); | |
textcolor(0); | |
putchar(186); | |
textcolor(12); | |
cprintf(" ESC:Iesire "); | |
textcolor(0); | |
gotoxy(wherex()+(yzone-9)*4, wherey()); | |
putchar(186); | |
printf("\n "); | |
putchar(200); | |
for(int j = 0; j < 10; j++){ | |
putchar(205); | |
} | |
putchar(202); | |
for(int j = 0; j < 11; j++){ | |
putchar(205); | |
} | |
putchar(202); | |
for(int j = 0; j < (yzone-5)*4-4; j++){ | |
putchar(205); | |
} | |
putchar(188); | |
gotoxy(5,3); | |
} | |
//============================================================================= | |
// ----- Desenarea meniului | |
//============================================================================= | |
// deseneaza un meniu cu "items" rinduri | |
// avind 2 coloane prima cu lungimea "length1" | |
// a 2 cu lungimea "length2" | |
void deseana_meniu (int items, int length1, int length2){ | |
char command[100]; | |
sprintf(command, "mode %d, %d", length1+length2+7, 2*(items-1)+5); | |
system(command); | |
system("color 03"); | |
textbackground(0); | |
textcolor(3); | |
gotoxy(3,2); | |
putchar(201); | |
for (int i = 0; i < length1; i++) putchar(205); | |
putchar(203); | |
for (int i = 0; i < length2; i++) putchar(205); | |
putchar(187); | |
gotoxy(3, wherey()+1); | |
putchar(186); | |
gotoxy(wherex()+length1, wherey()); | |
putchar(186); | |
gotoxy(wherex()+length2, wherey()); | |
putchar(186); | |
gotoxy(3, wherey()+1); | |
for (int i = 0; i < items-1; i++){ | |
putchar(204); | |
for (int j = 0; j < length1; j++) putchar(205); | |
putchar(206); | |
for (int j = 0; j < length2; j++) putchar(205); | |
putchar(185); | |
gotoxy(3, wherey()+1); | |
putchar(186); | |
gotoxy(wherex()+length1, wherey()); | |
putchar(186); | |
gotoxy(wherex()+length2, wherey()); | |
putchar(186); | |
gotoxy(3, wherey()+1); | |
} | |
putchar(200); | |
for (int i = 0; i < length1; i++) putchar(205); | |
putchar(202); | |
for (int i = 0; i < length2; i++) putchar(205); | |
putchar(188); | |
textcolor(7); | |
gotoxy(5,3); | |
} | |
//============================================================================= | |
// ----- Afisare cursor | |
//============================================================================= | |
// aceasta functie seteaza cursorul | |
// foloseste biblioteca windows.h | |
void arata_cursor(bool show){ | |
// tip de date ce determina consola | |
HANDLE hConsoleOutput; | |
// o structura de date in care se salveaza setarile cursorului | |
CONSOLE_CURSOR_INFO structCursorInfo; | |
// determinare consola | |
hConsoleOutput = GetStdHandle( STD_OUTPUT_HANDLE ); | |
// sustrage datele despre cursor | |
GetConsoleCursorInfo( hConsoleOutput, &structCursorInfo ); | |
// setam cimpul .bVisible = tipul indicat ca parametru care este de tipp boolean | |
structCursorInfo.bVisible = show; | |
// setam optiunea curenta a cursorului | |
SetConsoleCursorInfo( hConsoleOutput, &structCursorInfo ); | |
} | |
//============================================================================= | |
// ----- Marimi fereastra | |
//============================================================================= | |
// functia determina marimile consolei | |
void marimi_fereastra(int *x, int *y){ | |
// tip de date ce determina consola | |
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); | |
// structura de date in care se salveaza informatia despre fereastra | |
CONSOLE_SCREEN_BUFFER_INFO csbi; | |
// sustragem datele despre fereastra | |
GetConsoleScreenBufferInfo(hStdout, &csbi); | |
// trimitem informatia necesara catre parametri | |
*x = csbi.srWindow.Right - csbi.srWindow.Left + 1; | |
*y = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; | |
} | |
//============================================================================= | |
// ----- Sfirsit program | |
//============================================================================= | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment