如何在糖果迷之类的游戏中为瓷砖分配颜色

Posted

技术标签:

【中文标题】如何在糖果迷之类的游戏中为瓷砖分配颜色【英文标题】:How do i allocate colors to tiles in a game like candy crush 【发布时间】:2016-03-25 11:16:04 【问题描述】:

我用 C/C++ 开发了一个部分游戏,其中瓷砖被交换Here。 我现在想实现糖果粉碎,我知道画糖果需要很多努力。让瓷砖完成这项工作。 在为瓷砖分配颜色的部分中,我不希望三种颜色出现在一行或一列中。我如何以有效的方式做到这一点。 我目前正在像这样随机分配颜色:

board[i][j].color=rand()%3;

看起来像这样:

是的,我不希望一行或一列中的三个单元格或图块具有相同的颜色,即不超过两个相同颜色的相邻图块。 我的意思是我不想要一个颜色被分配一次并且检查一行中的三个瓷砖是否具有相同颜色的解决方案。如果没有再次为所有图块生成颜色。那将太天真和昂贵。 另一种解决方案可能是在按光栅顺序将颜色分配给图块之前,检查下方或左侧的两个图块是否具有相同的颜色,如果分配了其他颜色。这也是显而易见的。有没有更好的办法?

在 Weather Wane 的回答之后,我发布了使用 STL 迭代器和 set_difference 方法执行设置差异操作的代码。我正在尝试的是在从一组颜色中随机选择之前,我通过使用集合操作仅消除已经重复两次(下方或左侧)的那些颜色来形成该集合。代码有问题。我对STL了解不多。谁能指导我如何正确使用它。

for(j=0;j<maxy;j++)
for(i=0;i<maxx;i++)

    int first[] = 0,1,2,3,fsize,i34;
    std::vector<int> v(5);                     
    std::vector<int>::iterator it;

    board[i][j].x0=x0+i*dx+1;
    board[i][j].x1=x0+(i+1)*dx-1;
    board[i][j].y0=y0+j*dy+1;
    board[i][j].y1=y0+(j+1)*dy-1;


    if((i-1)>=0&&board[i-1][j].color==0&&(i-2)>=0&&board[i-2][j].color==0)
    int second[] = 0;
    std::sort (first,first+4);     
    it=std::set_difference (first, first+4, second, second+1, v.begin());
    v.resize(it-v.begin());                      
    std::copy(v.begin(), v.end(), first);
    
    fsize=v.size();
    if((i-1)>=0&&board[i-1][j].color==1&&(i-2)>=0&&board[i-2][j].color==1)
    int second[] = 1;
    std::sort (first,first+fsize);     //  5 10 15 20 25
    it=std::set_difference (first, first+fsize, second, second+1, v.begin());
                                            //  5 15 25  0  0  0  0  0  0  0
    v.resize(it-v.begin());                      //  5 15 25
    std::copy(v.begin(), v.end(), first);
    
    fsize=v.size();
    if((i-1)>=0&&board[i-1][j].color==2&&(i-2)>=0&&board[i-2][j].color==2)
    int second[] = 2;
    std::sort (first,first+fsize);     //  5 10 15 20 25
    it=std::set_difference (first, first+fsize, second, second+1, v.begin());
                                       //  5 15 25  0  0  0  0  0  0  0
    v.resize(it-v.begin());                      //  5 15 25
    std::copy(v.begin(), v.end(), first);
    
    fsize=v.size();
    if((j-1)>=0&&board[i][j-1].color==0&&(j-2)>=0&&board[i][j-2].color==0)
    int second[] = 0;
    std::sort (first,first+fsize);     //  5 10 15 20 25
    it=std::set_difference (first, first+fsize, second, second+1, v.begin());
                                       //  5 15 25  0  0  0  0  0  0  0
    v.resize(it-v.begin());                      //  5 15 25
    std::copy(v.begin(), v.end(), first);
    
    fsize=v.size();
    if((j-1)>=0&&board[i][j-1].color==1&&(j-2)>=0&&board[i][j-2].color==1)
    int second[] = 1;
    std::sort (first,first+fsize);     //  5 10 15 20 25
    it=std::set_difference (first, first+fsize, second, second+1, v.begin());
                              //  5 15 25  0  0  0  0  0  0  0
    v.resize(it-v.begin());                      //  5 15 25
    std::copy(v.begin(), v.end(), first);
    
    fsize=v.size();
    if((j-1)>=0&&board[i][j-1].color==2&&(j-2)>=0&&board[i][j-2].color==2)
    int second[] = 2;
    std::sort (first,first+fsize);     //  5 10 15 20 25
                                    // 10 20 30 40 50
    it=std::set_difference (first, first+fsize, second, second+1, v.begin());
                                  //  5 15 25  0  0  0  0  0  0  0
    v.resize(it-v.begin());                      //  5 15 25
    std::copy(v.begin(), v.end(), first);
    
    //  first=&v[0];
    fsize=v.size();
    cout<<v.size()<<" ";
    for(i34=0,it=v.begin();it!=v.end();it++)
    cout<<*it<<" "; first[i34++]=*it;
    cout<<" ";
    if(v.size()>0&&v.size()!=5)
    board[i][j].color=first[rand()%i34];
    else if (v.size()==5) board[i][j].color=first[rand()%4];
    
    cout<<"\n";

