Як поділити шестигранну сітку рівномірно серед російських гравців?


15

Я роблю просту гру на основі шестигранної сітки, і хочу, щоб карта була рівномірно розподілена між гравцями. Карта створена випадковим чином, і я хочу, щоб гравці мали приблизно рівну кількість комірок, із відносно невеликими площами. Наприклад, якщо на карті є чотири гравці та 80 комірок, кожен із гравців матиме близько 20 комірок (це не повинно бути точним). Також у кожного гравця повинно бути не більше чотирьох сусідніх комірок. Тобто, коли генерується карта, найбільші "шматки" не можуть містити більше чотирьох комірок.

Я знаю, що це не завжди можливо для двох-трьох гравців (оскільки це нагадує проблему "розфарбування карти"), і я в порядку з тим, щоб робити для них інші рішення (наприклад, створювати карти, які замість цього вирішують проблему). Але, для чотирьох-восьми гравців, як я міг підійти до цієї проблеми?


Стільниковий автомат - це простий спосіб, подібний до цього: Проста карта, чотири біоми, і як їх розподілити
MichaelHouse

Відповіді:


3

Це я би робив:

  1. Призначте всі комірки випадковим гравцям. На великих картах це, мабуть, може створити досить рівну кількість плиток для всіх гравців, на менших картах вам, мабуть, доведеться зробити деякі виправлення.
  2. Розбийте шматки, які занадто великі. Найпростіше зробити це взяти всі плитки шматками і знову призначити кожну плитку випадковим чином.
  3. У разі незбалансованої кількості комірок (наприклад, у гравця A 24 комірки, у гравця B - 16), переділіть пару комірок із представлених програвачів на недостатньо представлених гравців.
  4. Перевірте ще раз шматки. Якщо на кроці 3 були введені нові шматки, поверніться до кроку 2. Якщо ні, приємна карта!

PS Я не думаю, що ця проблема ніколи не є неможливою, проблема фарбування карти зовсім інша (для одного справа - навпаки, форми-> кольори замість кольорів-> призначення плитки).
Junuxx

Цей підхід мені подобається зовсім небагато, але чи не існує можливості його тривалий час, намагаючись збалансувати розміри площі?
manabreak

1
@manabreak: Я щось спробував. З невеликою зміною на крок 2 (перепризначення на велосипеді через усіх гравців, а не перерозподіл випадково) це працює досить добре. Я спробую написати це, коли матиму час.
Junuxx

1
Це виглядає саме те, що я шукав. :)
manabreak

1

Якщо припустити, що у вас загальна шестигранна клітка nта pгравці, де p <= n, найкращий спосіб вирішити це - це розподіл круглої робіни через стільникові автомати (CA).

Ініціалізація

Випадково (та / або використовуючи ту чи іншу евристику, наприклад відстань від центру карти), виберіть початкову клітинку для кожного гравця. Оскільки p <= nце не повинно бути проблемою.

Стільникові автомати

Вам потрібна повна зв’язок між вашими шестигранними клітинками. Я б запропонував 6-сусідський масив на комірку:

class Cell
{
   //... other members...
   Cell[6] neighbours = new Cell[6];
}

Використання масивів фіксованого розміру дозволяє існувати поняття топографічних напрямків між клітинками, чого не було б у списку чи векторі. Я рекомендую це, оскільки це може полегшити певні можливості навігації.

Ви також можете зберігати свою шістнадцяткову карту у двовимірному масиві із зрушеннями на рядок. Однак це може бути трохи менш інтуїтивно зрозумілим, ніж зберігати сусідський масив на комірку, лише через геометричне зміщення в кожному другому рядку.

Переконайтесь, що кожна клітина підключена до всього, що є сусідом. Ви можете робити цей рядок за рядком, клітинку за коміркою, коли ви генеруєте повну шестнадцятку. PS Якщо ви в кінцевому підсумку хочете непрямокутно обмежену шістнадцятку, ви можете просто видалити окремі комірки та посилання на ці клітини, щоб утворити негативні пробіли, що дозволяє створити контур органічної карти.

Круглоличний розподіл

Псевдокод:

count number of neutral cells in entire map, minus those starting cells taken by players
while neutral cells remain (or while true)
   for each player
      if player has not yet reached expected territory size in cells
         for each cell already constituting this player's territory
           if territory can grow by one cell into a neutral neighbour
              grow into neighbour
              reduce neutral cell count for entire map by one
              if no more neutral cells remain in map
                 break out of outermost while loop immediately
              else
                 continue to next player immediately
begin game

Цей алгоритм дасть можливість кожному гравцеві вирощувати свою територію за допомогою одного кругообігу, за умови, що територія гравця ще має дійсне місце для зростання. Якщо деякі гравці блоковані рости далі, алгоритм, незважаючи на це продовжує зростати території гравців , які дійсно все ще мають дійсне зростаюче простір. Ви можете легко обмежити кожного гравця однаковою кількістю комірок, як тільки одна з них досягає межі, але це повинно бути досить простим, щоб ви зрозуміли, якщо бажаєте.

Це забезпечить "домашні території" максимального розміру для кожного гравця. Якщо ви хочете додатково мати "острівні" території, щоб виконати квоту на кількість комірок для цього гравця, то, як тільки у гравця не вистачає місцевого простору для зростання, ви можете вибрати нову стартову клітинку зі списку нейтральних комірок і продовжуйте той самий процес "зростання", звідти. Таким чином, у вас вийде красивий розмір, узгоджені набори островів для кожного гравця, а не випадковий шум.


