Код без ошибок компилируется, а когда запускается крашит с ошибкой Expression: vector subscript out of range

#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include "TXLib.h"

const int CELL_SIZE = 50; // Размер ячейки игрового поля
const int INVENTORY_SIZE = 5; // Размер инвентаря электрика
const int MAX_LEVELS = 10; // Количество уровней игры

struct Point
{
    int x;
    int y;
};

struct Wire
{
    Point start;
    Point end;
    int length;
};

struct Socket
{
    Point position;
    int power;
};

struct Lamp
{
    Point position;
    int power;
};

class Game
{
public:
    Game();
    void run();

private:
    void loadLevels();
    void loadLevel(int level);
    void drawGame();
    void drawInventory();
    void drawSettings();
    void drawRating();
    void handleInput();
    void connectWires();
    void checkWin();
    void gameOver();
    void saveRating();
    void loadRating();
    void showRating();

    std::vector<std::vector<int>> levels;
    std::vector<Wire> wires;
    std::vector<Socket> sockets;
    std::vector<Lamp> lamps;
    std::vector<Wire> inventory;
    std::string playerName;
    int currentLevel;
    int score;
    bool gameRunning;
    bool settingsOpen;
    bool ratingOpen;
};

Game::Game()
{
    currentLevel = 0;
    score = 0;
    gameRunning = false;
    settingsOpen = false;
    ratingOpen = false;
}

void Game::loadLevels()
{
    std::ifstream file("levels.txt");
    if (!file)
    {
        std::cout << "Failed to open levels file." << std::endl;
        return;
    }

    std::string line;
    while (std::getline(file, line))
    {
        std::vector<int> level;
        for (char c : line)
        {
            level.push_back(c - '0');
        }
        levels.push_back(level);
    }

    file.close();
}

void Game::loadLevel(int level)
{
    wires.clear();
    sockets.clear();
    lamps.clear();
    inventory.clear();

    std::vector<int> levelData = levels[level];
    int width = levelData[0];
    int height = levelData[1];

    int index = 2;
    for (int y = 0; y < height; y++)
    {
        for (int x = 0; x < width; x++)
        {
            int cell = levelData[index++];
            if (cell == 1)
            {
                Socket socket;
                socket.position = { x, y };
                socket.power = levelData[index++];
                sockets.push_back(socket);
            }
            else if (cell == 2)
            {
                Lamp lamp;
                lamp.position = { x, y };
                lamp.power = levelData[index++];
                lamps.push_back(lamp);
            }
        }
    }
}

void Game::drawGame()
{
    txSetFillColor(TX_WHITE);
    txClear();

    // Отрисовка игрового поля
    for (int y = 0; y < levels[currentLevel][1]; y++)
    {
        for (int x = 0; x < levels[currentLevel][0]; x++)
        {
            txRectangle(x * CELL_SIZE, y * CELL_SIZE, (x + 1) * CELL_SIZE, (y + 1) * CELL_SIZE);
        }
    }

    // Отрисовка проводов
    for (const Wire& wire : wires)
    {
        txSetColor(TX_BLACK);
        txSetFillColor(TX_BLACK);
        txRectangle(wire.start.x * CELL_SIZE, wire.start.y * CELL_SIZE, wire.end.x * CELL_SIZE, wire.end.y * CELL_SIZE);
    }

    // Отрисовка розеток
    for (const Socket& socket : sockets)
    {
        txSetColor(TX_BLUE);
        txSetFillColor(TX_BLUE);
        txRectangle(socket.position.x * CELL_SIZE, socket.position.y * CELL_SIZE, (socket.position.x + 1) * CELL_SIZE, (socket.position.y + 1) * CELL_SIZE);
        txTextOut(socket.position.x * CELL_SIZE + 5, socket.position.y * CELL_SIZE + 5, std::to_string(socket.power).c_str());
    }

    // Отрисовка лампочек
    for (const Lamp& lamp : lamps)
    {
        txSetColor(TX_YELLOW);
        txSetFillColor(TX_YELLOW);
        txRectangle(lamp.position.x * CELL_SIZE, lamp.position.y * CELL_SIZE, (lamp.position.x + 1) * CELL_SIZE, (lamp.position.y + 1) * CELL_SIZE);
        txTextOut(lamp.position.x * CELL_SIZE + 5, lamp.position.y * CELL_SIZE + 5, std::to_string(lamp.power).c_str());
    }

    // Отрисовка инвентаря
    drawInventory();

    // Отрисовка настроек
    if (settingsOpen)
    {
        drawSettings();
    }

    // Отрисовка рейтинга
    if (ratingOpen)
    {
        drawRating();
    }
}

