Skip to content
Snippets Groups Projects
main.cpp 5.26 KiB
Newer Older
  • Learn to ignore specific revisions
  • Pelotrio's avatar
    Pelotrio committed
    #include <iostream>
    #include <ctime>
    #include <cstring>
    
    #include <fstream>
    #include <unordered_set>
    #include <map>
    #include <algorithm>
    
    Pelotrio's avatar
    Pelotrio committed
    #include <vector>
    #include "Field.h"
    
    
    #define DEBUG true
    
    Pelotrio's avatar
    Pelotrio committed
    
    using namespace std;
    
    
    map<string, int> highScores;
    
    string loadInstructions();
    
    bool menu(const string &instructionsString);
    
    void gameLoop();
    
    string getInput();
    
    void loadHighscores();
    
    void saveHighscores();
    
    
    Pelotrio's avatar
    Pelotrio committed
    void printHighscores();
    
    Pelotrio's avatar
    Pelotrio committed
    int main() {
        cout << "Mini-Minesweeper" << endl;
    
        string instructionsString = loadInstructions();
        loadHighscores();
    
    Pelotrio's avatar
    Pelotrio committed
        while (menu(instructionsString)) {}
    
    Pelotrio's avatar
    Pelotrio committed
    
    
        // Save highscores
        saveHighscores();
        return 0;
    }
    
    Pelotrio's avatar
    Pelotrio committed
    
    
    void saveHighscores() {
        ofstream highscoresFile("C:\\Users\\Admin\\CLionProjects\\MiniMineSweeper\\resources\\highscores.txt");
    
    Pelotrio's avatar
    Pelotrio committed
        for (auto &highScore: highScores) {
    
            highscoresFile << highScore.first << " " << highScore.second << endl;
    
    Pelotrio's avatar
    Pelotrio committed
        }
    
        highscoresFile.close();
    }
    
    bool menu(const string &instructionsString) {
        cout << "(1) Anleitung" << endl;
        cout << "(2) Spielen" << endl;
        cout << "(3) Highscores" << endl;
        cout << "(4) Beenden" << endl;
    
        int choice;
        cin >> choice;
        switch (choice) {
            case 1:
                cout << instructionsString << endl;
                break;
            case 2:
                gameLoop();
                break;
            case 3:
                cout << "Highscores" << endl;
    
    Pelotrio's avatar
    Pelotrio committed
                // Sort highscores
                printHighscores();
    
                break;
            case 4:
                return false;
            default:
                cout << "Falsche Eingabe" << endl;
                break;
    
    Pelotrio's avatar
    Pelotrio committed
        }
    
        return true;
    }
    
    
    Pelotrio's avatar
    Pelotrio committed
    void printHighscores() {
        vector<pair<string, int>> highscoreVector(highScores.begin(), highScores.end());
        sort(highscoreVector.begin(), highscoreVector.end(), [](const pair<string, int> &a, const pair<string, int> &b) {
            return a.second > b.second;
        });
        for (auto &highscore: highscoreVector) {
            cout << highscore.first << ": " << highscore.second << endl;
        }
    
    }
    
    void gameLoop() {
    
    Pelotrio's avatar
    Pelotrio committed
        Field field;
    
    Pelotrio's avatar
    Pelotrio committed
    
    
    Pelotrio's avatar
    Pelotrio committed
        field.generateMines();
        field.fillHiddenBoard();
        if (DEBUG) field.printHiddenBoard();
    
    Pelotrio's avatar
    Pelotrio committed
    
        bool gameOver = false;
        int moves = 0;
        while (!gameOver) {
            // Print the board
    
    Pelotrio's avatar
    Pelotrio committed
            field.printBoard();
    
    Pelotrio's avatar
    Pelotrio committed
    
            // Get the input in format "B3"
    
            string input = getInput();
    
    Pelotrio's avatar
    Pelotrio committed
    
            bool isFlag = false;
            // Check if a flag should be set
            if (input.rfind("Flag", 0) == 0) {
                input = input.substr(5);
                isFlag = true;
            }
    
    
    Pelotrio's avatar
    Pelotrio committed
            int col = input[0] - 'A';
    
    Pelotrio's avatar
    Pelotrio committed
            int row = input.length() == 2 ? input[1] - '0' - 1 : 9;
    
    Pelotrio's avatar
    Pelotrio committed
    
    
    Pelotrio's avatar
    Pelotrio committed
            if (isFlag) {
                field.flagField(row, col);
                continue;
            }
    
            if (!field.isOpen(row, col)) {
                if (field.isMine(row, col)) {
    
    Pelotrio's avatar
    Pelotrio committed
                    gameOver = true;
    
    Pelotrio's avatar
    Pelotrio committed
                    cout << "Du hast verloren!" << endl;
                    cout << "Du hast " << moves << " Züge gebraucht." << endl;
    
                    // Save highscore and let the user enter his name
                    cout << "Dein Name: ";
                    string name;
                    cin >> name;
                    // Compare the highscore with the existing ones and save it if it is better only insert up to 10
                    if (highScores.size() < 10 || moves < highScores.rbegin()->second) {
                        // Insert the new highscore at the right position only overwrite if the score is better
                        int score = highScores.at(name);
                        if (score == 0 || moves > score) {
                            highScores.insert({name, moves});
                        }
                    }
    
    Pelotrio's avatar
    Pelotrio committed
                } else {
                    field.openField(row, col);
                    moves++;
    
    Pelotrio's avatar
    Pelotrio committed
                }
            } else {
                cout << "Sie haben bereits auf dieses Feld geklickt!" << endl;
                continue;
            }
        }
    
    Pelotrio's avatar
    Pelotrio committed
    
    
    string getInput() {
        string input;
    
    Pelotrio's avatar
    Pelotrio committed
        // Get the input in format "B3" and the option to flag a field with "Flag B3"
        while (true) {
            getline(cin, input);
            if (input.rfind("Flag ", 0) == 0) {
    
    Pelotrio's avatar
    Pelotrio committed
            if (input.length() == 2) {
                if (input[0] >= 'A' && input[0] <= 'J' && input[1] >= '1' && input[1] <= '9') {
                    break;
    
    Pelotrio's avatar
    Pelotrio committed
            } else if (input.length() == 3) {
                if (input[0] >= 'A' && input[0] <= 'J' && input[1] == '1' && input[2] == '0') {
                    break;
    
    Pelotrio's avatar
    Pelotrio committed
            cout << "Falsche Eingabe" << endl;
    
    Pelotrio's avatar
    Pelotrio committed
        return input;
    
    }
    
    string loadInstructions() {
        // Load instructions from file TODO relative path
        ifstream instructions("C:\\Users\\Admin\\CLionProjects\\MiniMineSweeper\\resources\\instructions.txt");
        // Check if file is open and load all lines into a string
        string instructionsString;
        if (instructions.is_open()) {
            string line;
            while (getline(instructions, line)) {
                instructionsString += line + "\n";
            }
        }
        return instructionsString;
    }
    
    void loadHighscores() {
        ifstream highscoresFile("C:\\Users\\Admin\\CLionProjects\\MiniMineSweeper\\resources\\highscores.txt");
        string line;
        while (getline(highscoresFile, line)) {
            string name = line.substr(0, line.find(' '));
            int score = stoi(line.substr(line.find(' ') + 1));
            highScores.insert({name, score});
        }
    }