What is a Java snake cookie clicker?

1.6K    Asked by JosephSlater in Java , Asked on Oct 11, 2022

This is my first graphical application I have made in my life (except HTML and Javascript-Applications, if that counts). It's a simple implementation of Cookie Clicker, the famous browser game. Unfortunately the size of the buttons equals the size of columns. That does not look good. I have seen a solution that uses two layouts. A GridLayout, and an additional FlotLayout. But the code looks so ugly, that I don't want to use this way of programming.


I would be very thankful if you have tips for me on how to improve the code quality! Programming a graphical application is much harder and more complex than writing textual applications.


import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class CookieClicker extends JFrame {
    // non graphical variables
    private int cookies = 0;
    private int clicker = 1;
    private int clickerPrice = 20;
    // graphical variables
    int numberOfColumns = 5;
    Container container;
    JLabel cookieLabel;
    JButton increaseCookiesButton;
    JLabel clickerLabel;
    JButton increaseClickerButton;
    // buildings
    Building bakery;
    boolean bakeryUnlocked;
    Building robot;
    boolean robotUnlocked;
    Building factory;
    boolean factoryUnlocked;
    public CookieClicker() {
        container = getContentPane();
        container.setLayout(new GridLayout(5, 1));
        bakery = new Building("Bakery", 0, 1, 20);
        bakeryUnlocked = false;
        robot = new Building("Robot", 0, 5, 100);
        robotUnlocked = false;
        factory = new Building("Factory", 0, 10, 200);
        factoryUnlocked = false;
        // produce cookies by hand
        cookieLabel = new JLabel("Cookies: " + cookies);
        increaseCookiesButton = new JButton("Increase Cookies");
        increaseCookiesButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                cookies += clicker;
            }
        });
        // improve clicking production rate
        clickerLabel = new JLabel("Clicker Level: " + clicker);
        increaseClickerButton = new JButton("Improve Clicker (Costs: " + clickerPrice + ")");
        increaseClickerButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                increaseClicker();
            }
            private void increaseClicker() {
                if(cookies >= clickerPrice) {
                    clicker++;
                    cookies -= clickerPrice;
                    clickerPrice *= 2;
                    JOptionPane.showMessageDialog(null, "You have improved your clicker!");
                } else {
                    JOptionPane.showMessageDialog(null, "You have not enough money!");
                }
            }
        });
        java.util.Timer actualizeProgress = new java.util.Timer();
        actualizeProgress.scheduleAtFixedRate(new TimerTask() {
            public void run() {
                cookieLabel.setText("Cookies: " + cookies);
                clickerLabel.setText("Clicker Level: " + clicker);
                increaseClickerButton.setText("Improve Clicker (Costs: " + clickerPrice + ")");
            }
        }, 0, 25);
        java.util.Timer getMoreBuildings = new java.util.Timer(); 
        getMoreBuildings.scheduleAtFixedRate(new TimerTask() {
            public void run() {
                if (bakeryUnlocked == false && clicker >= 2) {
                    bakery.unlock();
                    bakeryUnlocked = true;
                }
                if (robotUnlocked == false && bakery.getLevel() >= 2) {
                    robot.unlock();
                    robotUnlocked = true;
                }         
                if (factoryUnlocked == false && robot.getLevel() >= 2) {
                    factory.unlock();
                    factoryUnlocked = true;
                }
            }
        }, 0, 2000);
        java.util.Timer produceWithBuildings = new java.util.Timer();
        produceWithBuildings.scheduleAtFixedRate(new TimerTask() {
            public void run() {
                cookies += bakery.getProductionRate() + robot.getProductionRate() + factory.getProductionRate();
            }
        }, 0, 1000);
        container.add(cookieLabel);
        container.add(increaseCookiesButton);
        container.add(new JLabel("")); // blank label
        container.add(clickerLabel);
        container.add(increaseClickerButton);
    }
    public class Building {
        // non graphical variables
        private String name;
        private int level;
        private int productionRate;
        private int costs;
        // graphical variables
        JLabel label;
        JButton button;
        public Building(String name, int level, int productionRate, int costs) {
            // non graphical variables
            this.name = name;
            this.level = level;
            this.productionRate = productionRate;
            this.costs = costs;
            // graphical variables
            label = new JLabel();
            button = new JButton();
            button.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    improve();
                }
            });
        }
        public int getLevel() {
            return level;
        }
        public void unlock() {
            numberOfColumns += 3;
            container.setLayout(new GridLayout(numberOfColumns, 1));
            container.add(new JLabel(""));
            container.add(label);
            container.add(button);
            setSize(210, getHeight() + 120);
            actualize();
        }
        public void improve() {
            if(cookies >= costs) {
                level++;
                cookies -= costs;
                costs *= 2;
                JOptionPane.showMessageDialog(null, "You have improved the " + name + "!");
            } else {
                JOptionPane.showMessageDialog(null, "You have not enough money!");
            }
            actualize();
        }
        public int getProductionRate() {
            return productionRate * level;
        }
        public void actualize() {
            label.setText(name + " Prod. Rate: " + getProductionRate());
            button.setText("Improve (costs: " + costs + ")");
        }
    }
    public static void main(String[] args) {
        CookieClicker cookieClicker = new CookieClicker();
        cookieClicker.setTitle("Cookie Clicker");
        cookieClicker.setSize(210, 200);
        cookieClicker.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        cookieClicker.setVisible(true);
    }
}


