10
\$\begingroup\$

A while back I asked a question about my Simon Says game and did well on my assignment! But now we need to go back in a make some modifications to the game to be more advanced. I've done that as well, but I need some tips to make it more pristine and little cleaner, some things I'm still working on, but any help here would be greatly appreciated.

Here is a ZIP file with images and a few other resources.

And GitHub if needed.

Game Photo

Simon.java

/*
 * 
 */
package Simon;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Hashtable;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JSlider;
import javax.swing.Timer;

// TODO: Auto-generated Javadoc
/**
 * The Class Simon.
 */

public class Simon implements ActionListener, MouseListener
{

/** The simon. */
public static Simon simon;

/** The renderer. */
public Renderer renderer;

/** The Constant WIDTH and HEIGHT. */
public static int WIDTH = 800;
public static int HEIGHT = 800;

/** The index pattern. */
public int flashed = 0, dark, ticks, indexPattern;

/** The creating pattern. */
public boolean creatingPattern = true;

/** The pattern. */
public ArrayList<Integer> pattern;

/** The random. */
public Random random;

/** The game over. */
private boolean gameOver;

/** The first start. */
private boolean firstStart;

/** The timer. */
private Timer timer;

/** The high score. */
private int highScore;

/** The score. */
private int score;

/** JComponents. */
private JFrame frame;
private JSlider slider;
private JFrame child;

/** Panel colors. */
private Color topLeftColor = Color.GREEN;
private Color topRightColor = Color.RED;
private Color bottomLeftColor = Color.YELLOW;
private Color bottomRightColor = Color.BLUE;

/** Modes. */
private int difficultyAmount = 20;
private boolean increaseSpeedMode = false;
private boolean hardMode = false;
private JCheckBoxMenuItem increaseSpeed;
private JCheckBoxMenuItem hard;
private boolean played = false;

/** Data. */
ArrayList<Score> scores = new ArrayList<Score>();
ArrayList<Score> sessionScores = new ArrayList<Score>();

/**
 * Instantiates a new simon.
 */
public Simon()
{
    frame = new JFrame("Simon");
    timer = new Timer(20, this);
    firstStart = true;
    renderer = new Renderer();
    pattern = new ArrayList<Integer>();
    score = 0;
    highScore = 0;

    try {
        readScores();
    } catch (IOException e) {
        e.printStackTrace();
    }

    JMenuBar menuBar = setMenuBar();
    frame.setLayout(new BorderLayout());
    frame.setSize(HEIGHT+8,WIDTH+30);
    frame.addMouseListener(this);
    frame.setResizable(true);
    frame.add(renderer, BorderLayout.CENTER);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setJMenuBar(menuBar);
    renderer.addComponentListener(new ComponentAdapter() 
    {  
            public void componentResized(ComponentEvent evt) {
                HEIGHT = frame.getHeight();
                WIDTH = frame.getWidth();
            }
    });
    frame.setVisible(true);
    HEIGHT = frame.getHeight();
    WIDTH = frame.getWidth();

}

public JMenuBar setMenuBar() {
    JMenuBar menuBar = new JMenuBar();

    /** Settings menu and submenus. */
    JMenu settings = new JMenu("Settings");
        JMenu colors = new JMenu("Choose Colors");
            JMenuItem topLeft = new JMenuItem("Top Left");
            JMenuItem topRight = new JMenuItem("Top Right");
            JMenuItem bottomLeft = new JMenuItem("Bottom Left");
            JMenuItem bottomRight = new JMenuItem("Bottom Right");
            topLeft.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    changePanelColor("topLeft");
                }
            });
            topRight.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    changePanelColor("topRight");
                }
            });
            bottomLeft.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    changePanelColor("bottomLeft");
                }
            });
            bottomRight.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    changePanelColor("bottomRight");
                }
            });
            colors.add(topLeft);
            colors.add(topRight);
            colors.add(bottomLeft);
            colors.add(bottomRight);
        JMenu mode = new JMenu("Choose Mode");
            JMenuItem difficulty = new JMenuItem("Choose Speed");
            increaseSpeed = new JCheckBoxMenuItem("Increased Speed Mode");
            hard = new JCheckBoxMenuItem("Hard Mode");
            difficulty.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    selectDifficulty();
                }
            });
            increaseSpeed.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    if(!increaseSpeedMode) {
                        increaseSpeedMode = true;
                        hardMode = false;
                        hard.setState(false);
                    } else {
                        increaseSpeedMode = false;
                    }
                }
            });
            hard.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    if(!hardMode) {
                        hardMode = true;
                        increaseSpeedMode = false;
                        increaseSpeed.setState(false);
                    } else {
                        hardMode = false;
                    }
                }
            });             
            mode.add(difficulty);
            mode.add(increaseSpeed);
            mode.add(hard);
        settings.add(colors);
        settings.add(mode);

    /** Stats menu. */
    JMenu stats = new JMenu("Stats");
        JMenuItem highScores = new JMenuItem("High Scores");
        JMenuItem history = new JMenuItem("History");
        stats.add(highScores);
        stats.add(history);
        highScores.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                displayHighScores();
            }
        }); 
        history.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                displayHistory();
            }
        }); 

    /** Help menu */
    JMenu help = new JMenu("Help");
        JMenuItem about = new JMenuItem("About");
        JMenuItem rules = new JMenuItem("Rules");
        help.add(about);
        help.add(rules);
        about.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                displayAbout();
            }
        }); 
        rules.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                displayRules();
            }
        });
    menuBar.add(settings);
    menuBar.add(stats);
    menuBar.add(help);

    return menuBar;
}

