Как создать несколько одинаковых контейнеров с одинаковыми именами, которые могут содержать (и сохранять) различные элементы / количества

Итак ... Я создал кучу "предметов" следующим образом, который во многих отношениях прекрасно работает для меня. На самом деле большая часть моего кода основана на этой структуре (усеченный список):

const items = {
  Pearls: {
    worth: 100,
    color: "white",
    use: // do something
  },
  Oyster: {
    pearlsInside: 6,
    something: "whatever"
  }
};

Затем у меня есть инвентарь игроков, настроенный следующим образом:

const player = {
    someVariable: "thingamabob",
    inventory: [
    ]
};

Когда игрок находит и берет с земли Устрицу или Жемчужину, я помещаю этот предмет (строку имени) в «массив инвентаря» игрока, а затем за кулисами позволяю им получить доступ / использовать соответствующие значения предметов из «объекта предметов» .

Легко, отлично работает, за исключением одной проблемы ... если игрок находит ДВЕ устрицы на земле, поднимает одну и извлекает из нее 3 жемчужины, а затем бросает ее обратно на землю, если игрок позже подберет обе устрицы у них будет оба, теперь у них 3 Жемчужины (у ранее не собранной Устрицы должно быть 6).

Это не проблема для предмета «Жемчуг», так как он сам по себе не является «контейнером», так сказать, на земле может быть сотня жемчужин, и игрок может получить их, использовать их и бросить по своему усмотрению без каких-либо последствий. ... это значит, что Жемчуг - это Жемчуг - это Жемчуг, и это прекрасно работает для меня с моей стороны.

Но когда я попал в эту Устрицу, я понял, что мне понадобятся несколько предметов с одним и тем же именем / типом, которые могут содержать различное количество Жемчуга.

Имейте в виду, что пользовательский интерфейс игрока всегда будет называть Устрицу устрицей только во всех случаях - например, земля или инвентарь никогда не будут отображаться в игре «Oyster1, Oyster2, Oyster666» - это будет «Oyster, Oyster, Oyster» или «3». Устрицы ». Только при дальнейшем рассмотрении можно обнаружить, что содержание отличается.

Итак ... насколько сильно мне придется испортить мою текущую структуру элементов, чтобы получить "контейнеры с одинаковыми именами"?

Если это поможет, я полагаю, ответ на этот вопрос может помочь решить - откуда у вас 2 одинаковых «фонарика» в комнате, но каждый с разной степенью заряда батареи - ИЛИ - «Вы найдете четыре золотых Colt 1911 года с матерью». жемчужных захватов на земле »(каждая с разным количеством боеприпасов, загруженных в их зажимы) - ИЛИ - (возможно) как у вас есть несколько сундуков с сокровищами, которые все просто видны / известны как« сундуки »в игре, все они содержат различную добычу.

Я предполагаю, что на данный момент для меня это скорее психический блок, в сочетании со страхом, что я зашел слишком далеко с моей текущей структурой / системой предметов / инвентаря и теперь мне придется значительно переделать.

1
0
81
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Я не уверен, что полностью понимаю ваш вопрос, но это может помочь.

Если вы используете ES6 (поскольку вы используете const, я думаю, что да), вы можете использовать Символы.

Symbols are new to JavaScript in ECMAScript 2015. A Symbol is a unique and immutable primitive value and may be used as the key of an Object property. In some programming languages, Symbols are called atoms. For more details see Symbol and the Symbol object wrapper in JavaScript.

«Символ» кажется довольно крутым, сейчас исследую. Когда я читаю все объяснения / документацию, это заставляет меня задаться вопросом, знаете ли вы какие-либо примеры его использования на практике (Jfiddles и т. д.)?

Curly Brackets 11.09.2018 01:02

Честно говоря, я изо всех сил пытаюсь полностью понять, как это реализовать, но кажется правильным для вашего варианта использования :)

Daut 11.09.2018 12:59

Пожалуйста, дайте мне знать, если у вас все получится, и загрузите свой код :)

Daut 12.09.2018 10:36

Я бы рекомендовал использовать идентификаторы для всего в вашем мире. Вы можете дать им тип, и каждый тип будет иметь отображаемое имя и другие метаданные, но тогда каждый экземпляр объекта может быть однозначно идентифицирован.

Попробуйте поискать GUID / UUID in Javascript, если вам нужна помощь в создании идентификаторов.

Забавно, я начал с того, что у каждого предмета был идентификатор и «имя», но предвидел проблемы с объектом oyster с именем «oyster», плюс избыточность вызова oyster, чтобы получить его имя «oyster», поэтому я перешел к имя переменной - это настройка имени, которой я поделился. При этом ... Я заранее штампую все свои объекты в items {}. Моя проблема в том, что я понятия не имею, сколько устриц будет в мире или упадет в в той же комнате или в том же инвентаре, и я бы никогда не захотел вручную провернуть 100 одинаковых объектов, каждый с разным значением идентификатора. Итак, как мне подойти?

