最近研究一个大大的贪吃蛇代码,自己开始试着写了写,已经对贪吃蛇的移动及规则方面的算法了解,主要是绘图方面有很大的困难,因为贪吃蛇的代码中将蛇的身体定义成多个坐标点,所以在绘图的过程中就必须要把这样的点给放大,与此同时蛇的移动范围又要在panel面板尺寸的基础上进行缩小,这样才使得游戏中设的移动不出问题。废话不说,上代码
Snake.java
import java.util.*;
import javax.swing.*;
public class Snake {
int len,wid;
static int up=1;
static int down=3;
static int left=2;
static int right=4;
int direction=4;
LinkedList snakeList = new LinkedList();
Node food;
Snakepanel pane;
boolean al[][];
static boolean run=true;
public Snake(Snakepanel pane,int x,int y)
{
len=x;
wid=y;
this.pane=pane;
al=new boolean[x][y];
for(int i=0;i<x;i++)
{
for(int j=0;j<y;j++)
al[i][j]=false;
}//设定边界,除蛇身以及食物以外的地方布尔值为false,
int length = len > 20 ? 10 : len / 2;
for(int i=0;i<length;i++)
{
int a=x/10+i;
int b=y/10;
snakeList.addFirst(new Node(a,b));//设置蛇身,蛇头朝右方向
}
food=createfood();
al[food.x][food.y]=true;
};
public void move(){
Node n=(Node)snakeList.getFirst();
int x=n.x;
int y=n.y;
if(direction==4)
x++;
if(direction==2)
x--;
if(direction==3)
y++;
if(direction==1)
y--;
if((0<=x&&x<=pane.len/15-1)&&(0<=y&&y<=pane.wid/15-2))
{
if(al[x][y])
{
if(x==food.x&&y==food.y)
{
snakeList.addFirst(food);
food =createfood();
al[food.x][food.y] = true;
}
else
{
JOptionPane.showMessageDialog(null, "GameOver");
System.exit(0);
}
}
else
{
snakeList.addFirst(new Node(x,y));
al[x][y]=true;
Node l=(Node)snakeList.getLast();
snakeList.removeLast();
al[l.x][l.y]=false;//蛇身移动,队头增加,队尾删除
}
}
else
{
JOptionPane.showMessageDialog(null, "GameOver");
System.exit(0);
}
pane.repaint();//重绘组件
}
public Node createfood()
{
int x=0,y=0;
do {
Random r = new Random();
x = r.nextInt(len-10);
y = r.nextInt(wid-10);
} while (al[x][y]);//排除食物产生在蛇身的可能
return new Node(x, y);
}
public void changeDirection(int newdirection)
{
if(direction%2!=newdirection%2)
{
direction=newdirection;
}//保证蛇不能回头
}
}
Node.java
public class Node {
int x,y;
public Node(int x,int y)
{
this.x=x;
this.y=y;
}
}
Snakepanel.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class Snakepanel extends JPanel implements KeyListener {//键盘事件接口
int len=400;
int wid=500;
int rectx=15;
int recty=15;//倍数设置
int count=1;
Snake snake;
Node n;
public Snakepanel()
{
snake=new Snake(this,len/rectx,wid/recty);
setBackground(Color.BLACK);
setSize(len,wid);
setFocusable(true);
addKeyListener(this);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);//打印容器中每个组件
LinkedList list = snake.snakeList;
Iterator it = list.iterator();
g.setColor(Color.white);
while (it.hasNext()) {
n = (Node) it.next();
drawNode(g, n);//调用迭代器并绘制蛇身颜色
}
g.setColor(Color.WHITE);
Node f = snake.food;
drawNode(g, f);//绘制食物颜色
}
public void keyPressed(KeyEvent e) {
int keycode = e.getKeyCode();
if (keycode == KeyEvent.VK_ENTER) {
begin();
} else if (keycode == KeyEvent.VK_UP) {
snake.changeDirection(Snake.up);
} else if (keycode == KeyEvent.VK_DOWN) {
snake.changeDirection(Snake.down);
} else if (keycode == KeyEvent.VK_LEFT) {
snake.changeDirection(Snake.left);
} else if (keycode == KeyEvent.VK_RIGHT) {
snake.changeDirection(Snake.right);
}
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
}//上述两种方法不需要实现,但必须空处理
public void drawNode(Graphics g, Node n) {
g.fillRect(n.x*rectx , n.y*recty , rectx-2, recty-2);
}//定义绘制方法
public void begin() {
if(count==1)
{
Snake.run = true;
SnakeThread thread = new SnakeThread(snake);
thread.start();
count++;
}//调用线程实现蛇体移动,已经修正按回车加速的BUG
}
}
SnakeThread.java
public class SnakeThread extends Thread {
Snake snake;
public SnakeThread(Snake s) {
snake = s;
}
public void run() {
Snake.run = true;
while (Snake.run) {
try {
snake.move();
sleep(150);//休眠时间,影响游戏速度
} catch (InterruptedException e) {
}
}
}
}
Snakeframe.java
import javax.swing.*;
import java.awt.*;
public class Snakeframe extends JFrame{
public Snakeframe() {
setSize(400, 505);
setTitle("贪吃蛇");
this.setLocation(360, 150);
Snakepanel panel = new Snakepanel();
add(panel, BorderLayout.CENTER);
}
}
Play.java
import javax.swing.*;
public class Play {
public static void main(String args[]) {
Snakeframe frame = new Snakeframe();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);//窗口是否可以改变大小
frame.setVisible(true);//显示窗口
JOptionPane.showMessageDialog(null, "回车键开始\n上,下,左,右控制蛇的方向");
}
}