找了好多案例,发现都是贴图的,要么就是代码无法运行的,好不容易找到一个,结果代码粘贴的辣眼睛。


接下来就是整个贪吃蛇,包结构        

Java贪吃蛇不会死自动吃东西 java贪吃蛇总结_java

贪吃蛇这个原理:

  • 蛇身打印,利用矩形填充打印方块,几个方块存储在数组中,按顺序打印出来。数组存储的数据时按键方向判断之后对相应方向、比如上或者下加上高度或者宽度。
  • 蛇移动,就是不停刷新界面,重新绘制方块。方块的绘制上面连接里面有,刷新方块上面连接也有。
  • 键盘控制方向,键盘是new一个键盘监视器,把他给SnakeClient,然后new SnakeClient时候就可以调用。每个按键都有自己的代码,用getKeyCode返回按键值,然后用一个case给方向Direction赋值。其中方向,用了一个枚举类型来存储四个方向,不用枚举应该也可以,使用字符串常量,或者一个变量给四个值来判断方向,我还没有尝试,大家有兴趣可以自己试试。
  • 吃食物,用一个矩形区域检测,这个是java自带的,直接调用Rectangle中的这个检测函数。把food的矩形和蛇头的矩形区域比较。比较之后再次重新调用food的set函数设置food下次出现位置。
  • this涉及的比较多,函数重写有一点,就是paint,还有repaint调用。学会这个对对象和类有挺大帮助。

代码缺点:

  1. 还没实现蛇身碰撞检测,这会加大代码量,本代码力求最简单
  2. 还没实现边界检测,蛇会跑到界面外
  3. 还没实现计分板功能,虽然这个需求比较简单,但是我们的目标是尽量少的代码,让初学者能看懂

第一个是显示界面,运用线程启动,用刷新来重新绘制图形

package cn.led.snake;


import java.awt.*;
import java.awt.event.*;

public class SnakeClient extends Frame{	
	Snake mySnake = new Snake(this);
	Food food = new Food(this);

	public void lanch(){
		this.setBounds(200,100, 700,700); //设置窗体大小和位置
		this.setTitle("我是贪吃蛇");
		this.setVisible(true); //使用该属性才能显示窗体
		this.setBackground(Color.black);
		//实现程序运行关闭的功能
		this.addWindowListener(new WindowAdapter(){
			public void windowClosing(WindowEvent e){
				System.exit(-1);
			}
		});
		this.addKeyListener(new KeyMointer());//调用键盘,不启用这个无法开启键盘控制
		new Thread(new PaintThread()).start();//开启线程
	}

	//画图函数,这个是重写paint,貌似是Frame类的内置函数
	public void paint(Graphics g){
		mySnake.paint(g);
		food.paint(g);
	}

	class PaintThread implements Runnable{
		public void run() {
			//while(true)保持蛇能一直运行
			while(true){
				repaint();
				try {
					//物体运行太快,肉眼无法追踪,这是减慢速度,使得肉眼能跟上刷新速度
					Thread.sleep(250);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}				
			}
		}
	}

	//键盘控制
	class KeyMointer extends KeyAdapter{
		public void keyPressed(KeyEvent e){
			mySnake.keyPress(e);
		}
	}

	public static void main(String[] args){
		SnakeClient snakeClient = new SnakeClient();
		snakeClient.lanch();
	}
}

第二个是蛇的绘制

package cn.led.snake;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;


public class Snake {
	final static int WIDTH = 20;//蛇身的宽
	final static int HEIGHT = 20;//蛇身的高
	final static int maxLong = 900;//蛇最多节数	
	enum Direction{Left,Up,Right,Down};//方向枚举

	int number = 5;//蛇身初始化节数

	int[] x = new int[maxLong];//蛇身x轴位置
	int[] y = new int[maxLong]; //蛇身y轴位置
	Direction snakeDirection ; 
	SnakeClient sc;

