2015-05-12 4 views
2

Я работаю над игрой Саймона. Одна из проблем, которые возникают у меня, - это то, что после первого уровня мои цвета не будут меняться/загораться. Я проследил код и включил инструкции печати, чтобы убедиться, что код работает правильно.Цвет Класс Не меняющийся Цвета

import java.awt.*; 
import java.awt.event.KeyEvent; 
import java.awt.event.KeyListener; 
import java.awt.geom.AffineTransform; 
import java.awt.geom.Arc2D; 
import java.awt.geom.PathIterator; 
import java.awt.geom.Point2D; 
import java.awt.geom.Rectangle2D; 
import java.util.ArrayList; 

import javax.swing.Icon; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JOptionPane; 

public class SimonShape extends JFrame implements KeyListener { 


private int width; 
private int height; 
private int x; 
private int y; 
private int TURN = 45; 


private int level = 1; 

//speed of the light up sequence 
private int lightUpSpd = 500; 

//chooses random color based on numbers 0-3 
private int random; 

//keeps track of user inputs 
private int compCounter = 0; 

ArrayList<Integer> comp = new ArrayList<Integer>(); 


private Color blue = Color.BLUE.darker(); 
private Color red = Color.RED.darker(); 
private Color yellow = Color.YELLOW.darker(); 
private Color green = Color.GREEN.darker(); 


public SimonShape (int width, int height, int x, int y) 
{ 


    this.width = width; 
    this.height = height; 
    this.x = x; 
    this.y = y; 


    JLabel label = new JLabel(); 


    setSize(800,800); 
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    setLocationRelativeTo(null); 
    setVisible(true); 



    label.setFocusable(true); 
    label.setOpaque(true); 
    label.addKeyListener(this); 
    this.add(label); 
    setVisible(true); 
    label.requestFocusInWindow(); 


    randomColorChange(); 
} 


private void randomColorChange() 
{ 
    try 
    { 
     JOptionPane.showMessageDialog(this, "Level " + level); 
     random = (int) (Math.random() * 4); 
     comp.add(random); 

     //light up sequence 
     for (int i = 0; i < level; i++) 
     { 

      if (comp.get(i) == 0) 
      { 
       green = green.brighter(); 
       System.out.println("light"); 
       repaint(); 
       Thread.sleep(lightUpSpd); 
       System.out.println("dark"); 
       green = green.darker(); 
       repaint(); 
      } 

      else if (comp.get(i) == 1) 
      { 
       red = red.brighter(); 
       repaint(); 
       System.out.println("light"); 
       Thread.sleep(lightUpSpd); 
       System.out.println("dark"); 
       red = red.darker(); 
       repaint(); 
      } 

      else if (comp.get(i) == 2) 
      { 
       blue = blue.brighter(); 
       repaint(); 
       System.out.println("light"); 
       Thread.sleep(lightUpSpd); 
       System.out.println("dark"); 
       blue = blue.darker(); 
       repaint(); 
      } 

      else { 

       yellow = yellow.brighter(); 
       repaint(); 
       System.out.println("light"); 
       Thread.sleep(lightUpSpd); 
       System.out.println("dark"); 
       yellow = yellow.darker(); 
       repaint(); 
      } 

      Thread.sleep(lightUpSpd/2); 
     } 


    } 
     catch (InterruptedException e){ 
      e.printStackTrace(); 
     } 

} 

public void keyPressed(KeyEvent e) 
{ 

    if (e.getKeyCode() == KeyEvent.VK_DOWN) 
    { 
     blue = blue.brighter(); 
     repaint(); 
    } 
    if (e.getKeyCode() == KeyEvent.VK_LEFT) 
    { 
     red = red.brighter(); 
     repaint(); 
    } 
    if (e.getKeyCode() == KeyEvent.VK_UP) 
    { 
     green = green.brighter(); 
     repaint(); 
    } 
    if (e.getKeyCode() == KeyEvent.VK_RIGHT) 
    { 
     yellow = yellow.brighter(); 
     repaint(); 
    } 

} 


public void keyReleased(KeyEvent e) { 

    if (e.getKeyCode() == KeyEvent.VK_UP) 
    { 
     green = green.darker(); 
     repaint(); 

     if (0 == comp.get(compCounter)) 
     { 
      compCounter++; 

      if (compCounter == comp.size()) 
      { 
       // next level 
       // reset compCounter 
       JOptionPane.showMessageDialog(this, "Correct!"); 
       lightUpSpd = lightUpSpd - 5; 
       level++; 
       compCounter = 0; 
       randomColorChange(); 
      } 
     } 
     else 
     { 
      //incorrect, end game; 
      JOptionPane.showMessageDialog(this, "Incorrect"); 
      this.setVisible(false); 
      this.dispose(); 
      return; 
     } 


    } 

    if (e.getKeyCode() == KeyEvent.VK_DOWN) 
    { 
     blue = blue.darker(); 
     repaint(); 

     if (2 == comp.get(compCounter)) 
     { 
      compCounter++; 

      if (compCounter == comp.size()) 
      { 
       // next level 
       // reset compCounter 
       JOptionPane.showMessageDialog(this, "Correct!"); 
       lightUpSpd = lightUpSpd - 5; 

       level++; 
       compCounter = 0; 
       randomColorChange(); 
      } 
     } 
     else 
     { 
      //incorrect; end game; 
      JOptionPane.showMessageDialog(this, "Incorrect"); 
      this.setVisible(false); 
      this.dispose(); 
      return; 
     } 


    } 

    if (e.getKeyCode() == KeyEvent.VK_RIGHT) 
    { 
     yellow = yellow.darker(); 
     repaint(); 

     if (3 == comp.get(compCounter)) 
     { 
      compCounter++; 

      if (compCounter == comp.size()) 
      { 
       // next level 
       // reset compCounter 
       JOptionPane.showMessageDialog(this, "Correct!"); 
       lightUpSpd = lightUpSpd - 5; 
       level++; 
       compCounter = 0; 
       randomColorChange(); 
      } 
     } 
     else 
     { 
      //incorrect; end game; 
      JOptionPane.showMessageDialog(this, "Incorrect"); 
      this.setVisible(false); 
      this.dispose(); 
      return; 
     } 


    } 

    if (e.getKeyCode() == KeyEvent.VK_LEFT) 
    { 
     red = red.darker(); 
     repaint(); 
     //user.add(1); 
     if (1 == comp.get(compCounter)) 
     { 
      compCounter++; 

      if (compCounter == comp.size()) 
      { 
       // next level 
       // reset compCounter 
       JOptionPane.showMessageDialog(this, "Correct!"); 
       lightUpSpd = lightUpSpd - 5; 
       level++; 
       compCounter = 0; 
       randomColorChange(); 
      } 
     } 
     else 
     { 
      //incorrect; end game; 
      JOptionPane.showMessageDialog(this, "Incorrect"); 
      this.setVisible(false); 
      this.dispose(); 
      return; 
     } 


    } 
} 

public void keyTyped(KeyEvent e) {} 

public void paint(Graphics g) 
{ 

    Graphics2D g2 = (Graphics2D) g; 


    // Blue Section 
    g2.setStroke(new BasicStroke(1.0f)); 
    g2.setPaint(blue); 
    g2.fill(new Arc2D.Double(x,y,width,height,180+TURN,90,Arc2D.PIE)); 

    // Red Section 
    g2.setStroke(new BasicStroke(2.0f)); 
    g2.setPaint(red); 
    g2.fill(new Arc2D.Double(x,y,width,height,90+TURN,90,Arc2D.PIE)); 

    // Yellow Section 
    g2.setStroke(new BasicStroke(2.0f)); 
    g2.setPaint(yellow); 
    g2.fill(new Arc2D.Double(x,y,width,height,-90+TURN,90,Arc2D.PIE)); 

    // Green Section 
    g2.setStroke(new BasicStroke(2.0f)); 
    g2.setPaint(green); 
    g2.fill(new Arc2D.Double(x,y,width,height,360+TURN,90,Arc2D.PIE)); 

} 
} 