【问题讨论】:

看起来像一些动态规划问题。你可能需要在这个领域搜索一些算法,我相信有一个解决方案。无法从我的脑海中得到这个名字。 从问题中不清楚限制是否是 a) 在整行或整列中不超过 2 种不同颜色,b) 不超过 2 块任何一种颜色,或 c) 不超过超过 2 个相邻颜色匹配的图块。 【参考方案1】:

无论如何,您必须实现一个函数来计算一个图块是否在“3 个相同颜色的图块组”中。

实现它并在你的颜色分配函数中使用它。

希望是:

对于每个图块。 选择一个随机颜色,直到它不构成“3个相同颜色的瓷砖组”。

【讨论】:

【参考方案2】:

不要反复选择一种颜色,然后用您的规则检查它,而是应用规则首先并制作一组可用颜色。然后随机选择数组索引。如果没有可用的颜色:倒回,从上一个列表中删除之前选择的颜色。

假设你有 3 种颜色。而不是重复使用

board[i][j].color = rand() % 3;

直到颜色符合规则,您可以构建一个符合规则的颜色数组,例如

int avail_color[3];
int num_avail;

然后你选择这样的颜色

board[i][j].color = avail_color[ rand() % num_avail ];

类似于Fisher-Yates shuffle。

【讨论】:

先生,在我目前的方案中,填充avail_color[] 需要与运行循环相同的计算。并且avail_color中的元素数量将是可变的,这在C,C++中是不允许的 你不会避免执行你的规则。使用我的方法,你不需要重复调​​用rand(),直到找到合适的颜色,可能会多次使用规则检查相同的颜色。并且数组不是可变长度的,它是长度[3]。 var num_avail 告诉您该数组中有多少种颜色 - 实际使用的元素数量。【参考方案3】:

我想要的是实现减集操作,在该操作中我排除了那些在左侧或下方重复两次的随机选择的颜色。

for(i=0;i<maxx;i++)
        for(j=0;j<maxy;j++)
        exzero=exone=extwo=exthree=0;
            board[i][j].x0=x0+i*dx+1;
            board[i][j].x1=x0+(i+1)*dx-1;
            board[i][j].y0=y0+j*dy+1;
            board[i][j].y1=y0+(j+1)*dy-1;
            if((i-1)>=0&&board[i-1][j].color==0&&(i-2)>=0&&board[i-2][j].color==0)
                exzero=1;
            if((i-1)>=0&&board[i-1][j].color==1&&(i-2)>=0&&board[i-2][j].color==1)
                exone=1;
            if((i-1)>=0&&board[i-1][j].color==2&&(i-2)>=0&&board[i-2][j].color==2)
                extwo=1;
            if((i-1)>=0&&board[i-1][j].color==3&&(i-2)>=0&&board[i-2][j].color==3)
                            exthree=1;
            if((j-1)>=0&&board[i][j-1].color==0&&(j-2)>=0&&board[i][j-2].color==0)
                exzero=1;
            if((j-1)>=0&&board[i][j-1].color==1&&(j-2)>=0&&board[i][j-2].color==1)
                exone=1;
            if((j-1)>=0&&board[i][j-1].color==2&&(j-2)>=0&&board[i][j-2].color==2)
                extwo=1;
            if((j-1)>=0&&board[i][j-1].color==3&&(j-2)>=0&&board[i][j-2].color==3)
                            exthree=1;
            compositebin=exzero|exone<<1|extwo<<2|exthree<<3;
        //  cout<<compositebin<<" ";
            switch(compositebin)
            
            case 0:board[i][j].color=rand()%4;break;
            case 1:board[i][j].color=rand()%2?1:2;break;
            case 2:board[i][j].color=rand()%2?0:2;break;
            case 3:board[i][j].color=2;break;
            case 4:board[i][j].color=rand()%2?1:0;break;
            case 5:board[i][j].color=1;break;
            case 6:board[i][j].color=0;break;
            case 7:break;
            case 8:board[i][j].color=rand()%2?rand()%2?0:1:2;break;
            case 9:board[i][j].color=rand()%2?1:2;break;
            case 10:board[i][j].color=rand()%2?0:2;break;
            case 11:board[i][j].color=2;break;
            case 12:board[i][j].color=rand()%2?1:0;break;
            case 13:board[i][j].color=1;break;
            case 14:board[i][j].color=0;break;
            case 15:break;
            

        

使用标志排除零,排除一,排除二和排除三以排除四种颜色的这段代码做得很好。我形成一个复合二进制数,并根据它的值进行切换,从0,1,2,3的子集中随机选择。

【讨论】:

以上是关于如何在糖果迷之类的游戏中为瓷砖分配颜色的主要内容,如果未能解决你的问题,请参考以下文章

如何在 info.plist 文件中为特定游戏关卡中保存的颜色设置创建条目?

如何在Java中获取2048中瓷砖的值[关闭]

在移动设备上没有触发第二次点击画布

SOJ4459 skysky's game(贪心优先队列)

如何在 Xcode 6 的 XIB Interface Builder 中为 Mac 应用程序分配按钮

更改 SKTileMapNode 中特定图块的颜色