	public Snake(SnakeClient sn) {
		this.number = 5;
		//初始化蛇身,不初始化可能会随机出现在界面外
		for(int i=0;i<=number;i++){
			x[i] = 100;
			y[i] = 100;
		}
		//初始方向
		this.snakeDirection = Direction.Right;
		this.sc = sn;
	}

	public void move() {
		if(this.snakeDirection==Direction.Down) {
			for (int i = 0; i < number; i++) {
				x[i] = x[i+1];
				y[i] = y[i+1];
			}
			y[number] = y[number]+HEIGHT;
		}
		else if(this.snakeDirection==Direction.Right) {
			for (int i = 0; i < number; i++) {
				x[i] = x[i+1];
				y[i] = y[i+1];
			}
			x[number] = x[number]+WIDTH;
		}
		else if(this.snakeDirection==Direction.Up) {
			for (int i = 0; i < number; i++) {
				x[i] = x[i+1];
				y[i] = y[i+1];
			}
			y[number] = y[number]-HEIGHT;
		}
		if(this.snakeDirection==Direction.Left){
			for (int i = 0; i < number; i++) {
				x[i] = x[i+1];
				y[i] = y[i+1];
			}
			x[number] -= WIDTH;
		}
	}

	//方向键对蛇的控制
	public void keyPress(KeyEvent e){
		int press = e.getKeyCode();
		switch(press){
		case KeyEvent.VK_LEFT:
			this.snakeDirection = Direction.Left;
			break;
		case KeyEvent.VK_UP:
			this.snakeDirection = Direction.Up;
			break;
		case KeyEvent.VK_RIGHT:
			this.snakeDirection = Direction.Right;
			break;
		case KeyEvent.VK_DOWN:
			this.snakeDirection = Direction.Down;
			break;
		}
	}

	public void paint(Graphics g){
		Color c = g.getColor();
		g.setColor(Color.blue);  //设置颜色为蓝色
		for (int i = 0; i <=number; i++) { //最后一个画出的是蛇头
			if (i==number) {
				g.setColor(Color.yellow);
				g.fillRect(x[number], y[number], 20, 20); //蛇头设置成黄色
			}
			g.fillRect(x[i], y[i], 20, 20); //填充矩形
		}
		g.setColor(c);
		move();
		eatFood(this.sc.food);
	}


	//蛇吃食物
	public void eatFood(Food food){
		//判断是否产生碰撞,返回true则刷新食物
		if(this.getRec().intersects(food.getRec())){ 
			number++; //吃到食物蛇长度+1
			x[number] = sc.food.getX();
			y[number] = sc.food.getY();
			this.sc.food.setX(((int)(Math.random()*29))*Snake.WIDTH);
			this.sc.food.setY((int)(Math.random()*29+1)*Snake.HEIGHT);
		}
	}

	public Rectangle getRec(){
		return new Rectangle(x[number],y[number],WIDTH,HEIGHT);
	}


}

第三个是食物绘制代码

package cn.led.snake;

import java.awt.*;



public class Food {
	public static int WIDTH = 20;
	public static int HEIGHT = 20;
	private boolean isLive = true;//判断食物是否还在
	int x ,y;//初始化食物出现地点
	SnakeClient ms;
	
	
	public Food(SnakeClient ms){
		x = ((int)(Math.random()*50))*SnakeClient.WIDTH;
		y = (int)(Math.random()*50)*SnakeClient.HEIGHT;
		isLive = true;
		this.ms = ms;
	}
	
	public boolean isLive() {
		return isLive;
	}

	public void setLive(boolean isLive) {
		this.isLive = isLive;
	}

	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}

	public int getY() {
		return y;
	}

	public void setY(int y) {
		this.y = y;
	}

	//画食物
	public void paint(Graphics g){
		if(isLive==true){
			Color c = g.getColor();
			g.setColor(Color.red);
			g.fillRect(x, y, WIDTH, HEIGHT);
		}
	}
	
	public Rectangle getRec(){
		return new Rectangle(x,y,WIDTH,HEIGHT);
	}
}

 

运行效果图---------动图-----------

Java贪吃蛇不会死自动吃东西 java贪吃蛇总结_初始化_02