ответ

5

Похоже, вы пытаетесь написать графический интерфейс Swing в виде линейной программы консоли, и я удивлен, что он работает на всех. Если вы не возражаете, позвольте мне предложить несколько предложений:

  1. Не рисуйте непосредственно в методе краски JFrame, так как это может испортить графику вашего графического интерфейса. Вы не называете метод super.paint(g) JFrame, и поэтому меня не удивило бы, если ваша программа сильно усложнит задачу отладки проблем с картинкой и артефактов, так как вы разрываете цепочку рисования на очень критическом этапе.
  2. Вместо этого, если вы должны рисовать с помощью Graphics, сделайте это в paintComponent переопределении JPanel.
  3. Не называть Thread.sleep(...) так, как вы это делаете в графическом интерфейсе Swing, так как если вы не понимаете правила потоковой передачи Swing и не заботитесь, вы рискуете потерять весь графический интерфейс. Вместо этого, если вам нужна временная задержка, используйте таймер Swing.
  4. Это управляемая событиями программа GUI, и поэтому нет места для цикла for, который продвигает уровни. Вместо этого пользователь может взаимодействовать с графическим интерфейсом и основывать ответы GUI на состояние графического интерфейса без линейного типа программирования для цикла. Это одна из самых сложных концепций для понимания при обучении программированию на основе событий, но это критическая концепция.
  5. DRY: не повторяйте себя. У вас есть много повторяющийся код, который можно легко объединить в методы, и это сделает ваш код много проще отладить и улучшить.
  6. Используйте Key Bindings, а не KeyListener, так как вам не нужно использовать kludge, чтобы заставить фокус перейти на ваш JFrame или JPanel.
  7. По возможности попытайтесь выделить логику программы из представления (GUI). Создайте класс модели или классы, полностью независимые от GUI, а затем создайте графический интерфейс вокруг этих классов. Это также упростит работу и отладка вашей программы. Стремитесь сделать GUI как немой, насколько это возможно, оставив все мозги модели. Позже вы могли бы подумать о создании «Control» для управления связью между ними.

