Java贪吃蛇,部分实现,适合作为新手练习作业。

一、概要设计

游戏规则:

由于基本都玩过,再次不在啰嗦。


游戏要素:

1、地图(map)

2、蛇(snake)

3、食物(food)

4、规则(rule)


输入设定:

1、通过键盘上的上、下、左、右进行游戏控制。

2、通过键盘的P控制游戏的暂停(pause)/开始(start)、N(new)控制新的一局的开始。


输出内容:(*为特定条件下激活)

1 、 游戏速度

2 、 游戏进行时间

3 、 贪吃蛇长度

4*、显示游戏结束信息


基本游戏默认参数:

1、地图大小(20X20)

2、地图单元格width = 20, height =20;

3、游戏速度为 (1051 - level*50)ms 初始等级为1,最高等级为20.

4、初始贪吃蛇长度为3


规则:

1、贪吃蛇碰触墙壁或者自身时,游戏结束。

2、贪吃蛇不能朝反方向进行移动。 ( 即:若当前贪吃蛇头部朝向的方向为南,则向北移动是无效的操作。)

3、贪吃蛇达到一定长度时,游戏结束。

4、食物位置随机生成。


未完成部分:

见Snack类中moveTo()方法的TODO标签处。

作业:

1、实现贪吃虫的自动移动。

2、增加游戏计时功能。(游戏时间)

3、增加暂停功能。

4、处理不同因移动造成的情况,进行相应处理

二、详细设计

画布类(Canvas):

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.util.Vector;

import javax.swing.JPanel;


public class Canvas extends JPanel{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	/*画布参数*/
	public static final int PADDING = 10; //画布内边距
	public static final int CELL_SIZE = 20; //单元格大小
	public static final int CELL_COLUMN = 20; //单元格列数
	public static final int CELL_ROW = 20; //单元格行数
	public static final Color BACKGROUND = Color.WHITE; //画布背景颜色
	public int canvasWidth = 2*PADDING + CELL_SIZE*CELL_COLUMN;
	public int canvasHeight = 2*PADDING + CELL_SIZE*CELL_ROW;
	/*画布中的对象*/
	public Snake snake; //贪吃蛇
	private GameMap map; //地图(容器)
	// ------------------------------------
	// 构造方法
	// ------------------------------------
	public Canvas() {
		setPreferredSize(null); //设置面板大小
		startGame();
	}
	
	/*从Point坐标值转换为swing中的坐标值*/
	public int transformX(int pointX){ return 0;}
	public int transformY(int pointY){ return 0;}

	/*开始游戏*/
	public void startGame(){
		map = new GameMap();
		snake = new Snake(map);
		/*初始化开始一条位置,并且长度为3的贪吃蛇*/
		snake.enqueue(map.getPoint(10, 12));
		snake.enqueue(map.getPoint(10, 11));
		snake.enqueue(map.getPoint(10, 10));
		map.randomFood(snake);
	}
	
	/*绘制界面*/
	@Override
	public void paint(Graphics g) {
		super.paint(g);
		/*绘制网格,测试用*/
//		for(int i=0;i<=CELL_COLUMN;i++)
//			g.drawLine(PADDING, PADDING+CELL_SIZE*i, PADDING +CELL_SIZE*CELL_COLUMN, PADDING+CELL_SIZE*i);
//		for(int i=0;i<=CELL_ROW;i++)
//			g.drawLine(PADDING + CELL_SIZE*i, PADDING, PADDING + CELL_SIZE*i, PADDING + CELL_SIZE*CELL_ROW);
		
		/*画贪吃蛇*/
		Vector<Point> body = snake.getBody();
		for(int i=0;i<body.size();i++){
			/*头部画黄色*/
			Point p = body.get(i);
			if(i == body.size()-1){
				Color oldColor = g.getColor();
				g.setColor(Color.yellow);
				g.fillRect((int)p.getX(),(int) p.getY(), CELL_SIZE, CELL_SIZE);
				g.setColor(oldColor);
			}else
				g.fillRect((int)p.getX(),(int) p.getY(), CELL_SIZE, CELL_SIZE);
		}
		
		/*画食物*/
		Point food = map.getFood();
		if(food != null){
			//画食物
			Color oldColor = g.getColor();
			g.setColor(Color.red);
			g.fillRect((int)food.getX(), (int)food.getY(), CELL_SIZE, CELL_SIZE);
			g.setColor(oldColor);
		}
	}
	
