码迷,mamicode.com
首页 > 其他好文 > 详细

Cocos2d-x 3.0final 终结者系列教程12-Vector&map&value

时间:2014-05-31 21:45:53      阅读:363      评论:0      收藏:0      [点我收藏+]

标签:cocos2d-x   vector map value   

昨天中午北京温度为40度,在中午12:16分我来到篮球场,思考了1分钟决定开站

转球:

我和另外3名队友开始半场,

球传到我手的刹那顿时烫的我持球不稳,顿时问道了淡淡的胶皮味道和烤肉味道的混搭。

这时我来了一个腾空跳投,

球---------爆炸了。。。。。。。。

听新闻说昨天在路上都是 “熟人”

一位老大爷不慎被车刮倒了,大爷二话没说立马爬了起来,围观众人议论纷纷:

“大爷人不错”,“大爷素质真高”,“大爷身体可真好”

大爷说:

“快拉 秦皇岛吧,烫腚”。

估计昨天又有不少沿街乞讨人士和流浪狗失去生命(咋没人管管)

------------------------------------------------分割线---------------------------------------------------

在做Cocos2d-x2.0人的人们估计正在使用CCArray,CCDirectionary,CCDouble,CCFloat这些正搞得很爽,但不得不说

它们在V3.0中不用了。

看下3.0中的数据结合类Vector,Map,Value(建议大家自行阅读源码,本文只介绍如何使用,关于引用计数的概念推荐大家看我的视频),

以下案例来自TestCpp:

void TemplateVectorTest::onEnter()

