std::vector 中的对象未正确保存属性

Objects in std::vector not saving attributes correctly

我遇到的问题是,当我更改对象的属性时,更改不是 'saving'。更容易向您展示正在发生的事情。

我正在学习 c++ 并决定构建一个小型国际象棋应用程序。每个 Piece 都是一个单独的对象。

它们存储在 std::vector

std::vector<Piece> pieces;

它们是这样初始化的

for (int i = 0; i < 2; i++)
{
    Piece p;
    p.Init(i*2+1, 1, renderer, SQUARE_SIZE, "king");
    pieces.push_back(p);
}

当我点击鼠标时我想select所有棋子(暂时)

for (int i = 0; i < pieces.size(); i++)
            {
                Piece p = pieces[i];
                p.Select();
            }

问题 是在调用 Select() 函数时,当我开始渲染它们的 selected 属性时 false.奇怪的是 这不会 发生在 vector 中未包含的片段,称为 k

在你问之前,我的代码中没有任何地方将 selected 设置为 false :)(除了构造函数 :P )

此外,如果您觉得不赞成,请先给我留言,我会尽力解决!

这是完整的文件。 (不确定这是否是插入它们的正确方法)

Piece.h

#include <iostream>
#include <SDL2/SDL.h>
#include <SDL2/SDl_image.h>
#include <array>
#include <vector>

class Piece
{
public:
    Piece();

    void Init(int _x, int _y, SDL_Renderer* renderer, int SQUARE_SIZE, std::string type);
    void SetPos(int _x, int _y, int _w);
    void LoadTexture(SDL_Renderer* renderer, std::string type);
    void LoadMovementVector(std::string type);
    void Render(SDL_Renderer* renderer);
    void Select(){ selected = true; std::cout << "called\n";}
    bool isSelected(){ return selected; }
    int GetX(){ return x; } // SDL_Point
    int GetY(){ return y; }

private:
    int x, y;
    std::vector<int> move_vector;
    bool selected;
    SDL_Rect rect;
    SDL_Texture* texture;
};

Piece.cpp

#include <iostream>
#include <SDL2/SDL.h>
#include <SDL2/SDl_image.h>
#include <vector>

#include "Piece.h"

Piece::Piece()
    : x(0)
    , y(0)
    , selected(false)
{

}
void Piece::Init(int _x, int _y, SDL_Renderer* renderer, int SQUARE_SIZE, std::string type)
{
    SetPos(_x, _y, SQUARE_SIZE);
    LoadTexture(renderer, type);
    LoadMovementVector(type);
}
void Piece::Render(SDL_Renderer* renderer)
{
    //selected = true;
    //std::cout << selected << std::endl;
    if (selected)
    {
        SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
        SDL_RenderFillRect(renderer, &rect);  
    }
    if (texture != nullptr)
    {
        SDL_RenderCopy(renderer, texture, nullptr, &rect);
    }
    else 
    {
        SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
        SDL_RenderFillRect(renderer, &rect);    
    }
}
void Piece::LoadMovementVector(std::string type)
{
    if (type == "king"){ // There literally has to be a better way to init std::vector
        int arr[4] = {1,1,1,0};
        for (int i = 0; i < 4; i++){ move_vector.push_back(arr[i]); }
    }

    for (int i = 0; i < move_vector.size(); i++)
    {
        std::cout << move_vector[i];
    }
    std::cout << std::endl; 
}
void Piece::LoadTexture(SDL_Renderer* renderer, std::string type)
{
    std::string source;
    if (type == "king"){
        source = "wk.png"; 
    } 
    texture = IMG_LoadTexture(renderer, "res/wk.png");
}
void Piece::SetPos(int _x, int _y, int _w)
{
    x = _x; 
    y = _y; 
    rect.x = _w*(_x-1); 
    rect.y = _w*(8-_y); 
    rect.w = _w; 
    rect.h = _w; 
    std::cout << x << y << std::endl;
}

Main.cpp

#include <iostream>
#include <math.h>
#include <SDL2/SDL.h>
#include <SDL2/SDl_image.h>

#include "Piece.h"

using namespace std::chrono;

// Would be 'const int' but I want to make the board resizeable
int SCREEN_WIDTH = 800;
int SCREEN_HEIGHT = 800;
int BOARD_WIDTH, BOARD_HEIGHT, SQUARE_SIZE;

SDL_Window* window;
SDL_Renderer* renderer;

std::vector<Piece> pieces;
Piece k;