Просто играть с некоторыми кода. Нет, где рядом с полным решением ...

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.RenderingHints; 
import java.awt.Shape; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.KeyEvent; 
import java.awt.geom.Arc2D; 
import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.LinkedHashMap; 
import java.util.List; 
import java.util.Map; 
import java.util.Random; 

import javax.swing.*; 

public class SimonGui { 
    private static void createAndShowGui() { 
     final SimonPanel simonPanel = new SimonPanel(600, 600, 1000); 

     // create a list or random directions, just to test the GUI 
     Random random = new Random(); 
     final List<Direction> dirList = new ArrayList<>(); 
     for (int i = 0; i < 15; i++) { 
     int randomDirIndex = random.nextInt(Direction.values().length); 
     Direction randomDir = Direction.values()[randomDirIndex]; 
     dirList.add(randomDir); 
     }   

     JFrame frame = new JFrame("SimonGui"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(simonPanel); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 

     // display the colors from the random list of directions, 
     // but wait 400 msecs to allow time for the GUI to display 
     new Timer(400, new ActionListener() { 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      // have JPanel display the colors in the list 
      simonPanel.displayDirectionList(dirList); 

      // then stop this timer (timer should run just once) 
      ((Timer) e.getSource()).stop(); 
     } 
     }).start(); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGui(); 
     } 
     }); 
    } 
} 

@SuppressWarnings("serial") 
class SimonPanel extends JPanel { 
    private static final int GAP = 10; 
    private int displayColorDelay; 
    private int prefW; 
    private int prefH; 
    private Map<Direction, Shape> dirShapeMap = new LinkedHashMap<>(); 
    private Direction activeDir = null; 
    private Timer displayColorTimer; 

    public SimonPanel(int prefW, int prefH, int displayColorDelay) { 
     this.prefW = prefW; 
     this.prefH = prefH; 
     this.displayColorDelay = displayColorDelay; 

     int x = GAP; 
     int y = GAP; 
     int width = prefW - 2 * GAP; 
     int height = prefH - 2 * GAP; 
     int degree = 45; 
     for (Direction direction : Direction.values()) { 
     Shape shape = new Arc2D.Double(x, y, width, height, degree, 90, Arc2D.PIE); 
     dirShapeMap.put(direction, shape); 
     degree += 90; 
     } 

     setKeyBindings(); 
    } 

