贪吃蛇是个十分经典的游戏,而且做起来也很有意思

刚开始打算使用网格布局来做,后来发现使用画布会有更高的效率,也更容易实现

这个就当做我的第一个版本吧,给出详细的解析,步骤

素材是在别人那里来的

下面是效果图

贪吃蛇_ide


main函数new 一个JFrame,设定好窗口的一些属性

import javax.swing.JFrame;

public class Main {
public static void main(String[] args) {
JFrame snakeFrame = new JFrame();
snakeFrame.setBounds(330, 5, 800, 725);// 窗口位置,大小
snakeFrame.setResizable(false);// 窗口大小不可变
snakeFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// 点击关闭按钮的操作

SnakeJPanel snakeJPanel = new SnakeJPanel();
snakeFrame.add(snakeJPanel);// 将面板加到窗口

snakeFrame.setVisible(true);// 设为可见
}
}


游戏显示都是使用画布来做的,所以再建一个类,继承JPanel

首先定义好相关变量

/// 定义区/
final int MAXLEN = 200;//蛇身最大长度


boolean isStared = false;// 游戏是否开始
boolean isFailed = false;// 游戏是否结束
boolean isFirst;// 是否第一次打开游戏
// 设置游戏的默认属性
int snakeLen;// 蛇身长度(包括蛇头)
int score = 0;// 得分
String direction = "R";// 蛇头方向
//蛇头,蛇身,食物的图片(一定要注意图片的位置书写,不然就会无法显示,而且也没有任何提示)
ImageIcon body = new ImageIcon("src//img//body.png");
ImageIcon down = new ImageIcon("src//img//down.png");
ImageIcon food = new ImageIcon("src//img//food.png");
ImageIcon left = new ImageIcon("src//img//left.png");
ImageIcon right = new ImageIcon("src//img//right.png");
ImageIcon up = new ImageIcon("src//img//up.png");

/* 蛇的每一部分
* snakex[0], snakey[0]表示蛇头
* snakex[1], snakey[1]表示蛇身的第一个部分......
* 里面的参数表示位置
* */
int[] snakex = new int[MAXLEN];
int[] snakey = new int[MAXLEN];

// 随机生成食物(需要根据游戏面板的大小来设定)
Random ran = new Random();
int foodX = ran.nextInt(30) * 25 + 25;//一个图像为25像素,也就是一行有30个图片,从25像素开始显示
int foodY = ran.nextInt(26) * 25 + 25;

// 计时器
// Timer(delay, listener)
// 每五十毫秒调用一次监听(也就是50毫秒走一步)
Timer timer = new Timer(150, this);


然后是构造方法和对游戏的初始化

public SnakeJPanel() {
isFirst = true;// 第一次打开游戏
this.setFocusable(true);
init();// 初始化
this.addKeyListener(this);
}


// 初始化
public void init() {
snakeLen = 3;// 蛇神长度
score = 0;// 分数
direction = "R";
stringTime = "0";
snakex[0] = 100;
snakex[1] = 75;
snakex[2] = 50;
snakey[0] = 75;
snakey[1] = 75;
snakey[2] = 75;
}


再将面板画出来,覆盖paint()方法

