贪吃蛇 Java版(基于GUI)

完全自己写的小程序,主要难点在控制蛇身的运动上,已经较好的解决,不完善的地方是没有进行画面双缓冲,但刷新频率较低,所以闪烁现象较不明显。

界面如下:




import java.awt.*;
import java.awt.event.*;
import java.util.List;
import java.util.ArrayList;


public class SnakeClient extends Frame {
	/**
	 * 贪吃蛇主客户端
	 * 蛇头可动,鸡蛋随机出现
	 * 0.4蛇身跟随着运动
	 */
	private static final long serialVersionUID = 1L;
	private static int WIDTH=406,HEIGHT=428;
	List<Snake> snakes=new ArrayList<Snake>();
	List<Egg> eggs=new ArrayList<Egg>();
	Snake s=new Snake(3,25,true,0,this);
	Snake body1=new Snake(3,45,false,1,this);
	Snake body2=new Snake(3,65,false,2,this);
	
	boolean eat=false;
	
	
	Egg e=new Egg();
	
	public static void main(String []args){
		SnakeClient sc=new SnakeClient();
		sc.launchFrame();
        
	}
	
	void launchFrame(){
		this.setBounds(100, 100, WIDTH, HEIGHT);
		this.setVisible(true);
		this.setResizable(false);
		this.addWindowListener(new WinCloseMonitor());
//		bug2 :忘记加入监听,导致方向不能控制
		this.addKeyListener(new KeyMonitor());
		new Thread(new MyThread()).start();
		snakes.add(s);
		eggs.add(e);		
		
	}
	
	class WinCloseMonitor extends WindowAdapter{
//      bug1 错把windowClosing 写成WindowClosing
//		以后重写函数时注意复制或利用Eclipse的重写功能
		public void windowClosing(WindowEvent e){
			System.exit(0);
		}
		
	}
	
	public void paint(Graphics g){
		for(int i=0;i<snakes.size();i++){
			Snake sn=snakes.get(i);
			if(s.hitSnake(sn)&&!sn.head){
				snakes.removeAll(snakes);
				return;
			}
			sn.draw(g);
			if(sn.eatEgg(e)) eat=true;
		}
		if(eat){
			snakes.add(new Snake(snakes.get(snakes.size()-1).oldX,snakes.get(snakes.size()-1).oldY,
					false,snakes.size(),this));
			eat=false;
			eggs.remove(e);
			e=new Egg();
			eggs.add(e);
		}
			e.draw(g);
		
	}
	
	class MyThread implements Runnable{
		@Override
		public void run() {
			while(true){
				repaint();
				try {
					Thread.sleep(350);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}	
	}
	
	class KeyMonitor extends KeyAdapter{
		@Override
		public void keyPressed(KeyEvent e) {
			s.keyPressed(e);
		}
		
	}
	
}

import java.awt.*;
import java.awt.event.KeyEvent;
public class Snake {
	int x,y,oldX,oldY;
	int id;
	private static int WIDTH=20,HEIGHT=20,dx=20,dy=20;
	static Direction dir=Direction.STOP;
	boolean head;//判断是否是是蛇头
	SnakeClient sc=null;
	private boolean live;
	
	public Snake(int x, int y, boolean head,int id,SnakeClient sc) {
		this.x = x;
		this.y = y;
		this.head = head;
		this.id=id;
		this.sc=sc;
	}
	
	void draw(Graphics g){
		move();
		Color c=g.getColor();
		if(head){
			g.setColor(Color.red);
		}else{
			g.setColor(Color.green);
		}
		g.fillRect(x, y, WIDTH, HEIGHT);
		g.setColor(Color.black);
		g.drawRect(x, y, WIDTH, HEIGHT);
		g.setColor(c);
		
	}
    
	public void keyPressed(KeyEvent e) {
		if(!head) return;
		int key=e.getKeyCode();
		switch(key){
			case KeyEvent.VK_UP:
				if(Direction.D==dir) break;
				dir=Direction.U;
				break;
			case KeyEvent.VK_DOWN:
				if(Direction.U==dir) break;
				dir=Direction.D;
				break;
			case KeyEvent.VK_LEFT: 
				if(Direction.R==dir) break;
				dir=Direction.L;
				break;
			case KeyEvent.VK_RIGHT: 
				if(Direction.L==dir) break;
				dir=Direction.R;
				break;
			case KeyEvent.VK_F2:
				if(!live){
					sc.snakes.add(sc.s);
				}
		}
	}
	
//	从蛇头到蛇尾编号id从0递增,根据id来移动蛇身,具体如下,记录下当前位置oldX,oldY
//	当move()时,根据id-1的蛇身改变自己的位置;
	void move(){
		oldX=x;
		oldY=y;
		if(!head){
			if(dir==Direction.STOP) return;
			for(int i=0;i<sc.snakes.size();i++){
				if(sc.snakes.get(i).id==id-1){
					x=sc.snakes.get(i).oldX;
					y=sc.snakes.get(i).oldY;
				}
			}
			return;
		}		
		switch(dir){

		case U: 
			y-=dy;
			break;
		case R:
			x+=dx;
			break;
		case D:
			y+=dy;
			break;
		case L:
			x-=dx;
			break;
		case STOP:
			break;
		}
		//新版贪吃蛇,当到达边界时从另外一边出来
		if(x<3) x=383;
		if(x>383) x=3;
		if(y<25) y=405;
		if(y>405) y=25;
	}
	
	public Rectangle getRect(){
		return new Rectangle(x,y,WIDTH-1,HEIGHT-1);
	}
	
	boolean eatEgg(Egg e){
		if(!head) {
			return false;
		}
		else{
			return e.getRect().intersects(this.getRect());
		}
	}
	
	boolean hitSnake(Snake s){
		if(!head) return false;
		if(s.getRect().intersects(this.getRect())){
			live = false;
			return true;
		}else{
			return false;
		}
	}
}

import java.awt.*;
import java.util.*;

public class Egg {

	private static int WIDTH=20,HEIGHT=20;
	private static Random r=new Random();
	int x=3+20*r.nextInt(20);
	int y=25+20*r.nextInt(20);
	
	void draw(Graphics g){
		Color c=g.getColor();
		g.setColor(Color.pink);

		g.fillOval(x, y, WIDTH, HEIGHT);
		g.setColor(c);
	}
	
	public Rectangle getRect(){
		return new Rectangle(x,y,WIDTH,HEIGHT);
	}
}

public enum Direction {
	U,R,D,L,STOP;
}















  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值