在 C++ 中使用递归将倒计时减法倒计时为零的游戏模式

Subtraction count down to zero game pattern with recursion in c++

本文关键字:倒计时 模式 游戏 递归 C++      更新时间:2023-10-16

使用递归,我必须为一个游戏制作一个AI,其中计算机将从4,3或1中进行选择,并从1到99(包括1到99(之间的给定数字中减去它。这个游戏将在人工智能和人类之间进行。但是,AI 无法从 4、3 或 1 中选择任何随机数。它必须始终选择有助于它赢得游戏的值。此外,当数字像 2 时,人工智能或人类不能选择 4 或 3,因为它大于 2,所以他们必须选择 1。还假设 AI 是玩家 2,而人类始终是玩家 1。

例如:如果起始号码是n = 7,那么玩家1选择1,n = 6,那么计算机选择4和新的n = 2。玩家 1 将选择 1 和 n = 1。然后 AI 将选择 1 和 n = 0。因此,人工智能赢得了比赛。

到目前为止,我对这个问题的看法:

我知道不同的数字,直到 6 应该由 AI 选择(从 4、3 或 1(来赢得比赛。

例如:当 n = 1 时,选择 1 n = 2,选择 1 ; n = 3,选择 3 ; n =4,选择 4 ; n = 5,选择 3 ; n = 6,选择4

;

但是我找不到一种通用算法,可以应用于从 1 到 99 的所有数字以赢得比赛。 我想知道并理解如何获得一个通用的递归方程和递归算法,就像斐波那契级数中的函数递归一样:

斐波那契(n - 1( + 斐波那契(n - 2(

通过AI在4 3或1之间选择数字以赢得比赛。

我没有递归经验,所以请尝试详细解释算法。

我假设不能采取行动的玩家输掉了比赛。 你似乎没有在任何地方提到它,但这就是它的样子。


首先,请注意,每个数字要么是获胜位置,要么是失败位置,供玩家回合,无论它是哪个玩家。 例如,数字 7 是一个失败的位置:如果当前玩家选择 1,另一个玩家以 4 响应;如果是 3 或 4,则分别为 4 或 3。

递归关系如下所示:

win(x) = not win(x-1) or not win(x-3) or not win(x-4)

事实上,如果有一个动作导致亏损,我们可以通过选择这个动作来获胜。如果没有,我们的对手将获胜,假设他们从那时起就打得很完美。

现在,不是实现递归,而是使用它从下到上计算每个数字的输赢状态,并将其存储在数组中,如下所示:

win[0] := false
win[1] := true
win[2] := false
win[3] := true
for x := 4, 5, ..., 99:
win[x] := not win[x-1] or not win[x-3] or not win[x-4]

这样,您只需进行 100 次简单的计算,而不是遍历从数字 99 开始的所有可能游戏的巨大递归树。

现在,计算了这个win数组,如何从数字x移动? 如果win[x] = false,任何一步都可以:如果我们的对手打得完美,我们无论如何都会输。 如果win[x] = true,找出win[x-1]win[x-3]win[x-4]中存在(小心下溢!(并且是假的,然后进行该移动。


最后,观察计算数组如下所示:

[0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1]

显然,有一个周期 7. 因此,对于这个确切的游戏,只需查看我们的数模 7 的其余部分,就可以完全不使用数组来制定自定义策略。 事实上,你在问题中几乎做到了,只是在前面加上"余模 7 是......"并添加一些关于零的内容:

例如:当 n = 1 时,选择 1 n = 2,选择 1 ; n = 3,选择 3 ; n =4,选择 4 ; n = 5,选择

3 ; n = 6,选择 4 ;

这是我针对您的问题的代码,它可能会对您有所帮助

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
int main(){
//init nimbers
int arr[100];
fill(arr,arr+100,-1);
arr[0]=0;
queue<int> q;
q.push(0);
while(q.size()>0){
int u=q.front();
q.pop();
if (u+1<100 && arr[u+1]!=1)
{
arr[u+1]=(arr[u]+1)%2;
q.push(u+1);
}
if (u+3<100 && arr[u+3]!=1)
{
arr[u+3]=(arr[u]+1)%2;
q.push(u+3);
}
if (u+4<100 && arr[u+4]!=1)
{
arr[u+4]=(arr[u]+1)%2;
q.push(u+4);
}
}
int n=7;
cout<<"Welcome to the Gamen";
cout<<"You are player 1n AI is player 2n";
int play=0;
while(n>0){
if (play%2==0)
{
int step=-1;
cout<<"Enter your move?";
cin>>step;
n-=step;
cout<<"Now n="<<n<<endl;
}
else{
int step=1;
if(n-1>=0 && arr[n-1]==0) step=1;
if(n-3>=0 && arr[n-3]==0) step=3;
if(n-4>=0 && arr[n-4]==0) step=4;
n-=step;
cout<<"AI played "<<step<<" moven";
cout<<"Now n="<<n<<endl;
}
play=(play+1)%2;
}
if (play)
{
cout<<"You won";
}
else cout<<"AI won";
return 0;
}