貪吃蛇的簡單實現

遊戲很簡單 但是實現起來也要動腦子的(難道我做別的東西都沒用腦子麼?)

雖然寫出來以後覺得不難 

我的GUI做的不好 見笑O(∩_∩)O~

初學者可以參考一下 老鳥請無視吧

時間倉促 沒有完善

現在的已知問題 

1.Applet模式運行的時候 不能自動設置焦點  (百度了許久沒有答案 求大神指點)

2.遊戲偶爾會產生ConcurrentModificationException 

原因貌似是我在處理KeyListner的時候沒有判斷 迭代器是否在迭代就操作鏈表造成的,目前無解

先這樣 有新的發現隨時更新微笑

/*
 * 貪吃蛇
 * 2011/10/05
 * LSN
 */
package com.lsn.Snake;
/**
 * JDK 1.6 Eclipse 3.6編譯通過
 * 操作方法:1.上下左右 移動蛇頭 
 * 			2. 回車暫停恢復遊戲
 * 
 * 待解決問題 :程序以applet方式運行時 不能自動設置焦點到applet
 */
import java.awt.Color;
import java.awt.Event;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.util.Iterator;
import java.util.LinkedList;

import javax.swing.JApplet;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

public class Snake extends JApplet implements Runnable,KeyListener{
	//方向常量
	
	private static final int[] DIR_UP={0,-1};
	private static final int[] DIR_DOWN={0,1};
	private static final int[] DIR_LEFT={-1,0};
	private static final int[] DIR_RIGHT={1,0};
	
	//屏幕的寬度和高度
	private static final int SCR_W=16*21+32;
	private static final int SCR_H=16*21+32;
	
	//遊戲運行狀態
	private static final int GS_RUNNING=1;
	private static final int GS_PAUSED=-1;
	
	private LinkedList<int[]> snake;				//蛇體 用鏈表來存
	
	//蛇頭位置和運動方向
	private int snakeHeadPositionX;
	private int snakeHeadPositionY;
	private int[] snakeHeading;

	private BufferedImage ofs;						//圖像緩衝 Off Screen Buffer
	
	//果子的位置
	private int appleX;
	private int appleY;
	

	private boolean gameOver=false;					//遊戲結束的標誌
	private int score;								//得分
	private int hiscore=0;							//最高得分

	private int gameStatus=GS_RUNNING;				//遊戲狀態
	
	
	@Override
	public void init() {
		//初始化 蛇
		snake=new LinkedList<int[]>();
		for(int i=0;i<4;i++){
			snake.addFirst(DIR_UP);
		}
		//初始化蛇頭
		snakeHeading=DIR_UP;
		snakeHeadPositionX=10;
		snakeHeadPositionY=10;
		
		//初始化遊戲狀態
		gameOver=false;
		score=0;
		ofs=new BufferedImage(SCR_W, SCR_H, BufferedImage.TYPE_4BYTE_ABGR);
		
		//隨機產生一個果子O(∩_∩)O~
		randomApple();
		
	}

	//隨機產生果子 
	private void randomApple() {
		
		appleX=(int)(Math.random()*21);
		appleY=(int)(Math.random()*21);
		if (appleX==snakeHeadPositionX && appleY==snakeHeadPositionY) randomApple();
		if (appleX==0 || appleY==0 || appleX==22 || appleY==22 || onSnake(appleX,appleY)) randomApple();
		
	}
	
	//判斷指定座標是否在蛇身上
	private boolean onSnake(int x, int y) {
		
		Iterator<int[]> it=snake.iterator();
		
		int sx=snakeHeadPositionX;
		int sy=snakeHeadPositionY;
		while(it.hasNext()){
			int[] d=it.next();
			sx+=d[0]*-1;
			sy+=d[1]*-1;
			if (x==sx && y==sy) return true;
		}

		return false;
	}
	
	//構造方法中加入鍵盤監聽器設置焦點
	public Snake() {
		addKeyListener(this);
		this.requestFocus();
	}
	@Override
	public void start() {
		new Thread(this).start();
	}
	
	//主線程
	@Override
	public void run() {
		while(true){
			while(!gameOver){
				if(gameStatus==Snake.GS_RUNNING){//判斷遊戲是否運行中
					gameProcess();
					this.repaint();
				}
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {

					e.printStackTrace();
				}
				
			}
			//遊戲結束處理
			JOptionPane.showMessageDialog(this, "遊戲結束\n得分:"+score+"\n最高分"+hiscore, "貪吃蛇", JOptionPane.INFORMATION_MESSAGE);
			this.init();
			
		}
	}

