数字游戏程序

时间:2015-01-28 17:30:28

标签: c++ algorithm recursion logic

我尝试为this question编写C ++程序。我假设所有玩家都玩得很完美,而且该程序也可以完美地对抗它。我尝试使用递归(通过在每一步将问题减少为2个较小的问题)。 “最终状态”给出的值告诉您是赢(1)还是丢(0)。我的代码有什么问题,因为手动设计解决方案会产生不同的结果。

#include<iostream>
using namespace std;

bool win(int player,int no_of_players,int counter)
{
    if(no_of_players==1)
        return 1;
    if(counter>=10)
    {
        --no_of_players;
        counter=0;
    }
    if(player>no_of_players)
        player=0;
    if(win(player+1,no_of_players,counter+1)==0)
    {
        cout<<"\nMove 1";
        return 1;
    }
    if(win(player+1,no_of_players,counter+2)==0)
    {
        cout<<"\nMove 2";
        return 1;
    }
    cout<<"\nLosing position";
    return 0;
}

int main()
{
    int a=win(0,2,1);
    cout<<"\nFinal state :"<<a;
    return 0;
}

2 个答案:

答案 0 :(得分:2)

正如杰弗里指出的那样,这场比赛无法解决更多的两名球员。所以我理解现在的问题是为什么你的程序对两个玩家都不起作用。

你的双人游戏逻辑中最大的问题是你误解了counter的价值。 counter在您的代码中有效地意味着玩家现在需要写的价值(也可以选择在此之后编写counter + 1)。所以你恰当地假设如果counter >= 10,那么一个玩家输了,尽管你处理它的方式可能不正确。我所做的,因为我们在这里讨论的是双人游戏,如果return 0大于或等于counter,则会立即10

现在主要问题 - 你调用递归函数的方式。你第一次打电话是正确的

if(win(player+1,no_of_players,counter+1)==0)

你把它传递给另一个玩家(顺便说一下,你没有以任何方式使用player变量,所以我只是将它从代码中删除),在板上写counter ,此时我们知道counter不是10,因此编写它是安全的。

然而,你的第二次电话是错误的。

if(win(player+1,no_of_players,counter+2)==0)

在棋盘上写下countercounter + 1之后,你有效地将转弯传给了下一位玩家。但是等一下,如果counter + 110怎么办?你需要这样称呼它:

if(counter + 1 < 10 && win(player+1,no_of_players,counter+2)==0)

换句话说,如果第二个转弯会导致打印10,甚至不考虑转两圈。

最后,您认为最后一个问题是,如果您将其称为win(1, 2, 1)win(2, 2, 1),您的程序将返回不同的值。您没有使用变量player,因此它不能返回不同的值。您的win函数无法说明序号为player的玩家是否获胜,它说的是当前玩家是否获胜。因此,为了测试它实际上是否有效,更改初始值counter,模拟第一个玩家的不同转弯更有意义,以查看返回值如何变化。例如,第一个玩家输了,所以win(1, 2, 1)0,无论第一个玩家做出什么回合,第二个玩家都会赢,所以win(2, 2, 2)win(2, 2, 3)是{ {1}}。

这是它的外观。我对您的代码进行了两处更改:如果1return 0,则立即将其设为counter,并按上述方式更改第二次递归调用的方式。我没有删除10player变量,但它们实际上不再用于代码中了:

no_of_players

答案 1 :(得分:1)

你的方法存在很多问题。

主要的一点是,由于这不是一个简单的双人最小最大值,你不能简单地递归地返回一个分数。对于给定玩家的每次游戏,您必须返回每个玩家将获得的分数。类似的东西:

void得分(int currentPlayer,int toWrite,int outScores [],int nbOut)

如果 currentPlayer 要从写入,用写一个或两个数字,将返回 outScores 中所有玩家的得分> nbOut 玩家已经出局。

尽管如此,这还不是最佳选择。递归尝试10个玩家的所有解决方案意味着下降超过50个级别,分支因子为2.您需要一些动态编程才能提高效率。

我做了编码。它适用于4名玩家,最大值为10.对于更多玩家来说,它变得非常慢。正如我所说,动态编程就是你所寻找的,在这里。

