#include #include #include #include #include #include #include #include #define size 20 #define mines 60 int tilesLeft = (size * size) - mines; int flags = 0; int cursorX = 0; int cursorY = 0; int timerSeconds = 0; int timerMinutes = 0; //Status hry: 0 = hra nezačala, 1 = výhra, 2 = prohra, 3 = hra běží int gameStatus = 0; char tileField[size][size]; char mineLocations[size][size]; char mineCount[size][size]; char covered = 'c'; char uncovered = '0'; char mine = 'm'; char flag = 'f'; //EMOJI ZOOOOOOOONA //Znaky, které do konzole vypisuje funkce drawField() char coveredTile[] = "🌫️"; char mineTile[] = "💣"; //char cursorTile[] = "💠"; - Nakonec použita barva pozadí místo tohoto char flagTile[] = "🚩"; char zeroTile[] = "⬛"; char oneTile[] = "1️⃣"; char twoTile[] = "2️⃣"; char threeTile[] = "3️⃣"; char fourTile[] = "4️⃣"; char fiveTile[] = "5️⃣"; char sixTile[] = "6️⃣"; char sevenTile[] = "7️⃣"; char eightTile[] = "8️⃣"; int generateStartingField(); int drawField(); int monitorKeys(); int generateMines(); int disableCanonicalMode(); int moveCursorDown(); int moveCursorUp(); int moveCursorLeft(); int moveCursorRight(); int uncoverTiles(); int flagSwitch(); int uncoverMines(); int countMines(); int fastUncover(); int fastUncoverUncoverAndContinue(); int win(); int prepareGame(); int checkForBomb(); int checkFlags(); int startTimer(); int main(){ //Příprava hry srand(time(NULL)); generateStartingField(); generateMines(); countMines(); drawField(); struct termios orig_termios; disableCanonicalMode(&orig_termios); //Průběh hry monitorKeys(); return 0; } //Hlavní herní funkce, která udržuje hru a spouští další funkce int monitorKeys(){ char keyPressed = getchar(); switch(tolower(keyPressed)){ case 'w': moveCursorUp(); break; case 'a': moveCursorLeft(); break; case 'd': moveCursorRight(); break; case 's': moveCursorDown(); break; case 'f': flagSwitch(); break; case 'e': case ' ': uncoverTiles(); } if(tilesLeft < 1){ win(); } drawField(); monitorKeys(); return 0; } void* timer(void* arg) { while (1) { sleep(1); timerSeconds++; if(timerSeconds > 59){ timerSeconds = 0; timerMinutes++; } system("clear"); drawField(); } return NULL; } int prepareGame(){ generateMines(); countMines(); gameStatus = 3; if(mineCount[cursorY][cursorX] == '0'){ startTimer(); return 0; } prepareGame(); return 0; } //Vygeneruje počáteční pole int generateStartingField(){ int i = 0; while(i < size){ int ii = 0; while(ii < size){ tileField[i][ii] = covered; ii++; } i++; } return 0; } //Vygeneruje rozmíštění min int generateMines(){ int i = 0; while(i < size){ int ii = 0; while(ii < size){ mineLocations[i][ii] = '0'; ii++; } i++; } i = 0; while(i != mines){ int mineX = rand() % size; int mineY = rand() % size; mineLocations[mineY][mineX] = 'm'; i++; } return 0; } //Spočítá počet min v okolí všech bloků a uloží pro pozdější užití int countMines(){ int i = 0; while(i < size){ int ii = 0; while(ii < size){ //Pokud je na pozici miny tak skip if(mineLocations[i][ii] == 'm'){ ii++; continue; } int minesNextToTile = 0; minesNextToTile = checkForBomb(ii-1, i, minesNextToTile); minesNextToTile = checkForBomb(ii, i-1, minesNextToTile); minesNextToTile = checkForBomb(ii-1, i-1, minesNextToTile); minesNextToTile = checkForBomb(ii+1, i-1, minesNextToTile); minesNextToTile = checkForBomb(ii-1, i+1, minesNextToTile); minesNextToTile = checkForBomb(ii+1, i+1, minesNextToTile); minesNextToTile = checkForBomb(ii, i+1, minesNextToTile); minesNextToTile = checkForBomb(ii+1, i, minesNextToTile); mineCount[i][ii] = '0' + minesNextToTile; ii++; } i++; } } int checkForBomb(int x, int y, int numberOfMines){ if(x < 0 || x >= size || y < 0 || y >= size || mineLocations[y][x] != 'm'){ return numberOfMines; } return numberOfMines+1; } //Překreslí hrací pole to terminálu int drawField(){ system("clear"); int i = 0; int ii = 0; int fieldSize = sizeof(tileField) / sizeof(tileField[0]); printf("\n"); while(i < fieldSize){ ii = 0; while(ii < fieldSize){ if(gameStatus == 2){ printf("\033[%dm", 40 + 1); } if(gameStatus == 1){ printf("\033[%dm", 40 + 2); } if (i == cursorY && ii == cursorX){ printf("\033[%dm", 40 + 4); } switch (tileField[i][ii]){ case 'c': printf(coveredTile); break; case 'm': printf(mineTile); break; case 'f': printf(flagTile); break; case '0': printf(zeroTile); break; case '1': printf(oneTile); break; case '2': printf(twoTile); break; case '3': printf(threeTile); break; case '4': printf(fourTile); break; case '5': printf(fiveTile); break; case '6': printf(sixTile); break; case '7': printf(sevenTile); break; case '8': printf(eightTile); break; default: printf("n"); } printf(" \033[%dm", 40 + 0); ii++; } printf("\n"); i++; } printf("\n\n\033[%dm", 47); printf(" \033[%dm", 30); printf("POHYB = WASD, VLAJKA = F, ODKRÝT = E nebo SPACE"); printf(" \033[%dm", 40); printf("\n\n\033[%dm", 34); printf("\e[1mZbývá min: "); printf("\033[0;31m%d", mines-flags); printf("\n\033[0;34m\e[1mČas: \033[0;31m"); printf("%d", timerMinutes); printf(":"); //Protože richard je perfekcionalista if(timerSeconds < 10){ printf("0"); } printf("%d", timerSeconds); printf("\033[0;30m\n\n"); return 0; } //Vypnutí can. módu, aby bylo možné zaznamenávat stisk kláves int disableCanonicalMode(struct termios *orig_termios){ struct termios newTermios; tcgetattr(STDIN_FILENO, orig_termios); newTermios = *orig_termios; newTermios.c_lflag &= ~(ICANON | ECHO); newTermios.c_cc[VMIN] = 1; newTermios.c_cc[VTIME] = 0; tcsetattr(STDIN_FILENO, TCSANOW, &newTermios); } //Funkce pro pohybování kurzorem int moveCursorDown(){ if(cursorY != (size - 1)){ cursorY++; } return 0; } int moveCursorUp(){ if(cursorY != 0){ cursorY--; } return 0; } int moveCursorLeft(){ if(cursorX != 0){ cursorX--; } return 0; } int moveCursorRight(){ if(cursorX != (size - 1)){ cursorX++; } return 0; } //Označení tile vlaječkou :3 int flagSwitch(){ startTimer(); char tile = tileField[cursorY][cursorX]; if(tile == covered){ tileField[cursorY][cursorX] = flag; flags++; } if(tile == flag ){ tileField[cursorY][cursorX] = covered; flags--; } if(flags == mines){ checkFlags(); } return 0; } //Odekreje tile nebo ukončí hru pokud narazí na bombu int uncoverTiles(){ if(gameStatus == 0){ prepareGame(); } if(tileField[cursorY][cursorX] == 'f'){ return 0; } if(mineLocations[cursorY][cursorX] == 'm'){ gameStatus = 2; uncoverMines(); printf("\033[%dm", 30 + 1); printf("\nProhrál jsi!\n"); exit(0); } tileField[cursorY][cursorX] = mineCount[cursorY][cursorX]; tilesLeft--; fastUncover(cursorX, cursorY); return 0; } //Odhalí všechny miny int uncoverMines(){ int i = 0; while(i < size){ int ii = 0; while(ii < size){ if(mineLocations[i][ii] == 'm'){ tileField[i][ii] = mine; } ii++; } i++; } drawField(); return 0; } int fastUncover(int x, int y){ if(mineCount[y][x] != '0'){ return 0; } fastUncoverUncoverAndContinue(x-1,y); fastUncoverUncoverAndContinue(x,y-1); fastUncoverUncoverAndContinue(x-1,y-1); fastUncoverUncoverAndContinue(x+1,y-1); fastUncoverUncoverAndContinue(x-1,y+1); fastUncoverUncoverAndContinue(x+1,y+1); fastUncoverUncoverAndContinue(x+1,y); fastUncoverUncoverAndContinue(x,y+1); return 0; } int fastUncoverUncoverAndContinue(int x, int y){ if(!(tileField[y][x] == covered || tileField[y][x] == flag) || x < 0 || x >= size || y < 0 || y >= size){ return 0; } tilesLeft--; tileField[y][x] = mineCount[y][x]; fastUncover(x, y); return 0; } int win(){ gameStatus = 1; uncoverMines(); printf("\033[%dm", 30 + 2); printf("\nVyhrál jsi!\n"); exit(0); return 0; } //Zkontroluje zda jsou flagy správně dané na minách int checkFlags(){ int i = 0; while(i < size){ int ii = 0; while(ii < size){ if(tileField[i][ii] != flag){ ii++; continue; } if(mineLocations[i][ii] != 'm'){ return 0; } ii++; } i++; } win(); return 0; } //Zapnout časoměru int startTimer(){ if(timerSeconds == 0 && timerMinutes == 0){ pthread_t thread_id; int interval = 2; pthread_create(&thread_id, NULL, timer, &interval); } }