Algorithm 找到一个平衡这个游戏的算法
我试着提取问题中我遇到麻烦的部分,这是我正在做的更大项目的一部分(不是家庭作业)。我认为把它描述成一个游戏是最容易的(因为我需要它来完成我正在做的游戏)。按照我的描述,这是一个单人游戏 开始从两个位置中的一个开始:Algorithm 找到一个平衡这个游戏的算法,algorithm,Algorithm,我试着提取问题中我遇到麻烦的部分,这是我正在做的更大项目的一部分(不是家庭作业)。我认为把它描述成一个游戏是最容易的(因为我需要它来完成我正在做的游戏)。按照我的描述,这是一个单人游戏 开始从两个位置中的一个开始: 重量(2,0,-1)和一个红色播放 重量(3,1,-1)和两个红色 结束游戏在您没有更多游戏时结束。目标是以重量(0,0,0)结束游戏 有两种类型的播放红色和蓝色。给定一个剧本,你可以从四个作品中选择一个:a、B、C、D,它们会给你带来额外的重量和可能的额外剧本。规则如下: 在
- 重量
和一个(2,0,-1)
播放红色
- 重量
和两个(3,1,-1)
红色
(0,0,0)
结束游戏
有两种类型的播放红色
和蓝色
。给定一个剧本,你可以从四个作品中选择一个:a、B、C、D
,它们会给你带来额外的重量和可能的额外剧本。规则如下:
- 在
播放时:红色
- A添加权重
(0,-2,-1)
- B添加重量
并添加一个(1,-1,-1)
播放红色
- C加上重量
和两个(2,0,-1)
红色
- D增加重量
和两个(0,2,1)
播放蓝色
- A添加权重
blue
播放的规则类似,但权重的前两列是交换的,最后一列是反向的,播放的类型是反向的,因此您可以得到以下结果:
- 在
播放时:蓝色
- A增加重量
(-2,0,1)
- B添加重量
,并添加一个(-1,1,1)
播放蓝色
- C增加重量
和两个(0,2,1)
播放蓝色
- D增加重量
和两个(2,0,-1)
播放红色
- A增加重量
我正试图编写一个程序,通过选择游戏来赢得游戏,这样当你没有更多的游戏时,最终的平衡是
(0,0,0)
。只是我似乎做不到。所以现在我认为可能没有赢得这场比赛的算法。我很想知道为什么会这样。如果有人对我如何证明这一点有任何想法,请让我知道!!或者,如果你尝试并找到了获胜的方法,那么也请告诉我。谢谢 将红牌和蓝牌的数量视为你位置的两个额外维度。这大大降低了问题的复杂性
下面,最后两个维度代表剩余的红色和蓝色,再次说明了问题
开始从两个位置中的一个开始:
- 重量
(2,0,-1,1,0)
- 重量
(3,-1,-1,2,0)
(0,0,0,0,0)
给定一个剧本,你可以从八个作品中选择一个:Ar、Br、Cr、Dr、Ab、Bb、Cb、Db
,它们会给你额外的重量。规则如下:
- Ar添加权重
(0,-2,-1,-1,0)
- Br添加权重
(1,-1,-1,0,0)
- Cr增加重量
(2,0,-1,1,0)
- Dr添加重量
(0,2,1,-1,2)
- Ab增加重量
(-2,0,1,0,-1)
- Bb增加重量
(-1,1,0,0)
- Cb增加重量
(0,2,1,0,1)
- Db增加权重
(2,0,-1,2,-1)
现在,它可以作为一个8变量方程来求解。可能我遗漏了一些东西,但仅通过检查,这一系列步骤似乎应该有效:
- 以“重量<代码>(2,0,-1)和一个<代码>红色播放”开始
- 拿一个
play,一个red
,它“增加了重量C
和两个(2,0,-1)
plays”,剩下的是重量red
和两个(4,0,-2)
playsred
- 拿一个
play,一个red
,它“增加重量a
”,剩下重量(0,-2,-1)
和一个(4,-2,-3)
playred
- 拿一个
play,一个red
,它“增加了重量D
和两个(0,2,1)
plays”,剩下的是重量blue
和两个(4,0,-2)
playsblue
- 拿一个
play,一个blue
,它“增加重量a
”,剩下重量(-2,0,1)
和一个(2,0,-1)
playblue
- 拿一个
蓝色的
玩法,一个
,它“增加了重量a
”,只剩下重量(-2,0,1)
,没有玩法(0,0,0)
move weight plays
------ --------- -------
(2,0,-1) red
red C (4,0,-2) red x2
red A (4,-2,-3) red
red D (4,0,-2) blue x2
blue A (2,0,-1) blue
blue A (0,0,0) -
。没有
编辑以添加: 我是如何发现这一点的: 既然这个问题引起了很多兴趣,也许我应该解释一下我是如何找到上述解决方案的。这基本上是运气;我偶然发现了两个关键的观察结果:
和红色A
按重量相互抵消(前者添加红色D
,后者添加(0,-2,-1)
),总共添加两个(0,2,1)
播放(都来自蓝色
),没有红色D
播放;因此,如果您一个接一个地播放,您可以将两个红色
播放“转换”为两个红色
播放蓝色
取消了初始权重(它添加蓝色A
),并且不添加播放,因此整个问题可以通过将一个(2,0,-1)
播放“转换”为一个红色
播放来解决蓝色
red C
开始,以便将两个red
剧本“转换”为两个blue
剧本,我立即发现red C
也是blue A
重量的“反面”,因此也可以用blue A
来取消。在我的脑海里,这一切似乎抵消了perfectl
move weight plays
------ --------- -------
(3,1,-1) red x2
red A (3,-1,-2) red
red B (4,-2,-3) red
red D (4,0,-2) blue x2
blue A (2,0,-1) blue
blue A (0,0,0) -
Start 1: (2, 0, -1) Reds=1 Blues=0
Red B ==> (3, -1, -2) Reds=1 Blues=0
Red B ==> (4, -2, -3) Reds=1 Blues=0
Red D ==> (4, 0, -2) Reds=0 Blues=2
Blue A ==> (2, 0, -1) Reds=0 Blues=1
Blue A ==> (0, 0, 0) Reds=0 Blues=0
Start 2: (3, 1, -1) Reds=2 Blues=0
Red A ==> (3, -1, -2) Reds=1 Blues=0
Red B ==> (4, -2, -3) Reds=1 Blues=0
Red D ==> (4, 0, -2) Reds=0 Blues=2
Blue A ==> (2, 0, -1) Reds=0 Blues=1
Blue A ==> (0, 0, 0) Reds=0 Blues=0
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SO8683939
{
struct State
{
public int V1;
public int V2;
public int V3;
public int Reds;
public int Blues;
public int Tokens { get { return Reds + Blues; } }
public string Description;
public State(int v1, int v2, int v3, int reds, int blues)
{
V1 = v1;
V2 = v2;
V3 = v3;
Reds = reds;
Blues = blues;
Description = null;
}
public State Add(State other)
{
State sum;
sum.V1 = V1 + other.V1;
sum.V2 = V2 + other.V2;
sum.V3 = V3 + other.V3;
sum.Reds = Reds + other.Reds;
sum.Blues = Blues + other.Blues;
sum.Description = null;
return sum;
}
public override string ToString()
{
var detail = string.Format("({0}, {1}, {2}) Reds={3} Blues={4}", V1, V2, V3, Reds, Blues);
if (Description != null)
{
return Description + ": " + detail;
}
return detail;
}
}
class Program
{
static void Main(string[] args)
{
var start1 = new State(2, 0, -1, 1, 0) { Description = "Start 1" };
var start2 = new State(3, 1, -1, 2, 0) { Description = "Start 2" };
var end = new State(0, 0, 0, 0, 0);
var redA = new State(0, -2, -1, -1, 0) { Description = "Red A" };
var redB = new State(1, -1, -1, 0, 0) { Description = "Red B" }; ;
var redC = new State(2, 0, -1, 1, 0) { Description = "Red C" }; ;
var redD = new State(0, 2, 1, -1, 2) { Description = "Red D" }; ;
var redOptions = new[] { redA, redB, redC, redD };
var blueA = new State(-2, 0, 1, 0, -1) { Description = "Blue A" };
var blueB = new State(-1, 1, 1, 0, 0) { Description = "Blue B" };
var blueC = new State(0, 2, 1, 0, 1) { Description = "Blue C" };
var blueD = new State(2, 0, -1, 2, -1) { Description = "Blue D" };
var blueOptions = new[] { blueA, blueB, blueC, blueD };
var startingPosition = start1;
var maxSolutionLength = 5;
var rand = new Random();
var path = new List<State>();
while (true)
{
var current = startingPosition;
path.Clear();
//Console.WriteLine("Starting");
//Console.WriteLine(current);
while (true)
{
State selected;
if (current.Reds == 0)
{
selected = blueOptions[rand.Next(4)];
}
else if (current.Blues == 0)
{
selected = redOptions[rand.Next(4)];
}
else
{
if (rand.NextDouble() < 0.5)
{
selected = blueOptions[rand.Next(4)];
}
else
{
selected = redOptions[rand.Next(4)];
}
}
//Console.WriteLine(selected);
path.Add(selected);
current = current.Add(selected);
//Console.WriteLine(current);
if (current.Equals(end))
{
Console.WriteLine("Success!");
var retrace = startingPosition;
Console.WriteLine(retrace);
foreach (var selection in path)
{
retrace = retrace.Add(selection);
Console.WriteLine("{0} ==> {1}", selection.Description, retrace);
}
Console.ReadLine();
break;
}
else if (current.Tokens == 0)
{
// fail
//Console.WriteLine("Fail");
break;
}
else if (path.Count >= maxSolutionLength)
{
// fail
//Console.WriteLine("Fail");
break;
}
}
}
}
}
}