1. 前言 :
这个游戏的经典程度就不用说了吧,相信大家都玩过,而且在学习之初说不定也都还写过呢,
这个实际上写了已经很久了,所以可能注释, 代码风格等信息可能不是那么的好看
设计的思路 : 根据蛇头定时更新蛇的结点, 重绘, 请注意每一个蛇结点方向的控制, 开始界面的闪烁绘制, 涉及线程
元素介绍 :
蛇 : 即我们控制的角色
墙 : 障碍物, 蛇装在上面会挂掉
食物 : 蛇的食物, 我们的目标
2. 基本的数据结构介绍 :
2.1 Food : 也就是一个基本的位置的封装
package snake;
// 食物
public class Food {
// 坐标
private int x;
private int y;
// 初始化
public Food(int x, int y) {
this.x = x;
this.y = y;
}
public Food() {
super();
}
// setter & getter
// ... 省略
}
2.2 Node : 蛇由结点构成, 封装”蛇结点”
package snake;
// the Node in snake
public class Node {
// 坐标以及方向
private int x;
private int y;
private int direction;
// 初始化
public Node() {
super();
}
public Node(int x, int y) {
this.x = x;
this.y = y;
}
public Node(int x, int y, int direction) {
this.x = x;
this.y = y;
this.direction = direction;
}
// setter & getter
// ... 省略
// for debug ...
public String toString(){
return x+"--"+y+" ";
}
}
2.3 Snake 封装了蛇的数据结构, 以及动作
package snake;
// the Snake class
public class Snake {
private LinkedList<Node> nodes; // all nodes in the snake
private Node lastNode; // the lastNode snake moved
private int direction; // the direction of snake
private int lastDirection;
private int length; // the length of snake
private int initLength = 4; // the default value of snake body length
private int xMinLimit; // the min of X position
private int xMaxLimit;
private int yMinLimit;
private int yMaxLimit;
private boolean isEnd; // is game end
public Snake(int x, int y, int panelWidth, int panelHeight){
nodes = new LinkedList<Node>();
init(panelWidth, panelHeight);
xMinLimit = x+MainPanel.WIDTH;
xMaxLimit = panelWidth-panelWidth%MainPanel.WIDTH-MainPanel.WIDTH;
yMinLimit = y+MainPanel.HEIGHT;
yMaxLimit = panelHeight-panelWidth%MainPanel.HEIGHT-MainPanel.HEIGHT;
}
// initialization some variable
public void init(int panelWidth, int panelHeight) {
int halfWidth = panelWidth/2;
int halfHeight = panelHeight/2;
int firstX = halfWidth - halfWidth%MainPanel.WIDTH;
int firstY = halfHeight - halfHeight%MainPanel.HEIGHT;
for(int i=0; i<initLength; i++){
nodes.add(new Node(firstX+MainPanel.WIDTH*i, firstY, 3));
}
length = 4;
direction = 3;
lastDirection = 3;
lastNode = null;
}
public Snake(){
nodes = new LinkedList<Node>();
}
// the function control the snake move
public void move(){
Node headNode = getHead();
Node newNode = null;
switch(direction){
case 0:
newNode = moveUp(headNode);
break;
case 1:
newNode = moveRight(headNode);
break;
case 2:
newNode = moveDown(headNode);
break;
case 3:
newNode = moveLeft(headNode);
break;
default:
break;
}
if(newNode!=null){
lastNode = nodes.removeLast();
if(!containsPosition(newNode)){
nodes.addFirst(newNode);
}else{
isEnd = true;
}
updateNodeDirection(direction); // update the direction of snake body
}else{
isEnd = true;
}
}
// update the direction of snake body
private void updateNodeDirection(int direction) {
ListIterator it = nodes.listIterator();
Node nodeNow = null, nodePre = null;
if(it.hasPrevious()){
for(int i=0; i<length-1; i++){
nodeNow = (Node)it.previous();
if(it.hasPrevious()){
nodePre = (Node)it.previous();
nodeNow.setDirection(nodePre.getDirection());
}
}
}
getHead().setDirection(direction);
}
// move to specified direction
private Node moveLeft(Node headNode) {
if((headNode.getX()-MainPanel.WIDTH)>=xMinLimit){
return new Node(headNode.getX()-MainPanel.WIDTH, headNode.getY());
}
return null;
}
private Node moveDown(Node headNode) {
if((headNode.getY()+MainPanel.HEIGHT)<=yMaxLimit){
return new Node(headNode.getX(), headNode.getY()+MainPanel.HEIGHT);
}
return null;
}
private Node moveRight(Node headNode) {
if((headNode.getX()+MainPanel.WIDTH)<=xMaxLimit){
return new Node(headNode.getX()+MainPanel.WIDTH, headNode.getY());
}
return null;
}
private Node moveUp(Node headNode) {
if((headNode.getY()-MainPanel.HEIGHT)>=yMinLimit){
return new Node(headNode.getX(), headNode.getY()-MainPanel.HEIGHT);
}
return null;
}
// add a Node for snake[while snake eat the food]
public void addNode(int x, int y){
addNode(new Node(x, y));
length++;
}
public void addNode(Node node){
nodes.add(node);
}
public List<Node> getNodes(){
return nodes;
}
public Node getHead(){
return nodes.getFirst();
}
public Node getTail(){
return nodes.getLast();
}
public Node getBody(int index){
return nodes.get(index);
}
public int getLength(){
return this.length;
}
public void setDirection(int direction){
this.direction = direction;
}
public int getDirection(){
return this.direction;
}
public Node getLastNode(){
return lastNode;
}
public void setLastDirection(int lastDirection){
this.lastDirection = lastDirection;
}
public boolean containsPosition(Node node){
return containsPosition(node.getX(), node.getY());
}
// judge if snake contains the specified position
public boolean containsPosition(int x, int y){
for(Node node : nodes){
if(isNodeEqualWithXY(node, x, y)){
return true;
}
}
return false;
}
public boolean isEatFood(Food food) {
return isNodeEqualWithXY(getHead(), food.getX(), food.getY());
}
// judge if the node's position equals x and y
public boolean isNodeEqualWithXY(Node node, int x, int y){
if(node.getX()==x && node.getY()==y){
return true;
}
return false;
}
public void addBody(Food food) {
nodes.addLast(lastNode);
}
public boolean isEnd(){
return isEnd;
}
public void setIsEnd(boolean isEnd){
this.isEnd = isEnd;
}
public void endGame() {
nodes.clear();
}
}
2.4 至于其他的界面相关的东西, 这里就不在赘述了
3下载链接 [包含图片, 源码] :
http://download.csdn.net/detail/u011039332/8978839
运行时截图 :
注 : 因为作者的水平有限,必然可能出现一些bug, 所以请大家指出!