2013-08-24 3 views
1

Я работаю над программой решения sudoku, и мне нужен arraylist, который содержит числа от 1 до 9 для каждого квадрата на плате 9x9. Каждый из этих arraylists соответствует возможным номерам, которые могут идти в этом квадрате, если число не может идти на этом квадрате, оно удаляется из списка.Java: 2D массив arraylists?

Я хочу, чтобы иметь возможность подтянуть ArrayList текущего квадрата она работает на, как, например, если бы я хотел, чтобы удалить номер 7 из ArrayList, соответствующий квадрат (3,5)

arrayOfLists[3][5].remove(Integer.valueOf(7)); 

Однако я не могу понять, как это сделать. Когда я пытаюсь создать массив я получаю эту ошибку в строке, где я декларировать свой массив ArrayLists

Невозможно создать общий массив ArrayList

Вот мой код:

//create arraylist 
    ArrayList<Integer> nums = new ArrayList<Integer>(); 

    //fill arraylist with numbers 1-9 
    for (int i = 1; i < 10; i++) { 
     nums.add(i); 
    } 

    //create 9x9 array of arraylists 
    ArrayList<Integer>[][] array = new ArrayList<Integer>[9][9]; 

    //fill each element of array with arraylist of numbers 1-9 
    for(int i = 0; i<9; i++){ 
     for(int j = 0; j<9; j++){ 
      array[i][j] = nums; 
     }  
    } 

} 

Я делаю это неправильно или не удается создать массив arraylists? Если это невозможно, как мне это сделать?

+0

См. Ответы: http://stackoverflow.com/questions/11113095/how-can-i-initialize-my-generic-array, http://stackoverflow.com/questions/4549192/create-an-array -of-arrayliststring-elements – Kevin

+1

замените 10 элементов 'ArrayList ' на 'boolean [9]' и установите те, которые удалены на 'false' – zapl

+0

Я не видел этого ни в одном из ответов на этих ссылках, но Я просто попробовал 'private class IntegerArrayList расширяет ArrayList {...}' и объявляет конструкторы вроде ArrayList, которые использовали 'super (...)'; то я смог использовать 'new IntegerArrayList [9] [9]', а методы 'ArrayList' отлично работали над компонентами массива, например. 'А [I] [J] .add (п)'. Есть ли причина, по которой этот подход не сработает? – ajb

ответ

0

Несколько вещей:

1) В вашей для цикла, массив [я] [J] = Nums; Это приведет к тому же объекту в каждом элементе массива. Если вы вызове remove() на одном элементе массива, это повлияет на всех остальных. Вы хотите создать отдельный объект списка для каждого элемента.

2) Программа для интерфейсов; объявлять nums как List, а не ArrayList.

3) Используйте список списков в отличие от любого массива списков.

List<List<List<Integer>>> list = new ArrayList<List<List<Integer>>>(); 
    for(int i = 0; i<9; i++){ 
     List<List<Integer>> row = new ArrayList<List<Integer>>(); 
     for(int j = 0; j<9; j++){ 
      List<Integer> nums = new ArrayList<Integer>(); 
      for (int k = 1; k < 10; k++) { 
       nums.add(i); 
      } 
      row.add(nums); 
     } 
     list.add(row); 
    } 

    // You can still get an element by index 
    int x = list.get(3).get(1).remove(6); 

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

1

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

У вас есть фиксированная доска, состоящая из 9 фиксированных квадратов, столбцов и строк, каждое положение которых может занимать номер 1-9.

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

+0

Почему вы продолжаете говорить «если» вместо «из»? –

+0

@ Zoltán Да, я, похоже, много чего делаю. Это потому, что я публикую довольно много исключительно на моем iPhone, и слишком часто мой правый палец не сгибается достаточно, чтобы попасть в «о» и вместо этого «Я». Объедините это с моим зрением, как дерьмом, и я не замечаю ошибку. Ты спрашивал! :) – Bohemian

+0

спасибо за ответ :) –

-1

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

private static class IntegerArrayList extends ArrayList<Integer> { 
    IntegerArrayList() { super(); } 
    IntegerArrayList (Collection<? extends Integer> c) { super(c); } 
    IntegerArrayList (int initialCapacity) { super(initialCapacity); } 
} 

Теперь вы можете сказать что-то вроде

IntegerArrayList[][] array = new IntegerArrayList[9][9]; 

и элементы, такие как массив [1] [2] наследует все методы ArrayList (array[1][2].remove(something) работает отлично). Я сделал класс private static, думая, что вы можете вложить его в какой-то другой класс, если это единственное место, которое вы будете использовать, но вы можете сделать его общедоступным, если хотите.Кроме того, я скопировал все три конструктора с ArrayList; вы можете устранить ненужные, но я не вижу веских оснований.

Я думаю, что проблема заключается в том, что new ArrayList<Integer>[9][9] запрещен, потому что он создаст массив, который не будет проверять тип (из-за стирания типа). Но я думаю, что добавление собственного не-генерического типа, который наследуется от ArrayList<Integer>, восстанавливает безопасность типа.

Но я не специалист по общим вопросам, и меня не удивит, если кто-то более осведомлен, чем я, проблема с этим решением. Но мне показалось, что это работает отлично, без каких-либо предупреждений компилятора о неконтролируемом типе или что-то еще.

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

+0

'IntegerArrayList' кажется глупым способом написания' ArrayList ' – Navin

+0

@Navin Вы, наверное, пропустили весь смысл. Дело в том, что вы ** не можете ** написать 'ArrayList ' из-за правил Java о дженериках и массивах (в частности, 'new ArrayList [9] [9]' является незаконным). Поэтому вам нужен другой подход, и одна из возможностей заключается в определении не общего имени, которое по сути является синонимом для 'ArrayList '. Если вам не нравится имя, которое я выбрал, попробуйте лучше. Я не умею изобретать имена. Но если это ваш downvote, пожалуйста, удалите его, так как вы неправильно поняли проблему. – ajb

+0

Я этого не замечал. Вы не можете написать 'ArrayList [] table = (ArrayList []) (новый ArrayList [4]);'? Только декларируемый тип имеет значение для дженериков, поэтому это также должно быть безопасным по типу. – Navin

0

Вы можете полностью удалить материал 2d и сохранить один список, предоставив каждому квадрату уникальный номер из 1 ... 81. Поэтому, если вы работаете с 3,5 ячейками, это означает, что в списке есть 9 * 2 + 5 = 23-й элемент. Это значительно упростит манипулирование списками. Вы можете использовать единственный метод, чтобы дать уникальный индекс ячейки, учитывая тип ссылки (3,5)

1

Используйте поле бит вместо списка массивов. То есть, используйте целое число, где биты 1-9 представляют возможности чисел. Тестирование, добавление, удаление одного числа - O (1), и он имеет фиксированный объем памяти. Инкапсулируйте целое число в свой собственный объект, который знает операции.

+0

Кроме того, для этого конкретного использования кажется вероятным, что программа захочет протестировать более одного номера одновременно. (Я никогда не пытался написать решателя Sudoku, это основано на мыслительных процессах, с которыми я сталкиваюсь, когда сам их решаю.) С этой целью использование битов целого числа может привести к более простому коду. Хорошая идея об инкапсулировании целого числа. – ajb

Смежные вопросы