{

    UnitTestDemo::onEnter();

    Vector<Node*> vec;//定义一个向量,其实是对stl Vector的封装,只是加入了对象的内存计数管理

    CCASSERT(vec.empty(), "");

    CCASSERT(vec.capacity() == 0, "");

    CCASSERT(vec.size() == 0, "");

    CCASSERT(vec.max_size() > 0, "");

    auto node1 = Node::create();

    node1->setTag(1);

    vec.pushBack(node1);//在向量添加一个元素

    CCASSERT(node1->getReferenceCount() == 2, "");

    auto node2 = Node::create();

    node2->setTag(2);

    vec.pushBack(node2);//添加元素 编号会从0开始

    CCASSERT(vec.getIndex(node1) == 0, "");

    CCASSERT(vec.getIndex(node2) == 1, "");


    auto node3 = Node::create();

    node3->setTag(3);

    vec.insert(1, node3); //插入元素

    CCASSERT(vec.at(0)->getTag() == 1, "");

    CCASSERT(vec.at(1)->getTag() == 3, "");

    CCASSERT(vec.at(2)->getTag() == 2, "");


    // Test copy constructor

    Vector<Node*> vec2(vec);  //复制一个向量

    CCASSERT(vec2.size() == vec.size(), "");

    ssize_t size = vec.size();

    for (ssize_t i = 0; i < size; ++i)

    {

        CCASSERT(vec2.at(i) == vec.at(i), "");

        CCASSERT(vec.at(i)->getReferenceCount() == 3, "");

        CCASSERT(vec2.at(i)->getReferenceCount() == 3, "");

    }


    // Test copy assignment operator

    Vector<Node*> vec3;

    vec3 = vec2;

    CCASSERT(vec3.size() == vec2.size(), "");

    size = vec3.size();

    for (ssize_t i = 0; i < size; ++i)

    {

        CCASSERT(vec3.at(i) == vec2.at(i), "");

        CCASSERT(vec3.at(i)->getReferenceCount() == 4, "");

        CCASSERT(vec2.at(i)->getReferenceCount() == 4, "");

        CCASSERT(vec.at(i)->getReferenceCount() == 4, "");

    }


    // Test move constructor (Lambda 表达式,定义一个函数用于创建一个Vector,关于Lambda建议看我的视频)

    auto createVector = [this](){

        Vector<Node*> ret;

        for (int i = 0; i < 20; i++)

        {

            ret.pushBack(Node::create());

        }

        int j = 1000;

        for (auto& child : ret)

        {

            child->setTag(j++);

        }

        return ret;

    };

    Vector<Node*> vec4(createVector());

    for (const auto& child : vec4)

    {

        CC_UNUSED_PARAM(child);

        CCASSERT(child->getReferenceCount() == 2, "");

    }


    // Test init Vector<T> with capacity

    Vector<Node*> vec5(10);

    CCASSERT(vec5.capacity() == 10, "");

    vec5.reserve(20);

    CCASSERT(vec5.capacity() == 20, "");


    CCASSERT(vec5.size() == 0, "");

    CCASSERT(vec5.empty(), "");


    auto toRemovedNode = Node::create();

    vec5.pushBack(toRemovedNode);

    CCASSERT(toRemovedNode->getReferenceCount() == 2, "");


    // Test move assignment operator

    vec5 = createVector();

    CCASSERT(toRemovedNode->getReferenceCount() == 1, "");

    CCASSERT(vec5.size() == 20, "size should be 20");


    for (const auto& child : vec5)    //这也是C++11新特性,好用吧,不像STL用迭代器那么麻烦

    {

        CC_UNUSED_PARAM(child);

        CCASSERT(child->getReferenceCount() == 2, "");

    }


    // Test Vector<T>::find

    CCASSERT(vec.find(node3) == (vec.begin() + 1), "");

    CCASSERT(std::find(std::begin(vec), std::end(vec), node2) == (vec.begin() + 2), "");


    CCASSERT(vec.front()->getTag() == 1, "");

    CCASSERT(vec.back()->getTag() == 2, "");


    CCASSERT(vec.getRandomObject(), "");

    CCASSERT(!vec.contains(Node::create()), "");

    CCASSERT(vec.contains(node1), "");

    CCASSERT(vec.contains(node2), "");

    CCASSERT(vec.contains(node3), "");

    CCASSERT(vec.equals(vec2), "");

    CCASSERT(vec.equals(vec3), "");


    // Insert

    vec5.insert(2, node1);

    CCASSERT(vec5.at(2)->getTag() == 1, "");

    CCASSERT(vec5.size() == 21, "");

    vec5.back()->setTag(100);

    vec5.popBack();

    CCASSERT(vec5.size() == 20, "");

    CCASSERT(vec5.back()->getTag() != 100, "");


    // Erase and clear

    Vector<Node*> vec6 = createVector();

    Vector<Node*> vec7 = vec6;  // Copy for check


    CCASSERT(vec6.size() == 20, "");

    vec6.erase(vec6.begin() + 1);  //

    CCASSERT(vec6.size() == 19, "");

    CCASSERT((*(vec6.begin() + 1))->getTag() == 1002, "");

    vec6.erase(vec6.begin() + 2, vec6.begin() + 10);

    CCASSERT(vec6.size() == 11, "");

    CCASSERT(vec6.at(0)->getTag() == 1000, "");

    CCASSERT(vec6.at(1)->getTag() == 1002, "");

    CCASSERT(vec6.at(2)->getTag() == 1011, "");

    CCASSERT(vec6.at(3)->getTag() == 1012, "");

    vec6.erase(3);

    CCASSERT(vec6.at(3)->getTag() == 1013, "");

    vec6.eraseObject(vec6.at(2));

    CCASSERT(vec6.at(2)->getTag() == 1013, "");

    vec6.clear();

    

    auto objA = Node::create(); // retain count is 1

    auto objB = Node::create();

    auto objC = Node::create();

    {

        Vector<Node*> array1;

        Vector<Node*> array2;

        

        // push back objA 3 times

        array1.pushBack(objA); // retain count is 2

        array1.pushBack(objA); // retain count is 3

        array1.pushBack(objA); // retain count is 4

        

        array2.pushBack(objA); // retain count is 5

        array2.pushBack(objB);

        array2.pushBack(objC);

        

        for (auto obj : array1) {

            array2.eraseObject(obj);

        }

        CCASSERT(objA->getReferenceCount() == 4, "");

    }

    CCASSERT(objA->getReferenceCount() == 1, "");

    {    //这是一个代码块,出了块引用计数会恢复,是一个AutoReleasePool

        Vector<Node*> array1;

        // push back objA 3 times

        array1.pushBack(objA); // retain count is 2

        array1.pushBack(objA); // retain count is 3

        array1.pushBack(objA); // retain count is 4

        CCASSERT(objA->getReferenceCount() == 4, "");

        array1.eraseObject(objA, true); // Remove all occurrences in the Vector.

        CCASSERT(objA->getReferenceCount() == 1, "");

        

        array1.pushBack(objA); // retain count is 2

        array1.pushBack(objA); // retain count is 3

        array1.pushBack(objA); // retain count is 4

        

        array1.eraseObject(objA, false);

        CCASSERT(objA->getReferenceCount() == 3, ""); // Only remove the first occurrence in the Vector.

    }


    // Check the retain count in vec7

    CCASSERT(vec7.size() == 20, "");

    for (const auto& child : vec7)

    {

        CC_UNUSED_PARAM(child);

        CCASSERT(child->getReferenceCount() == 2, "");

    }


    // Sort  排序,结合Lambda

    Vector<Node*> vecForSort = createVector();

    std::sort(vecForSort.begin(), vecForSort.end(), [](Node* a, Node* b){

        return a->getTag() >= b->getTag();

    });


    for (int i = 0; i < 20; ++i)

    {

        CCASSERT(vecForSort.at(i)->getTag() - 1000 == (19 - i), "");

    }


    // Reverse

    vecForSort.reverse();

    for (int i = 0; i < 20; ++i)

    {

        CCASSERT(vecForSort.at(i)->getTag() - 1000 == i, "");

    }


    // Swap

    Vector<Node*> vecForSwap = createVector();

    vecForSwap.swap(2, 4);

    CCASSERT(vecForSwap.at(2)->getTag() == 1004, "");

    CCASSERT(vecForSwap.at(4)->getTag() == 1002, "");

    vecForSwap.swap(vecForSwap.at(2), vecForSwap.at(4));

    CCASSERT(vecForSwap.at(2)->getTag() == 1002, "");

    CCASSERT(vecForSwap.at(4)->getTag() == 1004, "");


    // shrinkToFit

    Vector<Node*> vecForShrink = createVector();

    vecForShrink.reserve(100);

    CCASSERT(vecForShrink.capacity() == 100, "");

    vecForShrink.pushBack(Node::create());

    vecForShrink.shrinkToFit();

    CCASSERT(vecForShrink.capacity() == 21, "");


    // get random object

    // Set the seed by time

    srand((unsigned)time(nullptr));

    Vector<Node*> vecForRandom = createVector();

    log("<--- begin ---->");

    for (int i = 0; i < vecForRandom.size(); ++i)

    {

        log("Vector: random object tag = %d", vecForRandom.getRandomObject()->getTag());

    }

    log("<---- end  ---->");


    // Self assignment

    Vector<Node*> vecSelfAssign = createVector();

    vecSelfAssign = vecSelfAssign;

    CCASSERT(vecSelfAssign.size() == 20, "");


    for (const auto& child : vecSelfAssign)

    {

        CC_UNUSED_PARAM(child);

        CCASSERT(child->getReferenceCount() == 2, "");

    }


    vecSelfAssign = std::move(vecSelfAssign);

    CCASSERT(vecSelfAssign.size() == 20, "");


    for (const auto& child : vecSelfAssign)

    {

        CC_UNUSED_PARAM(child);

        CCASSERT(child->getReferenceCount() == 2, "");

    }


    // const at

    Vector<Node*> vecConstAt = createVector();

    constFunc(vecConstAt);

}


