java 简单版贪吃蛇小游戏

     在利用java编程的时候,我们应该用面向对象的编程思想来写。

   贪吃蛇游戏中,你应该要知道有几个对象,每个对象中应该有森马方法和属性。

GamePanel类    //显示类 

Void display();          //显示

Food类    //食物类

boolean isSnakeEatFood(Snake);  //判断蛇是否吃到食物

   void drawMe();    //显示食物

Snake类    //     

 void move();   //移动

   void  changeDirection();  //改变方向

   void eatFood();    //吃食物

   boolean isEatBody();  //判断是否吃到自己

   void drawMe();    //显示自己

Ground类  //障碍物类

boolean isSnakeEatRock(Snacke);  //判断蛇是否吃到石头

   void drawMe();  //显示自己

Controller类  //业务逻辑来类

Controller.java

package cn.itcast.snake.controller;

import java.awt.Point;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Random;

import cn.itcast.snake.entities.Food;
import cn.itcast.snake.entities.Ground;
import cn.itcast.snake.entities.Snake;
import cn.itcast.snake.listener.SnakeListener;
import cn.itcast.snake.util.Global;
import cn.itcast.snake.view.GamePanel;
//控制器
//处理逻辑,处理按钮
public class Controller extends KeyAdapter implements SnakeListener {
	private Snake snake;
	private Food food;
	private Ground ground;
	private GamePanel gamePanel;
	
	public Controller(Snake snake, Food food, Ground ground, GamePanel gamePanel) {
		this.snake = snake;
		this.food = food;
		this.ground = ground;
		this.gamePanel = gamePanel;
	}
	//利用键盘来控制蛇的方向
	@Override
	public void keyPressed(KeyEvent e) {
		switch(e.getKeyCode()){
		case KeyEvent.VK_UP:
			snake.changeDirection(snake.UP);
			break;
		case KeyEvent.VK_DOWN:
			snake.changeDirection(snake.DOWN);
			break;
		case KeyEvent.VK_LEFT:
			snake.changeDirection(snake.LEFT);
			break;
		case KeyEvent.VK_RIGHT:
			snake.changeDirection(snake.RIGHT);
			break;
		}
	}
	
	@Override
	public void snakeMoved(Snake snake) {
		//判断蛇吃到食物否?
		if(food.isSnakeFood(snake)){
			snake.eatFood();
			food.newFood(ground.getPoint());
		}
		//吃到石头就结束游戏
		if(ground.isSnakeEatRock(snake)){
			snake.die();
		}
		//吃到自己的身体结束游戏
		if(snake.isEatBody()){
			snake.die();
		}
		gamePanel.display(snake, food, ground);
	}
	
	
	public void newGame(){
		snake.start();
		food.newFood(ground.getPoint());
	}	
}
Food.java

package cn.itcast.snake.entities;

import java.awt.Graphics;
import java.awt.Point;
import  cn.itcast.snake.util.Global;;
public class Food extends Point{
	//显示新的食物
	public void newFood(Point p){
		this.setLocation(p);
	}
	
	//判断是否迟到食物
	public boolean isSnakeFood(Snake snake){
		return this.equals(snake.getHead());
	}
	//显示食物
	public void drawMe(Graphics g){
		g.fill3DRect(x*Global.CELL_SIZE, y*Global.CELL_SIZE, 
				Global.CELL_SIZE, Global.CELL_SIZE, true);
	}
}
Ground.java

package cn.itcast.snake.entities;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.util.Random;

import javax.xml.bind.annotation.XmlElementDecl.GLOBAL;

import cn.itcast.snake.util.Global;

//石头类
public class Ground {
	
	private int[][] rocks = new int[Global.WIDTH][Global.HEIGHT];
	//利用构造函数产生石头
	public Ground(){
		for(int x = 0; x<Global.HEIGHT; x++){
			rocks[x][0] = 1;
			rocks[x][Global.WIDTH-1] = 1;
		}
	}
	
	//判断是否吃到了石头
	public boolean isSnakeEatRock(Snake snake){
		for(int x = 0; x<Global.WIDTH; x++){
			for(int y = 0; y<Global.HEIGHT; y++){
				if(rocks[x][y] ==1 &&
						(x == snake.getHead().x && y==snake.getHead().y)){
					return true;
				}
			}
		}
		return false;
	}
	
	//随机产生食物的坐标
		public Point getPoint(){
			int x = 0, y = 0;
			Random random = new Random();
			do{
				x = random.nextInt(Global.WIDTH);
				y = random.nextInt(Global.HEIGHT);
			}while(rocks[x][y]==1);
			return new Point(x,y);
		}
		
	//显示石头
	public void drawMe(Graphics g){
		g.setColor(Color.DARK_GRAY);
		for(int x = 0; x<Global.WIDTH; x++){
			for(int y = 0; y<Global.HEIGHT; y++){
				if(rocks[x][y] == 1){
					g.fill3DRect(x*Global.CELL_SIZE, y*Global.CELL_SIZE, 
							Global.CELL_SIZE,Global.CELL_SIZE, true);
				}
			}
		}
	}
}
Snake.java

