nemám rád pojmenovávání commitů

main
jakub 1 year ago
commit 3d498ae176
  1. 473
      minesweeper.c

@ -0,0 +1,473 @@
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>
#include <time.h>
#include <ctype.h>
#include <string.h>
#include <pthread.h>
#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);
}
}
Loading…
Cancel
Save