public void changePanelColor(String panel) {
    Color initialColor = null;
    if(panel.equals("topLeft")) { initialColor = topLeftColor; }
    if(panel.equals("topRight")) { initialColor = topRightColor; }
    if(panel.equals("bottomLeft")) { initialColor = bottomLeftColor; }
    if(panel.equals("bottomRight")) { initialColor = bottomRightColor; }
    Color newColor = JColorChooser.showDialog(frame,"Select Panel Color",
            initialColor );
    if(panel.equals("topLeft")) { topLeftColor = newColor; }
    if(panel.equals("topRight")) { topRightColor = newColor; }
    if(panel.equals("bottomLeft")) { bottomLeftColor = newColor; }
    if(panel.equals("bottomRight")) { bottomRightColor = newColor; }

    renderer.repaint();
}

public void selectDifficulty() {
    child = new JFrame();
    slider = new JSlider(2, 40);
    slider.setValue(difficultyAmount);
    JButton ok = new JButton("OK");

    Hashtable<Integer, JLabel> labelTable = new Hashtable<Integer, JLabel>();
    labelTable.put( new Integer( 2 ), new JLabel("Fast") );
    labelTable.put( new Integer( 21 ), new JLabel("Medium") );
    labelTable.put( new Integer( 40 ), new JLabel("Slow") );
    slider.setLabelTable(labelTable);
    slider.setPaintLabels(true);

    ok.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            difficultyAmount = slider.getValue();
            child.setVisible(false);
        }
    });

    child.add(slider, BorderLayout.NORTH);
    child.setSize(200,100);
    child.add(ok);
    child.setVisible(true);
}

public void displayAbout() {
    child = new JFrame();
    child.setTitle("About");
    JButton ok = new JButton("OK");
    ok.setSize(150, 50);
    JLabel label = new JLabel();
    label.setText("<html>Welcome to Simon Says! "
            + "<br>Based on the popular children's game, this game has everything the original did and more! "
            + "<br>With select modes for increasing speeds over the course of the game and changing colors! </html>");

    ok.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            child.setVisible(false);
        }
    });

    child.add(label, BorderLayout.NORTH);
    child.add(ok, BorderLayout.SOUTH);
    child.setSize(400,150);
    child.setVisible(true);
}

public void displayRules() {
    child = new JFrame();
    child.setTitle("Rules");
    JButton ok = new JButton("OK");
    ok.setSize(150, 50);
    JLabel label = new JLabel();
    label.setText("<html>Simon says is a simple game.<br>A sequence of colors will flash before your eyes.<br>" +
            "Select those colors in the same order afterwards.<br>A new color is added every round!</html>");

    ok.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            child.setVisible(false);
        }
    });

    child.add(label, BorderLayout.NORTH);
    child.add(ok, BorderLayout.SOUTH);
    child.setSize(400,150);
    child.setVisible(true);
}