@Override
public void paint(Graphics graphics) {
graphics.clearRect(450, 0, 150, 25);//清空指定区域

graphics.fillRect(25, 25, 750, 650);// (330, 5, 800, 725)
// 上面显示信息--分数,时间
graphics.setColor(Color.BLACK);
graphics.setFont(new Font("楷体", Font.BOLD, 20));
//分数
graphics.drawString("分数:" + score*10, 450, 20);

// 蛇头
if (direction.equals("R")) {
right.paintIcon(this, graphics, snakex[0], snakey[0]);
} else if (direction.equals("L")) {
left.paintIcon(this, graphics, snakex[0], snakey[0]);
} else if (direction.equals("U")) {
up.paintIcon(this, graphics, snakex[0], snakey[0]);
} else if (direction.equals("D")) {
down.paintIcon(this, graphics, snakex[0], snakey[0]);
}
// 蛇身
for (int i = 1; i < snakeLen; i++) {
body.paintIcon(this, graphics, snakex[i], snakey[i]);
}
// 如果第一次进入游戏
if (isFirst) {
graphics.setColor(Color.white);
graphics.setFont(new Font("方正舒体", Font.BOLD, 38));
graphics.drawString("~~欢迎来到贪吃蛇游戏~~", 180, 270);

graphics.setFont(new Font("方正舒体", Font.BOLD, 22));
graphics.drawString("游戏规则:", 350, 400);
graphics.drawString("空格键开始或停止游戏", 285, 450);
graphics.drawString("方向键来控制蛇的方向", 285, 475);
isFirst = false;
return;
}
// 如果是继续游戏(没有开始且没有失败)
if (!isStared && !isFailed && !isFirst) {
graphics.setColor(Color.white);
graphics.setFont(new Font("方正舒体", Font.BOLD, 38));
graphics.drawString("~~请按空格键开始游戏~~", 180, 270);
}
// 如果已经失败了
if (!isStared && isFailed && !isFirst) {
graphics.setColor(Color.white);
graphics.setFont(new Font("方正舒体", Font.BOLD, 35));
graphics.drawString("游戏结束", 320, 180);
graphics.drawString("~~请按空格键继续~~", 220, 240);
}
// 如果已经开始
if (isStared) {
// 显示食物
food.paintIcon(this, graphics, foodX, foodY);
}
}


最后也是最为关键的,也就是监听了

ActionListener  和  KeyListener 进行时间和键盘的监听

@Override
public void actionPerformed(ActionEvent e) {
if (isStared && !isFailed) {
// 蛇身
for (int i = snakeLen; i > 0; i--) {
snakex[i] = snakex[i - 1];
snakey[i] = snakey[i - 1];
}
// 蛇头
if (direction.equals("U")) {
snakey[0] -= 25;
if (snakey[0] < 25) {
snakey[0] = 650;
}
} else if (direction.equals("D")) {
snakey[0] += 25;
if (snakey[0] > 650) {
snakey[0] = 25;
}
} else if (direction.equals("L")) {
snakex[0] -= 25;
if (snakex[0] < 25) {
snakex[0] = 750;
}
} else if (direction.equals("R")) {
snakex[0] += 25;
if (snakex[0] > 750) {
snakex[0] = 25;
}
}
// 吃掉食物
if (foodX == snakex[0] && foodY == snakey[0]) {
// 重新定义食物位置
foodX = ran.nextInt(30) * 25 + 25;
foodY = ran.nextInt(26) * 25 + 25;
// 蛇身长度加一,分数改变
snakeLen++;
score++;
}
// 如果蛇吃掉了自己?
for (int i = snakeLen; i > 0; i--) {
if (snakex[i] == snakex[0] && snakey[i] == snakey[0]) {
isFailed = true;
isStared = false;
}
}
}
repaint();
}

@Override
public void keyPressed(KeyEvent e) {
timer.start();
int key = e.getKeyCode();
// 空格键
if (KeyEvent.VK_SPACE == key) {
// 如果已经失败了就重新开始
// 否则就暂停或开始
if (isFailed) {
isFailed = false;
isStared = false;
init();
} else {
isStared = !isStared;
}
}

if (key == KeyEvent.VK_UP && !direction.equals("D")) {// 方向--上
direction = "U";
} else if (key == KeyEvent.VK_DOWN && !direction.equals("U")) {// 方向--下
direction = "D";
} else if (key == KeyEvent.VK_LEFT && !direction.equals("R")) {// 方向--左
direction = "L";
} else if (key == KeyEvent.VK_RIGHT && !direction.equals("L")) {// 方向--右
direction = "R";
}
repaint();
}

@Override
public void keyTyped(KeyEvent e) {}
@Override
public void keyReleased(KeyEvent e) {}



最后,如果有需要的,可以到这里来下载整个小程序

​​贪吃蛇1​​

相关的事项在那也讲到了的

当然,如果仅仅是参考一下的就完全没必要了,因为这里的代码已经很全