Translate

пятница, 2 сентября 2011 г.

Пишем простое приложение на android для создания тестов. Хранение массивов в ресурсах

  В прошлый раз мы расставили кнопки согласно плану. Теперь пришло время подумать над логикой приложения.



  База вопросов - строковый массив - будет хранится в ресурсах. Однако класть ее в strings.xml неправильно - тогда пришлось бы создавать для каждого вопроса новый ресурс.
  Существует еще один вид ресурсов, позволяющий хранить массивы любых типов данных. Они хранятся в файле arrays.xml. Создадим такой. Для тестирования создадим подобие базы - она будет хранится в arrays.xml в следующем формате:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <array name="Questions">
        <item>/nQuestion1/Variant11/Variant12/Variant13/Variant14/1/</item>
        <item>/nQuestion2/Variant21/Variant22/Variant23/Variant24/2/</item>
        <item>/nQuestion3/Variant31/Variant32/Variant33/Variant34/3/</item>
        <item>/nQuestion4/Variant41/Variant42/Variant43/Variant44/4/</item>
        <item>/nQuestion5/Variant51/Variant52/Variant53/Variant54/1/</item>
        <item>/nQuestion6/Variant61/Variant62/Variant63/Variant64/2/</item>
        <item>/nQuestion7/Variant71/Variant72/Variant73/Variant74/3/</item>
        <item>/nQuestion8/Variant81/Variant82/Variant83/Variant84/4/</item>
    </array>
</resources>Syhi-подсветка кода
  Все, что расположено между тегами array, является единицами массива. Для каждого вопроса мы закодируем вопрос, его 4 варианта ответа и номер правильного в вашенаписанном виде. n - любой символ, который должен присутствовать, таковы особенности алгоритма обработки этих строк, который будет изложен и разобран ниже.  Разделитель (знак /) теперь ни в коем случае нельзя использовать ни в вопросах, ни в ответах.
 В коде создадим 3 массива: первый содержит строки с вопросами, второй - двумерный - матрицу ответов, а третий - коды правильных вариантов. Также нужно объявить переменную, хранящую количество вопросов в базе. Заведем константу еще и для разделительного символа - вдруг нам захочется его изменить:

 

private static final int QUESTIONS=8;
private static final char DELIMITER='/';
private String[][] AnsMatrix=new String[VARIANTS][QUESTIONS];
private int[] RightAnswers=new int[QUESTIONS];
private String[] Ques=new String[QUESTIONS];
private TypedArray Base;Syhi-подсветка кода

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

  Теперь будем писать важную функцию LoadQuestions, которая распределит наши данные по массивам:
 


private void LoadQuestions(){
        Resources res=getResources();
        Base=res.obtainTypedArray(R.array.Questions);
        for (int i=0;i<QUESTIONS;i++){
                Ques[i]=getSubstringBetweenDelimiters(0,1,Base.getString(i));
                for (int j=0;j<VARIANTS;j++){
                        AnsMatrix[j][i]=getSubstringBetweenDelimiters(j+1,j+2,Base.getString(i));
                }
                RightAnswers[i]=Integer.parseInt(getSubstringBetweenDelimiters(VARIANTS+1,VARIANTS+2,Base.getString(i)));
        }
}Syhi-подсветка кода
 Вероятно, вы заметили, что в этом коде использован метод getSubstringBetweenDelimiters(), который надо подготовить перед написанием алгоритма.

 Он принимает 3 параметра: исходную строку, и два целых числа и определяют подстроку, лежащую в исходной строке между теми по счету разделителями, которые определяют первые 2 аргумента. Например, в строке "/cats/dogs/pets/rats/" при целых параметрах  2 и 3 должен возвратить строку pets. Код метода:
 

private String getSubstringBetweenDelimiters(int k, int m, String str){
        int index1=0;
        int index2=0;
        int len=str.length();
        int dels=0;
        for (int i=0;i<len;i++){
            if (str.charAt(i)==DELIMITER){
                dels++;
            }
            if (dels==k){
                index1=i;
            }
            if (dels==m){
                index2=i;
            }
        }
        return str.substring(index1+2, index2+1);
 }Syhi-подсветка кода
    Для извлечения подстроки нужно будет узнать индексы разделителей на заказанных местах. За это отвечают переменные index1 и index2. Затем определим длину исходной строки (для цикла) и инициализируем счетчик разделителей в 0. Затем обойдем всю строку, и если текущий символ является разделителем, прибавим к счетчику 1. Здесь же, если значение счетчика совпало с одним их целых аргументов функции, можно присваивать соответствующему индексу номер текущего символа.
  В конце мы просто возьмем подстроку от одного индекса до второго. Тут, правда, есть один нюанс: мы должны их немного изменить из за характера строковых операций Java.
  Теперь вернемся к LoadQuestions(). Первые две строки инициализируют строковый массив из ресурсов.Затем мы обойдем все вопросы и:
 -Занесем в массив вопросов подстроку от первого до второго разделителя.
  -Для каждого из вариантов ответа занесем в соответствующую ячейку двумерного массива подстроку от 1+n до 2+n разделителя
  -Последнюю часть строки определим как элемент массива кодов правильных ответов.
  На сегодня все, в следующий раз мы завершим разработки нашего детища.


Скачать исходник всей программы можно здесь

8 комментариев:

  1. Анонимный1 июля 2012 г., 12:53

    Все классно, давно ищу такую программу. Как посмотреть на готовые исходники? Мне не все понятно. Где и в каком месте нужно прописать данный код?

    ОтветитьУдалить
  2. Добавил ссылку для скачивания исходников в конце статьи.

    ОтветитьУдалить
  3. Большое спасибо за исходники теперь понятнее. Димитер скажите, а можно реализовать интерфейс программы похожый на ___http://www.youtube.com/watch?v=LStnG8tVfXc&feature=plcp вот эту. То есть нужно что-бы при выборе ответа была возможность указывать несколько правильных ответов. И сразу было видно, попадание или ошибка?

    ОтветитьУдалить
  4. Да, можно. Только для этого придется сильно менять код:

    -в XML файле нужно будет вместо одного правильного ответа указывать много. Сами правильные ответы в пределах /набор ответов/ надо разделять каким-то специальным знаком
    -лучше написать класс, содержащий массив из правильных ответов, сам массив мы должны получать путем разбора строки /набор ответов/ со специальными разделителями. Таким образом, придется хранить массив таких классов(вопросов же в базе много)
    -изменить код нажатия на кнопки. Пусть теперь мы будем менять цвет кнопок (синий - выбран ответ, красный - нет). Метод для изменения цвета: .setBackgroundColor(); Цвет можно писать константами : Color.RED; Color.BLUE или в шестнадцатиричной форме (0xff44ff)
    -при нажатии на кнопку с вопросом нужно будет проверить цвета всех кнопок и сверить их с набором правильных ответов из класса, затем вывести уведомление Toast о том, правильно ли выбраны ответы, затем перейти к следующему вопросу и покрасить все кнопки в начальный цвет

    ОтветитьУдалить
  5. Димитер
    огромное спасибо, Димитер скажите а этот вариант подойдет для теста с большим количеством вопросов? или лучше с бд работать?

    ОтветитьУдалить
  6. Да, это работает достаточно быстро. Теоретически можно и быстрее, но в этом просто нет необходимости.

    ОтветитьУдалить
  7. что бы как то представить скажу вопросов будет минимум 500 с картинками а количество ответов от 3 до 5 включительно

    ОтветитьУдалить

Related Posts Plugin for WordPress, Blogger...