所以我试图在中途模拟纸牌游戏。每个玩家都有一个猜测数组"其中包含其他玩家可能拥有的所有牌。这些阵列基于其他玩家的游戏历史。如果玩家无法效仿,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.我在这里缺少什么?这似乎应该是显而易见的。
答案 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)
如果你想为每个玩家维护一组可能的牌,整体算法将是:
重要的是不要猜测&#34;或推测在遵循这些步骤时,即,如果实际播放了卡片,则只能从步骤3中的一组中移除,或者根据游戏规则不可能有那张卡。 不根据概率从这些集合中删除卡片,只有100%的事实(如果需要,请参阅下面的假设)。
请注意,由于这些是集合,因此您可以使用NSMutableSet
获得更高的性能,并且它包含minusSet:
等方便的方法。
结果集将包含每个玩家可能以确定方式拥有的所有可能牌(假设该软件阻止违反游戏规则)。如果您希望有更多更小的套装,那就是&#34;猜测&#34;他们可能拥有的东西,您可以单独构建它们,并在更新所有可能的卡片集时使用interesectSet:
。
例如,猜测集也可以删除玩家愚蠢而不玩的牌而不是他们玩的牌,但这种猜测可能是错误的(因为玩家可能是愚蠢的),所以你不能依赖于猜测设置是正确的还是非空的(如果是,则回退到所有可能的卡的集合)。
如果你发现自己处于问题所描述的情况中,那套空卡片意味着你猜对了!因此,检查猜测的集合是否为空 - 如果不是,请使用它,如果是,则通过将该播放器的所有可能卡集复制到猜测集来恢复。这就是为什么你必须拥有所有可能性的事实,而不仅仅是猜测。
根据上述规则3,您必须始终保持所有可能卡片的平行设置和设置。这包括您运行的任何模拟游戏;您必须更新模拟中使用的集合,就像模拟的移动是真实的一样。由于您不想忘记实际集合,因此您需要为每轮模拟创建一个新副本。