贪吃蛇的简单实现

游戏很简单 但是实现起来也要动脑子的(难道我做别的东西都没用脑子么?)

虽然写出来以后觉得不难 

我的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();
	}
}


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