概述 相信大家都玩过Nokia手机上的贪吃蛇游戏。在该游戏中,玩家操纵一条贪吃的蛇在迷宫里行走,贪吃蛇按玩家所按的方向键折行,蛇头吃到各种食物(比如大力丸)后,会有各种反应(比如蛇身变长),如果贪吃蛇碰上墙壁或者自身的话,就GameOver了(当然也可能是减去一条生命)。要实现该游戏其实并不麻烦,关键就是要找到一个合适的核心算法。本文就给出一个参考实现,你可以基于该demo做扩展。要说明的一点是:本文只演示最核心的算法,要实现一个完整的游戏,你还需要做很多的扩展,重构。 实例代码 该程序包括3个java文件。一个是SnakeMIDlet,另外2个分别是一个Canvas(SnakeCanvas)和一个代表贪吃蛇的类Snake SnakeMIDlet.java import javax.microedition.lcdui.Display; import javax.microedition.midlet.MIDlet; import javax.microedition.midlet.MIDletStateChangeException; /** * @author Jagie */ public class SnakeMIDlet extends MIDlet { protected void startApp() throws MIDletStateChangeException { // TODO Auto-generated method stub Display.getDisplay(this).setCurrent(new SnakeCanvas()); } /* (non-Javadoc) * @see javax.microedition.midlet.MIDlet#pauseApp() */ protected void pauseApp() { // TODO Auto-generated method stub } /* (non-Javadoc) * @see javax.microedition.midlet.MIDlet#destroyApp(boolean) */ protected void destroyApp(boolean arg0) throws MIDletStateChangeException { // TODO Auto-generated method stub } } SnakeCanvas.java import javax.microedition.lcdui.Canvas; import javax.microedition.lcdui.Graphics; /** * @author Jagie * */ public class SnakeCanvas extends Canvas implements Runnable { Snake snake=new Snake(); SnakeCanvas(){ snake.init(); new Thread(this).start(); } protected void paint(Graphics g) { g.setColor(0); g.fillRect(0,0,this.getWidth(),this.getHeight()); snake.paint(g); } /** * 游戏主线程,驱动蛇移动 */ public void run(){ while(true){ snake.move(); repaint(); try { Thread.sleep(50); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } /** * 按键相应,产生新蛇头 */ protected void keyPressed(int c) { int ga=this.getGameAction(c); switch (ga) { case Canvas.UP: snake.breakInto(1); break; case Canvas.DOWN: snake.breakInto(3); break; case Canvas.LEFT: snake.breakInto(4); break; case Canvas.RIGHT: snake.breakInto(2); break; } } } Snake.java import java.util.Vector; import javax.microedition.lcdui.Graphics; /** * * @author Jagie * 贪吃蛇 */ public class Snake { //蛇环节,每个环节为一个int[] sec //sec[0]:环节起点x,sec[1]:环节起点y,sec[2]:环节方向,sec[3]:环节长度 Vector sections = new Vector(); /** * 初始化sections * 开始的时候,整条蛇只有一段。 * */ public void init() { int[] head = { 10, 10, 2, 50 }; sections.addElement(head); } /** * 绘制 * @param g */ public synchronized void paint(Graphics g) { if (sections.isEmpty()) { return; } g.setColor(0, 255, 0); for (int i = 0; i < sections.size(); i++) { int[] sec = (int[]) sections.elementAt(i); //sec[0]:起点x,sec[1]:起点y,sec[2]:方向,sec[3]:长度 switch (sec[2]) { case 1: g.drawLine(sec[0], sec[1], sec[0], sec[1] - sec[3]); break; case 2: g.drawLine(sec[0], sec[1], sec[0] + sec[3], sec[1]); break; case 3: g.drawLine(sec[0], sec[1], sec[0], sec[1] + sec[3]); break; case 4: g.drawLine(sec[0], sec[1], sec[0] - sec[3], sec[1]); break; } } } /** * * @author Jagie * * 蛇的爬行。本质上是蛇头长度++,蛇尾长度--.同时移动蛇尾起点。如果蛇尾长度小于0,则去掉蛇尾。 */ public synchronized void move() { if (sections.isEmpty()) { return; } //蛇尾 int[] tail = (int[]) sections.elementAt(sections.size() - 1); //蛇头 int[] head = (int[]) sections.elementAt(0); //根据蛇尾环节的方向移动蛇尾。 switch (tail[2]) { case 1: tail[1]--; break; case 2: tail[0]++; break; case 3: tail[1]++; break; case 4: tail[0]--; break; } //蛇尾缩短 tail[3]--; //蛇头增长 head[3]++; //蛇尾<0,则去掉蛇尾 if (tail[3] <= 0) { sections.removeElement(tail); } } /** * 蛇分段 * @param dir 新蛇头的方向 */ public synchronized void breakInto(int dir) { if (sections.isEmpty()) { return; } int[] head = (int[]) sections.elementAt(0); //新蛇头方向和旧蛇头方向一致,则无反应。 //TODO 可以考虑加速。 if (dir == head[2]) { return; } //增加新蛇头 int[] newhead=new int[4]; //新蛇头的起始位置,与旧蛇头的运动方向有关。 switch (head[2]) { case 1: newhead[0]=head[0]; newhead[1]=head[1]-head[3]; newhead[2]=dir; newhead[3]=0; //蛇头总是第一个元素 sections.insertElementAt(newhead, 0); break; case 2: newhead[0]=head[0]+head[3]; newhead[1]=head[1]; newhead[2]=dir; newhead[3]=0; sections.insertElementAt(newhead, 0); break; case 3: newhead[0]=head[0]; newhead[1]=head[1]+head[3]; newhead[2]=dir; newhead[3]=0; sections.insertElementAt(newhead, 0); break; case 4: newhead[0]=head[0]-head[3]; newhead[1]=head[1]; newhead[2]=dir; newhead[3]=0; sections.insertElementAt(newhead, 0); break; } } } 小结本文给出了一个简单的贪吃蛇的例子,演示了贪吃蛇游戏核心的一种参考算法 作者简介陈万飞,网名Jagie,培训师,爱好java技术.可通过chen_cwf@163.com与他联系.

评论