bool InitEverything();
bool InitSDL();
bool CreateWindow();
bool CreateRenderer();
void SetupRenderer();
void Quit();

void RunGame();
void Render();
void HandleInput();
void UpdateDimensions();

double GetDelta();
void RenderGameBoard(); 

bool loop = true;
auto timePrev = high_resolution_clock::now();

int main(int argc, char* args[])
{
    if (!InitEverything())
        return -1;

    std::cout << "Running Game..." << std::endl;  
    for (int i = 0; i < 2; i++)
    {
        Piece p;
        p.Init(i*2+1, 1, renderer, SQUARE_SIZE, "king");
        pieces.push_back(p);
    }
    k.Init(5, 1, renderer, SQUARE_SIZE, "king");
    RunGame();

    Quit();
    return 0;
}
void RunGame()
{
    while (loop)
    {
        HandleInput();
        Render();

        double delta = GetDelta();

    }
}
void Render()
{
    SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
    SDL_RenderClear(renderer);

    RenderGameBoard();

    for (int i = 0; i < pieces.size(); i++)
    {
        pieces[i].Render(renderer);
    }
    k.Render(renderer);

    SDL_RenderPresent(renderer);
}
void RenderGameBoard()
{
    for (int i = 0; i < 8; i++)
    {
        for (int j = 0; j < 8; j++)
        {
            if ((j%2==0&&i%2==0)||(j%2!=0&&i%2!=0))
                SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
            else
                SDL_SetRenderDrawColor(renderer, 180, 180, 180, 255);
            SDL_Rect r = {i*SQUARE_SIZE, j*SQUARE_SIZE, SQUARE_SIZE, SQUARE_SIZE};
            SDL_RenderFillRect(renderer, &r);
        }
    }
}
void HandleInput()
{
    SDL_Event event;
    while (SDL_PollEvent(&event))
    {
        if (event.type == SDL_QUIT)
            loop = false;
        else if (event.type == SDL_KEYDOWN)
        {

        }
        else if (event.type == SDL_MOUSEBUTTONDOWN)
        {
            if (event.button.button == SDL_BUTTON_LEFT)
            {
                k.Select();
                for (int i = 0; i < pieces.size(); i++)
                {
                    Piece p = pieces[i];
                    p.Select();
                }
                int x = floor(event.button.x/SQUARE_SIZE)+1;
                int y = 8-floor(event.button.y/SQUARE_SIZE);
                for (int i = 0; i < pieces.size(); i++)
                {
                    Piece p = pieces[i];
                    if (p.GetX() == x && p.GetY() == y)
                    {
                        p.Select();
                    }
                }
            }
        }
    }
}
void UpdateDimensions()
{
    BOARD_WIDTH = SCREEN_WIDTH;
    BOARD_HEIGHT = SCREEN_HEIGHT;
    SQUARE_SIZE = BOARD_WIDTH/8;
}
double GetDelta()
{
    auto timeCurrent = high_resolution_clock::now();

    auto timeDiff = duration_cast< nanoseconds >( timeCurrent - timePrev );

    double delta = timeDiff.count();

    delta /= 1000000000;

    timePrev = timeCurrent;
    return delta;
}
bool InitEverything()
{
    if (!InitSDL())
        return false;

    if (!CreateWindow())
        return false;

    if (!CreateRenderer())
        return false;

    SetupRenderer();
    UpdateDimensions();

    return true;
}
bool InitSDL()
{
    if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
    {
        std::cout << "SDL failed to initialize : " << SDL_GetError() << std::endl;
        return false;
    }
    return true;
}
bool CreateWindow()
{
    window = SDL_CreateWindow("Chess", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
    if (!window)
    {
        std::cout << "Failed to create window : " << SDL_GetError() << std::endl;
        return false;
    }
    return true;
}
bool CreateRenderer()
{
    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
    if (!renderer)
    {
        std::cout << "Failed to create renderer : " << SDL_GetError() << std::endl;
        return false;
    }
    return true;
}
void SetupRenderer()
{
    SDL_RenderSetLogicalSize(renderer, SCREEN_WIDTH, SCREEN_HEIGHT);
}
void Quit()
{
    SDL_DestroyWindow(window);
    SDL_Quit();
}

这个:

Piece p = pieces[i];

正在创建向量中索引 i 处的片段的副本

你之后调用的任何方法都是在副本上操作,而不是在数组中的部分上。

相反,引用它:

Piece& p = pieces[i];

之后,p 是向量中元素 i 的引用,您对其执行的任何操作都将在向量元素上执行。