//---------------------------以下是Map的使用-----------------------------------


void TemplateMapTest::onEnter()

{

    UnitTestDemo::onEnter();

    auto createMap = [this](){

        Map<std::string, Node*> ret;

        for (int i = 0; i < 20; ++i)

        {

            auto node = Node::create();

        

            node->setTag(1000 + i);

            ret.insert(StringUtils::toString(i), node);

        }


        return ret;

    };

    // Default constructor

    Map<std::string, Node*> map1;

    CCASSERT(map1.empty(), "");

    CCASSERT(map1.size() == 0, "");

    CCASSERT(map1.keys().empty(), "");

    CCASSERT(map1.keys(Node::create()).empty(), "");

    // Move constructor

    Map<std::string, Node*> map2 = createMap();

    for (const auto& e : map2)

    {

        CC_UNUSED_PARAM(e);

        CCASSERT(e.second->getReferenceCount() == 2, "");

    }

    // Copy constructor

    Map<std::string, Node*> map3(map2);

    for (const auto& e : map3)

    {

        CC_UNUSED_PARAM(e);

        CCASSERT(e.second->getReferenceCount() == 3, "");

    }

    // Move assignment operator

    Map<std::string, Node*> map4;

    auto unusedNode = Node::create();

    map4.insert("unused",unusedNode);

    map4 = createMap();

    CCASSERT(unusedNode->getReferenceCount() == 1, "");

    for (const auto& e : map4)

    {

        CC_UNUSED_PARAM(e);

        CCASSERT(e.second->getReferenceCount() == 2, "");

    }

    // Copy assignment operator

    Map<std::string, Node*> map5;

    map5 = map4;

    for (const auto& e : map5)

    {

        CC_UNUSED_PARAM(e);

        CCASSERT(e.second->getReferenceCount() == 3, "");

    }

    // Check size

    CCASSERT(map4.size() == map5.size(), "");

    for (const auto& e : map4)

    {

        CC_UNUSED_PARAM(e);

        CCASSERT(e.second == map5.find(e.first)->second, "");

    }

    // bucket_count, bucket_size(n), bucket

    log("--------------");

    log("bucket_count = %d", static_cast<int>(map4.bucketCount()));

    log("size = %d", static_cast<int>(map4.size()));

    for (int i = 0; i < map4.bucketCount(); ++i)

    {

        log("bucket_size(%d) = %d", i, static_cast<int>(map4.bucketSize(i)));

    }

    for (const auto& e : map4)

    {

        log("bucket(\"%s\"), bucket index = %d", e.first.c_str(), static_cast<int>(map4.bucket(e.first)));

    }

    log("----- all keys---------");

    // keys and at

    auto keys = map4.keys();

    for (const auto& key : keys)

    {

        log("key = %s", key.c_str());

    }


    auto node10Key = map4.at("10");

    map4.insert("100", node10Key);

    map4.insert("101", node10Key);

    map4.insert("102", node10Key);


    log("------ keys for object --------");

    auto keysForObject = map4.keys(node10Key);

    for (const auto& key : keysForObject)

    {

        log("key = %s", key.c_str());

    }

    log("--------------");


    // at in const function

    constFunc(map4);


    // find

    auto nodeToFind = map4.find("10");

    CC_UNUSED_PARAM(nodeToFind);

    CCASSERT(nodeToFind->second->getTag() == 1010, "");


    // insert

    Map<std::string, Node*> map6;

    auto node1 = Node::create();

    node1->setTag(101);

    auto node2 = Node::create();

    node2->setTag(102);

    auto node3 = Node::create();

    node3->setTag(103);

    map6.insert("insert01", node1);

    map6.insert("insert02", node2);

    map6.insert("insert03", node3);


    CCASSERT(node1->getReferenceCount() == 2, "");

    CCASSERT(node2->getReferenceCount() == 2, "");

    CCASSERT(node3->getReferenceCount() == 2, "");

    CCASSERT(map6.at("insert01") == node1, "");

    CCASSERT(map6.at("insert02") == node2, "");

    CCASSERT(map6.at("insert03") == node3, "");


    // erase

    Map<std::string, Node*> mapForErase = createMap();

    mapForErase.erase(mapForErase.find("9"));

    CCASSERT(mapForErase.find("9") == mapForErase.end(), "");

    CCASSERT(mapForErase.size() == 19, "");


    mapForErase.erase("7");

    CCASSERT(mapForErase.find("7") == mapForErase.end(), "");

    CCASSERT(mapForErase.size() == 18, "");


    std::vector<std::string> itemsToRemove;

    itemsToRemove.push_back("2");

    itemsToRemove.push_back("3");

    itemsToRemove.push_back("4");

    mapForErase.erase(itemsToRemove);

    CCASSERT(mapForErase.size() == 15, "");


    // clear

    Map<std::string, Node*> mapForClear = createMap();

    auto mapForClearCopy = mapForClear;

    mapForClear.clear();


    for (const auto& e : mapForClearCopy)

    {

        CC_UNUSED_PARAM(e);

        CCASSERT(e.second->getReferenceCount() == 2, "");

    }


    // get random object

    // Set the seed by time

    srand((unsigned)time(nullptr));

    Map<std::string, Node*> mapForRandom = createMap();

    log("<--- begin ---->");

    for (int i = 0; i < mapForRandom.size(); ++i)

    {

        log("Map: random object tag = %d", mapForRandom.getRandomObject()->getTag());

    }

    log("<---- end  ---->");


    // Self assignment

    Map<std::string, Node*> mapForSelfAssign = createMap();

    mapForSelfAssign = mapForSelfAssign;

    CCASSERT(mapForSelfAssign.size() == 20, "");


    for (const auto& e : mapForSelfAssign)

    {

        CC_UNUSED_PARAM(e);

        CCASSERT(e.second->getReferenceCount() == 2, "");

    }


    mapForSelfAssign = std::move(mapForSelfAssign);

    CCASSERT(mapForSelfAssign.size() == 20, "");


    for (const auto& e : mapForSelfAssign)

    {

        CC_UNUSED_PARAM(e);

        CCASSERT(e.second->getReferenceCount() == 2, "");

    }

}



