2013-11-07 2 views
0

Я создаю концентрационную игру.Как создать генератор чисел, который будет выбирать только один раз?

У меня есть буферный массив изображений, в котором я загружаю 25 листов спрайтов изображений.

public static BufferedImage[] card = new BufferedImage[25]; 

0 указатель есть карта задний. и 1 - 24 - значения для лицевой стороны карт, которые нужно проверить, если карты совпадают.

Что я свяжу, чтобы сделать это, у меня будет 4 трудности Легкий, нормальный, жесткий и экстремальный. У каждой сложности будет определенное количество карт, которые нужно будет нарисовать, а затем удвоить количество выбранных. например, уровень по умолчанию будет NORMAL, который составляет 12 совпадений, поэтому ему необходимо случайным образом выбрать 12 уникальных карт из массива Buffered Image, а затем удвоить каждое значение, чтобы у него было только 2 каждой карты, а затем перетасовать результаты.

Это то, что я получил до сих пор, но он всегда имеет дубликаты около 99% времени.

//generate cards 
        Random r = new Random(); 

        int j = 0; 


        int[] rowOne = new int[12]; 
        int[] rowTwo = new int[12]; 
        boolean[] rowOneBool = new boolean[12]; 

        for(int i = 0; i < rowOneBool.length; i++) 
         rowOneBool[i] = false; 


        for(int i = 0; i < rowOne.length; i++){ 
         int typeId = r.nextInt(12)+1; 
         while(rowOneBool[typeId]){ 
          typeId = r.nextInt(12)+1; 
          if(rowOneBool[typeId] == false); 
         } 

         rowOne[i] = typeId; 
         j=0; 
        } 

A sample run of my program

3 количеств я буду нуждающимися для генерации легка 6, нормальный 12 и 18 Жесткий экстремальные будут использовать все изображения, кроме индекса 0, который является задней частью карты.

+0

Если у вас есть конечное количество изображений, было бы довольно легко создать массив 'boolean' этого размера. Создайте случайное число, если этот индекс является ложным, установите его true и добавьте это изображение. Если это правда, сгенерируйте случайное число замены и продолжайте, пока вы не установите 6/12/18 в true. – nhgrif

+0

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

+1

Вставьте их в список, перетасуйте его, откройте список до размера списка трудностей, используйте addAll, чтобы добавить новый список в себя, снова перетасовать. – Tonithy

ответ

0

Из того, что я понимаю из вашего вопроса, ответ должен выглядеть примерно так: Иметь 2 класса, один из которых называется Randp, а другой - Main. Запустите Main и отредактируйте код в соответствии с вашими потребностями.

package randp; 


public class Main { 

    public static void main(String[] args) { 
     Randp randp = new Randp(10); 
     for (int i = 0; i < 10; i++) { 
      System.out.print(randp.nextInt()); 
     } 
    } 

} 


package randp; 

public class Randp { 

private int numsLeft; 
private int MAX_VALUE; 
int[] chooser; 

public Randp(int startCounter) { 
    MAX_VALUE = startCounter; //set the amount we go up to 
    numsLeft = startCounter; 
    chooser = new int[MAX_VALUE]; 
    for (int i = 1; i <= chooser.length; i++) { 
     chooser[i-1] = i; //fill the array up 

    } 
} 

public int nextInt() { 
    if(numsLeft == 0){ 
     return 0; //nothing left in the array 
    } 
    int a = chooser[(int)(Math.random() * MAX_VALUE)]; //picking a random index 
    if(a == 0) { 
     return this.nextInt(); //we hit an index that's been used already, pick another one! 
    } 
    chooser[a-1] = 0; //don't want to use it again 
    numsLeft--; //keep track of the numbers 
    return a; 

} 
} 
+0

Благодаря Jeeter, и всем остальным я создал новый проект и поставил в него вышеуказанный код, чтобы увидеть, как он работает и работает. Я попытаюсь интегрировать его в свой проект. –

+0

Нет проблем. Вам просто нужно добавить его как отдельный класс, а затем использовать разные объекты Randp в зависимости от уровней: Easy будет «new Randp (6)», Normal - «новый Randp (12)» и т. Д. Затем вместо вашего 'r.nextInt()' у вас есть, вызовите 'nextInt()' Randp'. – Jeeter

