2015-04-19 2 views
1

Я только начинаю с программирования на Java и написал программу для ротации x-сторонних кубиков x-times. Стороны и количество рулонов определяются пользователем. Программа выдает абсолютные и относительные частоты каждого номера в формате JTable. Все работает хорошо, пока вы не выберете большие числа для сторон и количество рулонов. Я получаю ArrayIndexOutOfBoundsException, но не могу найти соответствующие ошибки в коде.Dice Rolling - ArrayIndexOutOfBounds

package rolling; 

import java.awt.*; 
import java.util.*; 
import javax.swing.*; 
import javax.swing.table.TableCellRenderer; 
import javax.swing.JOptionPane; 

public class RollDice extends JPanel { 

    private static final long serialVersionUID = -6332129624300946462L; 
    JTable jt; 
    int i, k, j; //Counter for loops 

    /*========== CONSTRUCTOR CREATES TABLE OBJECT ==========*/ 
    public RollDice(int[] trial, int[] outcomes, int[] dice_numbers, 
    int[] count, float[] Rel_frequencies){ 

     String[] columnNames = {"Number of trial", "Outcome", "Dice Numbers", 
           "Absolute Frequencies", "Relative Frequencies"}; 

     Object[][] input = new Object[trial.length][columnNames.length]; 

     for (i=0; i<trial.length; i++){ 
      input[i][0] = trial[i]; 
     } 
     for (i=0; i<outcomes.length; i++){ 
      input[i][1] = outcomes[i]; 
     } 
     for (i=0; i<dice_numbers.length; i++){ 
      input[i][2] = dice_numbers[i]; 
     } 
     for (i=0; i<count.length; i++){ 
      input[i][3] = count[i]; 
     } 
     for (i=0; i<Rel_frequencies.length; i++){ 
      input[i][4] = Rel_frequencies[i]; 
     } 

     /*Checking the outcome! 
     for (i=0; i<trial.length; i++){ 
      System.out.println(); 
      for (k=0; k<columnNames.length; k++){ 
      System.out.printf("%d\t", input[i][k]); 
      } 
     }*/ 
     jt = new JTable(input,columnNames) 
     { 
      /** 
      * 
      */ 
      private static final long serialVersionUID = 1L; 

      public boolean isCellEditable(int input, int columns) 
      { 
       return false; 
      } 
      public Component prepareRenderer(TableCellRenderer r, int input, 
      int columns){ 
       Component c = super.prepareRenderer(r, input, columns); 

       if (input %2 == 0){ 
        c.setBackground(Color.WHITE); 
       } 
       else{ 
        c.setBackground(Color.LIGHT_GRAY); 
       } 
       if (isCellSelected(input, columns)){ 
        c.setBackground(Color.YELLOW); 
       } 
       return c; 
       } 
     }; 

     jt.setPreferredScrollableViewportSize(new Dimension(450, 600)); 
     jt.setFillsViewportHeight(true); 

     JScrollPane jps = new JScrollPane(jt); 
     add(jps); 
    } 

    public static int[] roll_dice(int sides, int rolls){ 
     int[] outcomes = new int[rolls]; 
     int i; //Counter for accessing array position (element) 
     for (i=0; i<rolls; i++){ 
      outcomes[i] = (int)(1 + Math.random() * sides); 
     } 
     return outcomes; 
    } 

    public static int[] Frequency_count(int[] outcomes, int sides){ 
     int[] count = new int[sides]; 
     int i; 
     int j, k = 0; 
     for(i=1; i<=sides; i++){ 
      for(j=0; j<outcomes.length; j++){ 
       if (outcomes[j] == i){ 
        count[k]++; 
       } 
      } 
      //System.out.printf("%d \t %d\n",i, count[k]); 
      k++; 
     } 
     return count; 
    } 

    public static float[] Relative_frequencies(int[] count, int sides, 
    int rolls){ 
     int i; 
     float[] Array = new float [sides]; 
     for(i=0; i<sides; i++){ 
      Array[i] = (float)count[i]/rolls * 100; 
      //String.format("%.3f", (float)Array[i]); 
      //System.out.printf("%d \t %.2f\n",i+1, Array[i]); 
     } 
     return Array; 
    } 

