2

我正在使用 Xcode 为 iPad 编写记忆游戏,当计算机处理转弯时,我在该例程中遇到了问题。当他击中一对时,他应该有另一个回合,这就是为什么我需要这个方法来有一个大的 while 循环,但是当这个循环被实现时,转动卡片的动画不再执行/显示。

编辑:

首先:感谢您的回答。我认为我像你说的那样构建了我的程序,但我需要一些更具体的帮助。我真的不知道下一步该怎么做。我只是尝试使用 animatewithduration,但动画随即触发,所以我将其注释掉。我上传了我的项目,让你更好地了解我做了什么,如果你能帮助我,那就太好了。->我的项目

更详细的描述:该应用程序从选项卡栏上的设置视图开始。您可以忽略它,只需按第一个选项卡即可开始游戏。有一个包含 48 个存储卡(24 对)的集合视图。出于测试目的,它们显示正面图像而不是背面。用户开始并有第一轮。他必须点击两张牌,它们会四处移动以显示背面。如果是对子,则玩家有另一轮,如果不是,则现在轮到计算机(两张牌存储在计算机敌人的内存中),用户不再能够触摸牌。轮到他了,如果他已经存储了一对,计算机就会在他的记忆中查找。如果是,他拿了两张牌,他们应该转身,应该再转一次。如果不是,他将随机选择第一张牌,如果他知道第二张牌在哪里,他会在记忆中查找。如果计算机因为他的记忆中没有适合的牌而没有找到对子,并且他随机选择的两张牌也不是对子,则轮到玩家,应用程序等待玩家触摸两张牌。

直到这里都很好,但现在问题来了。如果计算机敌人匹配了一对,他有另一个回合。这就是我使用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!");
4

1 回答 1

2

回顾你的项目,感觉就像你在尝试处理动画,它们本质上是异步的,就像同步操作一样。不幸的是,将一堆动画包装在一个while循环中是行不通的。如果你想用另一个动作完成计算机成功移动的动画,你必须为此采用一些异步模式。

简单的解决方案是简单地让计算机动画的最终完成块翻转成功匹配(是否knowsAPair成功,或者随机卡匹配内存中的一个,或者第二张随机选择的卡是否匹配第一张随机选择的卡)然后将对该方法的另一个调用分派processTurn到主队列(让计算机再试一次)。

一些不相​​关的观察

  1. 在你的knowsAPair中,如果它知道一对,你正在制作动画,但你没有做任何事情来从你的记忆中删除卡片,也没有触发processTurn再次运行。该例程有一些不必要的变量,并且即使在找到第一个匹配项之后也会继续寻找匹配项。

  2. 在让计算机随机排列卡片时,您似乎没有检查 (a) 卡片是否已经翻转;或者 (b) 第二张牌与第一张牌不匹配。


典型的编码模式不是while循环,而是更多的事件驱动模式,由用户的移动(例如手势识别器或按钮)触发。你想要这个方法

  • 检查一些布尔类属性,该属性指示是否接受用户移动(事实证明,您已经拥有这样的属性),如果没有,则提供一些不允许用户输入的反馈,然后立即退出;

  • 假设类属性指示要接受用户输入,然后您将关闭该布尔类属性以确保在设备完成必要的动画和计算机移动之前不会接受进一步的用户输入;

  • 动画用户的移动;

  • 动画计算机的移动,如果计算机得到另一个移动,当前移动的最终动画块应该启动计算机的下一步移动;当你完成后,

  • 重新打开表示允许用户移动的布尔属性。

顺便说一句,我看到你sleep在那里有一个声明。而不是sleep,如果你想推迟一些动画,你应该这样做dispatch_after(或者如果它是 a UIView animateWithDuration,使用带有delay参数的再现)。sleep但是强烈建议不要在主线程上做 a 。

希望这会有所帮助。最重要的是,转向事件驱动、回合制模式,使用一些控制属性来指示是否应该接受进一步的用户输入,因为动画是异步发生的。

如果我误解了你的游戏在做什么(我假设是一些回合制纸牌游戏),你可能想要编辑你的问题,并包括一个非常简短的游戏规则叙述性描述以及用户体验应该是什么。

于 2013-07-10T02:23:40.320 回答