I made some edits to your code for fun!


Check this link: https://drive.google.com/file/d/1BBblZPIUScPtr5kTHi0YAjA3phoeR2Gj/view?usp=sharing

The above link contains the whole project folder for the game. Note that this game needs images in a folder called Images and an audio file in a folder called Audio. The code for the game Java Snake Cookie Clicker is written below.

import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.io.File; //This library is used to search for the audio file in the game
import java.io.IOException; //This library is used when exceptions or errors occur while using the File library.
import javax.sound.sampled.*; //This library is especially needed when dealing with audio in this program.
//The above three libraries have to be imported for the music in the game.
import javax.swing.*;
public class CookieClicker extends JFrame {
    // non graphical variables
    private int cookies = 0;
    private int clicker = 1;
    private int clickerPrice = 20;
    //These two variables are used to dictate the size of the JFrame.
    private static int screenWidth=420;
    private static int screenHeight=400;
    private final static Font FONT=new Font("Serif", Font.BOLD, 14); //The fonts of most texts are set to this font. This is a bold Serif 14 font.
    private final static Colour WINDOW_COLOR=new Colour(125,125,125); //This grey colour is applied to the windows in the game.
    private final static Colour LABEL_COLOR= new Colour(0, 102, 0) ; //This green colour is applied to the labels.
    private final static Colour BUTTON_COLOR=new Colour(153,0,0); //This red colour is applied to the buttons.
    // graphical variables
    int numberOfColumns = 7;
    Container container;
    JLabel cookieLabel;
    JButton increaseCookiesButton;
    JLabel clickerLabel;
    JButton increaseClickerButton;
    // buildings
    Building bakery;
    boolean bakeryUnlocked;
    Building robot;
    boolean robotUnlocked;
    Building factory;
    boolean factoryUnlocked;
    //This image of a notification is used
    public static ImageIcon notification=new ImageIcon("Images/notification.jpg");
    public CookieClicker() {
        container = getContentPane();
        /**The first parameter of GridLayout is set to the variable numberOfColumns, which is equal to 7.
         * 7 columns is needed for the beginning of the game.
         */
        container.setLayout(new GridLayout(numberOfColumns, 1));
        container.setBackground(WINDOW_COLOR); //The container's background colour is set to the window colour.
        bakery = new Building("Bakery", 0, 1, 20, "Images/bakery.jpg");
        bakeryUnlocked = false;
        robot = new Building("Robot", 0, 5, 100, "Images/robot.jpg");
        robotUnlocked = false;
        factory = new Building("Factory", 0, 10, 200, "Images/factory.jpg");
        factoryUnlocked = false;
        // produce cookies by hand
        cookieLabel = new JLabel("Cookies: " + cookies);
        cookieLabel.setForeground(LABEL_COLOR);//The label's colour is set to the variable LABEL_COLOR.
        cookieLabel.setFont(FONT); //The label's font is set to the variable FONT.
        increaseCookiesButton=new JButton(new ImageIcon("Images/cookie.jpg"));
        /**The button's foreground colour is set to the variable BUTTON_COLOR.
         * Due to this, the button's text is the same as the colour of BUTTON_COLOR.
         * BUTTON_COLOR is a red colour, so the button's text is red.
         */
        increaseCookiesButton.setForeground(BUTTON_COLOR);
        //The text of the button is set to "Increase cookies".
        increaseCookiesButton.setText("Increase cookies");
        //The button's font is set to the variable FONT.
        increaseCookiesButton.setFont(FONT);
        //By putting the increaseCookiesButton into the first parameter of the function, this button's background aspects will be hidden.
        transparentBackground(increaseCookiesButton);
        increaseCookiesButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                cookies += clicker;
            }
        });
        // improve clicking production rate
        clickerLabel = new JLabel("Clicker Level: " + clicker);
        clickerLabel.setForeground(LABEL_COLOR);
        ImageIcon clickerIcon=new ImageIcon("Images/clicker.jpg");
        //The label's font is set to the variable FONT.
        clickerLabel.setFont(FONT);
        increaseClickerButton = new JButton(clickerIcon);
        /**The button's foreground colour is set to the variable BUTTON_COLOR.
         * Due to this, the button's text is the same as the colour of BUTTON_COLOR.
         * BUTTON_COLOR is a red colour, so the button's text is red.
         */
        increaseClickerButton.setForeground(BUTTON_COLOR);
        //By putting the increaseClickerButton into the first parameter of the function, this button's background aspects will be hidden.
        transparentBackground(increaseClickerButton);
        //The button's font is set to the variable FONT.
        increaseClickerButton.setFont(FONT);
        increaseClickerButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                increaseClicker();
            }
            private void increaseClicker() {
                /** This label is used to display a message to the user in the JOptionPane.
                 * The label's font is set to the variable FONT and the text colour, or foreground colour, of the label is set to the
                 * variable LABEL_COLOR.
                 */
                JLabel notificationLabel=new JLabel("");
                notificationLabel.setFont(FONT);
                notificationLabel.setForeground(LABEL_COLOR);
                if(cookies >= clickerPrice) {
                    clicker+;
                    cookies -= clickerPrice;
                    clickerPrice *= 2;
                    //The label's text is set to "You have improved your clicker!".
                    notificationLabel.setText("You have improved your clicker!");
                    /**The JOptionPane displays the notificationLabel in a plain message format.
                     *The title of the window is Notification and an image of a notification is shown.
                     */
                    JOptionPane.showMessageDialog(null, notificationLabel, "Notification", JOptionPane.PLAIN_MESSAGE, notification);
                } else {
                     //The label's text is set to "You do not have enough money!".
                    notificationLabel.setText("You do not have enough money!");
                    /**The JOptionPane displays the notificationLabel in a plain message format.
                     *The title of the window is Notification and an image of a notification is shown.
                     */
                    JOptionPane.showMessageDialog(null, notificationLabel, "Notification", JOptionPane.PLAIN_MESSAGE, notification);
                }
            }
        });
        java.util.Timer actualize Progress = new java.util.Timer();
        actualizeProgress.scheduleAtFixedRate(new TimerTask() {
            public void run() {
                cookieLabel.setText("Cookies: " + cookies);
                clickerLabel.setText("Clicker Level: " + clicker);
                increaseClickerButton.setText("Improve Clicker (Costs: " + clickerPrice + ")");
            }
        }, 0, 25);
        java.util.Timer getMoreBuildings = new java.util.Timer();
        getMoreBuildings.scheduleAtFixedRate(new TimerTask() {
            public void run() {
                if (bakeryUnlocked == false && clicker >= 2) {
                    bakery.unlock();
                    bakeryUnlocked = true;
                }
                if (robotUnlocked == false && bakery.getLevel() >= 2) {
                    robot.unlock();
                    robotUnlocked = true;
                }
                if (factoryUnlocked == false && robot.getLevel() >= 2) {
                    factory.unlock();
                    factoryUnlocked = true;
                }
            }
        }, 0, 2000);
        java.util.Timer produceWithBuildings = new java.util.Timer();
        produceWithBuildings.scheduleAtFixedRate(new TimerTask() {
            public void run() {
                cookies += bakery.getProductionRate() + robot.getProductionRate() + factory.getProductionRate();
            }
        }, 0, 1000);
        container.add(cookieLabel);
        container.add(increaseCookiesButton);
        container.add(new JLabel("")); // blank label
        container.add(clickerLabel);
        container.add(increaseClickerButton);
    }
    public class Building {
        // non graphical variables
        private String name;
        private int level;
        private int productionRate;
        private int costs;
        // graphical variables
        JLabel label;
        JButton button;
        ImageIcon icon; //This icon is applied to the button
       //The parameter iconName is equal to the location of an image in the files.
        public Building(String name, int level, int productionRate, int costs, String iconName) {
            // non graphical variables
            this.name = name;
            this.level = level;
            this.productionRate = productionRate;
            this.costs = costs;
            // graphical variables
            label = new JLabel();
            icon=new ImageIcon(iconName);
            button = new JButton(icon); //The button displays an icon image
            /** Here, the label's and button's fonts are both set to
             * the variable FONT. The button's colour is set to BUTTON_COLOR
             * and the label's colour is set to LABEL_COLOR.
             */
            label.setForeground(LABEL_COLOR);
            button.setForeground(BUTTON_COLOR);
            label.setFont(FONT);
            button.setFont(FONT);
            button.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    improve();
                }
            });
       /**By adding the variable button as an argument for transparentBackground,
        * the background aspects of the button are hidden.
        */
            transparentBackground(button);
        }
        public int getLevel() {
            return level;
        }
        public void unlock() {
            numberOfColumns += 3;
            container.setLayout(new GridLayout(numberOfColumns, 1));
            container.add(new JLabel(""));
            container.add(label);
            container.add(button);
            setSize(screenWidth, getHeight() + 120);
            actualize();
        }
        public void improve() {
            /** This label is used to display a message to the user in the JOptionPane.
             * The label's font is set to the variable FONT and the text colour, or foreground colour, of the label is set to the
             * variable LABEL_COLOR.
             */
            JLabel notificationLabel=new JLabel("");
            notificationLabel.setFont(FONT);
            notificationLabel.setForeground(LABEL_COLOR);
            if(cookies >= costs) {
                level++;
                cookies -= costs;
                costs *= 2;
                //The label's text is changed to tell the user what has been improved.
                notificationLabel.setText("You have improved the " + name + "!");
                /**The JOptionPane displays the notificationLabel in a plain message format.
                 *The title of the window is Notification and an image of a notification is shown.
                 */
                JOptionPane.showMessageDialog(null, notificationLabel, "Notification", JOptionPane.PLAIN_MESSAGE, notification);
            } else {
                //The label's text is changed to tell the user what has been improved.
                notificationLabel.setText("You have not enough money!");
                /**The JOptionPane displays the notificationLabel in a plain message format.
                 *The title of the window is Notification and an image of a notification is shown.
                 */
                JOptionPane.showMessageDialog(null, notificationLabel, "Notification", JOptionPane.PLAIN_MESSAGE, notification);
            }
            actualize();
        }
        public int getProductionRate() {
            return productionRate * level;
        }
        public void actualize() {
            label.setText(name + " Prod. Rate: " + getProductionRate());
            button.setText("Improve (costs: " + costs + ")");
        }
    }
    public static void main(String[] args) {
        CookieClicker cookieClicker = new CookieClicker();
        cookieClicker.setTitle("Cookie Clicker");
        /**The width of the JFrame is set to screenWidth.
         * The height of the JFrame is set to screenHeight.
         */
        cookieClicker.setSize(screenWidth, screenHeight);
        //The background of the JFrame is set to the variable WINDOW_COLOR
        cookieClicker.setBackground(WINDOW_COLOR);
        cookieClicker.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        cookieClicker.setVisible(true);
        //Resizable is set to false so the user is prevented from changing the size of the JFrame.
        cookieClicker.setResizable(false);
        //This function is called to customise UI related to panes.
        optionPaneCustomization();
        //This function is called to play the music of the game.
        music();
    }
    //This function takes in a button as a parameter and makes the background hidden.
    public static void transparentBackground(JButton button) {
        button.setBorderPainted(false); //The border of the button is not painted.
    }
    //This function customises UI related to panes.
    public static void optionPaneCustomization() {
        //The background colour of JOptionPanes is set to the variable WINDOW_COLOR.
        UIManager.put("OptionPane.background", WINDOW_COLOR);
        //The background colour of JPanels are set to the variable WINDOW_COLOR.
        UIManager.put("Panel.background", WINDOW_COLOR);
    }
    //This function is used to play the music in the game.
    public static void music() {
        /**The try and catch method is used to avoid compiler errors.
         * In the try method, the program tries to play music.
         */
        try {
            /**The variable audio is set to a .wav file.
             * The .wav file is accessed so that this music file can be played.
            */
            AudioInputStream audio=AudioSystem.getAudioInputStream(new File("Audio/CookieClicker.wav"));
            Clip soundClip=AudioSystem.getClip();
            soundClip.open(audio);
            //The music will loop endlessly until the program stops
            soundClip.loop(Clip.LOOP_CONTINUOUSLY);
        }
        /**In the catch method, the function audioError is called.
         * This function is only called when there has been an error
         * while playing the audio.
         */
         catch (UnsupportedAudioFileException e) {
            audioError();
        }
         catch (IOException e) {
            audioError();
        }
         catch (LineUnavailableException e) {
           audioError();
        }
    }
    /**In this function, a pop-up displays if an error with the audio in the game occurred.
     * The pop-up informs the user that an error with the audio in the game occurred.
     */
    public static void audioError() {
        ImageIcon errorIcon=new ImageIcon("Images/error.jpg"); //This variable stores an error icon, which is a .jpg.
        /** This label is used to display a message to the user in the JOptionPane.
         * The label's font is set to the variable FONT and the text colour, or foreground colour, of the label is set to the
         * variable LABEL_COLOR.
         */
        JLabel notificationLabel=new JLabel("");
        notificationLabel.setFont(FONT);
        notificationLabel.setForeground(LABEL_COLOR);
        notificationLabel.setText("There has been an error with the audio!");
        /**The JOptionPane displays the notificationLabel in a plain message format.
          *The title of the window is Error and an image of an error is shown.
          */
        JOptionPane.showMessageDialog(null, notificationLabel, "Error!", JOptionPane.PLAIN_MESSAGE, errorIcon);
    } 

}Edit: What I added to the original code is images for the buttons, stylized colours for all the elements in the GUI, and music. I also made other smaller edits as well.



