- 您的游戏是“控制器”,它负责管理功能以及模型与视图之间的通信。
- 您的视图应代表您的模型
- 您的模型(可能还有您的视图)应该提供事件通知支持,控制器需要对其进行监视,以便管理需求和逻辑。
首先,您的代码混乱不堪。您正在充分利用
static它,但它不会帮助您。
例如,我对您的
Tile课堂进行了重新设计,使其看起来更像这样。
public class Tile extends JLabel { public static Font font = new Font("Serif", Font.BOLD, 39); private char _c; public Tile(char c, Color background) { setBackground(background); setOpaque(true); _c = c; setText(convert()); } public static char randomLetter() { Random r = new Random(); char randomChar = (char) (97 + r.nextInt(25)); return randomChar; } public char getChar() { return _c; } public String convert() { return String.valueOf(getChar()); }}而不是
randomLetter每次调用
getChar或时都调用
convert它,只应在实际需要一个新字符时才使用它,否则您将永远不知道
Tile字符的实际含义是/将要以什么开头。
接下来,我们需要该模式的某种观察者契约,例如,它可以告诉我们什么时候发生了变化。
public interface ModelListener { public void tileWasRemoved(Tile tile);}没什么特别的,但这提供了一种方法,可以在删除a和实际删除
Modela时提供通知。
Tile``Tile
接下来,我对其进行了更新,
Model以使其实际成为“模型”。在
Model现在保持
list的
TileS和用于添加和删除它们提供的功能。它还为
ModelListener和事件触发提供支持
public class Model { private ArrayList<Tile> list = new ArrayList<Tile>(); private List<ModelListener> listeners = new ArrayList<>(25); public Model() { } public void addModelListener(ModelListener listener) { listeners.add(listener); } public void removeModelListener(ModelListener listener) { listeners.remove(listener); } protected void fireTileRemoved(Tile tile) { for (ModelListener listener : listeners) { listener.tileWasRemoved(tile); } } public void removeByChar(char value) { Iterator<Tile> iterator = list.iterator(); while (iterator.hasNext()) { Tile tile = iterator.next(); if (value == tile.getChar()) { fireTileRemoved(tile); iterator.remove(); } } } private void add(Tile tile) { list.add(tile); } private Iterable<Tile> getTiles() { return Collections.unmodifiableList(list); }}接下来,我转到
Game并对其进行了更新,以便将
Tiles
添加到
Model并使用
Model数据来设置UI。然后注册
KeyListener和
ModelListener
public Game() { model = new Model(); model.add(new Tile(Tile.randomLetter(), Color.WHITE)); model.add(new Tile(Tile.randomLetter(), Color.RED)); model.add(new Tile(Tile.randomLetter(), Color.GREEN)); model.add(new Tile(Tile.randomLetter(), Color.YELLOW)); Jframe frame = new Jframe(); frame.getContentPane().setLayout(new GridLayout(4, 1)); frame.setSize(500, 800); frame.setVisible(true); for (Tile tile : model.getTiles()) { frame.add(tile); } model.addModelListener(new ModelListener() { @Override public void tileWasRemoved(Tile tile) { frame.remove(tile); frame.revalidate(); frame.repaint(); } }); frame.getContentPane().addKeyListener(this); frame.getContentPane().setFocusable(true); frame.getContentPane().requestFocusInWindow();}最后,该
keyTyped事件现在要求
Model删除
Tile给定密钥中的一个…
@Overridepublic void keyTyped(KeyEvent e) { model.removeByChar(e.getKeyChar());}作为概念证明…
import java.awt.Color;import java.awt.EventQueue;import java.awt.Font;import java.awt.GridLayout;import java.awt.event.KeyEvent;import java.awt.event.KeyListener;import java.util.ArrayList;import java.util.Collections;import java.util.Iterator;import java.util.List;import java.util.Random;import javax.swing.Jframe;import javax.swing.JLabel;import javax.swing.UIManager;import javax.swing.UnsupportedLookAndFeelException;public class Game implements KeyListener { public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { ex.printStackTrace(); } new Game(); } }); } private Model model; public Game() { model = new Model(); model.add(new Tile(Tile.randomLetter(), Color.WHITE)); model.add(new Tile(Tile.randomLetter(), Color.RED)); model.add(new Tile(Tile.randomLetter(), Color.GREEN)); model.add(new Tile(Tile.randomLetter(), Color.YELLOW)); Jframe frame = new Jframe(); frame.getContentPane().setLayout(new GridLayout(4, 1)); frame.setSize(500, 800); frame.setVisible(true); for (Tile tile : model.getTiles()) { frame.add(tile); } model.addModelListener(new ModelListener() { @Override public void tileWasRemoved(Tile tile) { frame.remove(tile); frame.revalidate(); frame.repaint(); } }); frame.getContentPane().addKeyListener(this); frame.getContentPane().setFocusable(true); frame.getContentPane().requestFocusInWindow(); } @Override public void keyPressed(KeyEvent e) { } @Override public void keyReleased(KeyEvent e) { } @Override public void keyTyped(KeyEvent e) { model.removeByChar(e.getKeyChar()); } public interface ModelListener { public void tileWasRemoved(Tile tile); } public class Model { private ArrayList<Tile> list = new ArrayList<Tile>(); private List<ModelListener> listeners = new ArrayList<>(25); public Model() { } public void addModelListener(ModelListener listener) { listeners.add(listener); } public void removeModelListener(ModelListener listener) { listeners.remove(listener); } protected void fireTileRemoved(Tile tile) { for (ModelListener listener : listeners) { listener.tileWasRemoved(tile); } } public void removeByChar(char value) { Iterator<Tile> iterator = list.iterator(); while (iterator.hasNext()) { Tile tile = iterator.next(); if (value == tile.getChar()) { fireTileRemoved(tile); iterator.remove(); } } } private void add(Tile tile) { list.add(tile); } private Iterable<Tile> getTiles() { return Collections.unmodifiableList(list); } } public static class Tile extends JLabel { public static Font font = new Font("Serif", Font.BOLD, 39); private char _c; public Tile(char c, Color background) { setBackground(background); setOpaque(true); _c = c; setText(convert()); } public static char randomLetter() { Random r = new Random(); char randomChar = (char) (97 + r.nextInt(25)); return randomChar; } public char getChar() { return _c; } public String convert() { return String.valueOf(getChar()); } }}怎么…
作为一般经验法则,
KeyListener使用起来很麻烦,例如,您应该使用键绑定API
import java.awt.AWTKeyStroke;import java.awt.Color;import java.awt.EventQueue;import java.awt.Font;import java.awt.GridLayout;import java.awt.event.ActionEvent;import java.util.ArrayList;import java.util.Collections;import java.util.Iterator;import java.util.List;import java.util.Random;import javax.swing.AbstractAction;import javax.swing.Action;import javax.swing.ActionMap;import javax.swing.InputMap;import javax.swing.JComponent;import javax.swing.Jframe;import javax.swing.JLabel;import javax.swing.KeyStroke;import javax.swing.UIManager;import javax.swing.UnsupportedLookAndFeelException;public class Game { public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { ex.printStackTrace(); } new Game(); } }); } private Model model; public Game() { model = new Model(); model.add(new Tile(Tile.randomLetter(), Color.WHITE)); model.add(new Tile(Tile.randomLetter(), Color.RED)); model.add(new Tile(Tile.randomLetter(), Color.GREEN)); model.add(new Tile(Tile.randomLetter(), Color.YELLOW)); Jframe frame = new Jframe(); frame.getContentPane().setLayout(new GridLayout(4, 1)); frame.setSize(500, 800); frame.setVisible(true); for (Tile tile : model.getTiles()) { frame.add(tile); KeyStroke ks = KeyStroke.getKeyStroke(tile.getChar()); String name = "typed." + tile.getChar(); Action action = new TileAction(model, tile.getChar()); registerKeyBinding((JComponent)frame.getContentPane(), name, ks, action); } model.addModelListener(new ModelListener() { @Override public void tileWasRemoved(Tile tile) { frame.remove(tile); frame.revalidate(); frame.repaint(); } }); } public void registerKeyBinding(JComponent parent, String name, KeyStroke ks, Action action) { InputMap im = parent.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); ActionMap am = parent.getActionMap(); im.put(ks, name); am.put(name, action); } public class TileAction extends AbstractAction { private Model model; private char value; public TileAction(Model model, char value) { this.model = model; this.value = value; } @Override public void actionPerformed(ActionEvent e) { model.removeByChar(value); } } public interface ModelListener { public void tileWasRemoved(Tile tile); } public class Model { private ArrayList<Tile> list = new ArrayList<Tile>(); private List<ModelListener> listeners = new ArrayList<>(25); public Model() { } public void addModelListener(ModelListener listener) { listeners.add(listener); } public void removeModelListener(ModelListener listener) { listeners.remove(listener); } protected void fireTileRemoved(Tile tile) { for (ModelListener listener : listeners) { listener.tileWasRemoved(tile); } } public void removeByChar(char value) { Iterator<Tile> iterator = list.iterator(); while (iterator.hasNext()) { Tile tile = iterator.next(); if (value == tile.getChar()) { fireTileRemoved(tile); iterator.remove(); } } } private void add(Tile tile) { list.add(tile); } private Iterable<Tile> getTiles() { return Collections.unmodifiableList(list); } } public static class Tile extends JLabel { public static Font font = new Font("Serif", Font.BOLD, 39); private char _c; public Tile(char c, Color background) { setBackground(background); setOpaque(true); _c = c; setText(convert()); } public static char randomLetter() { Random r = new Random(); char randomChar = (char) (97 + r.nextInt(25)); return randomChar; } public char getChar() { return _c; } public String convert() { return String.valueOf(getChar()); } }}有关更多详细信息,请参见如何使用键绑定。



