Следующая статья является частью серии. Дополнительные статьи из этой серии см. В разделе «Клонирование игры 2048 на Ruby». Полный и окончательный код см. В суть.
Теперь, когда мы знаем, как будет работать алгоритм, пора подумать о данных, которые этот алгоритм будет работать. на. Здесь есть два основных варианта: какой-либо плоский массив или двумерный массив. У каждого есть свои преимущества, но прежде чем мы примем решение, нам нужно кое-что учесть.
СУХИЕ Пазлы
A распространенный метод работы с головоломками на основе сетки, где вы должны искать подобные шаблоны, – это написать одну версию алгоритма, который работает с головоломкой слева направо, а затем повернуть всю головоломку вокруг четырех раз. Таким образом, алгоритм должен быть написан только один раз, и он должен работать только слева направо. Это значительно снижает сложность и размер самой сложной части этого проекта.
Поскольку мы будем работать над головоломкой слева направо, это имеет смысл чтобы строки были представлены массивами. При создании двумерного массива в Ruby (или, точнее, того, как вы хотите, чтобы он был адресован и что на самом деле означают данные), вы должны решить, хотите ли вы иметь стек строк (где каждая строка сетки представлена массив) или стек столбцов (где каждый столбец является массивом). Поскольку мы работаем со строками, мы выберем строки.
Как этот 2D-массив вращается, мы перейдем к рассмотрению после того, как фактически построим такой array.
Построение двумерных массивов
Метод Array.new может принимать аргумент, определяющий размер массива, который вы хочу. Например, Array.new (5) создаст массив из 5 нулевых объектов. Второй аргумент дает вам значение по умолчанию, поэтому Array.new (5, 0) даст вам массив [0,0,0,0,0] . Итак, как создать двумерный массив?
Неправильный способ, и я вижу, что люди часто пытаются сказать Array. новый (4, Array.new (4, 0)) . Другими словами, массив из 4 строк, каждая строка представляет собой массив из 4 нулей. И поначалу кажется, что это работает. Однако запустите следующий код:
Это выглядит просто. Создайте массив нулей 4×4, установите верхний левый элемент в 1. Но распечатайте его, и мы получим…
Он установил весь первый столбец в 1, что дает? Когда мы создавали массивы, сначала вызывается самый внутренний вызов Array.new, создавая единственную строку. Затем одна ссылка на эту строку дублируется 4 раза, чтобы заполнить самый внешний массив. Затем каждая строка ссылается на один и тот же массив. Измените один, измените их все.
Вместо этого нам нужно использовать третий способ создания массива в Ruby. Вместо передачи значения методу Array.new мы передаем блок. Блок выполняется каждый раз, когда методу Array.new требуется новое значение. Итак, если вы скажете Array. new (5) {gets.chomp} , Ruby остановится и 5 раз запросит ввод. Итак, все, что нам нужно сделать, это просто создать новый массив внутри этого блока. В итоге мы получаем Array.new (4) {Array.new (4,0)} . Теперь давайте снова попробуем этот тестовый пример.
И он работает именно так, как вы и ожидали.
Итак, хотя Ruby не поддерживает двумерные массивы, мы все равно можем делать то, что нам нужно. Просто помните, что массив верхнего уровня содержит ссылки на подмассивы, и каждый подмассив должен ссылаться на другой массив значений.
Что представляет этот массив, зависит от вас. В нашем случае этот массив размещается в виде строк. Первый индекс – это строка, которую мы индексируем сверху вниз. Чтобы проиндексировать верхнюю строку головоломки, мы используем a [0] , чтобы проиндексировать следующую строку вниз, мы используем a [1] . Чтобы проиндексировать конкретную плитку во второй строке, мы используем a [1] [n] . Однако, если бы мы остановились на колоннах… это было бы то же самое. Ruby понятия не имеет, что мы делаем с этими данными, и, поскольку он технически не поддерживает двумерные массивы, то, что мы здесь делаем, является хакерской атакой. Доступ к нему только условно, и все будет держаться вместе. Забудьте, что должны делать данные внизу, и все может очень быстро развалиться.