我尝试为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;
}
答案 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)
在棋盘上写下counter
和counter + 1
之后,你有效地将转弯传给了下一位玩家。但是等一下,如果counter + 1
是10
怎么办?你需要这样称呼它:
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}}。
这是它的外观。我对您的代码进行了两处更改:如果1
为return 0
,则立即将其设为counter
,并按上述方式更改第二次递归调用的方式。我没有删除10
和player
变量,但它们实际上不再用于代码中了:
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 玩家离开时,将返回最高得分玩家玩家,其中计数器当前为计数器。