Я почти уверен, что это сработает, отсутствие тестовых данных или компилятора делает меня не на 100% уверенным:
private void BestItems()
{
_bestHead = GetBestItem(_heads);
_bestChest = GetBestItem(_chests);
_bestLeg = GetBestItem(_legs);
_bestFeet = GetBestItem(_feets);
}
private Stats GetBestItem(List<Stats> items)
{
double best = 0.0;
Stats result = null;
foreach stats item in items
{
double total = item.stamina * _scaleSta + item.power * _scalePower + item.armor * _scaleArmor;
if (total > best)
{
result = item;
}
}
return result;
}
Edit:
Шаги:
- Создайте список для каждого слота в порядке наиболее важного показателя (наименьшего первого)
- Используйте циклическое взвешивание, чтобы найти наименьшие значения попадания, которые соответствуют вашему рейтингу попаданий. (тебе понадобится это на каждый слот для моего следующего шага)
- Для каждого слота выберите предмет с лучшей статистикой, которая соответствует минимальному рейтингу попаданий в слоты.
вам понадобится много циклов один за другим, но это лучше, чем 2 ^ 28, я думаю: p
Edit2: Опять же, здесь все еще нет компилятора ... но это может сработать. Вы получите кучу потоков, хотя ...
Сведения о присоединении и ожидании потока см. Здесь (msdn) (посмотрите на мьютекс, монитор, ManualResetEvent, AutoResetEvent)
private void BruteForce()
{
var threads = new List<Thread>;
foreach (Stats head in _heads)
foreach (Stats chest in _chests)
foreach (Stats leg in _legs)
foreach (Stats feet in _feets)
{
if (threads.Count <= 2)
thread worker = new thread(addressof Process, new object() {head, chest, leg, feet, ...});
worker.start();
threads.add(worker);
}
foreach (Thread t in threads)
t.join(); //this might not be the best as it might make the main thread wait for each thread one after the other, not when all finished. A manual/auto reset is probably better here.
}
private void Process(params...)
{
int stamina = head.sta + chest.sta + leg.sta + feet.sta;
int power = head.power + chest.power + leg.power + feet.power;
int armor = head.armor + chest.armor + leg.armor + feet.armor;
int hit = head.hit + chest.hit + leg.hit + feet.hit;
double total = stamina * _scaleSta + power * _scalePower + armor * _scaleArmor;
lock _bestscore
{
if (total > _bestScore && hit >= 100)
{
_bestScore = total;
// Store best setup for output when done with bruteforce
_bestHead = head;
_bestChest = chest;
_bestLeg = leg;
_bestFeet = feet;
}
}
}
РЕДАКТИРОВАТЬ 4: Угадайте, у кого еще нет компилятора рядом с ним?
Что-то вроде этого должно гарантировать, что в любой момент у вас есть только 2 потока.
var threads = new Dictionary<Guid, Thread>;
private void BruteForce()
{
foreach (Stats head in _heads)
foreach (Stats chest in _chests)
foreach (Stats leg in _legs)
foreach (Stats feet in _feets)
{
while (threads.Count >= 2) {} //im sure thread.join or equivelent can do this instead of a nasty loop :p
var guid = Guid.NewGuid();
thread worker = new thread(addressof Process, new object() {guid, head, chest, leg, feet, ...});
worker.start();
threads.add(guid, worker);
}
foreach (Thread t in threads)
t.join(); //this might not be the best as it might make the main thread wait for each thread one after the other, not when all finished. A manual/auto reset is probably better here.
}
private void Process(params...)
{
int stamina = head.sta + chest.sta + leg.sta + feet.sta;
int power = head.power + chest.power + leg.power + feet.power;
int armor = head.armor + chest.armor + leg.armor + feet.armor;
int hit = head.hit + chest.hit + leg.hit + feet.hit;
double total = stamina * _scaleSta + power * _scalePower + armor * _scaleArmor;
lock _bestscore
{
if (total > _bestScore && hit >= 100)
{
_bestScore = total;
// Store best setup for output when done with bruteforce
_bestHead = head;
_bestChest = chest;
_bestLeg = leg;
_bestFeet = feet;
}
}
_threads.remove(guid)
}