贪吃蛇的JAVA实现

最近JAVA和JSwing上手练习了一下贪吃蛇

贪吃蛇的JAVA实现_第1张图片

先上代码 https://github.com/rgzhang2018/snake

欢迎交流和加入新的内容

用到了JSwing,下面是一些具体的思路

实现

 * 蛇:

采用单链表记录首尾,整个蛇被分为lattice格子,放在map里

 * 移动:
我在实现的过程中发现最难得反而是蛇的定义和实现。一直想着怎么样用单独的方法表示出蛇来,但是如果将蛇单独实现,总有些细节实现起来特别麻烦

其实蛇移动并非牵一发而动全身,其实身子是没有发生变化的,关键是两点:
a.头的移动
b.尾巴的移动
实现:
直接把蛇实现在地图的小格子里,不再单独设置子类或者ArrayList等,Map里加上蛇头的坐标,从而使得Map可以根据蛇头改变蛇的坐标(类似于变量交换)。为头部单独设置x,y,作为移动的方向(也可以作为静态变量x和y,不过没什么区别),为身子设置next指针,只要next.next不是尾巴,那么保持不变。如果next是尾巴,就把自己的设置为尾巴,并且改变next,使之成为普通地图块。(refresh方法)

 * 控制方向:

使用键盘事件,目前仅设置了wasd四个

 * 窗口设计:

view extends JPanel,控制显示,然后在Lattice里调用Graphics.draw(...)实现对每个格子的显示

下面是核心的map部分代码(包括自动移动,检测食物,增加长度等等)

import codes.myGame.snake.cell.Lattice;

import java.util.Random;

public class Smap {
	private boolean getFood = false;//如果得到食物,该指针设为true,并且在随后的autoChange里增加蛇的长度
	private boolean gameOver = false;
	private boolean directionChange = false;//这里标志的作用是保证在一次运动期间只会进行一次转向,使游戏更流畅
	private int MAP_SIZE;
	private Lattice[][] map;
	private int directionX = 0;//下一次头在当前位置的哪个方向上
	private int directionY = 1;//下一次头在当前位置的哪个方向上
	private int[] head = new int[2];//记录当前头的位置
	private int[] food = new int[2];//记录当前食物的位置

	public Smap(int size) {
		MAP_SIZE = size;
		map = new Lattice[MAP_SIZE][MAP_SIZE];
		for(int i=0;i

 

下面是显示部分的代码

显示分为两部分,一块是利用Graphics.draw()方法实现单个单元格的绘制,另一块设置view类继承自JPanel。负责绘制图画显示

public class Lattice {
	private boolean isBody = false;
	private boolean isHead = false;
	private boolean isFood = false;
	private boolean isRear = false;
	public Lattice next = null;


	public void setHead(boolean bool,Lattice next){
		isHead = bool;
		if(next!=null)this.next = next;
	}
	public void setBody(boolean bool,Lattice next){
		isBody = bool;
		if(next!=null)this.next = next;			//传入参数为null时,不改变当前的next
	}
	public void setRear(boolean bool,Lattice next){
		isRear = bool;
		this.next = next;
	}
	public void setFood(boolean bool){
		isFood = bool;
	}

	public Lattice next(){
		return next;
	}

	public boolean isHead(){
		return isHead;
	}
	public boolean isFood(){
		return isFood;
	}
	public boolean isRear(){
		return isRear;
	}
	public boolean isBody(){
		return isBody;
	}



	public void refresh(){
		if(isHead){
			isBody = true;
			isHead = false;
//			怎么设置下一个头呢?(考虑把DirectionX,Y放到Smap里,而不是这里)
		}else if(isBody){
			if(next.isRear){
				next.isRear = false;
				isRear = true;
				isBody = false;
			}
		}
	}
//	在这里设置细胞可见
	public void draw(Graphics g, int x, int y, int size) {
		g.setColor(black);
		g.drawRect(x, y, size, size);
		if ( isHead ) {
			g.setColor( red);
			g.fillRect(x, y, size, size);
		}else if ( isBody || isRear) {
			g.setColor(black);
			g.fillRect(x, y, size, size);
		}else if(isFood){
			g.setColor( blue);
			g.fillRect(x, y, size, size);
		}
	}
}

 

view部分:

import codes.myGame.snake.cell.Lattice;
import javax.swing.*;
import java.awt.*;


public class View extends JPanel {
	private static final long serialVersionUID = -5258995676212660595L;
	private static final int GRID_SIZE = 32;	//填充的像素数量
	private Smap thisMap;

	public View(Smap map) {
		thisMap = map;
	}

	@Override
	public void paint(Graphics g) {
		super.paint(g);
		int size = thisMap.getMAP_SIZE();
		for (int row = 0; row< size; row++ ) {
			for (int col = 0; col< size; col++ ) {
				Lattice lattice = thisMap.get(row, col);
				if ( lattice != null ) {
					lattice.draw(g, col*GRID_SIZE, row*GRID_SIZE, GRID_SIZE);//对应的格子的显示
				}
			}
		}
	}
	@Override
	public Dimension getPreferredSize() {//创建该div大小
		return new Dimension(thisMap.getMAP_SIZE()*GRID_SIZE+1, thisMap.getMAP_SIZE()*GRID_SIZE+1);
	}
}

 

你可能感兴趣的:(JAVA,小游戏)