public void displayHighScores() {
    child = new JFrame();
    JButton ok = new JButton("OK");
    ok.setSize(150, 50);
    JLabel label = new JLabel();
    String scoresText = "<html>";
    int counter = 0;

    for(Score s : scores) {
        counter++;
        if(counter < 11) {
            scoresText += counter+". "+s.getName()+": "+s.getValue()+"<br>";
        }
    }
    label.setText(scoresText);

    ok.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            child.setVisible(false);
        }
    });

    child.add(label, BorderLayout.NORTH);
    child.add(ok, BorderLayout.SOUTH);
    child.setSize(400,400);
    child.setTitle("Top 10 High Scores");
    child.setVisible(true);
}

public void displayHistory() {
    child = new JFrame();
    JButton ok = new JButton("OK");
    ok.setSize(150, 50);
    JLabel label = new JLabel();
    String scoresText = "<html>";
    int counter = 0;
    double totalScore = 0.0;

    for(Score s : sessionScores) {
        counter++;
        totalScore += s.getValue();
    }
    scoresText += "Games Played: "+counter+"<br>";
    scoresText += "Average Score: "+((double)totalScore/(counter*1.0));
    label.setText(scoresText);

    ok.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            child.setVisible(false);
        }
    });

    child.add(label, BorderLayout.NORTH);
    child.add(ok, BorderLayout.SOUTH);
    child.setSize(400,400);
    child.setTitle("Session History");
    child.setVisible(true);     
}

public void saveScores() throws FileNotFoundException, UnsupportedEncodingException {
    PrintWriter writer = new PrintWriter("scores.txt", "UTF-8");
    for(Score s : scores) {
        writer.println(s.getName());
        writer.println(s.getValue());
    }
    writer.close();
}

public void readScores() throws IOException {
    BufferedReader br = new BufferedReader(new FileReader("scores.txt"));
    try {
        int counter = 0;
        String line = br.readLine();
        String currentName = "";
        int currentScore;

        while (line != null) {
            if(counter%2 == 0) {
                currentName = line;
            }
            if(counter%2 == 1) {
                currentScore = Integer.parseInt(line);
                scores.add(new Score(currentName, currentScore));
            }
            line = br.readLine();
            counter++;
        }
    } finally {
        br.close();
    }
}

public void scramblePanels() {
    ArrayList<Integer> panels = new ArrayList<Integer>();
    ArrayList<Integer> newPattern = new ArrayList<Integer>();
    for(int i = 1; i < 5; i++) {
        panels.add(i);
    }
    Collections.shuffle(panels);
    for(int i = 0; i < pattern.size(); i++) {
        int panelNumber = pattern.get(i);
        newPattern.add(panels.get(panelNumber-1));
    }
    Color backupTopLeftColor = topLeftColor;
    Color backupTopRightColor = topRightColor;
    Color backupBottomLeftColor = bottomLeftColor;
    Color backupBottomRightColor = bottomRightColor;
    for(int i = 0; i < panels.size(); i++) {
        int panelNumber = panels.get(i);
        if(panelNumber == 1) { 
            if(i == 0) { topLeftColor = backupTopLeftColor; }
            if(i == 1) { topLeftColor = backupTopRightColor; }
            if(i == 2) { topLeftColor = backupBottomLeftColor; }
            if(i == 3) { topLeftColor = backupBottomRightColor; }
        }
        if(panelNumber == 2) { 
            if(i == 0) { topRightColor = backupTopLeftColor; }
            if(i == 1) { topRightColor = backupTopRightColor; }
            if(i == 2) { topRightColor = backupBottomLeftColor; }
            if(i == 3) { topRightColor = backupBottomRightColor; }
        }
        if(panelNumber == 3) { 
            if(i == 0) { bottomLeftColor = backupTopLeftColor; }
            if(i == 1) { bottomLeftColor = backupTopRightColor; }
            if(i == 2) { bottomLeftColor = backupBottomLeftColor; }
            if(i == 3) { bottomLeftColor = backupBottomRightColor; }
        }
        if(panelNumber == 4) { 
            if(i == 0) { bottomRightColor = backupTopLeftColor; }
            if(i == 1) { bottomRightColor = backupTopRightColor; }
            if(i == 2) { bottomRightColor = backupBottomLeftColor; }
            if(i == 3) { bottomRightColor = backupBottomRightColor; }
        }
    }
    for(int i = 0; i < pattern.size(); i++) {
        pattern.set(i, newPattern.get(i));
    }
}