    public static void main(String[] args) { 
     /*=========USER INPUT via GUI: DECISION ON HOW MANY TIMES 
      THE DICE IS ROLLED===* 
     *=========  AND HOW MANY SIDES THE DICE HAS ===*/ 

     String fn = JOptionPane.showInputDialog("Enter the number of sides 
     of the dice"); 
     String sn = JOptionPane.showInputDialog("Enter the number of rolls"); 

     int sides = Integer.parseInt(fn); // number of sides 
     int rolls = Integer.parseInt(sn); // number of rolls 

     JOptionPane.showMessageDialog(null, "You rolled a " + sides + " 
     sided dice " + rolls + " times!", "User Input", 
     JOptionPane.INFORMATION_MESSAGE); 

     /*=========GENERATING RANDOM NUMBERS (ROLLING THE DICE) WITH 
     "roll_dice" method========== 
     *========= AND COUNTING THE NO. OF TRIALS  ==========*/ 
     int[] outcomes = roll_dice(sides, rolls); 
     int[] trial = new int[rolls]; 
     int[] dice_numbers = new int[sides]; 

     int i, k; 
     k = 1; 
     for(i=0; i<rolls; i++){ 
      trial[i] = k; 
      //System.out.println(i + " " + k); 
      k++; 
     } 
     k = 1; 
     for(i=0; i<sides; i++){ 
      dice_numbers[i] = k; 
      //System.out.println(i + " " + k); 
      k++; 
     } 
     /*=========COUNTING THE FREQUENCIES OF EACH NUMBER==========*/ 
     //System.out.println("ABSOLUTE Frequencies plotted in FUNCTION:"); 
     int[] count = Frequency_count(outcomes, sides); 
     //System.out.println("RELATIVE Frequencies plotted in FUNCTION:"); 
     float[] Rel_frequencies = Relative_frequencies(count, sides, rolls); 


     /*=========CREATING A TABLE FORMAT WITH A JAVA 
     LIBRARY (JTABLE)==========*/ 
     JFrame jf = new JFrame(); 
     RollDice table1 = new RollDice(trial, outcomes, dice_numbers, 
     count, Rel_frequencies); 
     jf.setTitle("Absolute and Relative Frequencies of numbers for 
     an arbitrary Dice"); 
     jf.setSize(500, 700); 
     jf.setVisible(true); 
     jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     jf.add(table1); 
     } 
    } 
+1

В чем номер строки имеет место исключение? –

+0

Когда я ввожу «200» в качестве сторон и «100» для моего количества рулонов я получаю сообщение об ошибке:
** Исключение в потоке «главный»
java.lang.ArrayIndexOutOfBoundsException: 100
\t в rolling.RollDice , (RollDice.java:36)
\t на rolling.RollDice.main (RollDice.java:162) **
Таким образом, ошибка, кажется, несколько связанных с числом рулонов.
Однако я не могу найти ошибок в указанных строках 36 и 162. –

+0

@robby Это сообщение об ошибке: ** Исключение из темы "main" java.lang.ArrayIndexOutOfBoundsException: 100 \t at rolling.RollDice. (RollDice.java:36) \t при прокатке. RollDice.main (RollDice.java:162) ** –

ответ

0

Посмотрите на этот раздел кода здесь:

Object[][] input = new Object[trial.length][columnNames.length]; 

for (i=0; i<trial.length; i++){ 
    input[i][0] = trial[i]; 
} 
for (i=0; i<outcomes.length; i++){ 
    input[i][1] = outcomes[i]; 
} 
for (i=0; i<dice_numbers.length; i++){ 
    input[i][2] = dice_numbers[i]; 
} 
for (i=0; i<count.length; i++){ 
    input[i][3] = count[i]; 
} 
for (i=0; i<Rel_frequencies.length; i++){ 
    input[i][4] = Rel_frequencies[i]; 
} 

У вас есть input 2D массив набор до определенного размера, но тогда доступ к нему без раздумий.

Например, смотрите на это:

int[] trial = new int[rolls]; 
int[] dice_numbers = new int[sides]; 

Скажет, пользователь бросает 2 кубиков для 6-сторон кости (обычные кости). Затем, например, в третьем цикле вы получаете доступ к input[i][2], где i работает от 0 до 5, однако с trial.length = 2 вы получаете доступ к несуществующему индексу.

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

+0

Я думаю, что вы обратились не к основной проблеме кода. Петли for создаются правильно, предоставляя достаточно места для каждого элемента, так как я использовал оператор .length специально для соответствующего массива в каждом цикле. Проблема заключается в том, что, как заметил @RobbyCornelissen, первые два массива «проб» и «результаты» имеют другой размер, как и другие три массива «dice_numbers», «count» и «Rel_frequencies», если пользователь не решит установить «рулоны» 'и' size 'равны. Спасибо за ваш отзыв! –

0

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

Вы инициализируете свои dice_numbers и Relative_Frequencies массивы с длиной, равной количеству сторон, но первое измерение вашего массива input имеет размер только по количеству рулонов.

Затем, следующие фрагменты кода ошибки, потому что вы пытаетесь сохранить значения в позиции за пределами размеров input массива:

for (i=0; i<dice_numbers.length; i++){ 
    input[i][2] = dice_numbers[i]; 
} 
// ... 
for (i=0; i<Rel_frequencies.length; i++){ 
    input[i][4] = Rel_frequencies[i]; 
} 

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

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

Разделение этих двух наборов на два массива и две таблицы данных, вероятно, будет иметь большое значение для решения проблем, с которыми вы сталкиваетесь.

+0

Спасибо, что это полезно! Я не видел этого в первую очередь, хотя это совершенно очевидно. Есть ли возможность создавать нестатические многомерные массивы с гибким размером элемента в Java? –

+0

@StefanStiller 'static' или не -static' в действительности не влияет на него. Строго говоря, в Java нет массивов с гибкой длиной. Вероятно, вы захотите начать изучать коллекции Java. –