2017-02-07 11 views
-1

Проблема, с которой я сталкиваюсь, заключается в том, что при изменении атрибута объекта изменение не является «сохранением». Легче показать вам, что происходит.Объекты в std :: vector не сохраняют атрибуты правильно

Я учусь 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(); 
      } 

Вопрос заключается в том, что w hile функция 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(); 
} 
+0

Hahaha good pickup – Andy

ответ

5

Это:

Piece p = pieces[i]; 

создает копию элемента в индексе i в векторе.

Любые методы, которые вы вызываете после этого, работают на копии, а не на части в массиве.

Вместо этого возьмите ссылку на него:

Piece& p = pieces[i]; 

После этого p является ссылкой на элемент i в векторе и любые операции, которые выполняют на нем выполняются на элемент вектора.

+0

Был как раз обновлен с ссылкой harmic :) – Boz

+0

Ahh спасибо, гадать, мне нужно использовать указатели? Если вы не возражаете помочь мне с кодом? Действительно новичок в этой концепции. – Andy

+0

@ Энди не нужно использовать указатели, используйте ссылки, как указано в ответе – harmic