我希望用户能够合并两个项目,如果兼容将产生新项目。在此示例中,项目ID将保存为字符串。
我想知道最有效的方法是什么,同时确保交换的订单总是会产生相同的结果,因此用户可以输入订单:
item X + item Y = item Z
item Y + item X = item Z
我尝试过使用字典和对象,但我还没有能够得到任何工作。我还尝试了一些包含HashMap / HashSet的各种库,但没有任何工作。这里有一些pseduo代码:
itemRecipe1:HashSet = new HashSet();
itemRecipe1.add("2");//Add item with ID of 2
itemRecipe1.add("3");//Add item with ID of 3
inputRecipe:HashSet = new HashSet();
inputRecipe.add("3");//Add item with ID of 3 (swapped)
inputRecipe.add("2");//Add item with ID of 2 (swapped)
recipeList:HashMap = new HashMap();
receipeList.put(itemRecipe1, "11");//Recipe has been added, the result of the recipe should be item 11
//This should output as TRUE since the composition of itemRecipe1 and inputRecipe are the same, despite a different input order.
trace(receipeList.containsKey(inputRecipe));
如果有人有这个问题的解决方案,请知道,因为我愿意实施任何可以开展工作的设计。我只是不知道词典是如何工作的,因为关键顺序很重要。
答案 0 :(得分:1)
因此,您尝试将两个或多个对象相互关联。您需要的第一件事是一些原始数据,您可以使用它们来唯一地表示每个项目,通常是ID。这应该为您提供以下内容:
class Item {
public var _id:int;
public function Item(id:int) {
_id = id;
}
public function get id():int { return _id; }
}
现在您需要一些数据,使用此ID在多个项目之间建立关系。这可能就像下面一样简单,只需要一些额外的功能来查看这些ID的输入列表是否与关系匹配:
class ItemRelationship {
private var _items:Vector.<Item>;
public function ItemRelationship(items:Vector.<Item>) {
_items = items;
}
public function matches(ids:Vector.<int>):Boolean {
if (_items.length !== ids.length) {
return false;
}
for each (var item:Item in _items) {
var found:Boolean = false;
for each (var id:int in ids) {
if (item.id === id) {
found = true;
break;
}
}
if (!found) return false;
}
return true;
}
public function get items():Vector.<Item> { return _items; }
}
这让我们可以做这样的事情,假设我们有一堆带有ID的项目(item1
,item2
,...)。
var rel:ItemRelationship = new ItemRelationship(new <Item>[item1, item2]);
然后:
trace(rel.matches(new <int>[1,2])); // true
trace(rel.matches(new <int>[2,1])); // true
trace(rel.matches(new <int>[3,4])); // false
现在我们需要的是存储所有这些关系的东西,让我们根据输入ID列表获取一个:
class RelationshipCollection {
private var _relationships:Vector.<ItemRelationship>;
public function RelationshipCollection(relationships:Vector.<ItemRelationship>) {
_relationships = relationships;
}
public function find(ids:Vector.<int>):ItemRelationship {
for each(var relationship:ItemRelationship in _relationships) {
if (relationship.matches(ids)) return relationship;
}
return null;
}
}
在那里放置一系列关系:
var collection:RelationshipCollection = new RelationshipCollection(new <ItemRelationship>[
new ItemRelationship(new <Item>[item1, item4]),
new ItemRelationship(new <Item>[item2, item3])
]);
并给它一个旋转:
trace(collection.find(new <int>[1, 3])); // null (no match)
trace(collection.find(new <int>[1, 4])); // works
trace(collection.find(new <int>[3, 2])); // works
trace(collection.find(new <int>[2, 3])); // works
当然,为了便于阅读,您可以将每个类重命名为更适合其应用的内容,例如: Item => Potion
,ItemRelationship => Recipe
,RelationshipCollection => RecipeBook
。
答案 1 :(得分:0)
所以用户可以输入订单
第一步是限制可能的输入。如果允许任何类型的输入,则必须解析该输入,并且事情会很快变得复杂。
创建一种输入方法,只允许用户将两个项目放在一起,例如通过将项目拖放到仅2个插槽中。
我只是不知道词典是如何工作的,因为关键命令很重要。
重要的是要很好地设计密钥。
在评论中指出@George Profenza,您可以将ID更改为其他格式。您可以使用1, 2, 3, ... n
而不是1, 2, 4, ... 2^n
。优点是您可以通过按位或运算符(|)唯一地组合任意两个ID。在以下示例中,组合了两个这样的ID(二进制表示法):
00001
| 10000
--------
10001
如您所见,每个ID在二进制中占据一个单独的位置:第一个位置和第五个位置。通过或运算符组合意味着现在第1和第5位都是1.顺序并不重要。如果您以2的幂形式使用此类ID,则可以将它们组合起来,而不管顺序如何形成对,然后可以将其用作字典的键。
另一种解决方案是简单地对这对ID进行排序。
组合3-2变为2-3,组合2-3保持2-3。 2-3和3-2都会产生相同的结果。
然后,您可以相应地构建数据结构,即:外部数据结构用于较低的ID号,嵌套的内部数据结构用于较大的ID号。这是一些带有通用对象的伪代码:
var map:Object = {};
map["2"] = {"3":"combination 2-3"};
要访问它,您可以执行以下操作:
trace(map[Math.min(ID1, ID2)][Math.max(ID1, ID2)])
通过在数据结构中存储两种可能的组合,还有蛮力的方式。这段代码可能大致如下:
var map:Object = {};
map["2"] = {"3":"combination 2-3"};
map["3"] = {"2":"combination 2-3"};
现在两个
trace(map[ID1][ID2]);
和
trace(map[ID2][ID1]);
应该产生相同的结果。