/**
 * Start.
 */
public void start()
{
    random = new Random();
    indexPattern = 0;
    pattern.clear();
    dark = 2;
    flashed = 0;
    ticks = 0;
    score = 0;
}

/**
 * Start timer.
 */
public void starttimer()
{
    timer.start();
}

/**
 * The main method.
 *
 * @param args the arguments
 */
public static void main(String[] args)
{
    simon = new Simon();
}

/* (non-Javadoc)
 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
 */
@Override
public void actionPerformed(ActionEvent e)
{
    new Thread(new Runnable() { //clicks can be managed even while sequence being displayed
        public void run() {
            HEIGHT = frame.getHeight();
            WIDTH = frame.getWidth();
            ticks++;

            if (ticks % difficultyAmount == 0)
            {
                flashed = 0;

                if (dark >= 0)
                {
                    dark--;
                }
            }

            if (creatingPattern)
            {
                if (dark <= 0)
                {
                    if (indexPattern >= pattern.size())
                    {
                        flashed = random.nextInt(40) % 4 + 1;
                        pattern.add(flashed);
                        indexPattern = 0;
                        creatingPattern = false;
                        played = false;
                        try {
                            TimeUnit.MILLISECONDS.sleep(450);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        if(!creatingPattern && !gameOver) {
                            if(hardMode) {
                                scramblePanels();
                            }
                        }
                    }
                    else
                    {
                        flashed = pattern.get(indexPattern);
                        indexPattern++;
                        played = false;
                    }

                    dark = 2;
                }
            }
            else if (indexPattern == pattern.size())
            {
                creatingPattern = true;
                indexPattern = 0;
                dark = 2;
                score++;
                if(increaseSpeedMode && difficultyAmount > 2) {
                    difficultyAmount--;
                }
            }

            renderer.repaint();
        }
    }).start();
}

/**
 * Paint.
 *
 * @param g the g
 */
public void paint(Graphics2D g)
{
    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

    if (flashed == 1)
    {
        g.setColor(topLeftColor);
        if(!played) { 
            playSound(1);
            played = true;
        }
    }
    else
    {
        g.setColor(topLeftColor.darker());
    }

    g.fillRect(0, 0, WIDTH / 2, HEIGHT / 2);

    if (flashed == 2)
    {
        g.setColor(topRightColor);
        if(!played) { 
            playSound(2);
            played = true;
        }
    }
    else
    {
        g.setColor(topRightColor.darker());
    }

    g.fillRect(WIDTH / 2, 0, WIDTH / 2, HEIGHT / 2);

    if (flashed == 3)
    {
        g.setColor(bottomLeftColor);
        if(!played) { 
            playSound(3);
            played = true;
        }
    }
    else
    {
        g.setColor(bottomLeftColor.darker());
    }

    g.fillRect(0, HEIGHT / 2, WIDTH / 2, HEIGHT / 2);

    if (flashed == 4)
    {
        g.setColor(bottomRightColor);
        if(!played) { 
            playSound(4);
            played = true;
        }
    }
    else
    {
        g.setColor(bottomRightColor.darker());
    }

    g.fillRect(WIDTH / 2, HEIGHT / 2, WIDTH / 2, HEIGHT / 2);

    g.setColor(Color.BLACK);
    g.fillRoundRect(WIDTH/4+WIDTH/45, HEIGHT/4+HEIGHT/45, WIDTH/2-WIDTH/45, HEIGHT/2-HEIGHT/45, 300, 300);
    g.fillRect(WIDTH / 2 - WIDTH / 12, 0, WIDTH / 7, HEIGHT);
    g.fillRect(0, HEIGHT / 2 - HEIGHT / 12, WIDTH, HEIGHT / 7);

    g.setColor(Color.GRAY);
    g.setStroke(new BasicStroke(200));
    g.drawOval(-100, -100, WIDTH + 200, HEIGHT + 200);

    g.setColor(Color.BLACK);
    g.setStroke(new BasicStroke(10));
    g.drawOval(0, 0, WIDTH, HEIGHT);

    g.setColor(Color.WHITE);
    g.setFont(new Font("Arial", 1, WIDTH*HEIGHT/4500));

    if(firstStart)
    {
        g.setFont(new Font("Arial", 1, 100));
        g.drawString("Start", WIDTH / 2 - 120, HEIGHT / 2 + 24);
    }

    else if (gameOver)
    {
        g.setFont(new Font("Arial", 1, 100));
        g.drawString("Reset", WIDTH / 2 - 140, HEIGHT / 2 + 24);
    }
    else
    {
        g.drawString(indexPattern + "/" + pattern.size(), WIDTH / 2 - WIDTH/10, HEIGHT / 2 + HEIGHT/20);
    }
}

/* (non-Javadoc)
 * @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)
 */
@Override
public void mousePressed(MouseEvent e)
{
    played = false;
    int x = e.getX(), y = e.getY();

    if (!creatingPattern && !gameOver)
    {
        if (x > 0 && x < WIDTH / 2 && y > 0 && y < HEIGHT / 2)
        {
            flashed = 1;
            ticks = 1;
        }
        else if (x > WIDTH / 2 && x < WIDTH && y > 0 && y < HEIGHT / 2)
        {
            flashed = 2;
            ticks = 1;
        }
        else if (x > 0 && x < WIDTH / 2 && y > HEIGHT / 2 && y < HEIGHT)
        {
            flashed = 3;
            ticks = 1;
        }
        else if (x > WIDTH / 2 && x < WIDTH && y > HEIGHT / 2 && y < HEIGHT)
        {
            flashed = 4;
            ticks = 1;
        }

        if (flashed != 0)
        {
            if (pattern.get(indexPattern) == flashed)
            {
                indexPattern++;
            }
            else
            {
                gameOverSound();
                if (highScore < score)
                    highScore = score;
                JOptionPane.showMessageDialog(renderer, "HighScore: " + highScore,
                        "Your Scores", JOptionPane.INFORMATION_MESSAGE);
                gameOver = true;
                String name = JOptionPane.showInputDialog(renderer, "What's your name?");
                scores.add(new Score(name,score));
                sessionScores.add(new Score(name,score));
                Collections.sort(scores);
                try {
                    saveScores();
                } catch (FileNotFoundException e1) {
                    e1.printStackTrace();
                } catch (UnsupportedEncodingException e1) {
                    e1.printStackTrace();
                }
            }
        }
    }
    else if (gameOver || firstStart)
    {
        start();
        starttimer();

        if(!firstStart){
            gameOver = false;
        }
        firstStart = false;
    }
}

public void playSound(int i) {
    try
    {
        Clip clip = AudioSystem.getClip();
        clip.open(AudioSystem.getAudioInputStream(new File(i+".wav")));
        clip.start();
        TimeUnit.MILLISECONDS.sleep(150);
        clip.close();
    }
    catch (Exception exc)
    {
        exc.printStackTrace(System.out);
    }
}

public void gameOverSound() {
    try
    {
        played = true;
        Clip clip = AudioSystem.getClip();
        clip.open(AudioSystem.getAudioInputStream(new File("gameover.wav")));
        clip.start();
        TimeUnit.MILLISECONDS.sleep(5200);
        clip.close();
    }
    catch (Exception exc)
    {
        exc.printStackTrace(System.out);
    }       
}
/* (non-Javadoc)
 * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
 */
@Override
public void mouseClicked(MouseEvent e)
{
}

/* (non-Javadoc)
 * @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent)
 */
@Override
public void mouseReleased(MouseEvent e)
{
}

/* (non-Javadoc)
 * @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent)
 */
@Override
public void mouseEntered(MouseEvent e)
{
}

/* (non-Javadoc)
 * @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent)
 */
@Override
public void mouseExited(MouseEvent e)
{
}

}

