Работая над игрой на работе, и в какой-то момент игры игрок попадает в бонусную игру. Количество, которое им нужно, чтобы выиграть, предопределено, однако мы бы хотели придумать алгоритм, который использует сложение, умножение и деление, чтобы получить это количество за x шагов. Количество шагов также будет известно заранее, поэтому алгоритм просто должен будет выяснить, как использовать это количество шагов для достижения числа.
Вы можете использовать только вычисления от +1 до +15, x2, x4, / 2, / 4.
Вы можете превысить целевое число во время шагов, но должны в конечном итоге достичь целевого числа на последнем шаге. Количество шагов обычно составляет от 15 до 30, и вы всегда начинаете с 0.
Например:
Сумма: 100, Шаги: 10 ==
+10, +2, x2, +4, x4, +10, / 2, +15, +15, + 9
Сумма: 40, Шаги: 12 ==
+15, +1, +5, +2, +1, / 2, * 4, +6, +6, / 4, +5, * 2
Мне любопытно, может ли что-то подобное существовать? Я уверен, что мы можем что-то придумать, но я не хотел заново изобретать колесо, если есть общий алгоритм, который справится с этой задачей.
Обновление: внесены некоторые незначительные изменения в код @ FryGuy, чтобы сделать маршрут, по которому нужно достичь целевого числа, несколько случайным. Его решение работало отлично, как есть, но, увидев его работоспособным и приняв во внимание комментарии @Argote и @Moron, я понял, что нужно иметь некоторый уровень рандомизации, чтобы сделать его привлекательным для наших игроков. Добавил +1 к 10 шагам, чтобы достичь целевого числа 10, отлично работает, но «скучно» с точки зрения того, как мы будем его использовать. Большое спасибо всем, кто прокомментировал и ответил.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CR
{
class Program
{
static void Main(string[] args)
{
while (true)
{
int targetNumber = 20;
int steps = 13;
int[] route = null;
Boolean routeAcceptable = false;
// Continue choosing routes until we find one that is acceptable (doesn't average above or target win, but does exceed it at least once)
while(!routeAcceptable)
{
routeAcceptable = CalculateRoute(targetNumber, steps, out route) && route.Average() < targetNumber && route.Max() > targetNumber;
}
foreach (int i in route.Reverse())
{
Console.WriteLine(i);
}
Console.WriteLine("-----------------------");
Console.ReadLine();
}
}
static Boolean CalculateRoute(int targetNumber, int numSteps, out int[] route)
{
int maxValue = targetNumber * 16;
bool[,] reachable = new bool[numSteps + 1, maxValue];
// build up the map
reachable[0, 0] = true;
for (int step = 0; step < numSteps; step++)
{
for (int n = 0; n < maxValue; n++)
{
if (reachable[step, n])
{
foreach (int nextNum in ReachableNumbersFrom(n))
{
if (nextNum < maxValue && nextNum > 0)
{
reachable[step + 1, nextNum] = true;
}
}
}
}
}
// figure out how we got there
int[] routeTaken = new int[numSteps + 1];
int current = targetNumber;
for (int step = numSteps; step >= 0; step--)
{
routeTaken[step] = current;
bool good = false;
// Randomize the reachable numbers enumeration to make the route 'interesting'
foreach (int prev in RandomizedIEnumerbale(ReachableNumbersFromReverse(current)))
{
if (prev < targetNumber * 8)
{
if (reachable[step, prev])
{
current = prev;
good = true;
// Avoid hitting the same number twice, again to make the route 'interesting'
for (int c = numSteps; c >= 0; c--)
{
reachable[c, prev] = false;
}
break;
}
}
}
if (!good)
{
route = routeTaken;
return false;
}
}
route = routeTaken;
return true;
}
static IEnumerable<int> ReachableNumbersFrom(int n)
{
// additions
for (int i = 1; i <= 15; i++)
{
yield return n + i;
}
// mults/divides
yield return n / 2;
yield return n / 4;
yield return n * 2;
yield return n * 4;
}
static IEnumerable<int> ReachableNumbersFromReverse(int n)
{
// additions
for (int i = 1; i <= 15; i++)
{
if (n - i >= 0)
yield return n - i;
}
// mults/divides
if (n % 2 == 0)
yield return n / 2;
if (n % 4 == 0)
yield return n / 4;
yield return n * 2;
yield return n * 4;
}
static IEnumerable<int> RandomizedIEnumerbale(IEnumerable<int> enumerbale)
{
Random random = new Random(System.DateTime.Now.Millisecond);
return (
from r in
(
from num in enumerbale
select new { Num = num, Order = random.Next() }
)
orderby r.Order
select r.Num
);
}
}
}