贪吃蛇实现步骤
1.游戏窗口
package snake;
import javax.swing.*;
public class StartGame {
public static void main(String[] args) {
JFrame frame = new JFrame();
// 设置窗口大小
frame.setBounds(10, 10, 900, 700);
// 设置窗口大小固定
frame.setResizable(false);
// 设置窗口可关闭
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// 设置窗口可见
frame.setVisible(true);
}
}
注意:每个图片的大小为25,所以窗口大小的长和宽是25的倍数
2.获取图片
package snake;
import javax.swing.*;
import java.net.URL;
public class Data {
// 获取头部图片
public static URL headUrl = Data.class.getResource("statics/head.jpg");
public static ImageIcon head = new ImageIcon(headUrl);
// 获取向右的蛇头图片
public static URL rightUrl = Data.class.getResource("statics/right.png");
public static ImageIcon right = new ImageIcon(rightUrl);
// 获取向左的蛇头图片
public static URL leftUrl = Data.class.getResource("statics/left.png");
public static ImageIcon left = new ImageIcon(leftUrl);
// 获取向上的蛇头图片
public static URL upUrl = Data.class.getResource("statics/up.png");
public static ImageIcon up = new ImageIcon(upUrl);
// 获取向下的蛇头图片
public static URL downUrl = Data.class.getResource("statics/down.png");
public static ImageIcon down = new ImageIcon(downUrl);
// 获取身体图片
public static URL bodyUrl = Data.class.getResource("statics/body.png");
public static ImageIcon body = new ImageIcon(bodyUrl);
// 获取食物图片
public static URL foodUrl = Data.class.getResource("statics/food.png");
public static ImageIcon food = new ImageIcon(foodUrl);
}
3.设置游戏界面
package snake;
import javax.swing.*;
import java.awt.*;
public class GamePanel extends JPanel {
@Override
protected void paintComponent(Graphics g) {
// 清屏
super.paintComponent(g);
// 设置背景色
this.setBackground(Color.white);
// 设置头部位置
Data.head.paintIcon(this, g, 25, 25);
// 设置游戏界面位置及大小
g.fillRect(25, 75, 850, 625);
}
}
将游戏页面添加至游戏窗口
package snake;
import javax.swing.*;
public class StartGame {
public static void main(String[] args) {
JFrame frame = new JFrame();
// 设置窗口大小
frame.setBounds(10, 10, 900, 700);
// 游戏面板放到游戏窗口
frame.add(new GamePanel());
// 设置窗口大小固定
frame.setResizable(false);
// 设置窗口可关闭
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// 设置窗口可见
frame.setVisible(true);
}
}
4.设置蛇
4.1设置蛇头和蛇身
package snake;
import javax.swing.*;
import java.awt.*;
public class GamePanel extends JPanel {
// 蛇长度
private int length;
// 蛇头和身体的左边
private int[] snakeX = new int[34];
private int[] snakeY = new int[25];
@Override
protected void paintComponent(Graphics g) {
// 清屏
super.paintComponent(g);
// 设置背景色
this.setBackground(Color.white);
// 设置头部位置
Data.head.paintIcon(this, g, 25, 25);
// 设置游戏界面位置及大小
g.fillRect(25, 75, 850, 625);
// 初始化蛇
// 初始化蛇的长度为3
length = 3;
// 初始化蛇的头和身体坐标
snakeX[0] = 100;snakeY[0] = 100;
snakeX[1] = 75;snakeY[1] = 100;
snakeX[2] = 50;snakeY[2] = 100;
// 设置蛇头和蛇身
Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
for(int i = 1; i < length; i++) {
Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);
}
}
}
4.2提取初始化
package snake;
import javax.swing.*;
import java.awt.*;
public class GamePanel extends JPanel {
// 蛇长度
private int length;
// 蛇头和身体的左边
private int[] snakeX = new int[34];
private int[] snakeY = new int[25];
public GamePanel() {
init();
}
// 初始化
private void init() {
// 初始化蛇
// 初始化蛇的长度为3
length = 3;
// 初始化蛇的头和身体坐标
snakeX[0] = 100;snakeY[0] = 100;
snakeX[1] = 75;snakeY[1] = 100;
snakeX[2] = 50;snakeY[2] = 100;
}
@Override
protected void paintComponent(Graphics g) {
// 清屏
super.paintComponent(g);
// 设置背景色
this.setBackground(Color.white);
// 设置头部位置
Data.head.paintIcon(this, g, 25, 25);
// 设置游戏界面位置及大小
g.fillRect(25, 75, 850, 625);
// 设置蛇头和蛇身
Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
for(int i = 1; i < length; i++) {
Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);
}
}
}
4.3根据方向设置蛇头
package snake;
import javax.swing.*;
import java.awt.*;
public class GamePanel extends JPanel {
// 蛇长度
private int length;
// 蛇头和身体的左边
private int[] snakeX = new int[34];
private int[] snakeY = new int[25];
// 蛇头方向
private String fx;
public GamePanel() {
init();
}
// 初始化
private void init() {
// 初始化蛇
// 初始化蛇的长度为3
length = 3;
// 初始化蛇的头和身体坐标
snakeX[0] = 100;snakeY[0] = 100;
snakeX[1] = 75;snakeY[1] = 100;
snakeX[2] = 50;snakeY[2] = 100;
// 初始化蛇头方向
fx = "R";
}
@Override
protected void paintComponent(Graphics g) {
// 清屏
super.paintComponent(g);
// 设置背景色
this.setBackground(Color.white);
// 设置头部位置
Data.head.paintIcon(this, g, 25, 25);
// 设置游戏界面位置及大小
g.fillRect(25, 75, 850, 625);
// 设置蛇头
if (fx == "R") {
Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
} else if (fx == "L") {
Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);
} else if (fx == "U") {
Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);
} else if (fx == "D") {
Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);
}
// 设置蛇身
for(int i = 1; i < length; i++) {
Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);
}
}
}
5.设置食物
package snake;
import javax.swing.*;
import java.awt.*;
import java.util.Random;
public class GamePanel extends JPanel {
// 蛇长度
private int length;
// 蛇头和身体的左边
private int[] snakeX = new int[34];
private int[] snakeY = new int[25];
// 蛇头方向
private String fx;
// 食物坐标
private int foodX;
private int fondY;
private Random random = new Random();
public GamePanel() {
init();
}
// 初始化
private void init() {
// 初始化蛇
// 初始化蛇的长度为3
length = 3;
// 初始化蛇的头和身体坐标
snakeX[0] = 100;snakeY[0] = 100;
snakeX[1] = 75;snakeY[1] = 100;
snakeX[2] = 50;snakeY[2] = 100;
// 初始化蛇头方向
fx = "R";
// 初始化食物坐标
foodX = 25 + random.nextInt(34) * 25;
fondY = 25 + random.nextInt(25) * 25;
}
@Override
protected void paintComponent(Graphics g) {
// 清屏
super.paintComponent(g);
// 设置背景色
this.setBackground(Color.white);
// 设置头部位置
Data.head.paintIcon(this, g, 25, 25);
// 设置游戏界面位置及大小
g.fillRect(25, 75, 850, 625);
// 设置蛇头
if (fx == "R") {
Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
} else if (fx == "L") {
Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);
} else if (fx == "U") {
Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);
} else if (fx == "D") {
Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);
}
// 设置蛇身
for(int i = 1; i < length; i++) {
Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);
}
// 设置食物
Data.food.paintIcon(this, g, foodX, fondY);
}
}
注意:食物的坐标是随机的,所以用到随机函数,但是不超过总的坐标范围。
34 = 850 / 25
25 = 625 / 25
6.设置游戏状态
按下空格键游戏开始/暂停,游戏暂停显示文字“按下空格,开始游戏”。
监听空格键,按下空格键,游戏从暂停变成开始/开始变暂停。
package snake;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
public class GamePanel extends JPanel implements KeyListener {
// 蛇长度
private int length;
// 蛇头和身体的左边
private int[] snakeX = new int[34];
private int[] snakeY = new int[25];
// 蛇头方向
private String fx;
// 食物坐标
private int foodX;
private int fondY;
private Random random = new Random();
// 游戏状态
private boolean isStart = false;
public GamePanel() {
init();
// 设置焦点
this.setFocusable(true);
// 添加键盘监听
this.addKeyListener(this);
}
// 初始化
private void init() {
// 初始化蛇
// 初始化蛇的长度为3
length = 3;
// 初始化蛇的头和身体坐标
snakeX[0] = 100;snakeY[0] = 100;
snakeX[1] = 75;snakeY[1] = 100;
snakeX[2] = 50;snakeY[2] = 100;
// 初始化蛇头方向
fx = "R";
// 初始化食物坐标
foodX = 25 + random.nextInt(34) * 25;
fondY = 25 + random.nextInt(25) * 25;
}
@Override
protected void paintComponent(Graphics g) {
// 清屏
super.paintComponent(g);
// 设置背景色
this.setBackground(Color.white);
// 设置头部位置
Data.head.paintIcon(this, g, 25, 25);
// 设置游戏界面位置及大小
g.fillRect(25, 75, 850, 625);
// 设置蛇头
if (fx == "R") {
Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
} else if (fx == "L") {
Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);
} else if (fx == "U") {
Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);
} else if (fx == "D") {
Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);
}
// 设置蛇身
for(int i = 1; i < length; i++) {
Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);
}
// 设置食物
Data.food.paintIcon(this, g, foodX, fondY);
// 游戏暂停,显示按下空格,游戏开始
if (!isStart) {
// 设置字体颜色
g.setColor(Color.white);
// 设置字体
g.setFont(new Font("微软雅黑", Font.BOLD, 40));
// 设置文字
g.drawString("按下空格,游戏开始", 300, 300);
}
}
@Override
public void keyPressed(KeyEvent e) {
// 获取按键编码
int keyCode = e.getKeyCode();
// 按下空格键
if (keyCode == KeyEvent.VK_SPACE) {
isStart = !isStart;
}
// 重画
repaint();
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyTyped(KeyEvent e) {
}
}
注意:
该游戏页面获取焦点以及添加键盘监听,如果不加无法键盘监听无效。
空格监听后得重画,不然也无法正常显示。
7.蛇移动
用定时器实现蛇的移动
package snake;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
public class GamePanel extends JPanel implements KeyListener, ActionListener {
// 蛇长度
private int length;
// 蛇头和身体的左边
private int[] snakeX = new int[34];
private int[] snakeY = new int[25];
// 蛇头方向
private String fx;
// 食物坐标
private int foodX;
private int fondY;
private Random random = new Random();
// 游戏状态
private boolean isStart = false;
// 设置定时器
private Timer timer = new Timer(100, this);
public GamePanel() {
init();
// 设置焦点
this.setFocusable(true);
// 添加键盘监听
this.addKeyListener(this);
// 启动定时器
timer.start();
}
// 初始化
private void init() {
// 初始化蛇
// 初始化蛇的长度为3
length = 3;
// 初始化蛇的头和身体坐标
snakeX[0] = 100;snakeY[0] = 100;
snakeX[1] = 75;snakeY[1] = 100;
snakeX[2] = 50;snakeY[2] = 100;
// 初始化蛇头方向
fx = "R";
// 初始化食物坐标
foodX = 25 + random.nextInt(34) * 25;
fondY = 25 + random.nextInt(25) * 25;
}
@Override
protected void paintComponent(Graphics g) {
// 清屏
super.paintComponent(g);
// 设置背景色
this.setBackground(Color.white);
// 设置头部位置
Data.head.paintIcon(this, g, 25, 25);
// 设置游戏界面位置及大小
g.fillRect(25, 75, 850, 625);
// 设置蛇头
if (fx == "R") {
Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
} else if (fx == "L") {
Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);
} else if (fx == "U") {
Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);
} else if (fx == "D") {
Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);
}
// 设置蛇身
for(int i = 1; i < length; i++) {
Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);
}
// 设置食物
Data.food.paintIcon(this, g, foodX, fondY);
// 游戏暂停,显示按下空格,游戏开始
if (!isStart) {
// 设置字体颜色
g.setColor(Color.white);
// 设置字体
g.setFont(new Font("微软雅黑", Font.BOLD, 40));
// 设置文字
g.drawString("按下空格,游戏开始", 300, 300);
}
}
@Override
public void keyPressed(KeyEvent e) {
// 获取按键编码
int keyCode = e.getKeyCode();
// 按下空格键
if (keyCode == KeyEvent.VK_SPACE) {
isStart = !isStart;
}
// 重画
repaint();
}
@Override
public void actionPerformed(ActionEvent e) {
if (isStart) {
// 后一个坐标等于前面一个坐标
for (int i = length - 1; i > 0; i--) {
snakeX[i] = snakeX[i - 1];
snakeY[i] = snakeY[i - 1];
}
if (fx == "R") { // 向右头坐标横坐标+25
snakeX[0] += 25;
if (snakeX[0] > 850) {
snakeX[0] = 25;
}
} else if (fx == "L") { // 向左头横坐标-25
snakeX[0] -= 25;
if (snakeX[0] < 25) {
snakeX[0] = 850;
}
} else if (fx == "U") { // 向上头纵坐标-25
snakeY[0] -= 25;
if (snakeY[0] < 75) {
snakeY[0] = 625;
}
} else if (fx == "D") { // 向下头纵坐标+25
snakeY[0] += 25;
if (snakeY[0] > 625) {
snakeY[0] = 75;
}
}
// 重画
repaint();
// 启动定时器
timer.start();
}
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyTyped(KeyEvent e) {
}
}
8.通过方向键来控制蛇的移动
package snake;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
public class GamePanel extends JPanel implements KeyListener, ActionListener {
// 蛇长度
private int length;
// 蛇头和身体的左边
private int[] snakeX = new int[34];
private int[] snakeY = new int[25];
// 蛇头方向
private String fx;
// 食物坐标
private int foodX;
private int fondY;
private Random random = new Random();
// 游戏状态
private boolean isStart = false;
// 设置定时器
private Timer timer = new Timer(100, this);
public GamePanel() {
init();
// 设置焦点
this.setFocusable(true);
// 添加键盘监听
this.addKeyListener(this);
// 启动定时器
timer.start();
}
// 初始化
private void init() {
// 初始化蛇
// 初始化蛇的长度为3
length = 3;
// 初始化蛇的头和身体坐标
snakeX[0] = 100;snakeY[0] = 100;
snakeX[1] = 75;snakeY[1] = 100;
snakeX[2] = 50;snakeY[2] = 100;
// 初始化蛇头方向
fx = "R";
// 初始化食物坐标
foodX = 25 + random.nextInt(34) * 25;
fondY = 25 + random.nextInt(25) * 25;
}
@Override
protected void paintComponent(Graphics g) {
// 清屏
super.paintComponent(g);
// 设置背景色
this.setBackground(Color.white);
// 设置头部位置
Data.head.paintIcon(this, g, 25, 25);
// 设置游戏界面位置及大小
g.fillRect(25, 75, 850, 625);
// 设置蛇头
if (fx == "R") {
Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
} else if (fx == "L") {
Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);
} else if (fx == "U") {
Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);
} else if (fx == "D") {
Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);
}
// 设置蛇身
for(int i = 1; i < length; i++) {
Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);
}
// 设置食物
Data.food.paintIcon(this, g, foodX, fondY);
// 游戏暂停,显示按下空格,游戏开始
if (!isStart) {
// 设置字体颜色
g.setColor(Color.white);
// 设置字体
g.setFont(new Font("微软雅黑", Font.BOLD, 40));
// 设置文字
g.drawString("按下空格,游戏开始", 300, 300);
}
}
@Override
public void keyPressed(KeyEvent e) {
// 获取按键编码
int keyCode = e.getKeyCode();
// 按下空格键
if (keyCode == KeyEvent.VK_SPACE) {
isStart = !isStart;
}
// 监听方向键
if (keyCode == KeyEvent.VK_RIGHT) {
fx = "R";
} else if (keyCode == KeyEvent.VK_LEFT) {
fx = "L";
} else if (keyCode == KeyEvent.VK_UP) {
fx = "U";
} else if (keyCode == KeyEvent.VK_DOWN) {
fx = "D";
}
// 重画
repaint();
}
@Override
public void actionPerformed(ActionEvent e) {
if (isStart) {
// 后一个坐标等于前面一个坐标
for (int i = length - 1; i > 0; i--) {
snakeX[i] = snakeX[i - 1];
snakeY[i] = snakeY[i - 1];
}
if (fx == "R") { // 向右头坐标横坐标+25
snakeX[0] += 25;
if (snakeX[0] > 850) {
snakeX[0] = 25;
}
} else if (fx == "L") { // 向左头横坐标-25
snakeX[0] -= 25;
if (snakeX[0] < 25) {
snakeX[0] = 850;
}
} else if (fx == "U") { // 向上头纵坐标-25
snakeY[0] -= 25;
if (snakeY[0] < 75) {
snakeY[0] = 625;
}
} else if (fx == "D") { // 向下头纵坐标+25
snakeY[0] += 25;
if (snakeY[0] > 625) {
snakeY[0] = 75;
}
}
// 重画
repaint();
// 启动定时器
timer.start();
}
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyTyped(KeyEvent e) {
}
}
9.动态食物坐标和吃到食物长度+1
蛇头的坐标和食物的坐标重合为吃到食物。
package snake;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
public class GamePanel extends JPanel implements KeyListener, ActionListener {
// 蛇长度
private int length;
// 蛇头和身体的左边
private int[] snakeX = new int[34];
private int[] snakeY = new int[25];
// 蛇头方向
private String fx;
// 食物坐标
private int foodX;
private int fondY;
private Random random = new Random();
// 游戏状态
private boolean isStart = false;
// 设置定时器
private Timer timer = new Timer(100, this);
public GamePanel() {
init();
// 设置焦点
this.setFocusable(true);
// 添加键盘监听
this.addKeyListener(this);
// 启动定时器
timer.start();
}
// 初始化
private void init() {
// 初始化蛇
// 初始化蛇的长度为3
length = 3;
// 初始化蛇的头和身体坐标
snakeX[0] = 100;snakeY[0] = 100;
snakeX[1] = 75;snakeY[1] = 100;
snakeX[2] = 50;snakeY[2] = 100;
// 初始化蛇头方向
fx = "R";
// 初始化食物坐标
foodX = 25 + random.nextInt(34) * 25;
fondY = 25 + random.nextInt(25) * 25;
}
@Override
protected void paintComponent(Graphics g) {
// 清屏
super.paintComponent(g);
// 设置背景色
this.setBackground(Color.white);
// 设置头部位置
Data.head.paintIcon(this, g, 25, 25);
// 设置游戏界面位置及大小
g.fillRect(25, 75, 850, 625);
// 设置蛇头
if (fx == "R") {
Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
} else if (fx == "L") {
Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);
} else if (fx == "U") {
Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);
} else if (fx == "D") {
Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);
}
// 设置蛇身
for(int i = 1; i < length; i++) {
Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);
}
// 设置食物
Data.food.paintIcon(this, g, foodX, fondY);
// 游戏暂停,显示按下空格,游戏开始
if (!isStart) {
// 设置字体颜色
g.setColor(Color.white);
// 设置字体
g.setFont(new Font("微软雅黑", Font.BOLD, 40));
// 设置文字
g.drawString("按下空格,游戏开始", 300, 300);
}
}
@Override
public void keyPressed(KeyEvent e) {
// 获取按键编码
int keyCode = e.getKeyCode();
// 按下空格键
if (keyCode == KeyEvent.VK_SPACE) {
isStart = !isStart;
}
// 监听方向键
if (keyCode == KeyEvent.VK_RIGHT) {
fx = "R";
} else if (keyCode == KeyEvent.VK_LEFT) {
fx = "L";
} else if (keyCode == KeyEvent.VK_UP) {
fx = "U";
} else if (keyCode == KeyEvent.VK_DOWN) {
fx = "D";
}
// 重画
repaint();
}
@Override
public void actionPerformed(ActionEvent e) {
if (isStart) {
// 后一个坐标等于前面一个坐标
for (int i = length - 1; i > 0; i--) {
snakeX[i] = snakeX[i - 1];
snakeY[i] = snakeY[i - 1];
}
if (fx == "R") { // 向右头坐标横坐标+25
snakeX[0] += 25;
if (snakeX[0] > 850) {
snakeX[0] = 25;
}
} else if (fx == "L") { // 向左头横坐标-25
snakeX[0] -= 25;
if (snakeX[0] < 25) {
snakeX[0] = 850;
}
} else if (fx == "U") { // 向上头纵坐标-25
snakeY[0] -= 25;
if (snakeY[0] < 75) {
snakeY[0] = 625;
}
} else if (fx == "D") { // 向下头纵坐标+25
snakeY[0] += 25;
if (snakeY[0] > 625) {
snakeY[0] = 75;
}
}
if (foodX == snakeX[0] && fondY == snakeY[0]) {
// 重置食物坐标
foodX = 25 + random.nextInt(34) * 25;
fondY = 25 + random.nextInt(25) * 25;
// 长度+1
length++;
}
// 重画
repaint();
// 启动定时器
timer.start();
}
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyTyped(KeyEvent e) {
}
}
10.游戏失败
头的坐标和身体坐标重合,游戏即为失败。
游戏正常开始条件为失败状态为false以及游戏状态为开始。
空格监听,得先判断是否失败,否则在判断游戏是否开始
package snake;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
public class GamePanel extends JPanel implements KeyListener, ActionListener {
// 蛇长度
private int length;
// 蛇头和身体的左边
private int[] snakeX = new int[34];
private int[] snakeY = new int[25];
// 蛇头方向
private String fx;
// 食物坐标
private int foodX;
private int fondY;
private Random random = new Random();
// 游戏状态
private boolean isStart = false;
// 设置定时器
private Timer timer = new Timer(100, this);
// 失败状态
private boolean isFalse = false;
public GamePanel() {
init();
// 设置焦点
this.setFocusable(true);
// 添加键盘监听
this.addKeyListener(this);
// 启动定时器
timer.start();
}
// 初始化
private void init() {
// 初始化蛇
// 初始化蛇的长度为3
length = 3;
// 初始化蛇的头和身体坐标
snakeX[0] = 100;snakeY[0] = 100;
snakeX[1] = 75;snakeY[1] = 100;
snakeX[2] = 50;snakeY[2] = 100;
// 初始化蛇头方向
fx = "R";
// 初始化食物坐标
foodX = 25 + random.nextInt(34) * 25;
fondY = 25 + random.nextInt(25) * 25;
}
@Override
protected void paintComponent(Graphics g) {
// 清屏
super.paintComponent(g);
// 设置背景色
this.setBackground(Color.white);
// 设置头部位置
Data.head.paintIcon(this, g, 25, 25);
// 设置游戏界面位置及大小
g.fillRect(25, 75, 850, 625);
// 设置蛇头
if (fx == "R") {
Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
} else if (fx == "L") {
Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);
} else if (fx == "U") {
Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);
} else if (fx == "D") {
Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);
}
// 设置蛇身
for(int i = 1; i < length; i++) {
Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);
}
// 设置食物
Data.food.paintIcon(this, g, foodX, fondY);
// 游戏暂停,显示按下空格,游戏开始
if (isFalse) {
// 设置字体颜色
g.setColor(Color.white);
// 设置字体
g.setFont(new Font("微软雅黑", Font.BOLD, 40));
// 设置文字
g.drawString("游戏失败,按下空格,游戏开始", 300, 300);
} else {
if (!isStart) {
// 设置字体颜色
g.setColor(Color.white);
// 设置字体
g.setFont(new Font("微软雅黑", Font.BOLD, 40));
// 设置文字
g.drawString("按下空格,游戏开始", 300, 300);
}
}
}
@Override
public void keyPressed(KeyEvent e) {
// 获取按键编码
int keyCode = e.getKeyCode();
// 按下空格键
if (keyCode == KeyEvent.VK_SPACE) {
if (isFalse) {
isFalse = false;
} else {
isStart = !isStart;
}
}
// 监听方向键
if (keyCode == KeyEvent.VK_RIGHT) {
fx = "R";
} else if (keyCode == KeyEvent.VK_LEFT) {
fx = "L";
} else if (keyCode == KeyEvent.VK_UP) {
fx = "U";
} else if (keyCode == KeyEvent.VK_DOWN) {
fx = "D";
}
// 重画
repaint();
}
@Override
public void actionPerformed(ActionEvent e) {
if (isStart && !isFalse) {
for (int i = 1; i < length; i++) {
// 判断身体是否与蛇头重合
if (snakeX[i] == snakeX[0] && snakeY[i] == snakeY[0]) {
// 设为失败
isFalse = true;
// 重置游戏页面
init();
// 重画
repaint();
return;
}
}
// 后一个坐标等于前面一个坐标
for (int i = length - 1; i > 0; i--) {
snakeX[i] = snakeX[i - 1];
snakeY[i] = snakeY[i - 1];
}
if (fx == "R") { // 向右头坐标横坐标+25
snakeX[0] += 25;
if (snakeX[0] > 850) {
snakeX[0] = 25;
}
} else if (fx == "L") { // 向左头横坐标-25
snakeX[0] -= 25;
if (snakeX[0] < 25) {
snakeX[0] = 850;
}
} else if (fx == "U") { // 向上头纵坐标-25
snakeY[0] -= 25;
if (snakeY[0] < 75) {
snakeY[0] = 625;
}
} else if (fx == "D") { // 向下头纵坐标+25
snakeY[0] += 25;
if (snakeY[0] > 625) {
snakeY[0] = 75;
}
}
if (foodX == snakeX[0] && fondY == snakeY[0]) {
// 重置食物坐标
foodX = 25 + random.nextInt(34) * 25;
fondY = 25 + random.nextInt(25) * 25;
// 长度+1
length++;
}
// 重画
repaint();
// 启动定时器
timer.start();
}
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyTyped(KeyEvent e) {
}
}

浙公网安备 33010602011771号