另外,我认为如果玩家仍然会以同样的顺序输掉比赛,那么玩家更愿意只玩一次。

#include <memory.h>
#include <vector>
#include <iostream>
using namespace std;

const int NB_PLAYERS = 3;
const int MAX_VALUE = 10;

vector<pair<int, int>> scores(int currentPlayer, int toWrite, int outScores[], int nbOut)
{
    if (outScores[currentPlayer] == -1) // we're already out, lets just have the next player play
    {
        return scores((currentPlayer + 1) % NB_PLAYERS, toWrite, outScores, nbOut);
    }

    if (toWrite == MAX_VALUE) // one player is out
    {
        vector<pair<int, int>> ret;
        if (nbOut + 2 != NB_PLAYERS)
        {
            outScores[currentPlayer] = -1; // so the game can continue without us
            ret = scores((currentPlayer + 1) % NB_PLAYERS, 1, outScores, nbOut + 1);
        }
        else
        {
            for(int i=0; i < NB_PLAYERS; i++)
            {
                if (outScores[i] == 0)
                {
                    outScores[i] = NB_PLAYERS; // set the winner
                }
            }
        }
        outScores[currentPlayer] = nbOut + 1;
        ret.push_back(pair<int, int>(1,currentPlayer));
        return ret;
    }

    if (toWrite + 1 == MAX_VALUE) // no point playing to lose, if we can avoid it
    {
        vector<pair<int, int>> ret;
        ret = scores((currentPlayer + 1) % NB_PLAYERS, toWrite + 1, outScores, nbOut);
        ret.push_back(pair<int,int>(1,currentPlayer));
        return ret;
    }

    int scoresIfPlay1[NB_PLAYERS];
    int scoresIfPlay2[NB_PLAYERS];
    vector<pair<int,int>> ret1;
    vector<pair<int,int>> ret2;

    memcpy(scoresIfPlay1, outScores, sizeof(int) * NB_PLAYERS);
    memcpy(scoresIfPlay2, outScores, sizeof(int) * NB_PLAYERS);

    ret1 = scores((currentPlayer + 1) % NB_PLAYERS, toWrite + 1, scoresIfPlay1, nbOut); //recurse with both choices
    ret2 = scores((currentPlayer + 1) % NB_PLAYERS, toWrite + 2, scoresIfPlay2, nbOut);

    if (scoresIfPlay2[currentPlayer] > scoresIfPlay1[currentPlayer]) // pick the solution that yields the higher score
    {
        memcpy(outScores, scoresIfPlay2, sizeof(int) * NB_PLAYERS);
        ret2.push_back(pair<int,int>(2,currentPlayer));
        return ret2;
    }
    else
    {
        memcpy(outScores, scoresIfPlay1, sizeof(int) * NB_PLAYERS);
        ret1.push_back(pair<int,int>(1,currentPlayer));
        return ret1;
    }
}

int main()
{
    int outScores[NB_PLAYERS] = {0};

    vector<pair<int, int>> plays = scores(0, 1, outScores, 0);

    for(int i = 0; i < NB_PLAYERS; i++)
    {
        cout << "Player " << i << " has score " << outScores[i] << endl;
    }
    cout << endl;

    cout << "Plays were: " << endl;
    for(int i = plays.size() - 1; i >= 0; --i)
    {
        cout << "player " << plays[i].second << " plays " << plays[i].first << " times." << endl;
    }

}

===旧答案===

如上所述,问题不允许您判断您是赢还是输。为了做到这一点,你必须以这样或那样的方式改变规则:由于将有9个输家和1个赢家,任何未获胜的球员都可以改变他们的比赛方式,而他们仍然输球,影响谁获胜。例如。球员x失去任何一种方式,但可以使球员y赢或输。 x的播放方式未定义。

您需要选择一个场景:

  • 每个玩家都会尽可能快地消灭其他玩家,只要它不会让他们输掉。
  • 或者,之后被淘汰会产生更多积分。玩家将最大化他们的分数。

无论如何,解决方案应该比上面更复杂。你可能想要递归

int scoreFromPosition(int player,int no_of_players,int counter)

no_of_player 玩家离开时,

将返回最高得分玩家玩家,其中计数器当前为计数器

相关问题