骰子滚动 - ArrayIndexOutOfBounds

时间:2015-04-19 11:53:57

标签: java arrays swing

我刚刚开始使用Java编程并编写了一个程序,用于滚动x-sided骰子x次。侧面和卷数由用户输入定义。该程序以JTable格式给出每个数字的绝对和相对频率。一切都运作良好,直到您选择大量的侧面和卷数。我收到ArrayIndexOutOfBoundsException但无法在代码中找到任何相应的错误。

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);
        }
    }

2 个答案:

答案 0 :(得分: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开始,您正在访问不存在的索引。

你应该检查你的代码,这样你只能在初始化期间根据边界来访问你的数组(我不知道你的任务是否足以尝试并提出更好的建议)。

答案 1 :(得分:0)

如果你有更多的方面而不是卷,你似乎总会遇到这个问题。

您初始化dice_numbersRelative_Frequencies数组,其长度等于边数,但input数组的第一个维度仅根据卷数确定。< / p>

然后,由于您试图将值存储在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数组标注为更高的数字:边数或掷骰数。

然而,您的程序的概念性问题似乎是您尝试在同一个数组中存储两个不同的数据集,即一组关于实际滚动及其结果的数据,以及一组数据关于双方的频率分布。

将这两个分组分成两个数组和两个数据表可能会大大有助于解决您所面临的问题。