Curly Brackets 11.09.2018 00:22

как вы говорите, я определенно хочу «каждый экземпляр объекта уникально идентифицирован», но я хочу добиться этого с помощью одного «суперобъекта» (в моем примере кода), если хотите. Так что согласитесь с вашим подходом, не понимая, как его реализовать.

Curly Brackets 11.09.2018 00:24

То, что вы называете «одиночным суперобъектом», по сути, называется «классом». Я не знаю, каков ваш уровень навыков, но, возможно, вы захотите еще немного изучить объектно-ориентированное программирование. Хотя это и не требуется в JS, это хороший подход для описываемой вами системы. developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/…

Alex 12.09.2018 08:52

Оценил. Я определенно учусь ползать перед тем, как ходить, и, вероятно, буду глубоко погружаться в прототипы перед занятиями, однако я обязательно исследую это. Но вот что меня гложет ... Я знаю, что были некоторые надежные, по крайней мере, текстовые приключения, с инвентарями, в которых были клонированные предметы, которые могли иметь разные значения (игрок может носить 2 кожаных мешочка, каждый с разницей золотых монет) до 2015 года. Вероятно, именно здесь и заключается мой квест ... хммм ...

Curly Brackets 13.09.2018 02:10

Конечно, можно работать с простыми старыми объектами, имейте в виду, что в вашем инвентарном массиве есть экземпляры, соответствующие определенному прототипу. Другими словами, вы определяете их состав один раз, а затем вам нужно создать объекты новый, которые в конечном итоге попадут в инвентарь, см .: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

Alex 13.09.2018 10:14

Создал второй ответ, чтобы проиллюстрировать вышеизложенное

Alex 13.09.2018 10:44

Представляйте коллекции с массивами вместо объектов. Тогда вы можете иметь несколько одинаковых элементов внутри этого массива. Если вы затем дадите каждому элементу одинаковые свойства, у вас будет легкое сравнение. Чтобы различать элементы, используйте идентификаторы.

const inventory = [
  {
    color: "white",
    id: 1,
    name: "pearls",
    uses: [
      "buy",
      "craft",
      "trade",
      "sell"
    ],
    weight: 0.1,
    worth: 100
  },
  {
    color: "white",
    id: 2,
    name: "pearls",
    uses: [
      "buy",
      "craft",
      "trade",
      "sell"
    ],
    weight: 0.1,
    worth: 100
  },
  {
    color: "brown",
    id: 3,
    name: "wood",
    uses: [
      "buy",
      "craft",
      "trade",
      "sell"
    ],
    weight: 2,
    worth: 10
  }
];
const net_worth = inventory.reduce(( a, b ) => a + b.worth, 0 );
console.log( `two pearls and one wood are worth ${ net_worth }` );

const oyster = {
  color: "grey",
  id: 4,
  name: "oyster",
  uses: [
    "loot_pearls",
    "open"
  ],
  weight: 1,
  worth: 6
};
console.log( `opening the oyster gave you ${ oyster.worth } pearls` );

Мой «инвентарь» - это массив. Кроме того, я не знаком с «безымянными» объектами - у меня немного болит голова - помимо этого - я не понимаю, как другой идентификатор будет прикреплен к повторно используемому объекту. Это означает, что я создаю все свои предметы в мире заранее, и я создаю одну Устрицу, которую я хочу видеть во множестве во всем мире. Должен ли я вместо этого создать 100 объектов Oyster и вручную присвоить каждому из них уникальное значение идентификатора в моем начальном списке элементов {}?

Curly Brackets 11.09.2018 00:36

Кроме того, не провожая руки, я бы протолкнул предмет в массив вашего инвентаря (если игрок поднимает жемчужину). Похоже, мне пришлось бы одновременно нажимать 6 свойств / значений? Извините, поэтому я запутался в моем первоначальном подходе.

Curly Brackets 11.09.2018 00:38

Вот пример прототипов Oyster и Pearl и их создания.

// Some helper functions
function randomNum(max) {
  return Math.floor(Math.random() * Math.floor(max));
}

function randomColor() {
  var colors = ['white', 'blue', 'purple', 'yellow'];
  return colors[randomNum(3)];
}

// The Pearl prototype
function Pearl(worth, color, usageCallback) {
  this.worth = worth;
  this.color = color;
  this.use = usageCallback;
}
// Replace the default toString() function just for fun
Pearl.prototype.toString = function() {
	return 'A ' + this.color + ' colored pearl worth ' + this.worth; 
}

