java 贪吃蛇 想将MyFrame类中的菜单、键盘监听、事件监听、和绘制界面分离出来

小曾公子 发布于 2016/12/12 22:22
阅读 800
收藏 0
弄了好长时间都没有做好,所以拜托各位大神们帮帮忙,小弟在此谢过了~!~
package zeng;

public class Main
{
	public static void main(String[] args){
		new MyFrame();
	}
}

package zeng;

 public class Node {
	int x;
	int y;

	public Node(int x, int y) {
		this.x = x;
		this.y = y;
	}
}

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<Node> nodeArray = new LinkedList<Node>();
	
	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;
	}
}



加载中
OSCHINA
登录后可查看更多优质内容
返回顶部
顶部