	/*重载设置面板大小*/
	@Override
	public void setPreferredSize(Dimension d) {
		super.setPreferredSize(new Dimension(canvasWidth,canvasHeight));
	}
}
地图类(GameMap):


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



public class GameMap {

	/*地图坐标*/
	public Point[][] map;
	/*食物坐标*/
	private Point food;
	
	/*构造方法*/
	public GameMap() { 
		map = new Point[Canvas.CELL_ROW][Canvas.CELL_COLUMN];
		for (int i=0;i<Canvas.CELL_ROW ;i++) {
			for (int j=0;j<Canvas.CELL_COLUMN;j++) {
				map[i][j] = new Point(Canvas.PADDING+Canvas.CELL_SIZE*i,Canvas.PADDING+Canvas.CELL_SIZE*j);
			}
		}
	}
	
	/*得到指定位置的X,Y坐标*/
	public Point getPoint(int row,int column){
		return map[row][column];
	}
	
	/*得到指定point所在map中的索引*/
	public int[] pointAt(Point p){
		int row = (int) ( (p.getX()-Canvas.PADDING) / Canvas.CELL_SIZE);
		int column = (int)( (p.getY()-Canvas.PADDING) / Canvas.CELL_SIZE);
		return new int[]{row,column};
	}
	
	/*随机生成食物坐标*/
	public Point randomFood(Snake snake){
		Random random = new Random();
		int xPos = random.nextInt(Canvas.CELL_ROW);
		int yPos = random.nextInt(Canvas.CELL_COLUMN);
		
		while(true){
			if( !snake.getBody().contains(getPoint(xPos, yPos)) ){
				food = getPoint(xPos, yPos);
				return food;
			}else { 
				xPos = random.nextInt(Canvas.CELL_ROW);
				yPos = random.nextInt(Canvas.CELL_COLUMN);
			}
		}
	}
	
	/*设置食物位置*/
	public void setFood(Point food){
		this.food = food;
	}
	
	/*得到食物位置*/
	public Point getFood(){
		return food;
	}
}

贪吃蛇类(Snack):


import java.util.Vector;
import java.awt.Point;


public class Snake {

	/*贪吃蛇在地图中的点集合,[0]元素为蛇头,[size-1]元素为蛇尾*/
	private Vector<Point> body;
	/*贪吃蛇所在地图*/
	private GameMap map;
	
	/*构造方法*/
	public Snake(GameMap map){
		this.map = map;
		body = new Vector<Point>();
	}
	
	/*贪吃蛇移动或进食*/
	public void enqueue(Point p) {
		body.add(p);
	}
	
	/*判断贪吃蛇是否为空*/
	public boolean isEmpty(){
		return size() == 0;
	}
	
	/*返回贪吃蛇的长度*/
	public int size() {
		return body.size();
	}
	
	/*返回贪吃蛇头部的位置*/
	public Point getHead() {
		if(size()==0)
			throw new RuntimeException("贪吃蛇无头部");
		return body.get(size()-1);
	}
	
	/*返回贪吃蛇尾部的位置*/
	public Point getTail() {
		if(size()==0)
			throw new RuntimeException("贪吃蛇无尾部");
		return body.get(0);
	}
	
	/*返回头部后的第一个位置*/
	public Point getHeadAfter(){
		if(size()==1)
			throw new RuntimeException("贪吃蛇只有头部");
		return body.get(size()-2);
	}
	
	/*移除尾部*/
	public void removeTail(){
		body.remove(0);
	}
	