+0

У меня есть переменная, называемая cardToDraw. поэтому я сделал следующий Randp randp = new Randp (GameConstants.cardsToDraw); номер устанавливается, когда они выбирают кнопку воспроизведения. но когда я отправляюсь помещать его в объект карты, мне нужно каким-то образом получить значения Randp как int в этом операторе handler.addcard (новая GameCard (i * 90, (GameConstants.CENTER_Y - offsetY), rowOne [i], res)) в месте rowOne [i] –

0

Так я бы справился с этим. Вы бы переместить объекты BufferedImage в список, хотя я бы рассмотреть вопрос о создании объекта для «карт» вы используете ...

int removalAmount = 3; //Remove 3 cards at random... Use a switch to change this based upon difficulty or whatever... 
List<BufferedImage> list = new ArrayList<BufferedImage>(); 
list.addAll(Arrays.asList(card)); // Add the cards to the list, from your array. 
Collections.shuffle(list); 

for (int i = 0; i < removalAmount; i++) { 
    list.remove(list.size() - 1); 
} 

list.addAll(list); 
Collections.shuffle(list); 

for (BufferedImage specificCard : list) { 
    //Do something 
} 
1

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

Вот простой метод для создания уникальных случайных чисел с заданным припуском дублей:

public static void main(String[] args) { 
    int[] randoms = uniqueRandoms(new int[16], 1, 25, 3); 
    for (int r : randoms) System.out.println(r); 
} 

public static int[] uniqueRandoms(int[] randoms, int lo, int hi, int allowance) { 
    // should do some error checking up here 

    int range = hi - lo, duplicates = 0; 
    Random gen = new Random(); 

    for (int i = 0, k; i < randoms.length; i++) { 
     randoms[i] = gen.nextInt(range) + lo; 

     for (k = 0; k < i; k++) { 
      if (randoms[i] == randoms[k]) { 
       if (duplicates < allowance) { 
        duplicates++; 
       } else { 
        i--; 
       } 
       break; 
      } 
     } 
    } 

    return randoms; 
} 

Edit: испытано и исправлены. Теперь это работает. :)

0

Хорошо, я сказал, что дам вам что-то лучшее, и я это сделаю. Во-первых, давайте улучшим решение Джетера.

  1. У этого есть ошибка. Поскольку он полагается на 0 как «использованный» индикатор, он фактически не будет создавать индекс 0 до конца, что не является случайным.
  2. Он заполняет массив индексами, а затем использует 0 как эффективное булево значение, которое является избыточным. Если значение в индексе не равно 0, мы уже знаем, что это такое, это то же самое, что и индекс, который мы использовали для его получения. Он просто скрывает истинную природу алгоритма и делает его излишне сложным.
  3. Он использует рекурсию, когда это не нужно. Конечно, вы можете утверждать, что это улучшает ясность кода, но тогда вы рискуете столкнуться с StackOverflowException слишком большим количеством рекурсивных вызовов.

Таким образом, я представляю улучшенную версию алгоритма:

class Randp { 
    private int MAX_VALUE; 
    private int numsLeft; 
    private boolean[] used; 

    public Randp(int startCounter) { 
     MAX_VALUE = startCounter; 
     numsLeft = startCounter; 

     // All false by default. 
     used = new boolean[MAX_VALUE]; 
    } 

    public int nextInt() { 
     if (numsLeft <= 0) 
      return 0; 
     numsLeft--; 

     int index; 
     do 
     { 
      index = (int)(Math.random() * MAX_VALUE); 
     } while (used[index]); 

     return index; 
    } 
} 

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

class Randp { 
    private ArrayList<Integer> chooser = new ArrayList<Integer>(); 
    private int count = 0; 

    public Randp(int startCounter) { 
     for (int i = 0; i < startCounter; i++) 
      chooser.add(i); 
     Collections.shuffle(chooser); 
    } 

    public int nextInt() { 
     if (count >= chooser.size()) 
      return 0; 
     return chooser.get(count++); 
    } 
} 

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

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