Renderer.java

/*
 * 
 */
package Simon;


import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class Renderer extends JPanel
{

/* (non-Javadoc)
 * @see javax.swing.JComponent#paintComponent(java.awt.Graphics)
 */
@Override
protected void paintComponent(Graphics g)
{
    super.paintComponent(g);

    if(Simon.simon !=null)
    {   
        Simon.simon.paint((Graphics2D) g);
    }

}

}

Score.java

package Simon;

public class Score implements Comparable<Score> {
private String name;
private int value;

Score(String name, int value) {
    this.name = name;
    this.value = value;
}

public String getName() {
    return name;
}

public int getValue() {
    return value;
}

@Override
public int compareTo(Score o) {
    if(o instanceof Score) {
        Score other = (Score)o;
        if (this.value < other.value) {
            return 1;
        } else if (this.value > other.value) {
            return -1;
        }
    }
    return 0;
}

}
\$\endgroup\$
  • \$\begingroup\$ So a few things that bother me that I have a hard time with are: 1) The resizing of the window that doesn't resize the text in the middle or the game. 2) When playing on hard mode the game goes very slowly and is almost unplayable because of it. This is made with Java SE 1.7 \$\endgroup\$ – bnwinter Dec 11 '15 at 21:19
  • \$\begingroup\$ Are the comments a requirement of the class assignment? \$\endgroup\$ – bazola Dec 11 '15 at 22:34
  • \$\begingroup\$ They are, but they were auto generated and I haven't corrected them yet. \$\endgroup\$ – bnwinter Dec 11 '15 at 23:36