// The Oyster prototype
function Oyster(pearlsInside, something) {
  this.pearls = [];
  for (var i = 0; i < pearlsInside; i++) {
  	this.pearls.push(new Pearl(randomNum(100), randomColor(), function() {}))
  }
  this.something = something;
}
// Replace the default toString() function just for fun
Oyster.prototype.toString = function() {
	var description = 'The oyster contains ' + this.pearls.length + ' pearls: ';
  this.pearls.forEach(function(pearl) {
  	description += pearl + ', ';
  });
  return description;
}

// Here we instantiate our new objects
var oyster1 = new Oyster(6, 'Whatever');
var oyster2 = new Oyster(3, 'Whatever');

// And then we can use them
var container = document.getElementById('pearls');
container.appendChild(document.createTextNode(oyster1 + ''));
container.appendChild(document.createElement('br'));
container.appendChild(document.createElement('br'));
container.appendChild(document.createTextNode(oyster2 + ''));

// (or log them as strings)
console.log(oyster1 + '');
console.log(oyster2 + '');
<div id="pearls"></div>

Во-первых, спасибо за это, во-вторых, я позабочусь о вас в какой-то момент, обещаю ... в-третьих, не стесняйтесь нажимать на кнопку в любое время, у меня есть тенденция делать это с людьми ... затем ...

Curly Brackets 14.09.2018 02:34

У меня есть власть над созданием новых объектов в мире. У меня двоякая проблема от поколения к поколению. (A) Я не знаю, сколько устриц будет населять мир. Я не могу создать их экземпляры, как вы показали, иначе я бы использовал var oyster100 =. И (B) ниже ...

Curly Brackets 14.09.2018 02:37

(B) Не стремиться получить случайное количество жемчуга в устрице «при создании / генерации». Нужны устрицы, чтобы удерживать разное количество жемчуга, когда игрок добавляет / удаляет их на протяжении всей игры. NUTSHELL: В инвентаре есть два «динамически генерируемых» идентичных мешка (устрицы), черт возьми, даже один на земле. Это один и тот же мешок, за исключением того, что в каждом из них разное количество монет (жемчужин), потому что игрок добавлял () и удалял () монеты из каждого мешка, а также бросал / получал мешки, чтобы увидеть, что каждый из них сохранил свои индивидуальное (постоянно меняющееся) количество монет, которое игрок оставил.

Curly Brackets 14.09.2018 02:46

Возможно, я плохо объяснил свое затруднительное положение в моем OP. Я создал несколько рабочих систем инвентаризации. Включая тот, в котором я наполняю мешок (устрицу) монетами (жемчугом), удаляю часть монет, бросаю мешок и поднимаю его обратно, чтобы увидеть, сколько монет я оставил в нем. Однако все пошло наперекосяк, когда я ввел в игру два одинаковых мешка. Теперь, когда я манипулирую содержимым первого мешка, содержимое второго мешка такое же, как и первое. Я понимаю, почему это происходит. Цель моего вопроса - обойти это. И помните, что количество мешков динамично.

Curly Brackets 14.09.2018 02:56

Случайность и их создание в переменной - это просто возможность что-то напечатать; конечно же, в вашем собственном коде все это будет делать ваша игровая логика. Я попытался продемонстрировать разницу между тем, что описывает тип, и тем, что имеет определенный тип. При этом в Javascript иногда возникают сложности с областью видимости, когда обе вещи могут неожиданно указывать на одно и то же значение; если вы столкнетесь с такой проблемой, я бы рекомендовал начать новый вопрос с минимальным jsfiddle, который демонстрирует проблему.

Alex 14.09.2018 11:02
Ответ принят как подходящий

Я, конечно, слишком долго думал об этом.

Ни GUID / UUID, ни символов, ни супер-колдовства.

Сгенерировать уникальный идентификатор для одноименного объекта так же просто, как создать глобальную функцию (что может быть более глобальным, чем уникальный идентификатор для каждого объекта в игровом мире):

function generateId() { return idid += 1; }

А затем создайте новый элемент вот так:

function create(){ var item = new NewItem( {id: generateId(), name: "Widget", power: 6, energy: 0} ); }

который затем проталкивает конструктор как таковой:

function NewItem(item) { this.item = item; }

Затем вы помещаете каждый из этих вновь созданных элементов в свой массив «все элементы в мире» как объекты с множеством свойств, на которые можно ссылаться по мере необходимости.

Среди прочего, это позволяет перемещать в игре 100 «виджетов», каждый с другим идентификатором, что означает, что один виджет может иметь энергию: 0, а другой «виджет» может иметь энергию: 69 по ходу игры.

Готово и сделано. Переходим к следующей серьезной проблеме .... ПРОДОЛЖЕНИЕ СЛЕДУЕТ ...

Другие вопросы по теме