//--------------------------以下是Value的使用,它完成基本数据类型到对象的包装--------


void ValueTest::onEnter()

{

    UnitTestDemo::onEnter();

    

    Value v1;

    CCASSERT(v1.getType() == Value::Type::NONE, "");

    CCASSERT(v1.isNull(), "");

    

    Value v2(100);

    CCASSERT(v2.getType() == Value::Type::INTEGER, "");

    CCASSERT(!v2.isNull(), "");

    

    Value v3(101.4f);

    CCASSERT(v3.getType() == Value::Type::FLOAT, "");

    CCASSERT(!v3.isNull(), "");

    

    Value v4(106.1);

    CCASSERT(v4.getType() == Value::Type::DOUBLE, "");

    CCASSERT(!v4.isNull(), "");

    

    unsigned char byte = 50;

    Value v5(byte);

    CCASSERT(v5.getType() == Value::Type::BYTE, "");

    CCASSERT(!v5.isNull(), "");

    

    Value v6(true);

    CCASSERT(v6.getType() == Value::Type::BOOLEAN, "");

    CCASSERT(!v6.isNull(), "");

    

    Value v7("string");

    CCASSERT(v7.getType() == Value::Type::STRING, "");

    CCASSERT(!v7.isNull(), "");

    

    Value v8(std::string("string2"));

    CCASSERT(v8.getType() == Value::Type::STRING, "");

    CCASSERT(!v8.isNull(), "");


    auto createValueVector = [&](){

        ValueVector ret;

        ret.push_back(v1);

        ret.push_back(v2);

        ret.push_back(v3);

        return ret;

    };

    

    

    Value v9(createValueVector());

    CCASSERT(v9.getType() == Value::Type::VECTOR, "");

    CCASSERT(!v9.isNull(), "");


    auto createValueMap = [&](){

        ValueMap ret;

        ret["aaa"] = v1;

        ret["bbb"] = v2;

        ret["ccc"] = v3;

        return ret;

    };

    

    Value v10(createValueMap());

    CCASSERT(v10.getType() == Value::Type::MAP, "");

    CCASSERT(!v10.isNull(), "");

    

    auto createValueMapIntKey = [&](){

        ValueMapIntKey ret;

        ret[111] = v1;

        ret[222] = v2;

        ret[333] = v3;

        return ret;

    };

    

    Value v11(createValueMapIntKey());

    CCASSERT(v11.getType() == Value::Type::INT_KEY_MAP, "");

    CCASSERT(!v11.isNull(), "");

}

----------------------------亲,学会了没----------------------------



Cocos2d-x 3.0final 终结者系列教程12-Vector&map&value,布布扣,bubuko.com

Cocos2d-x 3.0final 终结者系列教程12-Vector&map&value

标签:cocos2d-x   vector map value   

原文地址:http://blog.csdn.net/sdhjob/article/details/27642509

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!