Created
July 23, 2012 23:12
-
-
Save Phitherek/3166846 to your computer and use it in GitHub Desktop.
Minesweeper v. 0.1
This file contains 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
// Minesweeper v. 0.1 (c) 2012 by Phitherek_ | |
#include <iostream> // Do streamów IO | |
#include <cstdlib> // EXIT_SUCCESS i inne przydatne rzeczy z C | |
#include <iomanip> // Do manipulacji streamem IO - ustawienie szerokości wierszy, aby zwiększyć czytelność planszy | |
using namespace std; // Odkrycie standardowej przestrzeni nazw - bo nic nam nie będzie kolidować z tą przestrzenią | |
struct field { // Struktura opisująca pole na planszy: | |
int bomb; // Czy jest bomba na tym polu? 1 - tak, 0 - nie | |
int checked; // Czy pole jest odkryte? 1 - tak, 0 - nie | |
int ba; // Ilość bomb wokół pola | |
int flag; // Flaga: 0 - brak, 1 - flaga, 2 - flaga jako niepewne (?) | |
}; | |
char itoa(int i) { // Funkcja zamieniająca liczby na znaki: | |
if(i == 0) { // Jeżeli i jest 0 | |
return '0'; // zwróć znak 0 | |
} else if(i == 1) { // itd... | |
return '1'; | |
} else if(i == 2) { | |
return '2'; | |
} else if(i == 3) { | |
return '3'; | |
} else if(i == 4) { | |
return '4'; | |
} else if(i == 5) { | |
return '5'; | |
} else if(i == 6) { | |
return '6'; | |
} else if(i == 7) { | |
return '7'; | |
} else if(i == 8) { | |
return '8'; | |
} else if(i == 9) { | |
return '9'; | |
} | |
} | |
char convert_printable(field f) { // Funkcja wypisująca pole w formacie możliwym do wyświetlenia na planszy: | |
if(f.checked == 0) { // Jeżeli pole nie jest odkryte: | |
if(f.flag == 0) { // Jeżeli nie ma flagi | |
return '#'; // Zwróć # - znak normalnego zakrytego pola | |
} else if(f.flag == 1) { // Jeżeli jest normalna flaga | |
return 'F'; // Zwróć F - znak flagi | |
} else if(f.flag == 2) { // Jeżeli jest flaga jako niepewne | |
return '?'; // Zwróć ? - znak flagi jako niepewne | |
} | |
} else if(f.checked == 1) { // Jeżeli pole jest odkryte: | |
if(f.bomb == 0) { // Jeżeli na polu nie ma bomby | |
return itoa(f.ba); // Zwróć znak oznaczający liczbę bomb wokół pola (konwersja za pomocą powyższej funkcji itoa) | |
} else { // Jeżeli na polu jest bomba | |
return 'o'; // Zwróć o - znak bomby | |
} | |
} | |
} | |
void display_board(field** board, int x, int y) { // Funkcja wyświetlająca planszę | |
cout << setw(2) << " " << " "; // Wyświetl 2 spacje o szerokości 2 | |
for(int i = 0; i < y; i++) { // Wyświetlenie numerów kolumn | |
cout << setw(2) << i << " "; // Wyświetl numer kolumny i spację po nim - o szerokości 2 | |
} | |
cout << endl; // Przejdź do następnej linii | |
for(int i = 0; i < x; i++) { // Pętla przechodząca po kolejnych wierszach planszy | |
cout << setw(2) << i << " "; // Wyświetl numer wiersza i spację - o szerokości 2 | |
for(int j = 0; j < y; j++) { // Pętla przechodząca po elementach wiersza | |
char tp; // Znak do wyświetlenia (ToPrint) | |
tp = convert_printable(board[i][j]); // Zdobądź znak danego pola za pomocą powyższej funkcji convert_printable | |
cout << setw(2) << tp << " "; // Wyświetl znak pola i spację - o szerokości 2 | |
} | |
cout << endl; // Przejdź do następnej linii | |
} | |
} | |
field** uncover_board(field** board, int x, int y) { // Funkcja odsłaniająca wszystkie pola w planszy | |
for(int i = 0; i < x; i++) { // Dwie pętle przechodzące po planszy | |
for(int j = 0; j < y; j++) { | |
board[i][j].checked = 1; // Odsłoń bieżące pole | |
} | |
} | |
return board; // Zwróć odsłoniętą planszę | |
} | |
field** uncover(field** board, int x, int y, int i, int j, int* flp) { // Funkcja odsłaniająca pole w planszy | |
int fl = *flp; // Wyłuskaj wartość licznika pól | |
if(i > -1 and i < x and j > -1 and j < y) { // Jeżeli nie wyszliśmy poza zakres planszy | |
if(board[i][j].checked == 0) { // Jeżeli pole nie jest jeszcze odsłonięte | |
if(board[i][j].ba > 0) { // Jeżeli są jakieś bomby wokół pola | |
board[i][j].checked = 1; // Odsłoń pole | |
fl--; // Zmniejsz licznik pól w funkcji | |
*flp = fl; // Zaktualizuj zewnętrzny licznik pól przez wskaźnik | |
} else { // Jeżeli nie ma bomb wokół pola | |
board[i][j].checked = 1; // Odsłoń pole | |
fl--; // Zmniejsz licznik pól w funkcji | |
*flp = fl; // Zaktualizuj zewnętrzny licznik pól przez wskaźnik | |
// Wywołaj rekursywnie funkcję odsłaniającą pole w planszy dla wszystkich pól wokół bieżącego: | |
board = uncover(board, x, y, i-1, j-1, flp); | |
board = uncover(board, x, y, i-1, j, flp); | |
board = uncover(board, x, y, i-1, j+1, flp); | |
board = uncover(board, x, y, i, j-1, flp); | |
board = uncover(board, x, y, i, j+1, flp); | |
board = uncover(board, x, y, i+1, j-1, flp); | |
board = uncover(board, x, y, i+1, j, flp); | |
board = uncover(board, x, y, i+1, j+1, flp); | |
} | |
} | |
} | |
return board; // Zwróć zmienioną planszę | |
} | |
field** gen_board(field** board, int x, int y, int l) { // Funkcja generująca planszę | |
srand(time(NULL)); // Zainicjuj generator liczb losowych | |
cout << "Generowanie planszy..." << endl; // Wyświetl informację o generowaniu planszy | |
for(int i = 0; i < x; i++) { // Zainicjuj wszystkie parametry pól w nowej planszy wartością 0 | |
for(int j = 0; j < y; j++) { | |
board[i][j].bomb = 0; | |
board[i][j].checked = 0; | |
board[i][j].ba = 0; | |
board[i][j].flag = 0; | |
} | |
} | |
while(l > 0) { // Dopóki mamy jeszcze bomby do rozstawienia | |
for(int i = 0; i < x; i++) { // Przechodzimy po planszy | |
for(int j = 0; j < y; j++) { | |
if (l > 0) { // Jeżeli mamy jeszcze bomby do rozstawienia | |
if(board[i][j].bomb == 0) { // Jeżeli na tym polu nie ma jeszcze bomby | |
int ch; // Zmienna przechowująca wartość losową | |
ch = rand()%10; // Wylosuj liczbę z zakresu 0-9 | |
if(ch == 5) { // Jeżeli liczba ta jest równa 5 | |
board[i][j].bomb = 1; // Przypisz bombę do bieżącego pola | |
} | |
if(board[i][j].bomb == 1) { // Jeżeli została wygenerowana bomba | |
l--; // Zmniejsz liczbę bomb pozostałych do rozstawienia | |
} | |
} | |
} | |
board[i][j].checked = 0; // Dla pewności zakrywamy bieżące pole | |
} | |
} | |
} | |
for(int i = 0; i < x; i++) { // Zliczanie parametru BombsAround - bomb wokół każdego pola - przechodzimy po planszy | |
for(int j = 0; j < y; j++) { | |
int bac = 0; // Dla danego pola inicjujemy licznik bomb wokół niego (BombsAroundCounter) | |
int a = i-1; // Zaczynamy od pola w górę i na lewo od bieżącego | |
int b = j-1; | |
if(a > -1 and b > -1 and a < x and b < y) { // Jeżeli nie jesteśmy poza zakresem | |
bac += board[a][b].bomb; // Dodaj wartość 1 lub 0 parametru bomb - czyli licznik zwiększy się, jak bomba będzie na polu | |
} | |
b++; // I tak dla każdego pola wokół bieżącego... | |
if(a > -1 and b > -1 and a < x and b < y) { | |
bac += board[a][b].bomb; | |
} | |
b++; | |
if(a > -1 and b > -1 and a < x and b < y) { | |
bac += board[a][b].bomb; | |
} | |
b = b-2; | |
a++; | |
if(a > -1 and b > -1 and a < x and b < y) { | |
bac += board[a][b].bomb; | |
} | |
b = b+2; | |
if(a > -1 and b > -1 and a < x and b < y) { | |
bac += board[a][b].bomb; | |
} | |
b = b-2; | |
a++; | |
if(a > -1 and b > -1 and a < x and b < y) { | |
bac += board[a][b].bomb; | |
} | |
b++; | |
if(a > -1 and b > -1 and a < x and b < y) { | |
bac += board[a][b].bomb; | |
} | |
b++; | |
if(a > -1 and b > -1 and a < x and b < y) { | |
bac += board[a][b].bomb; | |
} | |
board[i][j].ba = bac; // Ustaw parametr ba (BombsAround) dla danego pola - jest równy zliczonej ilości bomb | |
board[i][j].flag = 0; // Ustaw brak flagi dla bieżącego pola | |
} | |
} | |
return board; // Zwróć wygenerowaną planszę | |
} | |
int main() { // Główna funkcja programu | |
cout << "Minesweeper v. 0.1 (c) 2012 by Phitherek_" << endl; // Wyświetl nazwę programu, rok i autora, a jakże :) | |
int x, y, l; // Rozmiar planszy x*y, liczba bomb l | |
cout << "Podaj rozmiar planszy: " << endl << "x: "; // Prosimy użytkownika o rozmiar planszy - x | |
cin >> x; // Wczytujemy x | |
cout << "y: "; // Prosimy użytkownika o y | |
cin >> y; // Wczytujemy y | |
cout << "Podaj ilość bomb: "; // Prosimy użytkownika o ilość bomb l | |
cin >> l; // Wczytujemy l | |
char action = 'r'; // Ustawiamy bieżącą akcję - r (restart gry) | |
field **board = NULL; // Tworzymy tablicę reprezentującą planszę gry | |
board = new field *[x]; // Tworzymy tablicę wskaźników na początki wierszy | |
for(int i = 0; i < x; i++) { | |
board[i] = new field[y]; // Tworzymy wiersze | |
} | |
while(action != 'q') { // Dopóki akcja to nie q - wyjście - GŁÓWNA PĘTLA PROGRAMU | |
int status, bl, fl; // Tworzymy zmienne opisujące stan gry, liczbę bomb i liczbę pól | |
if(action == 'r') { // Jeżeli akcja to r - restart gry | |
board = gen_board(board, x, y, l); // Generujemy planszę | |
cout << "Rozpoczynam grę!" << endl; // I rozpoczynamy grę! | |
action = 'g'; // Zatem akcja to g - gra | |
status = 0; // Stan to 0, czyli gracz nie natknął się na bombę | |
bl = l; // Wczytaj liczbę bomb | |
fl = x*y; // Oblicz i wczytaj liczbę pól | |
} else if(action == 'g') { // Jeżeli gramy (akcja: g - gra) | |
if(status == 0) { // Jeżeli stan to 0 - gracz nie natknął się jeszcze na bombę | |
if(bl == fl) { // Jeżeli liczba pozostałych pól jest równa liczbie bomb... to gracz wygrał! | |
board = uncover_board(board, x, y); // Odsłaniamy planszę | |
cout << endl; // Na wszelki wypadek przechodzimy do nowej linii | |
display_board(board, x, y); // Wyświetlamy planszę | |
cout << endl; // Przechodzimy do nowej linii | |
cout << "Status: :D (WYGRANA!)" << endl << "r - Zagraj ponownie, q - wyjdź: "; // Wyświetlamy radosny status wygranej i pytamy użytkownika, co dalej | |
cin >> action; // Pobieramy akcję | |
if(action == 'q') { // Jeżeli akcja to q - wyjście | |
break; // Przerywamy główną pętlę programu | |
} // A jeżeli nie | |
continue; // To puszczamy kolejną iterację głównej pętli programu | |
} else { // Jeżeli liczba pozostałych pól to nie liczba bomb to gra trwa nadal | |
cout << "Status: :)" << endl; // Wyświetl uśmiechnięty status | |
} | |
} else { // Jeżeli jednak status to 1, czyli gracz stanął na bombie | |
board = uncover_board(board, x, y); // Odkrywamy planszę | |
cout << endl; // Na wszelki wypadek przechodzimy do nowej linii | |
display_board(board, x, y); // Wyświetlamy planszę | |
cout << endl; // Przechodzimy do nowej linii | |
cout << "Status: :( (PRZEGRANA!)" << endl << "r - Zagraj ponownie, q - wyjdź: "; // Wyświetlamy smutny status przegranej i pytamy użytkownika, co dalej | |
cin >> action; // Pobieramy akcję | |
if(action == 'q') { // Jeżeli akcja to q - wyjście | |
break; // Przerywamy główną pętlę programu | |
} // A jeżeli nie | |
continue; // Puszczamy kolejną iterację głównej pętli programu | |
} | |
cout << "Pozostało bomb: " << bl << endl << "Pozostało pól: " << fl << endl; // Wyświetlamy ilość bomb i pozostałych pól | |
display_board(board, x, y); // Wyświetlamy planszę | |
int c, d; // Zmienne c,d - współrzędne bieżącego pola | |
cout << endl << "Wprowadź współrzędne pola:" << endl << "Wiersz: "; // Prosimy użytkownika o indeks wiersza | |
cin >> c; // Wczytujemy indeks wiersza | |
cout << "Kolumna: "; // Prosimy użytkownika o indeks kolumny | |
cin >> d; // Wczytujemy indeks kolumny | |
if(c > -1 and c < x and d > -1 and d < y) { // Jeżeli pole jest na planszy | |
char sasasa; // Zmienna sasasa (od SubAction) - przechowuję podakcję akcji g - gra | |
cout << "o - odsłoń, f - o(d)flaguj, ? - o(d)flaguj jako niepewne: "; // Pytamy użytkownika o podakcję - co chce zrobić z polem | |
cin >> sasasa; // Pobieramy podakcję | |
if(sasasa == 'o') { // Jeżeli podakcja to o - odsłonięcie pola | |
if(board[c][d].checked == 1) { // Jeżeli pole jest już odsłonięte | |
cout << "Pole już odsłonięte!" << endl; // To informujemy użytkownika, że coś mu się chyba pomyliło | |
} else { // Jeżeli nie jest odsłonięte | |
if(board[c][d].bomb == 1) { // Jeżeli mamy bombę na polu | |
cout << "BOMBA!!!" << endl; // Ehm, playerze, stanąłeś na bombie... | |
status = 1; // Status: 1 - przegrana | |
} else { // W przeciwnym wypadku | |
uncover(board, x, y, c, d, &fl); // Odsłaniamy pole | |
} | |
} | |
} else if(sasasa == 'f') { // Jeżeli podfunkcja to f - flaga | |
if(board[c][d].flag == 1) { // Jeżeli pole jest oflagowane | |
board[c][d].flag = 0; // Zdejmij flagę | |
} else { // W przeciwnym wypadku | |
board[c][d].flag = 1; // Ustaw flagę | |
} | |
} else if(sasasa == '?') { // Jeżeli podakcja to ? - flaga jako niepewne | |
if(board[c][d].flag == 2) { // Jeżeli pole jest oflagowane jako niepewne | |
board[c][d].flag = 0; // Zdejmij flagę jako niepewne | |
} else { // W przeciwnym wypadku | |
board[c][d].flag = 2; // Ustaw flagę jako niepewne | |
} | |
} else { // Jeżeli podakcja to cokolwiek innego | |
cout << "Zły wybór!" << endl; // To niedobrze | |
} | |
} else { // Jeżeli jesteśmy poza zakresem planszy | |
cout << "Brak takiego pola!" << endl; // No to niedobrze | |
} | |
} | |
} | |
cout << "Dziękuję za grę!" << endl; // Zakończenie programu - ładnie dziękujemy za grę | |
return EXIT_SUCCESS; // I mówimy systemowi, że jest wszystko w porządku | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment