You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

256 lines
8.6 KiB
C

/*
* spielfeld.c
*
* Created on: Mar 15, 2024
* Author: Nico
*/
#include "spielfeld.h"
#include "main.h"
int** generateGameBoard(int size) {
// Speicher für das Spielfeld reservieren
int** gameBoard = (int**)malloc(size * sizeof(int*));
for (int i = 0; i < size; i++) {
gameBoard[i] = (int*)malloc(size * sizeof(int));
}
// Initialisierung des Spielfelds
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
gameBoard[i][j] = EMPTY_CELL;
}
}
return gameBoard;
}
uint32_t random_int(void) {
uint32_t z;
HAL_RNG_GenerateRandomNumber(&hrng, &z);
return z;
}
void placeBombs(int** gameBoard, int size, int numBombs) {
// Zufälligen Seed initialisieren
srand(random_int());
// Platzieren der Bomben
while (numBombs > 0) {
int x = rand() % size;
int y = rand() % size;
if (gameBoard[x][y] != BOMB_CELL) {
gameBoard[x][y] = BOMB_CELL;
numBombs--;
}
}
// Berechnen der Zahlen um die Bomben herum und Markieren mit NUMBER_CELL
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
if (gameBoard[i][j] != BOMB_CELL) {
int count = 0;
// Überprüfe die Zellen um die aktuelle Zelle (i, j)
for (int dx = -1; dx <= 1; dx++) {
for (int dy = -1; dy <= 1; dy++) {
int newX = i + dx;
int newY = j + dy;
// Überprüfe, ob die Zelle innerhalb des Spielfelds liegt und eine Bombe enthält
if (newX >= 0 && newX < size && newY >= 0 && newY < size && gameBoard[newX][newY] == BOMB_CELL) {
count++;
}
}
}
// Setze die Anzahl der umliegenden Bomben in die aktuelle Zelle
gameBoard[i][j] = count;
}
}
}
}
void displayGameBoardUART(int** gameBoard, int size, int numBombs, int numFlags) {
// Leere den Empfangspuffer der UART-Schnittstelle
clearSerialBuffer(&huart2);
char buffer[600]; // Puffer für den formatierten String
int offset = 0; // Offset für die Position im Puffer
offset += snprintf(buffer + offset, sizeof(buffer) - offset, "\rSpielfeld:\r");
// Formatieren des Spielfelds in den Puffer
offset += snprintf(buffer + offset, sizeof(buffer) - offset, "\r\n\n "); // Leerzeichen für die Ausrichtung
// Spaltenbezeichnungen (A, B, C, ...)
for (int i = 0; i < size; i++) {
char column = 'A' + i;
offset += snprintf(buffer + offset, sizeof(buffer) - offset, " %c", column);
}
offset += snprintf(buffer + offset, sizeof(buffer) - offset, "\r\n");
for (int i = 0; i < size; i++) {
offset += snprintf(buffer + offset, sizeof(buffer) - offset, "%2d ", i + 1); // Zeilennummer
for (int j = 0; j < size; j++) {
if (gameBoard[i][j] == BOMB_CELL) {
offset += snprintf(buffer + offset, sizeof(buffer) - offset, "* "); // Bombe
} else if (gameBoard[i][j] == EMPTY_CELL) {
offset += snprintf(buffer + offset, sizeof(buffer) - offset, ". "); // Leerzelle
} else if (gameBoard[i][j] == HIDDEN_CELL) {
offset += snprintf(buffer + offset, sizeof(buffer) - offset, "# "); // Verdeckte Zelle
} else if (gameBoard[i][j] == FLAG_CELL) {
offset += snprintf(buffer + offset, sizeof(buffer) - offset, "? "); // Verdeckte Zelle
} else {
offset += snprintf(buffer + offset, sizeof(buffer) - offset, "%d ", gameBoard[i][j]); // Zahl
}
}
offset += snprintf(buffer + offset, sizeof(buffer) - offset, "\r\n");
}
// Anzeige der verbleibenden Anzahl von Bomben
offset += snprintf(buffer + offset, sizeof(buffer) - offset, "\r\nVerbleibende Anzahl von Bomben: %d\r\n", numBombs - numFlags);
// Senden des formatierten Strings über UART
HAL_UART_Transmit(&huart2, (uint8_t*)buffer, offset, 100);
}
void freeGameBoard(int** gameBoard, int size) {
for (int i = 0; i < size; i++) {
free(gameBoard[i]);
}
free(gameBoard);
}
void freeHiddenGameBoard(int** hiddenGameBoard, int size) {
for (int i = 0; i < size; i++) {
free(hiddenGameBoard[i]);
}
free(hiddenGameBoard);
}
int** createHiddenGameBoard(int** gameBoard, int size) {
int** hiddenGameBoard = (int**)malloc(size * sizeof(int*));
for (int i = 0; i < size; i++) {
hiddenGameBoard[i] = (int*)malloc(size * sizeof(int));
}
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
hiddenGameBoard[i][j] = HIDDEN_CELL;
}
}
return hiddenGameBoard;
}
void getNewPosition(Position* pos, int dx, int dy, Position* newPos) {
newPos->col = pos->col + dy;
newPos->row = pos->row + dx;
}
void revealEmptyCells(int** gameBoard, int** hiddenGameBoard, int size, Position pos) {
// Aufdecken der leeren Zelle
hiddenGameBoard[pos.row][pos.col] = gameBoard[pos.row][pos.col];
// Wenn die Zelle leer ist, müssen auch benachbarte leere Zellen aufgedeckt werden
if (hiddenGameBoard[pos.row][pos.col] == EMPTY_CELL) {
for (int dx = -1; dx <= 1; dx++) {
for (int dy = -1; dy <= 1; dy++) {
if (dx == 0 && dy == 0) continue; // Überspringe die aktuelle Zelle
Position newPos;
getNewPosition(&pos, dx, dy, &newPos);
// Überprüfen, ob die benachbarte Zelle innerhalb des Spielfelds liegt und verdeckt ist
if (newPos.row >= 0 && newPos.row < size && newPos.col >= 0 && newPos.col < size && hiddenGameBoard[newPos.row][newPos.col] == HIDDEN_CELL) {
// Wenn die benachbarte Zelle leer ist, rekursiv fortfahren
revealEmptyCells(gameBoard, hiddenGameBoard, size, newPos);
}
}
}
}
}
int revealCell(int** gameBoard, int** hiddenGameBoard, int size, int row, int col) {
Position pos;
pos.row = row;
pos.col = col;
// Überprüfen, ob die Position im gültigen Bereich liegt
if (pos.row < 0 || pos.row >= size || pos.col < 0 || pos.col >= size) {
printf("Ungültige Position\n");
}
// Überprüfen, ob die Zelle bereits aufgedeckt ist
if (hiddenGameBoard[pos.row][pos.col] != HIDDEN_CELL) {
printf("Position bereits aufgedeckt\n");
}
if (gameBoard[pos.row][pos.col] == BOMB_CELL) {
handleBombExploded();
return 0;
}
// Wenn die Zelle leer ist, müssen auch benachbarte leere Zellen aufgedeckt werden
if (gameBoard[pos.row][pos.col] == EMPTY_CELL) {
revealEmptyCells(gameBoard, hiddenGameBoard, size, pos);
} else {
// Aufdecken der Zelle im verdeckten Spielfeld
hiddenGameBoard[pos.row][pos.col] = gameBoard[pos.row][pos.col];
}
return 1;
}
void setFlag(int** hiddenGameBoard, int row, int col, int* numFlags) {
if (hiddenGameBoard[row][col] == FLAG_CELL)
{
hiddenGameBoard[row][col] = HIDDEN_CELL;
(*numFlags)--;
}
else if (hiddenGameBoard[row][col] == HIDDEN_CELL)
{
hiddenGameBoard[row][col] = FLAG_CELL;
(*numFlags)++;
}
}
int checkWin(int** gameBoard, int** hiddenGameBoard, int size, int numBombs, int numFlags) {
// Überprüfen, ob alle Bombenpositionen mit einer Flagge markiert wurden
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
if (gameBoard[i][j] == BOMB_CELL && hiddenGameBoard[i][j] != FLAG_CELL) {
return 0; // Nicht gewonnen, da nicht alle Bomben markiert sind
}
}
}
// Überprüfen, ob alle nicht-Bombenfelder aufgedeckt wurden
int totalCells = size * size;
int uncoveredCells = 0;
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
if (gameBoard[i][j] != BOMB_CELL && hiddenGameBoard[i][j] != HIDDEN_CELL) {
uncoveredCells++;
}
}
}
// Das Spiel ist gewonnen, wenn alle nicht-Bombenfelder aufgedeckt wurden und alle Bomben mit einer Flagge markiert wurden
if (uncoveredCells == totalCells - numBombs && numFlags == numBombs) {
char message[] = "Herzlichen Glückwunsch! Du hast gewonnen! Starte neu mit der ON Taste.\r\n";
HAL_UART_Transmit(&huart2, (uint8_t*)message, sizeof(message), 100);
return 1;
}
}
void handleBombExploded() {
char message[] = "Spiel Verloren! Du hast eine Bombe getroffen\r\n";
HAL_UART_Transmit(&huart2, (uint8_t*)message, sizeof(message), 100);
}