	/*返回整个贪吃蛇*/
	public Vector<Point> getBody(){
		return body;
	}
	// -----------------------------------
	// 贪吃蛇行为
	// -----------------------------------
	
	/*是否为身体一部分*/
	public boolean isBody(Point p){
		if(body.contains(p))
			return true;
		return false;
	}
	
	/*贪吃蛇移动到地图指定点*/
	public void moveTo(int row,int column) {
		/*得到头部后第一个位置*/
		Point afterHead = getHeadAfter();
		/*判断要移动的位置是否有效*/
		if(!moveValid(row, column)){
			//TODO
			//
			//  添加你的处理方法,并将游戏结束
			//
			System.out.println("碰到墙壁了!");
			return;
		}
		/*判断是否为无效反方向移动*/
		if(map.getPoint(row, column).equals(afterHead)){
			//TODO
			//
			//  添加你的处理方法,但游戏继续
			//
			System.out.println("无效的反方向操作!");
			return;
		}
		/*判断是否碰到身体*/
		if(isBody(map.getPoint(row, column))){
			//TODO
			//
			//  添加你的处理方法,并将游戏结束
			//
			System.out.println("碰到身体了!");
			return;
		}
		/*判断是否移动到食物上*/
		if(map.getPoint(row, column).equals(map.getFood())){
			/*将食物添加到贪吃蛇身体中*/
			enqueue(map.getPoint(row, column));
			/*重新生成食物*/
			map.randomFood(this);
		}else{
			/*进行普通的移动*/
			enqueue(map.getPoint(row, column));
			removeTail();
		}
	}
	
	/*贪吃蛇向左移动*/
	public void moveLeft(){
		/*得到头部位置*/
		Point head = getHead();
		int[] cood = map.pointAt(head);
		moveTo(cood[0]-1, cood[1]);
	}
	
	/*贪吃蛇向右移动*/
	public void moveRight(){
		/*得到头部位置*/
		Point head = getHead();
		int[] cood = map.pointAt(head);
		moveTo(cood[0]+1, cood[1]);

	}
	/*贪吃蛇向上移动*/
	public void moveUp(){
		/*得到头部位置*/
		Point head = getHead();
		int[] cood = map.pointAt(head);
		moveTo(cood[0], cood[1]-1);

	}
	/*贪吃蛇向下移动*/
	public void moveDown(){
		/*得到头部位置*/
		Point head = getHead();
		int[] cood = map.pointAt(head);
		moveTo(cood[0], cood[1]+1);
	}
	/*贪吃蛇移动是否有效*/
	public boolean moveValid(int r,int c){
		if( r < 0 || r >= Canvas.CELL_ROW || c < 0 || c >= Canvas.CELL_COLUMN)
			return false;
		return true;
	}
}

游戏主界面类(GameFrame):

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;


public class GameFrame extends JFrame implements KeyListener{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private Canvas canvas;
	/*构造方法*/
	public GameFrame(){
		init();
	}
	
	/*初始化*/
	private void init(){
		this.setTitle("贪吃蛇         by:luiyikeke");
		canvas = new Canvas();
		add(canvas); /*添加画布到主面板*/
		pack();      /*自适应大小*/
		setResizable(false);  /*禁止调整窗口大小*/
		setLocationRelativeTo(null); /*窗口屏幕居中显示*/
		this.addKeyListener(this);
	}
	
	public static void main(String[] args) {
		new GameFrame().setVisible(true);
	}

	@Override
	public void keyPressed(KeyEvent e) {
		int keyCode = e.getKeyCode();
		if (38 == keyCode) {
			canvas.snake.moveUp();
		} else if (37 == keyCode) {
			canvas.snake.moveLeft();
		} else if (39 == keyCode) {
			canvas.snake.moveRight();
		} else if (40 == keyCode) {
			canvas.snake.moveDown();
		}
		canvas.repaint();
	}

	@Override
	public void keyReleased(KeyEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void keyTyped(KeyEvent e) {
		// TODO Auto-generated method stub
		
	}
}


评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值