2015-05-12 205 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 GUI作为线性控制台程序,我很惊讶它可以工作。如果你不介意,请让我提供一些建议:

  1. 不要直接在JFrame的绘制方法中绘制,因为这可能会弄乱你的GUI的图形。你不要调用JFrame的super.paint(g)方法,所以如果你的程序开发出奇怪的难以调试的绘画问题和工件,那么你就不会感到惊讶,因为你在非常关键的时刻打破了绘画链。
  2. 相反,如果您必须使用Graphics进行绘制,请在JPanel的paintComponent重写中执行此操作。
  3. 不要像在Swing GUI中那样调用Thread.sleep(...),因为如果您不了解Swing线程规则并小心谨慎,则可能会使整个GUI进入睡眠状态。相反,如果您需要时间延迟,请使用摆动计时器。
  4. 这是一个事件驱动的GUI程序,所以没有地方for循环提高水平。相反,让用户与GUI进行交互,并根据GUI的状态将GUI的响应建立在没有循环线性编程类型的基础上。这是学习事件驱动编程时最难理解的概念之一,但却是一个关键概念。
  5. 干:不要重复自己。你有很多重复的代码,可以很容易地合并到方法,这样做会使你的代码更容易调试和增强。
  6. 使用Key Bindings而不是KeyListener,因为您不必使用强制焦点转移到您的JFrame或JPanel的kludge。
  7. 只要有可能,尝试从视图(GUI)中分离出程序逻辑。创建一个模型类或者一个类,它完全独立于GUI,然后在这些类的周围创建一个GUI。这也将增加和调试您的程序更容易。努力使图形用户界面尽可能地成为愚蠢,将所有的大脑留给模型。稍后你可以考虑创建一个“控制”来处理两者之间的通信。

一些代码只是在玩。没有接近完整的解决方案...

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:我在我的回答开始时概述了我的建议。 –