代码目标:
有一条AI蛇,可以自己寻路,吃食物,并且符合基本规则,上下键控制蛇的速度,空格键实现开始和暂停
(悄悄的告诉你,这个代码,运气好,可以吃满屏,运气不好,一会就…你懂得,嘿嘿嘿)
代码结构
首先,我们需要创建5个类
1,Test.class
这个是用来创建窗口的,就是我们看到的画面
2,SnakePan.class(主要)
这个是用来画我们所看到的所有的图画。比如说蛇头,蛇身,食物…
3,.Node.class
是一个抽象类,下面的蛇和食物都是他的子类
4,Snake.class(主要)
就是一条蛇,可以移动,可以自动寻路
5,Food.class
就是食物,没啥可说的
日常搞怪,别介意
核心思想
1)首先要想确定一条蛇,可由蛇头,蛇尾,身体构成,食物单独拿出来。
2)接下来讲思想:
蛇的走位算法:
if(蛇头可以到达食物) {
if(蛇头尝试走一步依然可以到达蛇尾) {
蛇就可以真的走一步
}else {
蛇头去找蛇尾
}
}else {
蛇头去找蛇尾
}
A*寻路算法:
就是一直着离终点做小的距离的点,不懂可以去bibilili上搜一下
(由于我太菜,讲的不是太清楚)
图片资源:
由于上传图片后,下载需要积分,我想了想,还是算了,直接就放在这里了,如果你是电脑高手,你知道怎么拿走的。(嘻嘻嘻)
游戏代码:
1,
package snake01;
import javax.swing.JFrame;
public class Test {
public static void main(String[] args) {
JFrame jf = new JFrame("AI贪吃蛇");
jf.setBounds(400, 200, 782, 810);
jf.setResizable(false);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
SankePan pan = new SankePan();
jf.add(pan);
jf.setVisible(true);
}
}
2,
package snake01;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;
import com.sun.org.apache.xerces.internal.util.SynchronizedSymbolTable;
public class SankePan extends JPanel implements KeyListener,ActionListener{
ImageIcon up = new ImageIcon("up.png");
ImageIcon down = new ImageIcon("down.png");
ImageIcon left = new ImageIcon("left.png");
ImageIcon right = new ImageIcon("right.png");
ImageIcon title = new ImageIcon("title.jpg");
ImageIcon fod = new ImageIcon("food.png");
ImageIcon body = new ImageIcon("body.png");
Snake snake;
Food food;
boolean pass = false;
Random r=new Random();
Timer ti = new Timer(101,this);
public SankePan() {
this.setFocusable(true);
this.addKeyListener(this);
snake=new Snake();
food=new Food(snake.mp);
}
public void paint(Graphics g) {
super.paint(g);
this.setBackground(Color.BLACK);
for (int i = 1; i < snake.len; i++) {
body.paintIcon(this, g, snake.s[i][1] * 25, snake.s[i][0] * 25);
}
if (snake.dir == 3) {
right.paintIcon(this, g, snake.s[0][1] * 25, snake.s[0][0] * 25);
} else if (snake.dir == 1) {
left.paintIcon(this, g, snake.s[0][1] * 25, snake.s[0][0] * 25);
} else if (snake.dir == 2) {
up.paintIcon(this, g, snake.s[0][1] * 25, snake.s[0][0] * 25);
} else if (snake.dir == 4) {
down.paintIcon(this, g, snake.s[0][1] * 25, snake.s[0][0] * 25);
}
fod.paintIcon(this, g, food.y * 25, food.x * 25);
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
int key=e.getKeyCode();
System.out.println(key);
if(key==32) {
pass=!pass;
if(pass==true) ti.start();
else ti.stop();
}else if(key==40) {
if(ti.getDelay()>10) {
ti.setDelay(ti.getDelay()-10);
}
}else if(key==38) {
ti.setDelay(ti.getDelay()+10);
}
System.out.println("当前速度:"+ti.getDelay());
this.repaint();
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void actionPerformed(ActionEvent e) {
int a1=snake.getHead().x;
int a2=snake.getHead().y;
int b1=snake.getTail().x;
int b2=snake.getTail().y;
int f1=food.x;
int f2=food.y;
Node node1=snake.afs(f1,f2,a1,a2);
Node node2=null;
if(node1!=null) {
node2=snake.afs(b1, b2, node1.x, node1.y);
if(node2==null) {
node1=snake.afs(b1, b2, a1, a2);
}
}else {
node1=snake.afs(b1, b2, a1, a2);
}
snake.mp[f1][f2]=1;
a1=node1.x;
a2=node1.y;
if(a1==f1&&a2==f2) {
snake.run(a1, a2, 1);
food=new Food(snake.mp);
}else {
snake.run(a1, a2, 0);
}
repaint();
}
}
3,
package snake01;
public class Node implements Comparable{
int x,y;
int num;
Node(){
}
Node(int x,int y){
this.x=x;
this.y=y;
}
Node(int x,int y,int tx,int ty){
this.x=x;
this.y=y;
num=Math.abs(x-tx)+Math.abs(y-ty);
}
public int compareTo(Node other) {
return num-other.num;
}
}
4,
package snake01;
import java.util.PriorityQueue;
import java.util.Vector;
public class Snake {
int[][] s;
int len, dir;
int[][] mp, np;
int[][] to = { { 1, 0 }, { -1, 0 }, { 0, -1 }, { 0, 1 } };
public Snake() {
dir = 3;
mp = new int[35][35];
s = new int[900][2];
len = 3;
s[0][0] = 1;
s[0][1] = 3;
s[1][0] = 1;
s[1][1] = 2;
s[2][0] = 1;
s[2][1] = 1;
mp[1][1] = 1;
mp[1][2] = 1;
mp[1][3] = 1;
}
public void run(int x, int y, int t) {
if (t == 1) {
len++;
}else {
mp[s[len-1][0]][s[len-1][1]]=0;
}
mp[x][y]=1;
for (int i = len - 1; i > 0; i--) {
s[i][0] = s[i - 1][0];
s[i][1] = s[i - 1][1];
}
if(s[0][0] - x<0) {
dir=4;
}else if(s[0][0] - x>0) {
dir=2;
}else if(s[0][1] - y<0) {
dir=3;
}else if(s[0][1] - y>0) {
dir=1;
}
s[0][0] = x;
s[0][1] = y;
}
public Node getHead() {
return new Node(s[0][0],s[0][1]);
}
public Node getTail() {
return new Node(s[len-1][0],s[len-1][1]);
}
public Node getLastTail() {
return new Node(s[len-2][0],s[len-2][1]);
}
public Node afs(int x1, int y1, int x2,int y2) {
PriorityQueue pq = new PriorityQueue<>();
int[][] np = new int[35][35];
np[x1][y1]=1;
Node no=new Node(x1, y1, x2, y2);
pq.add(no);
while (pq.size() != 0) {
Node node = pq.remove();
for (int i = 0; i < 4; i++) {
int tx = node.x + to[i][0];
int ty = node.y + to[i][1];
if(tx == x2 && ty == y2) {
return node;
}
if (tx < 0 || tx >= 30 || ty < 0 || ty >= 30||np[tx][ty] == 1||mp[tx][ty] == 1) {
continue;
}
np[tx][ty] = 1;
Node n = new Node(tx, ty, x2, y2);
pq.add(n);
}
}
return null;
}
}
5,
package snake01;
import java.util.Random;
public class Food extends Node {
public Food(int[][] mp) {
Random r = new Random();
int x = r.nextInt(30);
int y = r.nextInt(30);
while (mp[x][y] == 1) {
x = r.nextInt(30);
y = r.nextInt(30);
}
this.x = x;
this.y = y;
}
}