PHP: правильная обработка циклов и замена

Во время программирования моей игры я столкнулся с проблемой при работе с нашей генетикой. Длинная и короткая наша генетика заключается в том, что их можно использовать и анализировать несколькими способами. В настоящее время они разбиты на B/b/b1/b2, O/o, W/w и C/c1/c2.

Проблема с кодом возникает в этот момент при обработке части C/c1/c2 строки, равной 6. Мне пришлось использовать текущий код, чтобы он не добавлял дополнительные последовательности C/c1/c2, однако, он сталкивается с проблемой, когда он не добавляет их в генетический код, который может быть BBooww-- (где - последовательность C/c1/c2) и часто добавляет многих к последовательности, подобной BBooww-- c2c2 (наш розовый альбинос последовательность).

Ниже приведены инструкции foreach и if, которые я использую. Любая помощь в сокращении или оптимизации

$coat_genes = str_split($coat_combination);
$full_coat_combination = "";

foreach($coat_genes as $coat_gene)
{ 
 if ($coat_gene != "-")
 {
 $full_coat_combination.= $coat_gene;
 continue;
 } else {

 if (strlen($full_coat_combination) <= 4 && strpos(strtolower($full_coat_combination), "oo") === false)
 {
 $o = "";

 $chance = rand(1, 2);

 $o .= ($chance == 1) 
 ? "O"
 : "o";

 if ($o == "O")
 {
 $chance = rand(1, 2);

 $o .= ($chance == 1) 
 ? "O"
 : "o";

 } else {
 $o .= "o";
 }

 $full_coat_combination .= $o;
 }

 if (strlen($full_coat_combination) <= 6 && strpos(strtolower($full_coat_combination) , "ww") === false)
 {
 $w = "";

 $chance = rand(1, 2);

 $w .= ($chance == 1) 
 ? "W"
 : "w";

 if ($w == "W")
 {
 $chance = rand(1, 2);

 $w .= ($chance == 1)
 ? "W" 
 : "w";
 } else {
 $w .= "w";
 }

 $full_coat_combination .= $w;
 }

 if (strlen($full_coat_combination) > 6 
 && strpos(strtolower($full_coat_combination) , "cc") === false 
 && strpos(strtolower($full_coat_combination) , "cc1") === false 
 && strpos(strtolower($full_coat_combination) , "cc2") === false 
 && strpos(strtolower($full_coat_combination) , "c1c1") === false 
 && strpos(strtolower($full_coat_combination) , "c1c2") === false 
 && strpos(strtolower($full_coat_combination) , "c2c1") === false 
 && strpos(strtolower($full_coat_combination) , "c2c2") === false)
 {
 $c = "";

 $chance = rand(1, 3);

 if ($chance == 1) 
 {
 $c.= "C";

 } elseif ($c == "c1") {
 $c.= "c1";
 } else {
 $c.= "c2";
 }

 if ($c == "C")
 {
 $chance = rand(1, 3);

 if ($chance == 1) 
 {
 $c.= "C";
 } elseif ($chance == 2) { 
 $c.= "c1";
 } else { 
 $c.= "c2";
 }
 } else {
 $chance = rand(1, 2);

 $c .= ($chance == 1) 
 ? "c1"
 : "c2";
 }
 $full_coat_combination.= $c;
 break;
 }
 }
}

Комбинация пальто извлекается из базы данных. Некоторые примеры следуют:

Melanistic: BB------ (O/o, W/w, C/c1/c2 соответственно) Клубника: BBooww-- (C/c1/c2) Синий Альбино (одна из наших наиболее проблемных последовательностей): bboo - c1c1 (W/w) Розовый альбинос (такой же, как синий): bboo - c2c2

Благодарю!

1 ответ

Я думал, что это похоже на интересную проблему. Если я правильно понимаю ваш вопрос и код:

  1. Ваша база данных содержит генетику, которая представлена в виде последовательностей из четырех пар. Эти последовательности встречаются в согласованном шаблоне, так что первая пара состоит из двух выборок из множества [B, b, b1, b2], второй пары из множества [O, o], третьей пары из множества [W, w] и четвертой пары из множества [C, c1, c2].

  2. Некоторые пары заменяются парами тире в качестве заполнителей. Ваша программа должна заменить тире случайными элементами из соответствующего набора, учитывая их размещение в основной последовательности. Поскольку ваш код не адресует первую пару (группа B), я предполагаю, что они всегда будут присутствовать.

  3. Чтобы построить пары замещения, вы сначала произвольно выбираете один элемент из соответствующего набора. Второй элемент также выбирается случайным образом, но если первый элемент является одним из вариантов нижнего регистра, второй элемент может быть не прописным.

Во-первых, я бы использовал регулярное выражение для разделения последовательности на свои компоненты, а не с помощью str_split, потому что некоторые из элементов состоят из нескольких символов.

preg_match_all('/([BbOoWwCc][12]?|-)/', $coat_combination, $coat_genes);

Когда у вас есть последовательность в массиве, вы можете перебирать ее, как вы сейчас делаете, но вместо того, $full_coat_combination повторно проверять $full_coat_combination, вы можете заменить каждую из тире на элемент из соответствующего набора, используя определенное правило для каждой позиции в последовательность.

$full_coat_combination = ''; // container for resulting sequence
$prev = ''; // to handle uppercase/lowercase requirement
$c_options = array('C', 'c1', 'c2');
foreach($coat_genes[0] as $i => $gene) {
 if ($gene == "-") {
 if ($i == 2) {
 // you may use rand(0,1) to generate a random boolean
 $gene = rand(0, 1) ? 'O' : 'o';
 } elseif ($i == 3) {
 $gene = 'o'; // default value is lowercase
 // if previous was uppercase, then randomly select upper or lower
 if ($prev == 'O') $gene = rand(0, 1) ? 'O' : 'o';
 } elseif ($i == 4) { // W uses the same logic as O
 $gene = rand(0, 1) ? 'W' : 'w';
 } elseif ($i == 5) {
 $gene = 'w';
 if ($prev == 'W') $gene = rand(0, 1) ? 'W' : 'w';
 } elseif ($i == 6) {
 // randomly select an element from the three possibilities
 $gene = $c_options[rand(0, 2)];
 } elseif ($i == 7) {
 // if the previous was not uppercase, exclude the index for upper
 $x = $prev == 'C' ? rand(0, 2) : rand(1, 2);
 $gene = $c_options[$x];
 }
 }
 $prev = $gene; // current becomes previous for the next iteration
 $full_coat_combination .= $gene;
}

licensed under cc by-sa 3.0 with attribution.