10
\$\begingroup\$

Use interfaces when possible

ArrayList<Score> scores = new ArrayList<Score>();
ArrayList<Score> sessionScores = new ArrayList<Score>();

You should use List here instead of ArrayList when declaring the variable. It is a good idea to do this as often as you can, including when writing the arguments for methods. This will allow you to change the ArrayList to another kind of container later without changing anything else, as long as it implements the List interface.

Bad Comments

/** The simon. */
public static Simon simon;

/** The renderer. */
public Renderer renderer;

/** The Constant WIDTH and HEIGHT. */
public static int WIDTH = 800;
public static int HEIGHT = 800;

It may be a requirement for your class assignment to have these kind of comments, but they are not good. Typically the names of your variables, methods and classes should self-document what they are, rather than being defined by comments.

Generally, comments should explain Why you are doing something, rather than How you are doing it or What it is. I looked at the rest of the code, and there are absolutely no comments inside your methods, so there are probably a few places where they are missing where they could be useful.

Enums

for(int i = 0; i < panels.size(); i++) {
        int panelNumber = panels.get(i);
        if(panelNumber == 1) { 
            if(i == 0) { topLeftColor = backupTopLeftColor; }
            if(i == 1) { topLeftColor = backupTopRightColor; }
            if(i == 2) { topLeftColor = backupBottomLeftColor; }
            if(i == 3) { topLeftColor = backupBottomRightColor; }
        }
        if(panelNumber == 2) { 
            if(i == 0) { topRightColor = backupTopLeftColor; }
            if(i == 1) { topRightColor = backupTopRightColor; }
            if(i == 2) { topRightColor = backupBottomLeftColor; }
            if(i == 3) { topRightColor = backupBottomRightColor; }
        }

Any time you are using simple integers inside switch statements, or in an if clause like this one, you should change them to an enum to improve the readability of the code.

Right now, you just have a number of panels in an array, and you know in your head which position in the array the panel will be. However, no one else reading your code (or possibly using it) will know that position 2 in the array is supposed to be the top right panel. You could have an enum such as PanelPositions that could contain the types TOP_LEFT, TOP_RIGHT, etc. However, I am trying to understand this code in order to recommend to you exactly how you might use an enum in this situation, but I cannot see the best way to do it. Which leads me to my next point:

Object Oriented Code and the Single Responsibility Principle

You should not need to iterate over an array of integers like this in order to implement the game of Simon Says. The reason you have funny code like this is that your Simon class is doing way too much. It's responsible for everything, such as choosing the new pattern, drawing everything to the screen, even saving the scores to disk.

The first step to achieve a more object oriented approach here would be to completely separate the rendering of the game from the game model backing it. Perhaps the Simon class would be in charge of drawing, and there could be a SimonGame class for the game model. The Simon class would look at the SimonGame class in order to get the information that it needs to draw things to the screen. The Simon class would only be responsible for starting the SimonGame game, drawing the current state to the screen, and receiving user input and passing it to the SimonGame. Then, the SimonGame class would do things such as validating whether the player has entered the correct sequence, and generating new sequences. In this way, each class has a single responsibility, and thus it is much easier to understand what the code does, both for someone else, and for yourself when you come back to this code one day. In the same way, I would recommend moving the writing of the scores to a separate class, or maybe into the Score class.

Using this approach for the panels could mean that your SimonGame class has a List of Panel objects, rather than trying to do all of this with integers and a for loop and if statements.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.