我正在尝试用C++为我正在开发的一款游戏建立一个库存系统。然而,当我调用Inventory::AddItem(Item i)时,库存系统中有一个bug,没有添加任何物品,并且该插槽仍然为空。目前,我通过std::vector<Item>处理库存,其中Item是一个结构,其中包含类型(如果它是可堆叠的)、堆栈中的最大块数、堆栈中的当前块数以及几个用于动画的对象。此外,我自动使用40个空块填充库存,这些空块的ID为INVENTORY_EMTPY_SLOT_ID.
代码如下:
typedef struct item {
int type; // this is whether the block is a foreground of background tile
int id; // use this for the id of objects
bool stackable; // true indicates that the block can be stacked
int max_num; // maximum number of blocks in a stack
int num; // the current number of blocks in the stack
Animation* use_animation; // the animation of the block or item when it is being used
Animation* other_animation; // secondary animation of item in case it is necessary
} Item;如何初始化空槽:
for (size_t x = 0; x < INVENTORY_MAX_SLOTS; x++) {
Item i = {0, INVENTORY_EMPTY_SLOT_ID, true, 1, 1, NULL, NULL};
this->items.push_back(i);
}添加项目
/*********BUG HERE:******************/
void Inventory::AddItem(Item item) {
// find all indexes with the same item.id
std::vector<size_t> indexes_w_same_item;
for (size_t i = 0; i < this->items.size(); i++) {
if (this->items[i].id == item.id) {
indexes_w_same_item.push_back(i);
}
}
// find the next empty slot
int next_empty_slot = -1;
for (size_t i = 0; i < this->items.size(); i++) {
if (this->items[i].id == INVENTORY_EMPTY_SLOT_ID) {
next_empty_slot = i;
}
}
// go through all the indexes with the same item.id
// and see if at least one of them is empty.
// if one is empty and has sufficient capacity,
// add the item and return. if it isn't, keep moving forward
for (size_t x = 0; x < indexes_w_same_item.size(); x++) {
if (item.id == this->items[indexes_w_same_item[x]].id) {
if (this->items[indexes_w_same_item[x]].num + item.num <= this->items[indexes_w_same_item[x]].max_num) {
this->items[indexes_w_same_item[x]].num += item.num;
return;
}
}
}
// if there is an empty slot, make a new stack
if (next_empty_slot >= 0) {
this->items[next_empty_slot].id = item.id;
this->items[next_empty_slot].max_num = item.max_num;
// clamp item.num so it doesn't exceed item.max_num
if (item.max_num > item.num) {
this->items[next_empty_slot].num = item.num;
} else {
this->items[next_empty_slot].num = item.max_num;
}
}
}发布于 2020-04-06 04:43:09
我知道你已经发现了这个错误,但是你的代码中有许多问题导致了这个错误,我想帮助你理解如何写出更好的代码,所以下次你会更容易找到它(甚至可以避免它!)。
add_item_to_existing_stack_if_possible和add_item_to_new_stack_if_possible.typedef这样的东西不应该出现在你的代码中,你应该使用operator<<代替std::cout,依此类推。Item对象快得多。<代码>H220<代码>G221#include <vector>
#include <array>
#include <iostream>
struct Animation;
struct Item {
int type;
int id;
bool is_stackable;
int max_num_blocks_in_stack;
int curr_num_of_blocks_in_stack;
Animation* used_animation; // if it is non nullable, you should consider to use it without a pointer (possibly a reference)
Animation* secondary_animation; // nullable - can be a pointer or std::optional
};
class Inventory
{
public:
bool add_item(Item&& item);
private:
bool is_slot_empty(size_t idx) const { return items[idx].id == INVENTORY_EMPTY_SLOT_ID; }
std::vector<size_t> find_indexes_of(const Item& item) const;
size_t find_next_empty_slot() const;
bool add_item_to_existing_stack_if_possible(const Item& item);
bool add_item_to_new_stack_if_possible(Item&& item);
void print() const;
static constexpr size_t MAX_INV_SIZE = 40; // can transform into a class template!
std::array<Item, MAX_INV_SIZE> items;
static constexpr int INVENTORY_EMPTY_SLOT_ID = -1;
};
std::vector<size_t> Inventory::find_indexes_of(const Item& item) const
{
std::vector<size_t> indexes{};
for (size_t idx = 0; idx < MAX_INV_SIZE; ++idx)
{
if (items[idx].id == item.id)
{
indexes.push_back(idx);
}
}
return indexes;
}
size_t Inventory::find_next_empty_slot() const
{
for (size_t idx = 0; idx < MAX_INV_SIZE; ++idx)
{
if (is_slot_empty(idx))
{
return idx;
}
}
return MAX_INV_SIZE; // invalid value!
}
void Inventory::print() const
{
for (size_t i = 0; i < MAX_INV_SIZE; ++i)
{
if (this->items[i].id != INVENTORY_EMPTY_SLOT_ID)
{
std::cout << "Inventory slot: " << i << "\n"
<< "Item ID: " << items[i].id << "\n"
<< "Item Num: " << items[i].curr_num_of_blocks_in_stack << "\n"
<< "Item Max Num: " << items[i].max_num_blocks_in_stack << std::endl;
//<< "Item Texture: " << textures[items[i].id] << std::endl;
}
}
}
bool Inventory::add_item_to_existing_stack_if_possible(const Item& item)
{
auto indexes_with_same_item = find_indexes_of(item);
for (auto idx : indexes_with_same_item)
{
if (item.id == items[idx].id)
{
if (items[idx].curr_num_of_blocks_in_stack + item.curr_num_of_blocks_in_stack <=
items[idx].max_num_blocks_in_stack)
{
items[idx].curr_num_of_blocks_in_stack += item.curr_num_of_blocks_in_stack;
return true;
}
}
}
return false;
}
bool Inventory::add_item_to_new_stack_if_possible(Item&& item)
{
size_t next_empty_slot = find_next_empty_slot();
if (next_empty_slot >= 0)
{
this->items[next_empty_slot] = std::move(item);
return true;
}
return false;
}
bool Inventory::add_item(Item&& item)
{
bool was_possible_to_add_to_existing_stack = add_item_to_existing_stack_if_possible(item);
if (!was_possible_to_add_to_existing_stack)
{
return add_item_to_new_stack_if_possible(std::move(item));
}
return false;
}发布于 2020-04-06 03:36:35
好吧,我想通了。在第二个for循环的末尾必须有一个中断,它在其中查找下一个空插槽,否则,它将检测到下一个空插槽作为库存中的最后一个插槽,假设您正在库存中添加第一个项目。因此,该项目没有显示在跳栏中。
以下是正确的解决方案:
void Inventory::AddItem(Item item) {
// find all indexes with the same item.id
std::vector<size_t> indexes_w_same_item;
for (size_t i = 0; i < this->items.size(); i++) {
if (this->items[i].id == item.id) {
indexes_w_same_item.push_back(i);
}
}
// find the next empty slot
int next_empty_slot = -1;
for (size_t i = 0; i < this->items.size(); i++) {
if (this->items[i].id == INVENTORY_EMPTY_SLOT_ID) {
next_empty_slot = i;
break;
}
}
// go through all the indexes with the same item.id
// and see if at least one of them is empty.
// if one is empty and has sufficient capacity,
// add the item and return. if it isn't, keep moving forward
for (size_t x = 0; x < indexes_w_same_item.size(); x++) {
if (item.id == this->items[indexes_w_same_item[x]].id) {
if (this->items[indexes_w_same_item[x]].num + item.num <= this->items[indexes_w_same_item[x]].max_num) {
this->items[indexes_w_same_item[x]].num += item.num;
return;
}
}
}
// if there is an empty slot, make a new stack
if (next_empty_slot >= 0) {
this->items[next_empty_slot] = item;
}
for (size_t i = 0; i < INVENTORY_MAX_SLOTS; i++) {
if (this->items[i].id != '.') {
printf("\nInventory slot: %d\n", i);
printf("Item ID: %c\n", this->items[i].id);
printf("Item Num: %d\n", this->items[i].num);
printf("Item Max Num: %d\n", this->items[i].max_num);
printf("Item Texture: %x\n", this->textures[this->items[i].id]);
}
}
return;}
https://stackoverflow.com/questions/61047811
复制相似问题