想把MyFrame里面的菜单、键盘监听、事件监听、绘制界面分离出来 各自形成一个类 ,
但是弄了好久也没有做出来,所以请教各位大神们,怎么讲这些分解出来。谢谢了~!~
(由于没有C币了 , 所以。。。抱歉了)
package zeng;
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Iterator;
import java.util.LinkedList;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
public class MyFrame extends KeyAdapter implements ActionListener{
JFrame frame ;
Canvas canvas;
Container container;
JLabel label; // 计分
Snake snake = null; // 蛇
public static final int DEFAULT_WIDTH = 800; // 界面宽
public static final int DEFAULT_HEIGHT = 600; // 界面高
public static final int nodeWidth = 10; // 结点宽
public static final int nodeHeight = 10; // 结点高
JMenuItem start = new JMenuItem("开始");
JMenuItem exit = new JMenuItem("退出");
JMenuItem paused = new JMenuItem("暂停/开始");
JMenuItem speedUp = new JMenuItem("加速");
JMenuItem speedDown = new JMenuItem("减速");
JMenuItem about = new JMenuItem("关于贪吃蛇");
JMenuBar menuBar;
JMenu file;
JMenu function;
JMenu help;
// 初始化游戏界面
public MyFrame()
{
// 设置界面
frame = new JFrame();
frame.setTitle("贪吃蛇");
frame.setLocation(200,200);
container = frame.getContentPane();
label = new JLabel("分数:", JLabel.CENTER);
container.add(label, BorderLayout.SOUTH);
canvas = new Canvas();
canvas.setSize(DEFAULT_WIDTH-20, DEFAULT_HEIGHT-20);
container.add(canvas, BorderLayout.CENTER);
menuBar = new JMenuBar();
frame.setJMenuBar(menuBar);
file = new JMenu("文件");
function = new JMenu("功能");
help = new JMenu("帮助");
file.add(start);
start.addActionListener(this);
file.add(exit);
exit.addActionListener(this);
function.add(paused);
paused.addActionListener(this);
function.add(speedUp);
speedUp.addActionListener(this);
function.add(speedDown);
speedDown.addActionListener(this);
help.add(about);
about.addActionListener(this);
menuBar.add(file);
menuBar.add(function);
menuBar.add(help);
frame.addKeyListener(this);
frame.pack();
frame.setResizable(false); // 窗口大小不能变化
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 窗口关闭方式
frame.setVisible(true); // 显示
begin(); // 开始游戏
}
// 绘制游戏界面(包括蛇和食物)
public void repaint(){
Graphics g = canvas.getGraphics();
// 背景
g.setColor(Color.LIGHT_GRAY);
g.fillRect(0, 0, DEFAULT_WIDTH, DEFAULT_HEIGHT);
// 蛇
g.setColor(Color.BLACK);
LinkedList<Node> snakeNode = snake.nodeArray;
Iterator<Node> it = snakeNode.iterator();
while (it.hasNext()) {
Node n = (Node) it.next();
drawNode(g, n);
}
// 食物
g.setColor(Color.RED);
Node n = snake.food;
drawNode(g, n);
updateScore();
}
// 绘画某一结点(蛇身或食物)
private void drawNode(Graphics g, Node n) {
g.fillRect(n.x * nodeWidth, n.y * nodeHeight, nodeWidth - 1, nodeHeight - 1);
}
// 更新分数
public void updateScore() {
String s = "分数:" + snake.score;
label.setText(s);
}
// 游戏开始,放蛇
void begin() {
if (snake == null || !snake.running) {
snake = new Snake(this, DEFAULT_WIDTH / nodeWidth, DEFAULT_HEIGHT / nodeHeight);
(new Thread(snake)).start();
}
}
// 菜单监听事件
@Override
public void actionPerformed(ActionEvent e){
if(snake.running){
if(e.getSource() == start){ // 开始
snake.running = false;
begin();
}
else if(e.getSource() == exit){ // 退出
int select=JOptionPane.showConfirmDialog(null, "确认退出", "提示",
JOptionPane.OK_CANCEL_OPTION, JOptionPane.INFORMATION_MESSAGE);
if(select==JOptionPane.OK_OPTION){
System.exit(0);
}
}
else if(e.getSource() == paused){ // 暂停/继续
snake.changePauseState();
}
else if(e.getSource() == speedUp){ // 加速
snake.speedUp();
}
else if(e.getSource() == speedDown){// 减速
snake.speedDown();
}
else if(e.getSource() == about){ // 关于贪吃蛇
JOptionPane.showMessageDialog(null, "贪吃蛇\n"+"制作人:小曾 计本1501\n"
+" 按上下左右键控制蛇的方向\n"
+" 按‘+’或PageUp 加速 、按‘-’或PageDown加速\n"
+" 按空格或p\t暂停/开始");
}
}
}
// 键盘监听
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (snake.running)
switch (keyCode) {
case KeyEvent.VK_UP: // 方向键:上
snake.changeDirection(Snake.UP);
break;
case KeyEvent.VK_DOWN: // 方向键:下
snake.changeDirection(Snake.DOWN);
break;
case KeyEvent.VK_LEFT: // 方向键:左
snake.changeDirection(Snake.LEFT);
break;
case KeyEvent.VK_RIGHT: // 方向键:右
snake.changeDirection(Snake.RIGHT);
break;
case KeyEvent.VK_ADD: // ‘+’键
case KeyEvent.VK_PAGE_UP: // PageUp键
snake.speedUp(); // 加速
break;
case KeyEvent.VK_SUBTRACT: // ‘-’键
case KeyEvent.VK_PAGE_DOWN: // PageDown键
snake.speedDown(); // 减速
break;
case KeyEvent.VK_SPACE: // 空格键
case KeyEvent.VK_P: // P键
snake.changePauseState(); // 暂停或继续
break;
default:
}
// 重新开始(回车键、S键)
if (keyCode == KeyEvent.VK_S || keyCode == KeyEvent.VK_ENTER) {
snake.running = false;
begin();
}
}
}
package zeng;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Random;
import javax.swing.JOptionPane;
public class Snake implements Runnable{
Node food;
MyFrame myFrame;
LinkedList nodeArray = new LinkedList();
int maxX;
int maxY;
boolean[][] matrix;
int timeInterval = 200;
int score = 0;
boolean running = false;
boolean paused = false;
double speedChangeRate = 0.75;
int direction = 2;
public static final int UP = 2;
public static final int DOWN = 4;
public static final int LEFT = 1;
public static final int RIGHT = 3;
// 初始化界面
public Snake(MyFrame myFrame, int maxX, int maxY){
this.myFrame = myFrame;
this.maxX = maxX;
this.maxY = maxY;
matrix = new boolean[maxX][];
for (int i = 0; i < maxX; ++i) {
matrix[i] = new boolean[maxY];
Arrays.fill(matrix[i], false);
}
int initArrayLength = maxX > 20 ? 10 : maxX / 2;
for (int i = 0; i < initArrayLength; ++i) {
int x = maxX / 2 + i;
int y = maxY / 2;
nodeArray.addLast(new Node(x, y));
matrix[x][y] = true;
}
food = createFood();
matrix[food.x][food.y] = true;
}
// 改变方向
public void changeDirection(int newDirection) {
if (direction % 2 != newDirection % 2) {
direction = newDirection;
}
}
// 生成食物和放置位置
private Node createFood() {
int x = 0;
int y = 0;
do {
Random r = new Random();
x = r.nextInt(maxX);
y = r.nextInt(maxY);
} while (matrix[x][y]);
return new Node(x, y);
}
// 蛇移动
public boolean moveOn() {
Node n = (Node) nodeArray.getFirst();
int x = n.x;
int y = n.y;
switch (direction) {
case UP:
y--;
break;
case DOWN:
y++;
break;
case LEFT:
x--;
break;
case RIGHT:
x++;
break;
}
if ((0 <= x && x < maxX) && (0 <= y && y < maxY)) {
if (matrix[x][y]) { // 吃到食物或者撞到身体
if (x == food.x && y == food.y) { // 吃到食物
nodeArray.addFirst(food); // 在头部加上一结点
score += 10;
food = createFood();
matrix[food.x][food.y] = true;
return true;
} else
return false; // 撞到身体
} else { // 什么都没有碰到
nodeArray.addFirst(new Node(x, y)); // 加上头部
matrix[x][y] = true;
n = (Node) nodeArray.removeLast(); // 去掉尾部
matrix[n.x][n.y] = false;
return true;
}
}
return false; // 越界(撞到墙壁)
}
// 蛇运动线程
public void run() {
running = true;
while (running) {
try {
Thread.sleep(timeInterval);
} catch (Exception e) {
break;
}
if (!paused) {
if (moveOn()) { // 未结束
myFrame.repaint();
} else { // 游戏结束
JOptionPane.showMessageDialog(null, "GAME OVER", "Game Over", JOptionPane.INFORMATION_MESSAGE);
break;
}
}
}
running = false;
}
// 加速
public void speedUp() {
timeInterval *= speedChangeRate;
}
// 减速
public void speedDown() {
timeInterval /= speedChangeRate;
}
// 暂停/继续
public void changePauseState() {
paused = !paused;
}
}
package zeng;
public class Node {
int x;
int y;
public Node(int x, int y) {
this.x = x;
this.y = y;
}
}
package zeng;
public class Main
{
public static void main(String[] args){
new MyFrame();
}
}