我正在使用Xcode为iPad编写内存游戏,当计算机处理转弯时,我遇到了一个问题。当他击中一对然后他应该有另一个转弯,这就是为什么我需要这个方法有一个大的while循环,但是当实现这个循环时,不再执行/显示转动卡片的动画。
起初:谢谢你的回答。 我认为我按照你说的那样组织了我的程序,但是我需要一些更具体的帮助。我真的不知道接下来该做什么。我只是尝试使用animatewithduration,但动画立即被触发,所以我评论了它。 我上传了我的项目,让你更好地了解我做了什么,如果你可以帮助我,那将是很好的。 - > myproject
更详细的说明: 该应用程序以标签栏上的设置视图开始。你可以忽略它,只需按下第一个标签即可开始游戏。有48个存储卡(24对)的集合视图。出于测试目的,它们显示的是正面图像而不是背面。用户启动并进行第一次转弯。他必须点击2张牌,他们会四处移动以显示背面。如果它是一对,玩家还有另一个转弯,如果没有,那么现在是计算机转向(两张卡存储在计算机敌人的记忆中)并且用户不再能够触摸卡。在开始时轮到他了,如果他已经存储了一对,那么计算机就会在他的记忆中找到它。如果是,他拿两张牌,他们应该转身,并应该转弯。如果不是,他将随机选择第一张牌,并在他的记忆中看到他是否知道第二张牌位于何处。如果计算机找不到对,因为他的记忆中没有合适的牌,他随机选择的两张牌也不是一对,玩家转身,应用等待玩家接触两张牌。
直到这里才能很好地运作,但现在出现了问题。如果计算机敌人匹配一对,他又转了一圈。这就是我使用while循环的原因。但是我需要做什么,在没有while循环的情况下实现tat算法?
该视图控制器中的代码如下所示:
NSLog(@"computer ist dran!");
//while(!playerVsCompViewController.isPlayersTurn)
//{
NSLog(@"test!!!!");
//sleep(1);
//pruefen ob computer ein paar kennt
// (Check whether the computer "knows" a pair)
if([playerVsCompViewController.computerEnemy knowAPair])
{
//wenn spiel noch nicht zu ende...
//(if game not to end)
}
else
{
//zufallszahl zum umdrehen der ersten karte
//(random number to turn over the first card)
int random = (arc4random() % [playerVsCompViewController.cards count]);
HTWMyCustomCell *cell1 = [[playerVsCompViewController.cards objectAtIndex:random] parentCell];
//erste karte umdrehen
// (first turn card)
[UIView transitionWithView:cell1 duration:1.0 options:UIViewAnimationOptionTransitionFlipFromRight animations:^
{
cell1.cellCard.showsFront = true;
cell1.cellImage.image = cell1.cellCard.backImage;
//wenn fertig soll zweite karte umgedreht werden
//(when ready to begin second card will be turned over)
} completion:^(BOOL finished)
{
//pruefen ob erste karte im paarkarte im gedaechtnis hat
//(Look for pair for first card in memory)
HTWCard *pairCard = [self memoriedPairCard:cell1.cellCard];
//wenn die paarkarte dazu im gedaechtnis gefunden wurde
//(when the pair was found in memory)
if(pairCard != NULL)
{
//zweite karte aufdecken
//(uncover second card)
[UIView transitionWithView:pairCard.parentCell duration:1.0 options:UIViewAnimationOptionTransitionFlipFromRight animations:^
{
pairCard.showsFront = true;
pairCard.parentCell.cellImage.image = pairCard.backImage;
} completion:^(BOOL finished)
{
//beide karten aus dem gedaechtnis loeschen
//(Delete both cards from the memory)
[self deleteCardesFromMemory:cell1.cellCard andSecondCard:pairCard];
}];
}
else
{
//wenn keine passende karte gefunden in der memory gefunden wurde
//(if no matching found in the memory card was found)
//zweite karte zufaellig umdrehen
//(Turn second card randomly)
int random2 = (arc4random() % [playerVsCompViewController.cards count]);
HTWMyCustomCell *cell2 = [[playerVsCompViewController.cards objectAtIndex:random2] parentCell];
[UIView transitionWithView:cell2 duration:1.0 options:UIViewAnimationOptionTransitionFlipFromRight animations:^
{
cell2.cellCard.showsFront = true;
cell2.cellImage.image = cell2.cellCard.backImage;
} completion:^(BOOL finished)
{
sleep(1);
//paerchen gefunden
//(pair found)
if(cell1.cellCard.frontImage == cell2.cellCard.frontImage)
{
//punkte an computer verteilen
//(distribute points to computer)
//karten aus dem gedaechtnis loeschen
//(delete cards from the memory)
[self deleteCardesFromMemory:cell1.cellCard andSecondCard:cell2.cellCard];
}
else
{
//kein paerchen gefunden
//(found no up pairs)
//karten ins gedaechtnis speichern
//(save cards to memory)
[self updateMemory:cell1.cellCard];
[self updateMemory:cell2.cellCard];
playerVsCompViewController.isPlayersTurn = true;
//karten wieder zurueckdrehen
//(cards to turn back again)
[UIView transitionWithView:cell1 duration:1.0 options:UIViewAnimationOptionTransitionFlipFromLeft animations:^
{
cell1.cellCard.showsFront = false;
cell1.cellImage.image = cell1.cellCard.frontImage;
} completion:^(BOOL finished1)
{
cell2.cellCard.showsFront = false;
[UIView transitionWithView:cell2 duration:1.0 options:UIViewAnimationOptionTransitionFlipFromLeft animations:^
{
cell2.cellCard.showsFront = false;
cell2.cellImage.image = cell2.cellCard.frontImage;
} completion:^(BOOL finished2)
{
//wenn spiel noch nicht vorbei ist
//spieler ist an der reihe
//(if game is not over yet
//player has its turn)
playerVsCompViewController.isPlayersTurn = true;
}];
}];
}// ende zufaellig paar getroffen (end coincidentally hit pair)
}]; // ende animation zweite karte (end animation second card)
}
}];
}
//}
NSLog(@"computer ist fertig!");
答案 0 :(得分:2)
回顾您的项目,感觉就像是在尝试处理动画,这些动画本质上是异步的,就像同步操作一样。不幸的是,在while
循环中包装一堆动画是行不通的。如果你想通过另一个动作完成计算机成功移动的动画,你必须为此采用一些异步模式。
简单的解决方案是简单地获得计算机动画的最终完成块,即成功匹配的翻转(无论knowsAPair
成功,还是随机卡匹配内存中的卡,或者是否是第二张随机选择的卡匹配第一个随机选择的卡)然后再调用processTurn
方法到主队列(让计算机再试一次)。
一些不相关的观察
在你的knowsAPair
中,如果它知道一对,你就是动画,但是你没有做任何事情要从你的记忆中删除这些牌,也没有触发processTurn
的运行再次。该例程有一些不必要的变量,即使在找到第一个匹配后仍继续寻找匹配。
在让计算机随机化卡片的同时,您似乎没有检查(a)卡片是否已被翻转;或者(b)第二张卡与第一张卡不匹配。
典型的编码模式不是while
循环,而是由用户的移动(例如,手势识别器或按钮)触发的更多事件驱动模式。你想要这个方法
检查一些布尔类属性,该属性指示是否接受用户移动(结果是,您已经有这样的属性),如果没有,则提供一些不允许用户输入的反馈,但是然后退出立即;
假设class属性指示要接受用户输入,那么您将关闭该boolean类属性以确保在设备完成必要的动画之前不会接受进一步的用户输入和计算机移动;
动画用户的动作;
为计算机的移动设置动画,如果计算机再次移动,则当前移动的最终动画块应启动计算机的下一步移动;当你完成后,
返回允许用户移动的布尔属性。
顺便说一句,我看到你在那里有sleep
陈述。如果您想推迟某些动画,则应该sleep
(或者如果它是dispatch_after
,而不是UIView animateWithDuration
,请使用带有delay
参数的再现。但强烈建议不要在主线程上执行sleep
。
希望这有点帮助。底线,移动到事件驱动的回合模式,使用一些控制属性来指示是否应该接受进一步的用户输入,因为动画是异步发生的。
如果我误解了你的游戏正在做什么(我假设一些基于回合制的纸牌游戏),你可能想要编辑你的问题并包含一个非常简短的游戏规则叙述和UX应该是什么。