Статьи

Функции обработки массивов

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

Чтобы осветить некоторые функции обработки массивов, которые предлагает PHP, я буду использовать некоторые компоненты Buraco — игры, очень популярной в моей части мира и очень похожей на Рамми. В реальном Бурако играют две колоды (104 карты) плюс две карты Джокера. В нем также есть колода карт, в которой хранятся все карты, которые не сдаются игрокам, но я не буду здесь их использовать, поэтому вам не нужно о них беспокоиться.

Представление колоды карт

Карты датируются, возможно, девятым веком, временем, когда листы бумаги впервые начали использоваться в Китае. Они пошли по пути других изобретений с Востока — сначала в арабский мир, откуда они были затем увезены в Европу, а затем в Новый Свет. В своей самой популярной на данный момент форме, французской колоде, колода игральных карт состоит из 52 карт, разделенных на четыре масти: булавы (♣), бриллианты (♦), червы (♥) и пики (♠). У каждой масти по 13 карт или лиц: A, 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q и K.

Вы можете написать массивы для хранения как костюмов, так и лиц:

<?php $suits = array ("clubs", "diamonds", "hearts", "spades"); $faces = array (1 => "A", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13"); 

Оба являются числовыми индексированными массивами, то есть имеют целочисленные ключи. Поскольку я явно не давал никаких ключей при определении $suits , PHP автоматически присваивает им ключи, начиная с 0. Итак, значение $suits[0] равно «club», а $suits[3] — «spades». Однако я предоставил ключ к первому элементу $ Faces. PHP назначает каждый новый ключ, беря максимальный целочисленный индекс и добавляя к нему 1. $faces[1] — это «A», $faces[2] — это «02», $faces[3] — это «03» и так далее. Вы заметите, что я заставил PHP начать индексирование $faces с 1, чтобы числовые лица карты были идентичны их соответствующим ключам.

Вы можете использовать два цикла foreach для создания мастер-массива из всех 52 карт, каждая из которых представлена ​​в виде строки в формате face | suit , например:

 <?php $deck = array(); foreach ($suits as $suit) { foreach ($faces as $face) { $deck[] = $face . "|" . $suit; } } 

Результат приведенного выше кода такой же, как если бы вы заполнили $deck вручную:

 <?php $deck = array("A|clubs", "02|clubs", "03|clubs", "04|clubs", ... "Q|spades", "K|spades"); 

Некоторые из более опытных читателей могут спросить, почему бы не использовать вложенный массив в отличие от строк, например:

 <?php $deck = array(); $deck["A"] = array("clubs", "diamonds", "hearts", "spades"); $deck["02"] = array("clubs", "diamonds", "hearts", "spades"); $deck["03"] = array("clubs", "diamonds", "hearts", "spades"); ... 

В этом-то и прелесть: строки иногда можно рассматривать как неассоциативные одноуровневые массивы, но, тем не менее, массивы! Фактически, та же функция, используемая для подсчета количества элементов в массиве — count() — также может использоваться для подсчета количества символов в строке! Позже вы увидите, как конвертировать строки в массивы.

Дело рук

Давайте начнем с перетасовки колоды и раздачи руки из 11 случайных карт. Для этого вы можете использовать функцию array_rand() . Возвращает массив ключей, взятых случайным образом из оригинала. Функция была разработана для возврата ключей, а не значений, поэтому она может работать с вложенными массивами так же эффективно, как и с одноуровневыми массивами, и вы всегда можете получить значения, если знаете ключ.

 <?php $myKeys = array_rand($deck, 11); $myHand = array(); foreach ($myKeys as $key) { $myHand[] = $deck[$key]; unset($deck[$key]); } с <?php $myKeys = array_rand($deck, 11); $myHand = array(); foreach ($myKeys as $key) { $myHand[] = $deck[$key]; unset($deck[$key]); } 

Первоначально $myKeys временный массив $myKeys , значения которого равны 11 случайным ключам, найденным в $deck . Затем цикл foreach использует значение $myKeys чтобы получить соответствующее значение из $deck в $myHand . Конечно, это не удаляет элементы из оригинальной колоды. Если бы вам пришлось снова вызывать array_rand() , вполне возможно, что вы могли бы получить несколько ключей, индексирующих снова некоторые карты, которые уже были извлечены! Чтобы этого не произошло, вызывается unset() чтобы удалить элемент из $deck чтобы убедиться, что его нельзя использовать повторно.

Чтобы выяснить, находится ли карта, скажем «06 | hearts» (6 ♥), в раздаче, вы можете использовать функцию in_array() . Сначала он принимает иглу , желаемое значение для поиска, а затем стог сена , массив для поиска.

 <?php if (in_array("06|hearts", $myHand)) { echo "I found it!"; } 

В качестве примечания о иголках и стогах сена евангелисты других языков любят находить ошибки в PHP (и, конечно, верно и обратное!). Единственная критика, которую я никогда не мог опровергнуть, это раздражающий противоречивый порядок параметров в PHP между похожими функциями. Некоторые функции, такие как in_array() , сначала принимают иглу, в то время как другие функции сначала принимают стог сена. Я знаю давних разработчиков PHP, которые до сих пор не могут вспомнить, какой порядок используют некоторые функции, так что не отчаивайтесь, если вам всегда нужно проверять онлайн-документацию.

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

Хорошее ведение домашнего хозяйства важно, и благодаря манере « лицо | масть» , в которой представлены карточки, сортировать их так же просто, как и использовать sort() . Эта функция упорядочивает элементы массива в возрастающем алфавитном и числовом порядке:

 <?php sort($myHand); 

Функция sort() отличается тем, что работает со своим собственным аргументом! Если вы хотите сохранить исходный порядок $myHand вам придется скопировать его в другую переменную перед сортировкой:

 <?php $preservedHand = $myHand; sort($myHand); 

Melds и Discards

Buraco, как и Rummy, — это игра в бега — последовательности, установленные на столе. Акт вытаскивания карт из руки на пробежку называется слиянием . Например, карты 9 ♦, 10 ♦, J ♦ и Q ♦, если они были в $myHand можно объединить для запуска. Программно это означает удаление карт из $myHand и помещение их в новый массив $myRuns . Вы можете использовать функцию array_slice() которая возвращает копию диапазона элементов из массива, очень похоже на то, как substr() работает со строками. Предполагая, что последовательности занимают позиции от 0 до 3 в $myHand :

 <?php $myRuns = array(); $myRuns[] = array_slice ($myHand, 0, 4); $myHand = array_slice($myHand, 5, 7); 

Первая строка создает массив $myRuns а вторая добавляет к нему вложенный массив, состоящий из 4 элементов из $myHand начиная с индекса 0, который является первой позицией в массиве. array_slice() не удаляет срез из исходного массива, что является проблемой, так как вам нужно удалить карты из вашей руки, которые вы слили или сбросили. Решением здесь является использование array_slice() во второй раз для переназначения других элементов $myHand себе.

В начале своего хода игрок должен либо взять одну карту из колоды или все карты из колоды сброса и добавить их в свою руку. Обе опции могут быть выполнены с помощью функции array_merge() . Функция возвращает массив, состоящий из всех элементов из указанных массивов в порядке их предоставления. Например, скажем, состояние игры выглядит так:

Рука игрока: 2 ♣, 5 ♥, 6 ♠, 6 ♥, 7 ♦, 8 ♥, K ♠
Прогон: 9 ♦, 10 ♦, J ♦, Q ♦
Сброс свай: 7 ♠, J ♠, 4 ♥, 4 ♦

Чтобы собрать все карты из колоды сброса и добавить их в руку игрока, вы можете написать:

 <?php $myHand = array_merge($myHand, $discarded); 

После этого $myHand будет содержать:

  массив («02 | клубы», «5 | сердечки», «06 | пики», «06 | сердечки», «07 | алмазы», ​​«08 | червы», «13 | пики», «07 | пики», «11 | пики», «04 | сердечки», «04 | бриллианты») 

Показ руки

Было бы неплохо отобразить одну или несколько карточек в браузере. Моя стратегия состоит в том, чтобы использовать нотацию | лицо | костюм для создания ряда HTML-тегов изображения, которые будут отображать лицо и графику костюма. Хотя это вряд ли является эффективным решением для реального приложения, оно дает мне возможность показать вам одну последнюю функцию, explode() .

 <?php foreach ($myHand as $card) { $tmpArray = explode("|", $card); echo '<img src="img/face_' . $faces[$tmpArray[0]] . '.png">"; echo '<img src="img/suit_' . $suits[$tmpArray[1]] . '.png">"; echo "&nbsp;"; // Just a blank space for visual separation } 

Каждый foreach просматривает все карты в $myHand и возвращает одно значение номинальной масти на каждой итерации в виде $card . Функция explode() берет каждое значение $card и разбивает его на две части, используя вертикальную черту в качестве разделителя. Затем он возвращает массив с таким количеством элементов, сколько есть частей. Я использую вертикальную черту здесь, но explode() будет работать с любым символом или последовательностью символов.

Резюме

PHP имеет более 70 функций, связанных с массивами. В этом уроке вы увидели, как использовать их всего несколько для выполнения некоторых базовых манипуляций с массивами. Эти функции являются инструментами, которые вы часто будете использовать для решения задач программирования или, как я их называю, задач. Важно наладить с ними знакомство, чтобы при планировании сценария вы могли принимать обоснованные решения на основе нужных вам результатов.

Изображение через Синди Хаггерти / Shutterstock