2014.11.17貪喫蛇------老師的修改而來

  1. <span style="font-size:18px;">package com.lovo;
    /**
     * 方向(枚舉類)
     * @author hechao
     *
     */
    public enum Direction {
    	UP, DOWN, LEFT, RIGHT
    }</span>
  2. <span style="font-size:18px;">package com.lovo;
    
    import java.awt.Color;
    import java.awt.Graphics;
    
    public class Egg {
    	private int x, y;
    	private int size = GameContext.EGG_SIZE;
    
    	public Egg() {
    		int minX = GameContext.WALL_X / 20;
    		int maxX = (GameContext.SQUARE_SIZE - GameContext.EGG_SIZE) / 20;
    		x = (int) (Math.random() * maxX + minX) * 20;
    		int minY = GameContext.WALL_Y / 20;
    		int maxY = maxX;
    		y = (int) (Math.random() * maxY + minY) * 20;
    	}
    
    	public int getX() {
    		return x;
    	}
    
    	public int getY() {
    		return y;
    	}
    
    	public void draw(Graphics g) {
    		g.setColor(Color.ORANGE);
    		g.fillOval(x, y, size, size);
    	}
    
    }
    </span>


  3. <span style="font-size:18px;">package com.lovo;
    
    public class GameContext {
    	
    	/**
    	 * 蛇的長度
    	 */
    	public static final int SNAKE_LENGTH = 1;
    	/**
    	 * 蛇頭初始位置的橫座標
    	 */
    	public static final int SNAKE_X = 260;
    	/**
    	 * 蛇頭初始位置的縱座標
    	 */
    	public static final int SNAKE_Y = 280;
    	/**
    	 * 蛇節點的大小
    	 */
    	public static final int SNAKE_SIZE = 20;
    	/**
    	 * 遊戲窗口的大小
    	 */
    	public static final int GAME_SIZE = 580;
    	/**
    	 * 遊戲場地的大小
    	 */
    	public static final int SQUARE_SIZE = 500;
    	/**
    	 * 刷新週期
    	 */
    	public static final int INTERVAL = 200;
    	/**
    	 * 圍牆起點的橫座標
    	 */
    	public static final int WALL_X = 40;
    	/**
    	 * 圍牆起點的縱座標
    	 */
    	public static final int WALL_Y = 40;
    	/**
    	 * 圍牆厚度
    	 */
    	public static final int WALL_WIDTH = 5;
    	/**
    	 * 蛋的大小
    	 */
    	public static final int EGG_SIZE = SNAKE_SIZE;
    	
    }
    </span>


  4. <pre name="code" class="java">package com.lovo;
    
    import java.awt.BasicStroke;
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Image;
    import java.awt.Stroke;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.KeyAdapter;
    import java.awt.event.KeyEvent;
    import java.awt.image.BufferedImage;
    import java.util.LinkedList;
    
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.Timer;
    
    @SuppressWarnings("serial")
    public class GameFrame extends JFrame {
    	private Image offImage = new BufferedImage(GameContext.GAME_SIZE, GameContext.GAME_SIZE, 1);
    	private Timer timer = null;
    	private int score;
    	private Snake snake = new Snake();		// 創建蛇的對象
    	private Egg egg = new Egg();			// 創建蛋的對象
    	private JLabel scoreLable;
    	private LinkedList<SnakeNode> list = snake.getList(); 
    	
    	public GameFrame() {
    		this.setTitle("貪喫蛇");
    		this.setSize(GameContext.GAME_SIZE, GameContext.GAME_SIZE);
    		this.setResizable(false);
    		this.setLocationRelativeTo(null);
    		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    		this.setLayout(null);
    		
    		this.addKeyListener(new KeyAdapter() {
    
    			@Override
    			public void keyPressed(KeyEvent e) {
    				Direction newDir = snake.getDir();
    				switch(e.getKeyCode()) {
    				case KeyEvent.VK_W:	//上
    					newDir = Direction.UP;
    					break;
    				case KeyEvent.VK_S:	// 下
    					newDir = Direction.DOWN;
    					break;
    				case KeyEvent.VK_A:	// 左
    					newDir = Direction.LEFT;
    					break;
    				case KeyEvent.VK_D:	// 右
    					newDir = Direction.RIGHT;
    					break;
    				case KeyEvent.VK_F2:
    					resetGame();
    					break;
    				}
    				if(snake.getDir() != newDir) {	// 如果新方向不同於蛇原來的方向
    					snake.changeDir(newDir);	// 調用蛇的changeDir方法修改蛇的方向
    				}
    			}
    			/**
    			 * 重置遊戲
    			 */
    			public void resetGame(){
    				score = 0;
    				list.clear();
    				snake.resetSnake();
    				timer.start();
    				egg = new Egg();
    				repaint();
    			}
    		});
    		
    		
    		timer = new Timer(GameContext.INTERVAL, new ActionListener() {
    			
    			@Override
    			public void actionPerformed(ActionEvent e) {
    				snake.move();	// 調用蛇的move方法讓蛇移動
    				if(snake.eatEgg(egg)) {	// 喫到蛋
    					snake.grow();		// 調用蛇的grow方法讓蛇變長
    					score++;
    					egg = new Egg();	// 重新創建一顆蛋
    				}
    				SnakeNode head = snake.getHead();
    				int x = head.getX();
    				int y = head.getY();
    				for(int i = 1; i < list.size(); i++){
    					SnakeNode sn = list.get(i);
    					if(sn.getX() == x && sn.getY() == y){
    						timer.stop();
    					}
    				}
    				if(x < GameContext.WALL_X || 
    						x > GameContext.WALL_X + GameContext.SQUARE_SIZE - GameContext.SNAKE_SIZE ||
    						y < GameContext.WALL_Y || 
    						y > GameContext.WALL_Y + GameContext.SQUARE_SIZE - GameContext.SNAKE_SIZE) {
    					timer.stop();
    				}
    				else {					
    					repaint();
    				}
    			}
    		});
    		scoreLable = new JLabel();
    		scoreLable.setBounds(50, 530, 100, 15);
    		GameFrame.this.add(scoreLable);	
    		timer.start();
    		
    	}
    	
    	@Override
    	public void paint(Graphics g) {	// 使用雙緩衝方式消除窗口閃爍(見下面步驟1-2-3)
    		// 1. 獲得內存中圖像的畫筆
    		Graphics offG = offImage.getGraphics();	
    		
    		// 2. 用offG在內存中繪製窗口上的所有內容
    		super.paint(offG);					// 消除殘影
    		Graphics2D g2d = (Graphics2D) offG;	// 將Graphics轉成其子類型Graphics2D並設置粗細
    		Stroke oldStroke = g2d.getStroke();	// 記錄畫筆粗細(保存現場)
    		g2d.setStroke(new BasicStroke(GameContext.WALL_WIDTH));	// 將畫筆加粗
    		offG.setColor(Color.BLACK);			// 設置畫筆爲黑色
    		int x = GameContext.WALL_X, y = GameContext.WALL_Y;
    		offG.drawRect(x, y, GameContext.SQUARE_SIZE, GameContext.SQUARE_SIZE);	// 繪製圍牆
    		g2d.setStroke(oldStroke);			// 還原畫筆粗細(恢復現場)
    		
    		snake.draw(offG);					// 調用蛇的draw方法繪製蛇 
    		egg.draw(offG);						// 調用蛋的draw方法繪製蛋
    		
    		// 3. 將內存中繪製好的圖直接畫到窗口上(雙緩衝)
    		g.drawImage(offImage, 0, 0, null);	// 第二個和第三個參數是繪圖的位置
    		scoreLable.setText("得分:" + score);
    	}
    }
    


    
    
  5. <span style="font-size:18px;">package com.lovo;
    
    class GameRunner {
    
    	public static void main(String[] args) {
    		new GameFrame().setVisible(true);
    	}
    }
    </span>


  6. <pre name="code" class="java">package com.lovo;
    
    import java.awt.Graphics;
    import java.util.LinkedList;
    
    /**
     * 蛇
     * @author 何超 
     *
     */
    public class Snake {
    	private Direction dir = Direction.LEFT;								// 方向
    	private LinkedList<SnakeNode> list = new LinkedList<SnakeNode>();	// 裝蛇的所有節點的容器(鏈表)
    	
    	/**
    	 * 構造器
    	 */
    	public Snake() {
    		// 初始化5個節點
    		for (int i = 0; i < GameContext.SNAKE_LENGTH; i++) {
    			list.add(new SnakeNode(GameContext.SNAKE_X + i * GameContext.SNAKE_SIZE, GameContext.SNAKE_Y));
    		}
    	}
    	/**
    	 * 獲得蛇結點容器
    	 * @return 蛇結點容器
    	 */
    	public LinkedList<SnakeNode> getList(){
    		return list;
    	}
    	/**
    	 * 改變方向
    	 * @param newDir 新的方向
    	 */
    	public void changeDir(Direction newDir) {
    		if(!((dir == Direction.LEFT && newDir == Direction.RIGHT) ||
    			(dir == Direction.RIGHT && newDir == Direction.LEFT) ||
    			(dir == Direction.UP && newDir == Direction.DOWN) ||
    			(dir == Direction.DOWN && newDir == Direction.UP))) {
    			dir = newDir;
    		}
    	}
    	
    	/**
    	 * 獲得蛇前進的方向
    	 */
    	public Direction getDir() {
    		return dir;
    	}
    	
    	/**
    	 * 獲得蛇頭
    	 */
    	public SnakeNode getHead() {
    		return list.get(0);	// 容器中的第一個節點就是蛇頭
    	}
    	
    	/**
    	 * 移動
    	 */
    	public void move() {
    		grow();
    		list.removeLast();			// 尾巴刪一個節點
    	}
    	
    	/**
    	 * 喫蛋
    	 * @param egg 蛋
    	 * @return 喫到蛋返回true否則返回false
    	 */
    	public boolean eatEgg(Egg egg) {
    		SnakeNode head = getHead();
    		return head.getX() == egg.getX() && head.getY() == egg.getY();
    	}
    	
    	/**
    	 * 長長一節
    	 */
    	public void grow() {
    		SnakeNode head = getHead();
    		int x = head.getX(), y = head.getY();
    		int size = GameContext.SNAKE_SIZE;
    		switch(dir) {
    		case UP:
    			y -= size;
    			break;
    		case DOWN:
    			y += size;
    			break;
    		case LEFT:
    			x -= size;
    			break;
    		case RIGHT:
    			x += size;
    			break;
    		}
    		SnakeNode newHead = new SnakeNode(x, y);	// 創建新的蛇頭節點
    		list.addFirst(newHead);		// 頭上加一個節點
    	}
    	/**
    	 * 重置
    	 */
    	public void resetSnake() {
    		// 初始化5個節點
    		for (int i = 0; i < GameContext.SNAKE_LENGTH; i++) {
    			list.add(new SnakeNode(GameContext.SNAKE_X + i * GameContext.SNAKE_SIZE, GameContext.SNAKE_Y));
    		}
    	}
    	/**
    	 * 繪製蛇
    	 */
    	public void draw(Graphics g) {
    		// 繪製蛇身上的每個節點
    		for(SnakeNode node : list) {
    			node.draw(g);
    		}
    	}
    	
    }
    


    
    
  7. <span style="font-size:18px;">package com.lovo;
    
    import java.awt.Color;
    import java.awt.Graphics;
    
    /**
     * 蛇身上的節點
     * @author 駱昊
     *
     */
    public class SnakeNode {
    	private int x, y;
    	private int size = GameContext.SNAKE_SIZE;
    	
    	/**
    	 * 構造器
    	 */
    	public SnakeNode(int x, int y) {
    		this.x = x;
    		this.y = y;
    	}
    	
    	/**
    	 * 蛇節點的橫座標
    	 */
    	public int getX() { return x; }
    	
    	/**
    	 * 蛇節點的縱座標
    	 */
    	public int getY() { return y; }
    
    	/**
    	 * 繪製
    	 */
    	public void draw(Graphics g) {
    		g.setColor(Color.GREEN);
    		g.fillRect(x, y, size, size);
    		g.setColor(Color.BLACK);
    		g.drawRect(x, y, size, size);
    	}
    }
    </span>


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章