Динамическое if-выражение? - PullRequest
4 голосов
/ 18 января 2012

Я работаю над клоном Game of Life (не могу связать вики, так как он не работает). Основные функциональные возможности выполнены, но я хочу дать пользователю возможность также определять свои собственные правила. Стандартная игра правил жизни:

Ячейка с 2 или 3 соседями продолжает жить.

Умирает ячейка с соседями 0-1 и 4-8.

Мертвая клетка с 3 соседями становится живой.

Это легко сделать с помощью двух операторов if. Но пользователь также может определить что-то вроде:

Ячейка с 1-3 или 5-7 соседями продолжает жить.

Умирает ячейка с другим номером.

Мертвая клетка с 2 или 4 соседями становится живой.

Как я могу реализовать это в операторах if? Могу ли я использовать какой-то список для проверки?

РЕДАКТИРОВАТЬ: Я вижу некоторые отличные решения здесь. Придется определить, что лучше всего подходит для моего кода. Для тех, кто все еще отвечает: я могу правильно обрабатывать ввод пользователя, не беспокойтесь об этом;)

У меня, вероятно, будет окно, в котором я спрашиваю How many neighbors to stay alive?, How many neighbours to become alive when dead?, с некоторыми текстовыми полями. Они также проверят правильность ввода.

(это C # в Unity3D)

Ответы [ 7 ]

1 голос
/ 18 января 2012

Я бы проверил только те условия, при которых клетка погибнет. Я бы структурировал свою функцию по линии:

bool CalculateIfDead(Cell c, int[] deadlyCountRules)
{       
   foreach(int n in deadlyCountRules)
   {
      if(c.NeighbourCount == n)
      {
         return true;
      }
   }
   return false;
}
1 голос
/ 18 января 2012

Попробуйте решение matix.

bool life[] = new bool[] {false, false, true, true, false, false, false, false, false};
bool die[] = new bool[] {true, true, false, false, true, true, true, true, true};
bool alive[] = new bool[] {false, false, false, true, false, false, false, false, false};

bool shouldLife=live[count];
bool shouldDie=die[count];
bool getAlive=alive[count];
1 голос
/ 18 января 2012

Я бы определил перечисление со значениями Propogate, Die, NoChange.

Затем создайте список / массив с элементом этого типа для каждого числа возможных соседей (от 0 до 8). Затем пользователь может установить этот список каким-либо образом (возможно, список перечислений, разделенных запятыми, в виде строк, который разделяется и приводится к типу перечисления).

Тогда все, что вам нужно сделать, это сосчитать соседей, выполнить поиск и действовать соответственно.

var UserActionList =
    "Die, Die, NoChange, NoChange, Propogate, Propogate, Die, Die, Die"
    .Split(',').Select(s => Enum.Parse(typeof(CellAction), s).ToArray();

// Count neighbours

swtich(UserActionList[NeighboursCount])
{
    case Die:
    /////

    case Propogate:
    /////
}
0 голосов
/ 18 января 2012

Хорошо, если пользователю разрешено определять неограниченное количество правил, которые вам может потребоваться перевести, а также проверить определения пользователей и создать файл кода C #, содержащий класс, и запустить его через провайдера CodeDom для C #, скомпилировать в сборку,и выполнить.этот файл должен возвращать результат всех заявлений, которые сгенерированы из определения пользователя.

Если количество опций ограничено, вы можете сохранить файл, в котором вы сохраняете вектор, который содержит двоичный массив всех комбинаций.который приводит к смерти.

0 голосов
/ 18 января 2012

это больше вопрос о дизайне и дизайне.Здесь нужно нечто похожее на шаблон стратегии.

http://www.oodesign.com/strategy-pattern.html

0 голосов
/ 18 января 2012

Итак, основная проблема - это предложение "Ячейка с другим номером _ ". Для этого есть два варианта.

-Просто запретите использовать это предложение и заставьте пользователя точно указывать, какие числа делать.

-Обращать это предложение как особый случай последним и присваивать ему любые неназначенные значения.

Я бы реализовал это с помощью массива #neighbours => IAction (IAction - это Same, Kill или Grow). Поскольку у вас есть только очень ограниченное число возможных подсчетов соседей, вы можете легко заполнить карту из заданных данных, и тогда вам даже не понадобятся никакие операторы if, просто прямой вызов IAction для индекса, если массив связан с текущим числом соседей.

0 голосов
/ 18 января 2012

То, что вы, вероятно, должны иметь, это что-то вроде класса

class DyingRule
{

   enum RuleResult{ Neutral , Death , Lives}; 

   //evaluates if according to this rule
   //death occurs.. pass parameter as needed
   RuleResult Evaluate();
}

И где-то в вашем коде вы поддерживаете их вектор. Пользователи могут свободно добавлять вектор и добавлять свои собственные правила.

Вы оцениваете их как

foreach ( currentRule in Rules )
   {
          RuleResult r = currentRule.Evaluate();
           if ( r ==  Death )
           {
                 ProcessDeath();
                 break;
           }
          else if ( r == Lives )
          {
                ProcessLiving();
                break;
          }
   } 

При желании вы можете иметь приоритет для правил и сортировать их по правилам, если правило заменяет другое

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...