随机分配来自多个阵列的数字

时间:2015-08-04 04:08:55

标签: objective-c

所以我试图在中途模拟纸牌游戏。每个玩家都有一个猜测数组"其中包含其他玩家可能拥有的所有牌。这些阵列基于其他玩家的游戏历史。如果玩家无法效仿,AI会从该玩家的猜测阵列中移除所有领牌的牌。例如,如果黑桃是主角并且第二个玩家放下心脏,代码将从玩家2中移除Spade套装中的所有牌。

我遇到的问题是以下情况:

OL  P   OR
1   1   1
    2   2
3   3   

在这里,OL(对手左)可以有牌1和3.P(伙伴)可以有牌1,2和3.最后,OR(对手右)可以有牌1和2.

现在代码并不聪明,无法处理OL选择卡1并且Parner选择卡2的情况。这导致对手右阵列完全为空,导致致命错误。

我试图通过在while循环中分发卡片来解决这个问题。只要任何阵列小于满,循环将继续随机分配卡。我对这种方法的问题在于它可能导致明显的无限循环,或者至少会显着降低游戏速度。

while (guessplayerOLfull==false || guessplayerPfull==false || guessplayerORfull==false)
{
    numplayerleft= 0;
    numpartner= 0;
    numplayerright= 0;

    [guessplayerOLremaining removeAllObjects];
    [guessplayerPremaining removeAllObjects];
    [guessplayerORremaining removeAllObjects];

    [guessplayerOL removeAllObjects];
    [guessplayerP removeAllObjects];
    [guessplayerOr removeAllObjects];

    [guessplayerOLremaining addObjectsFromArray:opplefthand];
    [guessplayerPremaining addObjectsFromArray:partnerhand];
    [guessplayerORremaining addObjectsFromArray:opprighthand];

    for (int m=0; m<[opplefthand count]-1; ++m)
    {
        if (![opprighthand containsObject:opplefthand[m]] && ![partnerhand containsObject:opplefthand[m]] )
        {
            numplayerleft=numplayerleft+1;
            [guessplayerOL addObject:opplefthand[m]];
            [guessplayerOLremaining removeObject:opplefthand[m]];
        }
    }

    for (int m=0; m<[partnerhand count]-1; ++m)
    {
        if (![opprighthand containsObject:partnerhand[m]] && ![opplefthand containsObject:partnerhand[m]] )
        {
            numpartner=numpartner+1;
            [guessplayerP addObject:partnerhand[m]];
            [guessplayerPremaining removeObject:partnerhand[m]];
        }
    }

    for (int m=0; m<[opprighthand count]-1; ++m)
    {
        if (![opplefthand containsObject:opprighthand[m]] && ![partnerhand containsObject:opprighthand[m]] )
        {
            numplayerright=numplayerright+1;
            [guessplayerOR addObject:opprighthand[m]];
            [guessplayerORremaining removeObject:opprighthand[m]];
        }
    }

    //Fill Player Left Array
    for (int n=0; n<[playerhand count] -1 -numplayerleft; n++)
    {
        if ([guessplayerOLremaining count]>1)
        {
            player_left_random =(arc4random() % ([guessplayerOLremaining count]-1));

            [guessplayerOL addObject:guessplayerOLremaining[player_left_random]];
            [guessplayerORremaining removeObject:guessplayerOLremaining[player_left_random]];
            [guessplayerPremaining removeObject:guessplayerOLremaining[player_left_random]];
            [guessplayerOLremaining removeObject:guessplayerOLremaining[player_left_random]];
        }
        else
        {
            player_left_random=0;
        }
    }

    for (int m=0; m<[guessplayerPremaining count]; ++m)
    {
        if (![opprighthand containsObject:guessplayerPremaining[m]] )
        {
            numpartner=numpartner+1;
            [guessplayerP addObject:guessplayerPremaining[m]];
            [guessplayerPremaining removeObject:guessplayerPremaining[m]];
        }
    }

    //Fill Partner Array
    for (int n=0; n<[playerhand count]-1 -numpartner; n++)
    {
        if ([guessplayerPremaining count]>1)
        {
            player_left_random =(arc4random() % ([guessplayerPremaining count]-1));

            [guessplayerP addObject:guessplayerPremaining[player_left_random]];
            [guessplayerOLremaining removeObject:guessplayerPremaining[player_left_random]];
            [guessplayerORremaining removeObject:guessplayerPremaining[player_left_random]];
            [guessplayerPremaining removeObject:guessplayerPremaining[player_left_random]];
        }
        else
        {
            player_left_random=0;
        }
    }

    [guessplayerOR addObjectsFromArray:guessplayerORremaining];

    if ([guessplayerOL count]==[playerhand count]-1)
    {
        guessplayerOLfull=true;
    }

    if ([guessplayerP count]==[playerhand count]-1)
    {
        guessplayerPfull=true;
    }

    if ([guessplayerOR count]==[playerhand count]-1)
    {
        guessplayerORfull=true;
    }

} //End While