package cn.itcast.snake.entities;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;

import cn.itcast.snake.listener.SnakeListener;
import cn.itcast.snake.util.Global;

public class Snake {
	public static final int UP = -1;
	public static final int DOWN  = 1;
	public static final int LEFT = 2;
	public static final int RIGHT = -2;
	private int oldDirection,newDirection;
	private Point oldTall; //最后的尾巴
	private boolean life;
	private LinkedList<Point> body = new LinkedList<Point>();
	private Set<SnakeListener> listeners = new HashSet<SnakeListener>();
	public Snake(){
		init();
	}
	
	public void die(){
		life = false;
	}
	//初始化蛇的长度
	public void init(){
		life = true;
		int x = Global.WIDTH/2;
		int y = Global.HEIGHT/2;
		for(int i=0; i<3; i++){
			body.addLast(new Point(x--,y));
		}
		oldDirection =newDirection= RIGHT;
	}
	//移动
	public void move(){
		//判断老方向和新方向是否是相反的方向
		if(!(oldDirection+newDirection == 0)){
			oldDirection = newDirection;
		}
		//1.去尾
		oldTall = body.removeLast();
		
		int x = body.getFirst().x;
		int y = body.getFirst().y;
		
		switch(oldDirection){
		case UP:
			y--;
			if(y<0){
				y = Global.HEIGHT-1;
			}
			break;
		case DOWN:
			y++;
			if(y>=Global.HEIGHT){
				y = 0;
			}
			break;
		case LEFT:
			x--;
			if(x<0){
				x = Global.WIDTH-1;
			}
			break;
		case RIGHT:
			x++;
			if(x>=Global.WIDTH){
				x = 0;
			}
			break;	
		}
		Point newHead = new Point(x, y);
		//2.加头
		body.addFirst(newHead);
	}
	//改变方向 
	public void changeDirection(int direction){
		newDirection = direction;
	}
	//吃食物
	public void eatFood(){
		//吃到食物后蛇的的身子变长
		body.addLast(oldTall);
	}
	//判断是否吃到自己
	public boolean isEatBody(){
		//从第一个元素开始,排除蛇头
		for(int i=1; i<body.size(); i++){
			if(body.get(i).equals(this.getHead())){
				return true;
			}
		}
		return false;
	}
	//显示蛇
	public void drawMe(Graphics g){
		g.setColor(Color.blue);
		for(Point p : body){
			g.fill3DRect(p.x*Global.CELL_SIZE, p.y*Global.CELL_SIZE, 
					Global.CELL_SIZE,Global.CELL_SIZE, true);
		}
	}
	
	//获取蛇的头节点
	public Point getHead(){
		return body.getFirst();
	}
	//线程来让蛇一直运动
	private class SnakeDriver implements Runnable{

		@Override
		public void run() {
			while(life){
				move();
				for(SnakeListener l : listeners){
					l.snakeMoved(Snake.this);
				}
				try {
					Thread.sleep(300);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}	
	}
	
	public void start(){
		new Thread(new SnakeDriver()).start();
	}
	
	//添加监听器
	public void addSnakeListener(SnakeListener l){
		if(l!=null){
			this.listeners.add(l);
		}
	}
	
}
Game.java

package cn.itcast.snake.game;

import java.awt.BorderLayout;

import javax.swing.JFrame;

import cn.itcast.snake.controller.Controller;
import cn.itcast.snake.entities.Food;
import cn.itcast.snake.entities.Ground;
import cn.itcast.snake.entities.Snake;
import cn.itcast.snake.util.Global;
import cn.itcast.snake.view.GamePanel;

public class Game {