void Game::drawInventory()
{
    int x = 0;
    int y = levels[currentLevel][1] * CELL_SIZE + 10;

    for (const Wire& wire : inventory)
    {
        txSetColor(TX_BLACK);
        txSetFillColor(TX_BLACK);
        txRectangle(x, y, x + wire.length * CELL_SIZE, y + CELL_SIZE);
        txTextOut(x + 5, y + 5, std::to_string(wire.length).c_str());
        x += wire.length * CELL_SIZE + 10;
    }
}

void Game::drawSettings()
{
    // Отрисовка окна настроек
    txSetColor(TX_BLACK);
    txSetFillColor(TX_WHITE);
    txRectangle(100, 100, 500, 300);

    // Отрисовка элементов окна настроек
    txTextOut(150, 150, "Player Name:");
    txTextOut(150, 200, "Difficulty:");

    // Отрисовка кнопки сохранения настроек
    txSetColor(TX_BLACK);
    txSetFillColor(TX_LIGHTGRAY);
    txRectangle(200, 250, 300, 280);
    txTextOut(220, 260, "Save");

    // Отрисовка текущих настроек
    txTextOut(300, 150, playerName.c_str());
    txTextOut(300, 200, "Normal");
}

void Game::drawRating()
{
    // Отрисовка окна рейтинга
    txSetColor(TX_BLACK);
    txSetFillColor(TX_WHITE);
    txRectangle(100, 100, 500, 300);

    // Отрисовка элементов окна рейтинга
    txTextOut(150, 150, "Player Name");
    txTextOut(300, 150, "Games Played");
    txTextOut(400, 150, "Score");

    // Отрисовка кнопки закрытия рейтинга
    txSetColor(TX_BLACK);
    txSetFillColor(TX_LIGHTGRAY);
    txRectangle(200, 250, 300, 280);
    txTextOut(220, 260, "Close");

    // Отрисовка рейтинга
    txTextOut(150, 170, "Player 1");
    txTextOut(300, 170, "10");
    txTextOut(400, 170, "1000");
}