在我看来应该有一些方法可以确定如果对手选择了卡牌,那么合作伙伴必须选择卡牌3.我在这里缺少什么?这似乎应该是显而易见的。

2 个答案:

答案 0 :(得分:1)

在四人游戏中......

如果每个玩家至少剩下四个选择,那么第一张牌就没有限制。您可以随意选择,从另一只手中取出卡,再次选择,等等。

当某些玩家的选择少于四个时,问题就出现了。特别是,如果三个玩家具有相同的三个选择,那么这些选择对于第四个玩家是不可用的。同样,如果两个玩家有两个相同的选择,那么其他两个玩家无法获得这些选择。如果一个玩家只有一个选择,那么其他三个选项都无法使用。

所以考虑到这种情况

OL  P   OR
1   1   1
    2   2
3   3   

如果OL选择卡1,那么你就剩下了

P  OR
2  2
3 

现在你有一个只有一个选择的玩家(OR)(2)。因此,2不是P的选项。

作为另一个例子,请考虑这种情况

OL  P   OR
1   1   1
2   2   2
3      

在这种情况下,两个玩家(P和OR)具有相同的两个选择(1和2)。因此,1和2不是OL的选项。所以,事实上情况真的是

OL  P   OR
3   1   1
    2   2

将这个扩展到四个玩家会让事情变得更有趣。考虑

ME  OL  P  OR
1   1   1  1
2   2   2  2
3   3
4

两个玩家(P和OR)有两个相同的选择(1和2),所以这会减少到

ME  OL  P  OR
3   3   1  1
4       2  2

但是现在一个玩家(OL)有一个选择(3),所以再次减少到

ME  OL  P  OR
4   3   1  1
        2  2

这些是实际的选择。

一般来说,

  • 迭代地应用规则,直到不可能减少为止
  • 为玩家选择一张卡
  • 从其他玩家的名单中删除该卡
  • 重复,直到选择所有卡

答案 1 :(得分:0)

如果你想为每个玩家维护一组可能的牌,整体算法将是:

  1. 将整套卡片添加到每个玩家的
  2. 从其他所有玩家的
  3. 中移开你自己的手牌
  4. 当玩家玩牌时:
    • 删除所有其他玩家的卡片
    • 对于玩牌的玩家组中的每张牌,如果游戏规则暗示他们不能给出他们刚玩过的牌,则将其删除
  5. 每当玩家的牌组只剩下一张牌时,它就是他们唯一可能拥有的牌 - 现在已经知道他们拥有了这张牌,并且该牌可以从其他牌手中移除。套装(最后可能只剩下一张卡)
  6. 重要的是不要猜测&#34;或推测在遵循这些步骤时,即,如果实际播放了卡片,则只能从步骤3中的一组中移除,或者根据游戏规则不可能有那张卡。 根据概率从这些集合中删除卡片,只有100%的事实(如果需要,请参阅下面的假设)。

    请注意,由于这些是集合,因此您可以使用NSMutableSet获得更高的性能,并且它包含minusSet:等方便的方法。

    结果集将包含每个玩家可能以确定方式拥有的所有可能牌(假设该软件阻止违反游戏规则)。如果您希望有更多更小的套装,那就是&#34;猜测&#34;他们可能拥有的东西,您可以单独构建它们,并在更新所有可能的卡片集时使用interesectSet:

    例如,猜测集也可以删除玩家愚蠢而不玩的牌而不是他们玩的牌,但这种猜测可能是错误的(因为玩家可能是愚蠢的),所以你不能依赖于猜测设置是正确的还是非空的(如果是,则回退到所有可能的卡的集合)。

    如果你发现自己处于问题所描述的情况中,那套空卡片意味着你猜对了!因此,检查猜测的集合是否为空 - 如果不是,请使用它,如果是,则通过将该播放器的所有可能卡集复制到猜测集来恢复。这就是为什么你必须拥有所有可能性的事实,而不仅仅是猜测。

    根据上述规则3,您必须始终保持所有可能卡片的平行设置和设置。这包括您运行的任何模拟游戏;您必须更新模拟中使用的集合,就像模拟的移动是真实的一样。由于您不想忘记实际集合,因此您需要为每轮模拟创建一个新副本。