如何为有趣的游戏开发递归函数。递归挑战

时间:2015-01-19 18:51:51

标签: c++ function recursion cocos2d-x tail-recursion

我正在开发一款儿童游戏。

它包含在

  • 3个标签
  • 6麻袋

enter image description here

每个袋子里面都有一个秘密水果:香蕉或西红柿 第一步是揭示一个麻袋,例如想象我们揭示麻袋2它是一个T(番茄)

enter image description here

现在的规则是你必须按照规则来分配标签给Sacks,规则是没有任何东西超过正确的标签

所以我们开始为麻袋分配标签。

enter image description here

enter image description here

最后:

enter image description here

我不知道如何开发一个递归函数来检查每个运动的有效性。我已经尝试了很多功能,但它变得不可能。 我认为最好的选择是创建

  • 递归功能
  • 检查是否有任何其他标签可能是所揭示的麻袋的可能解决方案。如果它发现另一个适合麻袋的标签(当然可能有未来的解决方案)是Game Over。

这个函数的伪代码是什么?或者您可以想象另一种开发此代码的方法? 我真的被困了,我在这里问,因为你很棒

不要忘记游戏正在寻找任何其他可能让游戏返回的动作,他希望你失败!

3 个答案:

答案 0 :(得分:1)

这里我有一个没有递归的可能解决方案。我知道您请求了伪代码,但我在JAVA中做了这件事只是为了确保它正常工作。至少它会给你另一个方向去看。

假设您有一个代表所有可能组合的数组,例如:

  • " 00" =>苹果苹果
  • " 01" =>苹果香蕉
  • " 10" =>香蕉苹果
  • " 11" =>香蕉的香蕉

因此,让我们进行验证,以确定MOVEMENT是否有效。

 public class TestCode {

    public static String[] stuff = new String[] { "00", "01", "10", "11" };
    public static Boolean isMySearchValid = false;

    public static void main(String[] args) {

        String first = "01"; // my first guess was "01" which is Apple-Banana

        isMySearchValid = isValid(first, "11"); // find out if 10 is valid and
                                                // also has not been taken
                                                // already
        System.out.println(isMySearchValid);
    }

    public static Boolean isValid(final String firstGuess, final String newGuess) {
        Boolean response = false;

        if (firstGuess == newGuess) {
            response = false; // Game Over, because the newGuess was already
                                // taken
            //System.out.println(response + " 1");
        } else {
            for (int i = 0; i < stuff.length; i++) {
                if (!stuff[i].contains(firstGuess)) {
                    if (stuff[i].contains(newGuess)) {
                        response = true;
                        System.out.println("VALID: because was found available in emelement : " + i);
                        break;
                    }

                }
            }
        }

        return response;
    }

}

第二种方法:(伪代码)

#define VALID_MOVE = 1;
#define TAG_ALREADY_EXIST = 2;
#define NOT_FOUND_OR_NOT_VALID = 3;


int isTagValid(sring[] ArrayOfTags, string tagToFind) {
    string[] tempArray = NULL;
    int response;

    if(tempArray != NULL) {
        foreach(string str in tempArray) {
            if (str == tagToFind)  {                
                response = TAG_ALREADY_EXIST;
            }
        }
    } else {
        foreach(string str in ArrayOfTags) {
            if (str == tagToFind) {
                tempArray.add(tagToFind);
                response = VALID_MOVE;
            } else {
                response = NOT_FOUND_OR_NOT_VALID;
            }
        }       

    }
    return response;
}

答案 1 :(得分:0)

我会假设你有一套固定的小水果,每一个都有一个相关的id。实现这一点的最简单方法是枚举:

enum Fruit {
    APPLE,
    PEAR,
    BANANA
};

这样,APPLE的值为0,PEAR为1,BANANA为2.现在,您可以通过数组表示任何麻袋对或卡片,告知其中有多少次出现是每个水果(每个元素将告诉与该指数对应的水果的出现次数)。例如,带有两个苹果的卡片将是{2, 0, 0},而带有苹果和香蕉的麻袋将是{1, 0, 1}。对于每个麻袋对,您还可以跟踪&#34;可见&#34;水果:如果前面提到的麻袋没有打开,我们有{0, 0, 0},当我们只露出苹果时,我们会{1, 0, 0}

现在,您需要做的就是弄清楚给定的卡是否与我们对给定的麻袋对的了解是相容的,就是检查每对元素,看看麻袋对的所有元素是否都是小于或等于卡片阵列的相应元素。不需要递归:

bool isCompatible(const vector<int> & card, const vector<int> & sack) {
    for (int i = 0; i < card.size(); i++) {
         if (card[i] < sack[i])
              return false;
    }
    return true;
}

bool isLegalMove(const vector<int> & movedCard, const vector<vector<int> > & otherCards, const vector<int> & sack) {
    if (!isCompatible(movedCard, sack))
        return false;
    for (int i = 0; i < otherCards.size(); i++) {
        if (isCompatible(otherCards[i], sack))
            return false;
    }
    return true;
}

编辑:我仍然不太了解游戏的机制,但这是模拟可能的游戏动作的一般方法,直到游戏结束。该代码假定任何移动都将使游戏进度接近结束,即它不可能绕圈转动(如果是,你需要额外的代码来跟踪哪个游戏陈述你已经尝试过了。)

我假设您的所有游戏状态都包含在名为GameState的类中,并且移动可以由Move表示。在您的情况下,您可能有两个Move子类,即OpenSack(包含麻袋索引)和MoveCard(包含要移动的卡的原始和最终位置)。你需要一个能够产生在给定游戏状态下可能移动的函数vector<Move *> generateMoves(GameState &)(注意,如果游戏状态是&#34;游戏超过&#34;,这个函数应该返回一个空向量)。 Move需要一个抽象函数GameState perform(const GameState &),由每个子类实现,它将实际执行移动并创建一个代表游戏状态的新GameState(而不是修改现有状态)搬家后。 (在具有较大状态的游戏中,最好实际修改状态,并使用reverse()方法来撤消移动的影响。)然后,模拟可以像这样实现: / p>

bool isSolvable(const GameState & currentState) {
    if (currentState.isValidFinalState())
        return true;
    vector<Move *> moves = generateMoves(currentState);
    for (int i = 0; i < moves.size(); i++) {
         GameState stateAfterMove = moves[i]->perform(currentState);
         if (isSolvable(stateAfterMove))
             return true;
    }
    return false;
}

这将展示所有可能的动作(这是可行的,因为它是这样的&#34;小&#34;游戏),如果任何一系列动作导致有效的解决方案,该功能将返回true

答案 2 :(得分:0)

请注意,如果你提出另一张牌作为游戏的情况,下一个动作应该能够成功解决游戏问题。仅仅检查1个动作的有效性是不够的,你需要检查直到游戏结束。

enter image description here

你将第3张牌(Banana |番茄)分配到3-4袋中,因为唯一一张满足2条规则的原因(水果在麻袋/卡片和卡片中的含量相同而不是麻袋).L

稍后,我们又做了一步。我们将第一张卡片(番茄|番茄)移到第3张袋子,因为我们必须满足“正确的卡片永远不会超过麻袋”的规则。如果算法只是一步检查,它会说正确的是另一种可能性=&gt;卡片2(Banana | Banana),所以它会告诉我们游戏结束。但算法不知道的是游戏变得无法解决因为我们上面有一张卡片待解决的唯一麻袋(番茄|番茄)

enter image description here