Skip to content

Instantly share code, notes, and snippets.

@unrevised6419
Last active August 23, 2017 19:14
Show Gist options
  • Save unrevised6419/d4ed4f08343bb3a59f8d84a8bf1a84fe to your computer and use it in GitHub Desktop.
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
//=============================================================================
// ----- 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