	//遊戲主處理
	private void gameProcess() {
		//修正:蛇頭運動和蛇運動不能分開
		//蛇頭運動
		snakeHeadPositionX+=snakeHeading[0];
		snakeHeadPositionY+=snakeHeading[1];
		//蛇運動
		snake.addFirst(snakeHeading);
		snake.removeLast();	

		//檢查蛇頭
		check(snakeHeadPositionX,snakeHeadPositionY);
		
	}
		
	//檢查蛇頭
	private void check(int x, int y) {
		if(x==0 || y==0 || x==22 || y==22 || onSnake(x,y)){
			gameOver=true;
		}
		if (appleX==x && appleY==y){
			score+=10;
			if(hiscore<score){
				hiscore=score;
			}
			snake.addFirst(snakeHeading);
			randomApple();
		}
		
	}

	//繪製圖形
	@Override
	public void update(Graphics g) {
		paint(g);
	}
	

	@Override
	public void paint(Graphics g) {
		drawMap(ofs);
		g.drawImage(ofs, 0, 0, this);
	}
	
	
	private void drawMap(BufferedImage ofs2) {
		Graphics2D pen=ofs2.createGraphics();
		pen.setColor(Color.green);
		pen.clearRect(0, 0, SCR_W, SCR_H);
		pen.setColor(Color.magenta);
		for(int i=0;i<23;i++){
			pen.fillRoundRect(i*16, 0, 13, 13, 3, 3);
			pen.fillRoundRect(i*16, SCR_H-16, 13, 13, 3, 3);
			pen.fillRoundRect(0, i*16, 13, 13, 3, 3);
			pen.fillRoundRect(SCR_W-16, i*16, 13, 13, 3, 3);
		}
		Iterator<int[]> it=snake.iterator();
		
		//畫蛇頭
		pen.setColor(Color.red);
		pen.fillRoundRect(snakeHeadPositionX*16, snakeHeadPositionY*16, 13, 13, 3, 3);
		
		int dx=snakeHeadPositionX;
		int dy=snakeHeadPositionY;
		//畫蛇身
		pen.setColor(Color.green);
		while(it.hasNext()){
			int[] d=it.next();
			dx+=d[0]*-1;
			dy+=d[1]*-1;
			pen.fillRoundRect(dx*16, dy*16, 13, 13, 3, 3);
		}
		
		//畫蘋果
		pen.setColor(Color.orange);
		pen.fillRoundRect(appleX*16, appleY*16, 13, 13, 3, 3);
	}
	@Override
	public void keyTyped(KeyEvent e) {
	}

	//處理鍵盤事件
	@Override
	public void keyPressed(KeyEvent e) {
		
		switch(e.getKeyCode()){
			case KeyEvent.VK_UP:
				if (snakeHeading==DIR_UP || snakeHeading==DIR_DOWN){
					break;
				} else{
					snakeHeading=DIR_UP;
				}
				break;
			case KeyEvent.VK_DOWN:
				snakeHeading=snake.getFirst();
				if (snakeHeading==DIR_UP || snakeHeading==DIR_DOWN){
					break;
				} else{
					snakeHeading=DIR_DOWN;
				}				
				break;
			case KeyEvent.VK_LEFT:
				snakeHeading=snake.getFirst();
				if (snakeHeading==DIR_LEFT || snakeHeading==DIR_RIGHT){
					break;
				} else{
					snakeHeading=DIR_LEFT;
				}				
				break;
			case KeyEvent.VK_RIGHT:
				snakeHeading=snake.getFirst();
				if (snakeHeading==DIR_LEFT || snakeHeading==DIR_RIGHT){
					break;
				} else{
					snakeHeading=DIR_RIGHT;
				}				
				break;
			case KeyEvent.VK_ESCAPE:
				System.exit(0);
				break;
			case KeyEvent.VK_ENTER:
				gameStatus=-gameStatus;
				break;
		}
	}

	@Override
	public void keyReleased(KeyEvent e) {
		// TODO Auto-generated method stub
		
	}
	//主方法 處理application方式運行
	public static void main(String[] args) {
		new JFrame("貪吃蛇"){
			private void init(){
				this.setBounds(100, 100, SCR_W+5, SCR_H+25);
				
				Snake game=new Snake();
				game.init();
				game.start();
				
				this.add("Center",game);
				this.setVisible(true);
				game.requestFocus();
			}
			protected void processEvent(java.awt.AWTEvent e) {
				if (e.getID()==Event.WINDOW_DESTROY){
					System.exit(0);
				}
			}
		}.init();
	}
}


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