结合两个项目(类似食谱)

时间:2016-02-09 20:22:54

标签: actionscript-3 flex

我希望用户能够合并两个项目,如果兼容将产生新项目。在此示例中,项目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));

如果有人有这个问题的解决方案,请知道,因为我愿意实施任何可以开展工作的设计。我只是不知道词典是如何工作的,因为关键顺序很重要。

2 个答案:

答案 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的项目(item1item2,...)。

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 => PotionItemRelationship => RecipeRelationshipCollection => 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]);

应该产生相同的结果。