Your Answer

Answers (2)

You should only gamble at fast payout casinos if you value your time and sanity! Waiting days or even weeks to receive your winnings is a frustrating experience nobody wants. Fast payout casinos prioritize efficiency, ensuring that players get their money quickly—sometimes in just hours, thanks to modern e-wallets and cryptocurrency options. This swift service reflects the casino's commitment to high-quality customer satisfaction and transparency. Fast Payout Casinos https://ictir2016.org/ understand that when you win, immediate access to your funds is crucial; so why settle for anything less? Slow-paying casinos are relics of the past, often burdened with outdated technology or poor customer service practices. Fast payout indicates not just speedy transactions but also typically mirrors superior overall operation, better customer support, and fewer headaches for patrons. Don’t settle for sluggish red-tape payouts—demand only the best gaming experiences where satisfaction reigns supreme through quick financial processes!

3 Months

i like the focus on responsible tools, since deposit limits and reality checks are the only things that keep my sessions sensible. ai tips sound interesting, but i’d be wary of people treating them as a shortcut to “beating” the casino. i’ve played a couple rounds via https://xxxtremeroulette.com/parimatch-casino/ and ended up using time limits straight after because the xxxtreme lightning multipliers hit so fast it’s easy to lose track. similar deal when i tried funky time through https://funkytimegame.org/mostbet-casino/ ; the bonus rounds and energy make the reality check pop-ups feel necessary. then jumped to crazy time on https://crazytimegame.org/melbet-casino/ and same thing — those big wheel spins fly by without the timer i’d be gone for hours. overall, the tools matter more than the game math if you want to stay in control.

4 Months

Interviews

Parent Categories