void Game::handleInput()
{
    if (txMouseButtons() & 1)
    {
        POINT mousePos = txMousePos();
        int mouseX = mousePos.x;
        int mouseY = mousePos.y;

        // Обработка клика по игровому полю
        if (mouseY < levels[currentLevel][1] * CELL_SIZE)
        {
            int cellX = mouseX / CELL_SIZE;
            int cellY = mouseY / CELL_SIZE;

            // Проверка, что выбранная ячейка является розеткой
            for (const Socket& socket : sockets)
            {
                if (socket.position.x == cellX && socket.position.y == cellY)
                {
                    // Проверка, что есть выбранный провод в инвентаре
                    if (!inventory.empty())
                    {
                        Wire wire;
                        wire.start = { cellX, cellY };
                        wire.end = { cellX, cellY };
                        wire.length = inventory.back().length;
                        wires.push_back(wire);
                        inventory.pop_back();
                    }
                    break;
                }
            }
        }
        // Обработка клика по инвентарю
        else if (mouseY < levels[currentLevel][1] * CELL_SIZE + CELL_SIZE)
        {
            int x = 0;
            int y = levels[currentLevel][1] * CELL_SIZE + 10;

            for (int i = 0; i < inventory.size(); i++)
            {
                int wireLength = inventory[i].length;
                if (mouseX >= x && mouseX <= x + wireLength * CELL_SIZE && mouseY >= y && mouseY <= y + CELL_SIZE)
                {
                    // Перемещение выбранного провода в конец инвентаря
                    Wire selectedWire = inventory[i];
                    inventory.erase(inventory.begin() + i);
                    inventory.push_back(selectedWire);
                    break;
                }
                x += wireLength * CELL_SIZE + 10;
            }
        }
        // Обработка клика по кнопке настроек
        else if (mouseY >= levels[currentLevel][1] * CELL_SIZE + CELL_SIZE && mouseY <= levels[currentLevel][1] * CELL_SIZE + 2 * CELL_SIZE)
        {
            settingsOpen = !settingsOpen;
        }
        // Обработка клика по кнопке рейтинга
        else if (mouseY >= levels[currentLevel][1] * CELL_SIZE + 2 * CELL_SIZE && mouseY <= levels[currentLevel][1] * CELL_SIZE + 3 * CELL_SIZE)
        {
            ratingOpen = !ratingOpen;
        }
        // Обработка клика по кнопке сохранения настроек
        else if (settingsOpen && mouseX >= 200 && mouseX <= 300 && mouseY >= 250 && mouseY <= 280)
        {
            playerName = "Player 1"; // Заглушка, сохранение настроек игрока
            settingsOpen = false;
        }
        // Обработка клика по кнопке закрытия рейтинга
        else if (ratingOpen && mouseX >= 200 && mouseX <= 300 && mouseY >= 250 && mouseY <= 280)
        {
            ratingOpen = false;
        }
    }
}

void Game::connectWires()
{
    for (Wire& wire : wires)
    {
        for (const Socket& socket : sockets)
        {
            if (wire.start.x == socket.position.x && wire.start.y == socket.position.y)
            {
                wire.start = socket.position;
                break;
            }
        }

        for (const Lamp& lamp : lamps)
        {
            if (wire.end.x == lamp.position.x && wire.end.y == lamp.position.y)
            {
                wire.end = lamp.position;
                break;
            }
        }
    }
}

void Game::checkWin()
{
    bool allConnected = true;

    for (const Wire& wire : wires)
    {
        bool connected = false;

        for (const Socket& socket : sockets)
        {
            if (wire.start.x == socket.position.x && wire.start.y == socket.position.y)
            {
                connected = true;
                break;
            }
        }

        if (!connected)
        {
            allConnected = false;
            break;
        }
    }

    if (allConnected)
    {
        score++;
        currentLevel++;
        if (currentLevel >= MAX_LEVELS)
        {
            gameRunning = false;
        }
        else
        {
            loadLevel(currentLevel);
        }
    }
}

void Game::gameOver()
{
    gameRunning = false;
    saveRating();
}

void Game::saveRating()
{
    std::ofstream file("rating.txt", std::ios::app);
    if (!file)
    {
        std::cout << "Failed to open rating file." << std::endl;
        return;
    }

    file << playerName << " " << score << std::endl;

    file.close();
}

void Game::loadRating()
{
    std::ifstream file("rating.txt");
    if (!file)
    {
        std::cout << "Failed to open rating file." << std::endl;
        return;
    }

    std::string line;
    while (std::getline(file, line))
    {
        std::cout << line << std::endl;
    }

    file.close();
}

void Game::showRating()
{
    ratingOpen = true;
    loadRating();
}

void Game::run()
{
    txCreateWindow(400, 450);
    //txSetFillColor(TX_WHITE);

    loadLevels();
    loadLevel(currentLevel);

    gameRunning = true;

    while (gameRunning)
    {
        drawGame();
        handleInput();
        connectWires();
        checkWin();
        txSleep(10);
    }

    showRating();
}

int main()
{
    Game game;
    game.run();

    return 0;
} 

Ответы (0 шт):