遊戲很簡單 但是實現起來也要動腦子的(難道我做別的東西都沒用腦子麼?)
雖然寫出來以後覺得不難
我的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(); } }