Хоча ви надаєте чудову документацію та псевдокод для свого алгоритму, я не впевнений, що це відповідає тому, про що питає запитувач. Питання зазначає, що "найбільші" шматки "не можуть містити більше чотирьох комірок", тоді як ваш алгоритм створює максимально велику зв'язану групу.
fnord

@fnord Ні, це не так. Ви неправильно не прочитали моєї відповіді. Я чітко ставив обмеження в псевдокоді: "якщо гравець ще не досяг очікуваного розміру території в клітинках". Вилучіть свій голос. Не соромтеся перевірити історію редагування цього питання, щоб переконатися, що це було так, перш ніж ваш коментар та голосування.
Інженер

Питання вимагає мати "не більше чотирьох сусідніх комірок", але кожен користувач повинен мати очікувану частину карти. Це, на мій погляд, означає, що електронна гра буде щось подібне до того, як ігри на ризик випадковим чином розподіляють карту для всіх гравців. Ваша відповідь розділяє карту на "домашні території" максимального розміру ". Щоправда, ваш алгоритм припиняється, коли досягається очікувана межа розміру території, але я не бачу способу, щоб той гравець отримав нові "острови", хоча ви це згадуєте в подальшому тексті.
fnord

@fnord Ваша логіка винна. У своєму останньому реченні ви визнаєте, що мій алгоритм зупиняється на розмірі острова n, і згодом суперечите собі, кажучи, що ви "не бачите способу", але це я так "згадую [як отримати острови] в подальшому тексті". Я відповів на це питання чи не відповів? Цей узагальнений алгоритм може використовуватися або для розсіювання осередків (обмеженням nдо 1), або для створення островів (шляхом встановлення n> 1). Таким чином, ви маєте в одному єдиному алгоритмі не тільки можливість розсіяння, але і групування. Як це не відповідає на питання ОП? Як це вартує грому?
Інженер

Я б редагував свій коментар вище, але це вже пізно. "Я не бачу шляху у вашому алгоритмі ". хоча ви згадуєте цю концепцію в подальшому тексті.
fnord

0

Іншим підходом було б розпочати з «справедливого», але регулярного розповсюдження, а потім використовувати додаток, подібний до симуляційного відпалу, щоб порушити регулярність, не втрачаючи справедливості:

  • Почніть з призначення кольорів всім клітинкам вашої сітки за звичайним малюнком (наприклад, у першому рядку є повторюваний шаблон '123412341234', а в наступному '341234123412' тощо). Це може привести до нерівномірного розподілу кольорів , якщо вашій карта особливо погано образні, але я припускаю , що ви починаєте з фіксованою картою, так що ви повинні бути в змозі знайти деяку равнораспределено правильне розфарбування цього.
  • Потім повторіть наступне протягом стільки кроків, скільки вам здається (немає справжнього критерію "готовості", тому експерименти підкажуть, що таке мінімально розумна кількість кроків):
    • Виберіть два елементи сітки навмання
    • Якщо вони мають один і той же колір, спробуйте ще раз (немає сенсу інакше, оскільки тоді заміна буде необов’язковою. У вас є лише 1/4 шанс потрапити на той самий колір і 1/16 шанс потрапити на той самий колір двічі поспіль, тому вам ніколи не доведеться занадто багато намагатися)
    • Тимчасово міняйте кольорами цих двох елементів
    • Перевірте розміри новостворених областей у місцях розташування елементів після заміни:
      • зробіть просту заливку назовні від нового місця кожного елемента, щоб визначити, наскільки великою областю цього кольору буде зроблений своп.
    • Якщо будь-який з цих двох регіонів перевищує ваш поріг, скасуйте попередній своп; інакше 'доопрацюйте' заміну кольорів двох елементів.

Тут головне: те, що ви поміняєте дві плями, означає, що ви ніколи не врівноважуєте кольори, і тест, який ви робите перед завершенням свого заміну, гарантує, що ви ніколи не створюєте занадто великі регіони. Якщо у вас є якісь засоби для відображення вашої сітки, ви навіть можете візуалізувати цей процес, щоб спостерігати, як він «будує» свої регіони за допомогою повторних свопів.

Якщо ви не можете почати з регулярного розподілу кольорів, що розподіляється рівномірно, тоді ви все одно зможете зробити щось подібне до рівномірного розподілу забарвлення: поки ваше забарвлення не буде розподілено рівномірно, виберіть елемент навмання; тоді, якщо це один із занадто представлених кольорів, тимчасово встановіть його на один із недостатньо представлених кольорів, а потім перевірте, чи не створюється занадто велика область нового кольору.


Стохастичні підходи неефективні. Для такого підходу, як мій, який приймає розглядаються кроки, час виконання наближається до O (n) для n комірок карти. Для вашого алгоритму це O (n * m), де m - кількість комірок, бажаних на острів (власне, для кожного потенційного острова). Завжди краще орієнтуватися на алгоритми, які мають легко оцінений час виконання. Замість того, щоб фіксувати випадково генеровану карту, краще сформувати карту, яка не зламана або випадкова, в першу чергу, за п ять кроків, підтримуючи таким чином керований, ефективний процес.
Інженер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.