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

时间:2017-02-07 03:51:06

标签: c++ class stdvector

我遇到的问题是,当我更改对象的属性时,更改并非“保存”。更容易向您展示正在发生的事情。

我正在学习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);
}

当我点击鼠标时,我想要选择所有部分(暂时)

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

问题是在调用Select()函数时,到我呈现selected属性为false时。奇怪地这不会发生在vector中未包含的内容中,称为k

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

此外,如果您想 downvoting ,请先发送评论,然后我会尝试修复它!

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

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();
}

1 个答案:

答案 0 :(得分:5)

此:

Piece p = pieces[i];

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

之后调用的任何方法都在副本上运行,而不是在数组中运行。

相反,请参考它:

Piece& p = pieces[i];

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