	public static void main(String[] args) {
		Snake snake = new Snake();
		Food food = new Food();
		Ground ground = new Ground();
		GamePanel gamePanel = new GamePanel();
		Controller controller = new Controller(
				snake,food,ground,gamePanel);
		JFrame frame = new JFrame();
		//关闭时退出程序
		frame.setTitle("简单版贪吃蛇@清凉");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		gamePanel.setSize(Global.WIDTH*Global.CELL_SIZE, Global.HEIGHT*Global.CELL_SIZE);
		frame.setSize(Global.WIDTH*Global.CELL_SIZE+10, Global.HEIGHT*Global.CELL_SIZE+35);
		frame.add(gamePanel,BorderLayout.CENTER);
		frame.addKeyListener(controller);
		gamePanel.addKeyListener(controller);
		snake.addSnakeListener(controller);
		frame.setVisible(true);
		controller.newGame();
		
	}

}

SnakeListener.java

package cn.itcast.snake.listener;

import cn.itcast.snake.entities.Snake;

public interface SnakeListener {
	//蛇移动
	void snakeMoved(Snake snake);
}
Global.java

package cn.itcast.snake.util;

public class Global {
	public static final int CELL_SIZE = 20;
	public static final int WIDTH = 15;
	public static final int HEIGHT = 15;
}
GamePanel.java

package cn.itcast.snake.view;

import java.awt.Color;
import java.awt.Graphics;

import javax.swing.JPanel;

import cn.itcast.snake.entities.Food;
import cn.itcast.snake.entities.Ground;
import cn.itcast.snake.entities.Snake;
import cn.itcast.snake.util.Global;
//画板类
public class GamePanel extends JPanel{
	private Snake snake;
	private Food food;
	private Ground ground;
	//显示
	public void display(Snake snake, Food food, Ground ground){
		this.snake = snake;
		this.food = food;
		this.ground = ground;
		this.repaint();
	} 
	//重绘
	@Override
	public void paint(Graphics g) {
		super.paint(g);
		g.setColor(new Color(0xcfcfcf));
		//g.setColor(new Color(0xcfcfcf));
		g.fillRect(0, 0, Global.WIDTH*Global.CELL_SIZE,
				Global.HEIGHT*Global.CELL_SIZE);
		this.ground.drawMe(g);
		this.snake.drawMe(g);
		this.food.drawMe(g);
	}
	
}
运行结果:










可以运行! (以下代码只是其中的一个类) package chy.snake.entities; import java.awt.Color; import java.awt.Graphics; import java.awt.Point; import java.util.HashSet; import java.util.LinkedList; import java.util.Set; import chy.snake.listener.SnakeListener; import chy.snake.util.Global; public class Snake { public static final int up = 1; public static final int down = -1; public static final int left = -2; public static final int right = 2; private int oldDirection,newDirection; //newDirection:一次时间 间隔内输入的最后方向 private Point oldTail; private boolean life; //life 为 true或者false,初始为true, 用于118行 private LinkedList<Point> body = new LinkedList<Point> (); //需要经常访问蛇的第一个和最后一个节点,使用链表LinkedList存放蛇的身体节点,因为它有getFirst(),getLast(),removeLast(),方法 private Set<SnakeListener> listeners = new HashSet<SnakeListener>(); public Snake(){ init(); } public void init(){ //初始化 int x = Global.WIDTH/2; int y = Global.HEIGHT/2; for(int i=0;i<3;i++){ //初始长度3 body.addLast(new Point(x-i,y)); //是addLast } oldDirection = newDirection = right; //初始方向 右 life = true; } public void die(){ life = false; } public void move(){ System.out.println("Snake's move"); if (!(oldDirection + newDirection == 0)){ oldDirection = newDirection; } //1.去尾 oldTail = body.removeLast(); int x = body.getFirst().x; int y = body.getFirst().y; //蛇头的x,y坐标 switch(oldDirection){ case up: y--; break; case down: y++; break; case left: x--; break; case right: x++; break; } Point newHead = new Point(x,y); //2.加头 body.addFirst(newHead); } public void changeDirection(int direction){ /*无效方向:在蛇的这一次移动之后和下一次移动之前的 这个时间间隔内输入了多个方向,只有最后一个方向 是 有效方向,其余的都为无效方向*/ System.out.println("Snake's changeDirection"); newDirection = direction; //将一个时间间隔内按得最后方向,赋给 newDirection } public void eatFood(){ System.out.println("Snake's eatFood"); body.addLast(oldTail); //后面的节点不去掉 } public boolean isEatFood(){ System.out.println("Snake's isEatFood"); return false; } public boolean isEatBody(Snake snake){ //比较蛇是否吃到身体 System.out.println("snake's isEatBody"); for(int i= 1;i<body.size();i++){ //i 从蛇头结点的下一个节点开始,排除蛇头结点 if(body.get(i).equals(this.getHead())){ //如果i 的节点 和 头结点 相同 return true; } } return false; } public void drawMe(Graphics g){ System.out.println("Snake's drawMe"); g.setColor(Color.GREEN); //设置蛇的颜色 for(Point p : body){ g.fill3DRect(p.x * Global.CELL_SIZE, p.y * Global.CELL_SIZE, Global.CELL_SIZE, Global.CELL_SIZE, true); } } public Point getHead(){ //得到蛇头节点,判断吃食物 return body.getFirst(); } private class SnakeDriver implements Runnable{ //线程,不停的调用move方法 @Override public void run() { // TODO 自动生成的方法存根 while(life){ // 42和46行,life为true 或者false move(); for(SnakeListener l : listeners){ l.snakeMoved(Snake.this); //循环,依次调用SnakeMoved方法 } try { Thread.sleep(300); } catch (InterruptedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } } } } public void start(){ new Thread(new SnakeDriver()).start(); //启动线程的方法 } public void addSnakeListener(SnakeListener l){ if(l != null){ this.listeners.add(l); } } }
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值