    public void displayDirectionList(List<Direction> dirList) { 
     displayColorTimer = new Timer(displayColorDelay, new DisplayColorTimerListener(dirList)); 
     displayColorTimer.start(); 
    } 

    private void setKeyBindings() { 
     Map<Direction, Integer> dirToKeyMap = new HashMap<>(); 
     dirToKeyMap.put(Direction.NORTH, KeyEvent.VK_UP); 
     dirToKeyMap.put(Direction.WEST, KeyEvent.VK_LEFT); 
     dirToKeyMap.put(Direction.SOUTH, KeyEvent.VK_DOWN); 
     dirToKeyMap.put(Direction.EAST, KeyEvent.VK_RIGHT); 

     int condition = WHEN_IN_FOCUSED_WINDOW; 
     InputMap inputMap = getInputMap(condition); 
     ActionMap actionMap = getActionMap(); 

     for (Direction dir : Direction.values()) { 
     int keyCode = dirToKeyMap.get(dir); 
     boolean keyReleased = false; // key pressed 
     KeyStroke pressedKeyStroke = KeyStroke.getKeyStroke(keyCode, 0, keyReleased); 
     inputMap.put(pressedKeyStroke, pressedKeyStroke.toString()); 
     actionMap.put(pressedKeyStroke.toString(), new KeyBindingAction(dir, keyReleased)); 

     keyReleased = true; // key released 
     KeyStroke releasedKeyStroke = KeyStroke.getKeyStroke(keyCode, 0, keyReleased); 
     inputMap.put(releasedKeyStroke, releasedKeyStroke.toString()); 
     actionMap.put(releasedKeyStroke.toString(), new KeyBindingAction(dir, keyReleased)); 
     } 

    } 

    @Override 
    public Dimension getPreferredSize() { 
     if (isPreferredSizeSet()) { 
     return super.getPreferredSize(); 
     } 
     return new Dimension(prefW, prefH); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Graphics2D g2 = (Graphics2D) g; 
     g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
     for (Direction direction : dirShapeMap.keySet()) { 
     Color color = (activeDir == direction) ? direction.getActiveColor() : direction.getPassiveColor(); 
     g2.setColor(color); 
     g2.fill(dirShapeMap.get(direction)); 
     } 
    } 

    private class KeyBindingAction extends AbstractAction { 
     private Direction dir; 
     private boolean keyReleased; 

     public KeyBindingAction(Direction dir, boolean keyReleased) { 
     this.dir = dir; 
     this.keyReleased = keyReleased; 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
     // TODO: action depending on direction and if key is pressed or released 
     } 
    } 

    private class TurnOffListener implements ActionListener { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
     activeDir = null; 
     repaint(); 
     } 
    } 

    private class DisplayColorTimerListener implements ActionListener { 
     private List<Direction> directionList; 
     private int counter = 0; 
     private Timer turnOffTimer; 

     public DisplayColorTimerListener(List<Direction> directionList) { 
     this.directionList = directionList; 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
     Timer timer = (Timer) e.getSource(); 
     if (counter == directionList.size()) { 
      activeDir = null; 
      timer.stop(); 
     } else { 
      activeDir = directionList.get(counter); 
      counter++; 

      // so there's a time gap in the display, so that same colors will 
      // be distinct 
      int turnOffDelay = (3 * timer.getDelay())/4; // turn off 3/4 time into display 
      turnOffTimer = new Timer(turnOffDelay, new TurnOffListener()); 
      turnOffTimer.setRepeats(false); 
      turnOffTimer.start(); 
     } 
     repaint();   
     } 
    } 
} 

enum Direction { 
    NORTH(Color.blue), 
    WEST(Color.yellow), 
    SOUTH(Color.red), 
    EAST(Color.green); 

    private Color color; 

    private Direction(Color color) { 
     this.color = color; 
    } 

    public Color getColor() { 
     return color; 
    } 

    public Color getPassiveColor() { 
     return color.darker(); 
    } 

    public Color getActiveColor() { 
     return color.brighter(); 
    } 

} 
+0

@igknighton: Я изложил свои рекомендации в начале моего ответа. –

Смежные вопросы