Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define _WIN32_WINNT 0x0500///imi trebuie pentru procedura MaximizeOutputWindow
- #include <stdio.h>
- #include <time.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <windows.h>
- #include <conio.h>
- class cell
- {
- public:
- bool viz;
- bool wall;///daca e perete sau nu
- bool trav;///daca are calator in el
- bool m_start;
- bool m_end;
- int x;
- int y;///coordonate celula
- int nod;///ce nod este
- void ini(int i, int j, int &k)///are rol de constructor
- {
- viz=false;
- trav=false;
- m_start=false;
- m_end=false;
- x=i;
- y=j;
- nod=0;
- if (!(i%2 == 0 && j%2 == 0))
- wall=true;
- else
- {
- wall=false;
- nod=k;
- k++;
- }
- };
- };
- const int dimmax=77;
- const int d[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
- struct mcoord
- {
- int x,y;
- };
- cell mtrx[dimmax+1][dimmax+1];
- cell vect[(dimmax)*(dimmax)-(dimmax/2)*(dimmax/2)+1];
- int index[dimmax*dimmax-(dimmax/2)*(dimmax/2)+1];
- int nrnoduri[(dimmax/2)*(dimmax/2)+1];
- int boss[(dimmax/2)*(dimmax/2)+1];
- mcoord crd[dimmax+1][dimmax+1];
- class tools
- {
- public:
- static void get_size(int &columns, int &rows)
- {
- CONSOLE_SCREEN_BUFFER_INFO csbi;
- GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
- columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
- rows = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
- }
- static void ClearScreen()
- {
- HANDLE hStdOut;
- CONSOLE_SCREEN_BUFFER_INFO csbi;
- DWORD count;
- DWORD cellCount;
- COORD homeCoords = { 0, 0 };
- hStdOut = GetStdHandle( STD_OUTPUT_HANDLE );
- if (hStdOut == INVALID_HANDLE_VALUE) return;
- /* Get the number of cells in the current buffer */
- if (!GetConsoleScreenBufferInfo( hStdOut, &csbi )) return;
- cellCount = csbi.dwSize.X *csbi.dwSize.Y;
- /* Fill the entire buffer with spaces */
- if (!FillConsoleOutputCharacter(
- hStdOut,
- (TCHAR) ' ',
- cellCount,
- homeCoords,
- &count
- )) return;
- /* Fill the entire buffer with the current colors and attributes */
- if (!FillConsoleOutputAttribute(
- hStdOut,
- csbi.wAttributes,
- cellCount,
- homeCoords,
- &count
- )) return;
- /* Move the cursor home */
- SetConsoleCursorPosition( hStdOut, homeCoords );
- }
- static int valid_read()
- {
- int nr;
- unsigned int i;
- bool ok,mistake;
- char s[100];
- ok=false;
- while (!ok)
- {
- nr=0;
- mistake=false;
- scanf("%s",s);
- for (i=0; i < strlen(s); i++)
- {
- if (isdigit(s[i]))
- nr=nr*10+s[i]-'0';
- else
- mistake=true;
- }
- if ((mistake) || (nr < 5) || (nr > 77) || (nr % 2 == 0))
- {
- ClearScreen();
- printf("\nDate invalide! Introduceti din nou numarul!\n");
- }
- else
- ok=true;
- }
- return nr;
- }
- static void color(int i)
- {
- HANDLE hConsole;
- hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
- SetConsoleTextAttribute(hConsole,i);
- }
- static void MaximizeOutputWindow()
- {
- HWND consoleWindow = GetConsoleWindow(); // This gets the value Windows uses to identify your output window
- ShowWindow(consoleWindow, SW_MAXIMIZE); // this mimics clicking on its' maximize button
- }
- static void gotoXY(short int x, short int y)
- {
- //Initialize the coordinates
- COORD coord = {x, y};
- //Set the position
- SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
- return;
- }
- };
- ///procedurile MaximizeOutputWindow, get_size, ClearScreen, color si gotoXY nu au fost implementate de mine; am gasit codul pe internet
- class maze
- {
- static const char c = 219;
- static const char c1 = 0;
- static int findboss(int x)
- {
- while (x != boss[x])
- x=boss[x];
- return x;
- }
- static void cell_merge(int a, int b)
- {
- if (nrnoduri[a] > nrnoduri[b])
- {
- boss[b]=a;
- nrnoduri[a]+=nrnoduri[b];
- }
- else
- {
- boss[a]=b;
- nrnoduri[b]+=nrnoduri[a];
- }
- }
- public:
- static void build (int dim1, int dim2)///initializez labirintul; are rol de constructor
- {
- int i,j,k;
- k=1;
- for (i=1; i<=dim1; i++)
- for (j=1; j<=dim2; j++)
- mtrx[i][j].ini(i,j,k);
- }
- static void draw(int dim1, int dim2)///desenez labirintul
- {
- int i,j,x,y,cl,rw;
- short int cr1,cr2;
- tools::get_size(cl,rw);
- x=(cl-dim2)/2;
- y=(rw-dim1)/2;
- cr1=0;
- for (i=1; i <= y; i++)
- {
- printf("\n");
- cr1++;
- }
- for (i=1; i <= dim1; i++)
- {
- cr2=-1;
- for (j=1; j<=x; j++)
- {
- printf(" ");
- cr2++;
- }
- for (j=1; j<=dim2; j++)
- {
- if (mtrx[i][j].wall == true)///e perete
- {
- tools::color(3);
- printf("%c",c);
- tools::color(15);
- }
- else if (mtrx[i][j].trav == true)///are calator
- {
- tools::color(14);
- printf("%c",c);
- }
- else if (mtrx[i][j].m_start == true)///e inceput de labirint
- {
- tools::color(12);
- printf("S");
- }
- else if (mtrx[i][j].m_end == true)///e sfarsit de labirint
- {
- tools::color(12);
- printf("E");
- }
- else///e celula accesibila
- printf("%c",c1);
- cr2++;
- crd[i][j].x=cr1;
- crd[i][j].y=cr2;
- }
- printf("\n");
- cr1++;
- }
- for (i=1; i <= y; i++)
- printf("\n");
- }
- static void maze_gen(int dim1, int dim2, int &ls, int &cs, int &le, int &ce)
- {
- int i,j,k,x,y,nrcconex,aux,boss1,boss2;
- cell cwall,v1,v2;
- bool ok;
- x=dim1*dim2-(dim2*(dim1/2+1)+(dim2/2+1)*(dim1/2));
- for (i=1; i<=x; i++)
- {
- boss[i]=i;///paduri de multimi disjuncte
- nrnoduri[i]=1;
- }
- nrcconex=x;///numarul de componente conexe
- k=1;
- for (i=1; i<=dim1; i++)
- for (j=1; j<=dim2; j++)
- {
- if (mtrx[i][j].wall == true)
- {
- vect[k]=mtrx[i][j];
- index[k]=k;
- k++;
- }
- }///pun toti peretii intr-un vector si ii indexez, retinand indicii in vectorul index
- srand(time(NULL));///se foloseste inainte de a aplica random
- x=dim2*(dim1/2+1)+(dim2/2+1)*(dim1/2);
- for (i=1; i<=x; i++)
- {
- k=rand()%x;
- k+=1;
- aux=index[i];
- index[i]=index[k];
- index[k]=aux;
- }///sortez intr-un mod random peretii
- k=1;
- while (nrcconex != 1)///c.t. nu am drum intre toate celulele ce trebuie sa fie accesibile din labirint
- {
- cwall=vect[index[k]];///extrag un perete din vectorul de pereti
- x=cwall.x;
- y=cwall.y;///extrag coordonatele peretelui
- ok=false;
- if (x+1 < dim1 && x-1 > 1)///ma asigur ca nu ies din matrice
- {
- if (mtrx[x+1][y].wall == false)///peretele desparte pe verticala 2 celule care nu sunt pereti
- {
- v1=mtrx[x+1][y];
- v2=mtrx[x-1][y];
- ok=true;
- }
- }
- if (y+1 < dim2 && y-1 > 1)///ma asigur ca nu ies din matrice
- {
- if (mtrx[x][y+1].wall == false)///peretele desparte pe orizontala 2 celule care nu sunt pereti
- {
- v1=mtrx[x][y+1];
- v2=mtrx[x][y-1];
- ok=true;
- }
- }
- if (ok)///daca peretele pe care l-am extras desparte 2 celule care nu sunt pereti
- {
- boss1=findboss(v1.nod);
- boss2=findboss(v2.nod);
- if (boss1 != boss2)///celulele nu fac parte din aceeasi componenta conexa
- {
- cell_merge(boss1,boss2);///le unesc
- mtrx[x][y].wall=false;///daram peretele
- nrcconex--;///scad numarul de componente conexe
- }
- }
- k++;///trec la urmatorul perete
- }
- k=rand()%4;///incep sa generez intrarea
- if (k == 0)
- {
- boss1=rand()%(dim1-1)+1;
- boss2=1;
- if (boss1%2 == 1)
- boss1++;
- }
- else if (k == 1)
- {
- boss1=rand()%(dim1-1)+1;
- boss2=dim2;
- if (boss1%2 == 1)
- boss1++;
- }
- else if (k == 2)
- {
- boss1=1;
- boss2=rand()%(dim2-1)+1;
- if (boss2%2 == 1)
- boss2++;
- }
- else if (k == 3)
- {
- boss1=dim1;
- boss2=rand()%(dim2-1)+1;
- if (boss2%2 == 1)
- boss2++;
- }
- mtrx[boss1][boss2].m_start=true;
- mtrx[boss1][boss2].wall=false;
- ls=boss1;
- cs=boss2;
- x=boss1;
- y=boss2;///termin de generat intrarea
- mtrx[boss1][boss2].trav=true;
- while (boss1 == x && boss2 == y)///ma asigur ca iesirea nu coincide cu intrarea
- {
- k=rand()%4;
- if (k == 0)
- {
- boss1=rand()%(dim1-1)+1;
- boss2=1;
- if (boss1%2 == 1)
- boss1++;
- }
- else if (k == 1)
- {
- boss1=rand()%(dim1-1)+1;
- boss2=dim2;
- if (boss1%2 == 1)
- boss1++;
- }
- else if (k == 2)
- {
- boss1=1;
- boss2=rand()%(dim2-1)+1;
- if (boss2%2 == 1)
- boss2++;
- }
- else if (k == 3)
- {
- boss1=dim1;
- boss2=rand()%(dim2-1)+1;
- if (boss2%2 == 1)
- boss2++;
- }
- }
- mtrx[boss1][boss2].m_end=true;///termin de generat iesirea
- mtrx[boss1][boss2].wall=false;
- le=boss1;
- ce=boss2;
- }
- static void solve(int dim1, int dim2, int lc, int cc, bool &ok)///ok este fals la apel
- {
- int i,x,y;
- for (i=0; i<4; i++)
- {
- x=lc+d[i][0];
- y=cc+d[i][1];
- if ((x >=1 && x <= dim1) && (y >=1 && y <= dim2))
- {
- if (mtrx[x][y].wall == false && mtrx[x][y].m_start == false && mtrx[x][y].viz == false && !ok)
- {
- mtrx[x][y].viz=true;
- solve(dim1,dim2,x,y,ok);
- }
- }
- }
- if (mtrx[lc][cc].m_end == true)
- ok=true;
- if (ok)
- mtrx[lc][cc].trav=true;
- }
- static void game(int dim1, int dim2, int ls, int cs, int le, int ce)
- {
- bool ok3,ok2,ok4;
- char key;
- int lc,cc,x,y;
- ok3=false;
- ok2=false;
- lc=ls;///linia curenta=lina de start
- cc=cs;///coloana curenta=coloana de start
- while (ok3 == false && ok2 == false)
- {
- char key = ' ';
- key = _getch();
- if (key == 'w')///sus
- {
- if (lc-1 >=1 && mtrx[lc-1][cc].wall == false)///nu ies din matrice si nu dau de un perete
- {
- x=crd[lc][cc].x;
- y=crd[lc][cc].y;
- mtrx[lc][cc].trav=false;
- tools::gotoXY(y,x);
- if (mtrx[lc][cc].m_start == true)///e inceput de labirint
- {
- tools::color(12);
- printf("S");
- }
- else if (mtrx[lc][cc].m_end == true)///e sfarsit de labirint
- {
- tools::color(12);
- printf("E");
- }
- else///e celula accesibila
- printf("%c",c1);
- x=x-1;
- mtrx[lc-1][cc].trav=true;
- if (mtrx[lc-1][cc].m_end == true)
- ok3=true;
- tools::gotoXY(y,x);
- tools::color(14);
- printf("%c",c);
- lc--;
- }
- }
- if (key == 's')///jos
- {
- if (lc+1 <= dim1 && mtrx[lc+1][cc].wall == false)///nu ies din matrice si nu dau de un perete
- {
- x=crd[lc][cc].x;
- y=crd[lc][cc].y;
- mtrx[lc][cc].trav=false;
- tools::gotoXY(y,x);
- if (mtrx[lc][cc].m_start == true)///e inceput de labirint
- {
- tools::color(12);
- printf("S");
- }
- else if (mtrx[lc][cc].m_end == true)///e sfarsit de labirint
- {
- tools::color(12);
- printf("E");
- }
- else///e celula accesibila
- printf("%c",c1);
- x=x+1;
- mtrx[lc+1][cc].trav=true;
- if (mtrx[lc+1][cc].m_end == true)
- ok3=true;
- tools::gotoXY(y,x);
- tools::color(14);
- printf("%c",c);
- lc++;
- }
- }
- if (key == 'a')///stanga
- {
- if (cc-1 >= 1 && mtrx[lc][cc-1].wall == false)///nu ies din matrice si nu dau de un perete
- {
- x=crd[lc][cc].x;
- y=crd[lc][cc].y;
- mtrx[lc][cc].trav=false;
- tools::gotoXY(y,x);
- if (mtrx[lc][cc].m_start == true)///e inceput de labirint
- {
- tools::color(12);
- printf("S");
- }
- else if (mtrx[lc][cc].m_end == true)///e sfarsit de labirint
- {
- tools::color(12);
- printf("E");
- }
- else///e celula accesibila
- printf("%c",c1);
- y=y-1;
- mtrx[lc][cc-1].trav=true;
- if (mtrx[lc][cc-1].m_end == true)
- ok3=true;
- tools::gotoXY(y,x);
- tools::color(14);
- printf("%c",c);
- cc--;
- }
- }
- if (key == 'd')///dreapta
- {
- if (cc+1 <= dim2 && mtrx[lc][cc+1].wall == false)///nu ies din matrice si nu dau de un perete
- {
- x=crd[lc][cc].x;
- y=crd[lc][cc].y;
- mtrx[lc][cc].trav=false;
- tools::gotoXY(y,x);
- if (mtrx[lc][cc].m_start == true)///e inceput de labirint
- {
- tools::color(12);
- printf("S");
- }
- else if (mtrx[lc][cc].m_end == true)///e sfarsit de labirint
- {
- tools::color(12);
- printf("E");
- }
- else///e celula accesibila
- printf("%c",c1);
- y=y+1;
- mtrx[lc][cc+1].trav=true;
- if (mtrx[lc][cc+1].m_end == true)
- ok3=true;
- tools::gotoXY(y,x);
- tools::color(14);
- printf("%c",c);
- cc++;
- }
- }
- if (key == 'h')
- ok2=true;
- }
- tools::ClearScreen();
- tools::color(15);
- if (ok3)
- printf("Bravo!");
- else
- {
- ok4=false;
- solve(dim1,dim2,lc,cc,ok4);
- draw(dim1,dim2);
- }
- }
- };
- int main()
- {
- int dim1,dim2,ls,cs,le,ce;
- bool ok;
- char c;
- tools::MaximizeOutputWindow();
- tools::color(15);
- printf("MAZE GENERATOR\n\n\n\n");
- printf("1)Alegeti dimensiunile labirintului.\n");
- printf("2)Jucati! (va miscati pe w,a,s,d, iar daca vreti rezolvarea, apasati tasta h)\n\n\n\n");
- printf("Care sunt dimensiunile labirintului?\n");
- printf("(numere ");
- tools::color(12);
- printf("impare");
- tools::color(15);
- printf(" mai mari decat ");
- tools::color(12);
- printf("3");
- tools::color(15);
- printf(" si mai mici decat ");
- tools::color(12);
- printf("79");
- tools::color(15);
- printf(")\n");
- printf("Care este prima dimensiune?\n");
- dim1=tools::valid_read();
- printf("Care este a doua dimensiune?\n");
- dim2=tools::valid_read();
- tools::ClearScreen();
- maze::build(dim1,dim2);
- maze::maze_gen(dim1,dim2,ls,cs,le,ce);
- maze::draw(dim1,dim2);
- maze::game(dim1,dim2,ls,cs,le,ce);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement