I've been working on this game for a couple weeks now as a purely personal project to help myself learn Java.   I'd like to know if I'm on the right track with my project.Items I'd like specific feedback on:GridBagLayout - I think I'm working this out okay?Classes - Do I need to break parts of this up into other pieces?Because the numbers could potentially increment past Integer values, I was advised to use BigInteger. The way that I did that, is that good practice?Any other suggestions are welcomed. I look forward to what you have to say. package DamageDealer;import javax.swing.*;import java.awt.*;import java.awt.GridBagLayout;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;import java.io.*;import java.math.*;import java.util.ArrayList;public class Take1 {    //Constants    //Variables and conversions from string to big integer for math purposes    int intBIResult = 0; //Used for BigInteger comparisons    String stringConstantOne = 1;    String stringConstantTen = 10;    String stringConstantHundred = 100;    String stringConstantThousand = 1000;    String stringConstantTenThousand = 10000;    String stringConstantHundredThousand = 100000;    BigInteger biConstantOne = new BigInteger(stringConstantOne);    BigInteger biConstantTen = new BigInteger(stringConstantTen);    BigInteger biConstantHundred = new BigInteger(stringConstantHundred);    BigInteger biConstantThousand = new BigInteger(stringConstantThousand);    BigInteger biConstantTenThousand = new BigInteger(stringConstantTenThousand);    BigInteger biConstantHundredThousand = new BigInteger(stringConstantHundredThousand);    //Point variables    //Values and conversions from string to big integer    String stringDamageOutput = 0;    String stringEPoints = 0;    String stringNewEPoints = 0;    String stringSpentEPoints = 0;    int intTotalClicks = 0;    BigInteger biDamageOutput = new BigInteger(stringDamageOutput);    BigInteger biEPoints = new BigInteger(stringEPoints);    BigInteger biNewEPoints = new BigInteger(stringNewEPoints);    BigInteger biSpentEPoints = new BigInteger(stringSpentEPoints);    //Unit variables    //Values and conversions from string to big integer     String stringUnit1 = 0;    String stringUnit2 = 0;    String stringUnit3 = 0;    String stringUnit4 = 0;    String stringUnit5 = 0;    BigInteger biUnit1 = new BigInteger(stringUnit1);    BigInteger biUnit2 = new BigInteger(stringUnit2);    BigInteger biUnit3 = new BigInteger(stringUnit3);    BigInteger biUnit4 = new BigInteger(stringUnit4);    BigInteger biUnit5 = new BigInteger(stringUnit5);    public static void main(String[] args) {        new Take1();    }    public Take1() {        javax.swing.SwingUtilities.invokeLater(new Runnable() {            @Override            public void run() {                Object[] atStartMessage = {New Game, Continue Game};                JPanel atStartMessagePanel = new JPanel();                atStartMessagePanel.add(new JLabel(Would you like to start a new game or continue an existing game?));                int result = JOptionPane.showOptionDialog(null, atStartMessagePanel, New Game?, JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE, null, atStartMessage, null);                if (result == JOptionPane.YES_OPTION) {                    //If yes selected for New Game? message, alert with warning to confirm new game!                    JPanel atStartNewGameMessagePanel = new JPanel();                    atStartNewGameMessagePanel.add(new JLabel(This will delete any currently saved data! Do you want to continue?));                    int result2 = JOptionPane.showConfirmDialog(null, atStartNewGameMessagePanel, Warning!, JOptionPane.YES_NO_OPTION);                    if (result2 == JOptionPane.YES_OPTION) {                        //If yes selected for Warning! message, start new game. Will not load saved data.                    } else if (result2 == JOptionPane.NO_OPTION) {                        //If no selected for Warning! message, load saved data.                        File saveFile = new File(res/saved_game_data.txt);                        if(saveFile.exists() && !saveFile.isDirectory()) {                         loadGameData();                        }                    } else {                        //If neither selected for Warning! message, load saved data.                        File saveFile = new File(res/saved_game_data.txt);                        if(saveFile.exists() && !saveFile.isDirectory()) {                         loadGameData();                        }                    }                } else if (result == JOptionPane.NO_OPTION) {                    //If no selected for New Game? message, then load game data.                     File saveFile = new File(res/saved_game_data.txt);                    if(saveFile.exists() && !saveFile.isDirectory()) {                     loadGameData();                    }                } else {                    //If neither selected for New Game? message, then load game data.                    File saveFile = new File(res/saved_game_data.txt);                    if(saveFile.exists() && !saveFile.isDirectory()) {                     loadGameData();                    }                }                try {                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); }                catch (UnsupportedLookAndFeelException ex) {                    ex.printStackTrace(); }                catch (IllegalAccessException ex) {                    ex.printStackTrace(); }                catch (InstantiationException ex) {                    ex.printStackTrace(); }                catch (ClassNotFoundException ex) {                    ex.printStackTrace(); }                JFrame frame = new JFrame(Button Clicker);                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);                frame.getContentPane().add(new addComponentsToPane());                frame.setSize(300, 500);                frame.setLocationRelativeTo(null);                frame.setVisible(true);                frame.setResizable(false);                //Save data at close                frame.addWindowListener(new WindowAdapter() {                    public void windowClosing(WindowEvent e) {                        BufferedWriter writerOut = null;                        try{                            // Create file                             writerOut = new BufferedWriter(new FileWriter(res/saved_game_data.txt));                            //Write data                            writerOut.write(String.valueOf(biDamageOutput) + \r\n +                                     String.valueOf(biEPoints) + \r\n +                                     String.valueOf(biNewEPoints) + \r\n +                                     String.valueOf(biSpentEPoints) + \r\n +                                     String.valueOf(biUnit1) + \r\n +                                     String.valueOf(biUnit2) + \r\n +                                     String.valueOf(biUnit3) + \r\n +                                     String.valueOf(biUnit4) + \r\n +                                     String.valueOf(biUnit5) + \r\n +                                     String.valueOf(intTotalClicks));                            //Close output stream                            writerOut.close();                            }catch (Exception e1){//Catch exception if any                              System.err.println(Error:  + e1.getMessage());                            }                    }                });            }            //Load Game Data            void loadGameData() {                try{                    FileInputStream fileStream = new FileInputStream(res/saved_game_data.txt);                    DataInputStream dataIn = new DataInputStream(fileStream);                    BufferedReader br = new BufferedReader(new InputStreamReader(dataIn));                    String strLine;                    ArrayList<String> savedData = new ArrayList<String>();                    while ((strLine = br.readLine()) != null) {                        savedData.add(strLine);                    }                    //System.out.println lines below used for testing purposes                    /*System.out.println(First line =  + savedData.get(0));                    System.out.println(Second line =  + savedData.get(1));                    System.out.println(Third line =  + savedData.get(2));                    System.out.println(Fourth line =  + savedData.get(3));                    System.out.println(Fifth line =  + savedData.get(4));                    System.out.println(Sixth line =  + savedData.get(5));                    System.out.println(Seventh line =  + savedData.get(6));                    System.out.println(Eighth line =  + savedData.get(7));                    System.out.println(Ninth line =  + savedData.get(8));                    System.out.println(Tenth line =  + savedData.get(9));*/                    biDamageOutput = new BigInteger(savedData.get(0));                    biEPoints = new BigInteger(savedData.get(1));                    biNewEPoints = new BigInteger(savedData.get(2));                    biSpentEPoints = new BigInteger(savedData.get(3));                    biUnit1 = new BigInteger(savedData.get(4));                    biUnit2 = new BigInteger(savedData.get(5));                    biUnit3 = new BigInteger(savedData.get(6));                    biUnit4 = new BigInteger(savedData.get(7));                    biUnit5 = new BigInteger(savedData.get(8));                    intTotalClicks = Integer.parseInt(savedData.get(9));                    dataIn.close();                }catch(Exception e1) {                    System.err.println(Error:  + e1.getMessage());                }            }        });    }       protected class addComponentsToPane extends JPanel {        /**         *          */        private static final long serialVersionUID = 1L;        public addComponentsToPane() {            JPanel appPanel = new JPanel(new GridBagLayout());            GridBagConstraints gbc = new GridBagConstraints();                   gbc.fill = GridBagConstraints.HORIZONTAL;            gbc.anchor = GridBagConstraints.CENTER;            gbc.insets = new Insets(5, 5, 5, 5);            /*            //Labels and buttons are coded based on grid, starting at (0,0) going to (1,10)            */            JLabel lblPointsText = new JLabel(Points: , JLabel.RIGHT);            //setBorder below used for testing purposes            //lblPointsText.setBorder(BorderFactory.createLineBorder(Color.black));            gbc.gridx = 0;            gbc.gridy = 0;            appPanel.add(lblPointsText, gbc);            JLabel lblEPointsValue = new JLabel(String.valueOf(biEPoints), JLabel.CENTER);            lblEPointsValue.setPreferredSize(new Dimension(100, 15));            //setBorder below used for testing purposes            //lblEPointsValue.setBorder(BorderFactory.createLineBorder(Color.black));            gbc.gridx = 1;            gbc.gridy = 0;            appPanel.add(lblEPointsValue, gbc);            JButton btnUnit1 = new JButton(new ImageIcon(res/a.knife.png));            btnUnit1.setBorder(BorderFactory.createEmptyBorder());            btnUnit1.setContentAreaFilled(false);            gbc.gridx = 0;            gbc.gridy = 1;            appPanel.add(btnUnit1, gbc);            JLabel lblUnit1 = new JLabel(String.valueOf(biUnit1), JLabel.CENTER);            gbc.gridx = 1;            gbc.gridy = 1;            appPanel.add(lblUnit1, gbc);            JLabel lblUnit1Description = new JLabel(<html>Cost: 10 Points<br>Damage: +1);            gbc.gridx = 2;            gbc.gridy = 1;            appPanel.add(lblUnit1Description, gbc);            JButton btnUnit2 = new JButton(new ImageIcon(res/b.pistol.png));            btnUnit2.setBorder(BorderFactory.createEmptyBorder());            btnUnit2.setContentAreaFilled(false);            gbc.gridx = 0;            gbc.gridy = 2;            appPanel.add(btnUnit2, gbc);            JLabel lblUnit2 = new JLabel(String.valueOf(biUnit2), JLabel.CENTER);            gbc.gridx = 1;            gbc.gridy = 2;            appPanel.add(lblUnit2, gbc);            JLabel lblUnit2Description = new JLabel(<html>Cost: 100 Points<br>Damage: +10);            gbc.gridx = 2;            gbc.gridy = 2;            appPanel.add(lblUnit2Description, gbc);            JButton btnUnit3 = new JButton(new ImageIcon(images/c.shotgun.png));            btnUnit3.setBorder(BorderFactory.createEmptyBorder());            btnUnit3.setContentAreaFilled(false);            gbc.gridx = 0;            gbc.gridy = 3;            appPanel.add(btnUnit3, gbc);            JLabel lblUnit3 = new JLabel(String.valueOf(biUnit3), JLabel.CENTER);            gbc.gridx = 1;            gbc.gridy = 3;            appPanel.add(lblUnit3, gbc);            JLabel lblUnit3Description = new JLabel(<html>Cost: 1000 Points<br>Damage: +100);            gbc.gridx = 2;            gbc.gridy = 3;            appPanel.add(lblUnit3Description, gbc);            JButton btnUnit4 = new JButton(new ImageIcon(images/d.rifle.png));            btnUnit4.setBorder(BorderFactory.createEmptyBorder());            btnUnit4.setContentAreaFilled(false);            gbc.gridx = 0;            gbc.gridy = 4;            appPanel.add(btnUnit4, gbc);            JLabel lblUnit4 = new JLabel(String.valueOf(biUnit4), JLabel.CENTER);            gbc.gridx = 1;            gbc.gridy = 4;            appPanel.add(lblUnit4, gbc);            JLabel lblUnit4Description = new JLabel(<html>Cost: 10000 Points<br>Damage: +1000);            gbc.gridx = 2;            gbc.gridy = 4;            appPanel.add(lblUnit4Description, gbc);            JButton btnUnit5 = new JButton(new ImageIcon(images/e.rlauncher.png));            btnUnit5.setBorder(BorderFactory.createEmptyBorder());            btnUnit5.setContentAreaFilled(false);            gbc.gridx = 0;            gbc.gridy = 5;            appPanel.add(btnUnit5, gbc);            JLabel lblUnit5 = new JLabel(String.valueOf(biUnit5), JLabel.CENTER);            gbc.gridx = 1;            gbc.gridy = 5;            appPanel.add(lblUnit5, gbc);            JLabel lblUnit5Description = new JLabel(<html>Cost: 100000 Points<br>Damage: +10000);            gbc.gridx = 2;            gbc.gridy = 5;            appPanel.add(lblUnit5Description, gbc);            JButton btnDamage = new JButton(Damage);                                  gbc.gridx = 0;            gbc.gridy = 10;            appPanel.add(btnDamage, gbc);            JLabel DamageOutput = new JLabel(String.valueOf(biDamageOutput), JLabel.CENTER);            gbc.gridx = 1;            gbc.gridy = 10;            appPanel.add(DamageOutput, gbc);            JLabel TotalClicks = new JLabel(Total Clicks:  + intTotalClicks);            gbc.gridx = 1;            gbc.gridy = 11;            appPanel.add(TotalClicks, gbc);            add(appPanel, gbc);            btnDamage.addActionListener(new ActionListener() {                public void actionPerformed(ActionEvent e) {                    intBIResult = 0;                    intBIResult = biUnit5.compareTo(biConstantOne);                    if (intBIResult == 0 || intBIResult == 1) {                        biDamageOutput = biDamageOutput.add(biUnit1.add(biConstantOne));                        biDamageOutput = biDamageOutput.add(biUnit2.multiply(biConstantTen));                        biDamageOutput = biDamageOutput.add(biUnit3.multiply(biConstantHundred));                        biDamageOutput = biDamageOutput.add(biUnit4.multiply(biConstantThousand));                        biDamageOutput = biDamageOutput.add(biUnit5.multiply(biConstantTenThousand));                                           } else {                        intBIResult = 0;                        intBIResult = biUnit4.compareTo(biConstantOne);                        if (intBIResult == 0 || intBIResult == 1) {                            biDamageOutput = biDamageOutput.add(biUnit1.add(biConstantOne));                            biDamageOutput = biDamageOutput.add(biUnit2.multiply(biConstantTen));                            biDamageOutput = biDamageOutput.add(biUnit3.multiply(biConstantHundred));                            biDamageOutput = biDamageOutput.add(biUnit4.multiply(biConstantThousand));                        } else {                            intBIResult = 0;                            intBIResult = biUnit3.compareTo(biConstantOne);                            if (intBIResult == 0 || intBIResult == 1) {                                biDamageOutput = biDamageOutput.add(biUnit1.add(biConstantOne));                                biDamageOutput = biDamageOutput.add(biUnit2.multiply(biConstantTen));                                biDamageOutput = biDamageOutput.add(biUnit3.multiply(biConstantHundred));                            } else {                                intBIResult = 0;                                intBIResult = biUnit2.compareTo(biConstantOne);                                if (intBIResult == 0 || intBIResult == 1) {                                    biDamageOutput = biDamageOutput.add(biUnit1.add(biConstantOne));                                    biDamageOutput = biDamageOutput.add(biUnit2.multiply(biConstantTen));                                } else {                                    biDamageOutput = biDamageOutput.add(biUnit1.add(biConstantOne));                                }                            }                        }                    };                    DamageOutput.setText(String.valueOf(biDamageOutput));                    biNewEPoints = (biDamageOutput.divide(biConstantTen).subtract(biSpentEPoints));                    if(biEPoints != biNewEPoints) {                        lblEPointsValue.setText(String.valueOf(biNewEPoints));                    }                     biEPoints = biNewEPoints;                    intTotalClicks++;                    TotalClicks.setText(Total Clicks:  + intTotalClicks);                }            });            //Cost = 10 Points            //Damage +1            btnUnit1.addActionListener(new ActionListener() {                public void actionPerformed(ActionEvent e) {                    intBIResult = 0;                    intBIResult = biEPoints.compareTo(biConstantTen);                    if (intBIResult == 0 || intBIResult == 1) {                        biUnit1 = biUnit1.add(biConstantOne);                        biEPoints = biEPoints.subtract(biConstantTen);                        biSpentEPoints = biSpentEPoints.add(biConstantTen);                        lblUnit1.setText(String.valueOf(biUnit1));                        lblEPointsValue.setText(String.valueOf(biEPoints));                    }                }            });            //Cost = 100 Points            //Damage +10            btnUnit2.addActionListener(new ActionListener() {                public void actionPerformed(ActionEvent e) {                    intBIResult = 0;                    intBIResult = biEPoints.compareTo(biConstantHundred);                    if (intBIResult == 0 || intBIResult == 1) {                        biUnit2 = biUnit2.add(biConstantOne);                        biEPoints = biEPoints.subtract(biConstantHundred);                        biSpentEPoints = biSpentEPoints.add(biConstantHundred);                        lblUnit2.setText(String.valueOf(biUnit2));                        lblEPointsValue.setText(String.valueOf(biEPoints));                    }                }            });            //Cost = 1,000 Points            //Damage +100            btnUnit3.addActionListener(new ActionListener() {                public void actionPerformed(ActionEvent e) {                    intBIResult = 0;                    intBIResult = biEPoints.compareTo(biConstantThousand);                    if (intBIResult == 0 || intBIResult == 1) {                        biUnit3 = biUnit3.add(biConstantOne);                        biEPoints = biEPoints.subtract(biConstantThousand);                        biSpentEPoints = biSpentEPoints.add(biConstantThousand);                        lblUnit3.setText(String.valueOf(biUnit3));                        lblEPointsValue.setText(String.valueOf(biEPoints));                    }                }            });            //Cost = 10,000 Points            //Damage +1,000            btnUnit4.addActionListener(new ActionListener() {                public void actionPerformed(ActionEvent e) {                    intBIResult = 0;                    intBIResult = biEPoints.compareTo(biConstantTenThousand);                    if (intBIResult == 0 || intBIResult == 1) {                        biUnit4 = biUnit4.add(biConstantOne);                        biEPoints = biEPoints.subtract(biConstantTenThousand);                        biSpentEPoints = biSpentEPoints.add(biConstantTenThousand);                        lblUnit4.setText(String.valueOf(biUnit4));                        lblEPointsValue.setText(String.valueOf(biEPoints));                    }                }            });            //Cost = 100,000 Points            //Damage +10,000            btnUnit5.addActionListener(new ActionListener() {                public void actionPerformed(ActionEvent e) {                    intBIResult = 0;                    intBIResult = biEPoints.compareTo(biConstantHundredThousand);                    if (intBIResult == 0 || intBIResult == 1) {                        biUnit5 = biUnit5.add(biConstantOne);                        biEPoints = biEPoints.subtract(biConstantHundredThousand);                        biSpentEPoints = biSpentEPoints.add(biConstantHundredThousand);                        lblUnit5.setText(String.valueOf(biUnit5));                        lblEPointsValue.setText(String.valueOf(biEPoints));                    }                }            });        }              }}
Button-clicking UI for a game
java;beginner;swing;layout
I haven't worked with Java in a long time, so I can't say much about language-specific issues or whether your use of AWT makes sense. But here is what I can say:ConstantsYou've got several 'constants' there, several of which (the strings) are only used to initialize other 'constants'. The extra indirection makes your code harder to read. Also, constant names are usually written in UPPERCASE, and they're normally marked as public static final - static, because you don't need a copy for each instance of your class, and final, because you don't want constants to change.So just write public static final BigInteger THOUSAND = new BigInteger(1000);. Note that you can also make use of a few existing BigInteger constants: BigInteger.ZERO, BigInteger.ONE and BigInteger.TEN.There's another problem with those constants however: they are actually used as the prices of units, so either their names are misleading or their use is incorrect.The load and save data code repeats the savegame filename several times - this is where a constant may actually be useful (assuming you don't plan on supporting multiple savegame slots).Take1 classTake1 is an undescriptive name. Game may be a better name, but it depends on what its intended purpose is.A constructor that's starting a thread, with important game-related functionality stuffed in an anonymous class is... peculiar. Constructors should generally not have side-effects - their purpose is to initialize an object. I would move that code to a StartGame method, which can then be called from main.run is doing too much: it's asking whether the user wants to start a new game or load an existing game, it's also starting the game, and finally it's saving the game. Those are 3 separate things that each deserve their own method. This helps keeping your code manageable.Your dialog result handling code contains the same load-game code 4 times. It can be rewritten to only contain that code once. For example, the else if (result == JOptionPane.NO_OPTION) and else clauses are doing the same thing, so the else if clause can safely be removed.You do have a loadGameData method. Why is there no matching saveGameData method? And why are these important methods located in an anonymous class? This sort of thing makes code hard to reuse and test.addComponentsToPane classThe game logic is heavily intertwined with UI-related code. It's hard to determine how the game works from just looking at this code. Again, the class name is undescriptive - it actually contains both game-logic and UI code, but the name only suggests the latter.The btnDamage click handler contains a lot of duplicated code. The nested if-else statements can be replaced with a few if statements:if (unit1Count.compareTo(BigInteger.ZERO) > 0) {    damage = damage.add(unit1Count.multiply(unit1Damage));}if (unit2Count.compareTo(BigInteger.ZERO) > 0) {    damage = damage.add(unit2Count.multiply(unit2Damage));}// And so on.Actually, you don't even need those if checks - multiplying by 0 produces 0, which can safely be added without affecting how much damage is dealt.You can also split this up into a 'total damage done so far' and a 'damage per click' variable. Clicking simply increments the total damage by the damage per click, while damage per click is increased after purchasing a unit.This can be improved further by using an array of units. At this point it's useful to create a Unit class that stores the name, cost, damage and count of a unit. This is the kind of data that you'll be modifying when you're balancing your game or when you're adding new unit types, so it helps if it's all in one place (For larger games, this sort of data is often stored in files, so game designers can modify it without the programmers having to recompile the game.):units = new Unit[] {    // Unit(string name, string image, BigInteger cost, BigInteger damage)    new Unit(knife, res/a.knife.png, TEN, ONE),    new Unit(pistol, res/b.pistol.png, HUNDRED, TEN),    // And so on}With an array or list of units, calculating damage can be done with a simple for loop. The same goes for creating unit purchase buttons and labels - a lot of repetitive code can be simplified there:for (Unit unit : units){    // The code here is executed once for each unit in the units list,    // so you can create a label and purchase button for each unit here.    // Also, rather than duplicating cost and damage in html strings,    // refer to unit properties instead (unit.cost, unit.damage, and so on)    // to build these html strings.}Other notesVariable names should be descriptive, they should help you (and others) understand what the code does. biUnit1 isn't very clear. unit1Count or numberOfUnit1Purchased would be better.Type prefixes (hungarian notation) are redundant. The declaration already tells you what type something is, and a modern-day IDE will also tell you when you hover over a variable name. I suppose it can be useful if you're just getting started though.intBIResult should not be a member variable - just declare a local variable inside each action listener method. You normally want to limit the scope of variables as much as possible. In this case however you don't even need a local variable. The following will do just fine:if (biUnit1.compareTo(biConstantOne) >= 0)The same goes for biNewEPoints - it's only used in a single method, and is derived from other variables, so it shouldn't be a member variable, nor does it need to be saved or loaded.