链接: https://pan.baidu.com/s/1Csg5X2qpeHJUUfVijI_9xw
提取码:hp8e
基于Java的贪吃蛇游戏
我设计的贪吃蛇游戏有三个窗口,开始界面,游戏界面,结束界面。
总共有5个类:GAME_START,GAME ,GAMEOVER,food,snake_border.
此程序用到了画图类方法paint,repaint(重绘方法,调用paint);
还有线程类来不断刷新界面,实现蛇的移动。
开始界面如下:
游戏界面
结束界面
GAME类
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JSplitPane;
import javax.swing.JButton;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JTextField;
import java.awt.SystemColor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.UIManager;
import java.awt.GridLayout;
import java.awt.Canvas;
public class GAME extends JFrame{
private JPanel contentPane;
static int Score=0;
MyThread mythread = new MyThread();
//蛇为双向链表
snake_border head=new snake_border(); //蛇头
snake_border p=head; //遍历指针
snake_border last=head; //蛇尾
JLabel scoreLabel = new JLabel("");//全局定义,方便显示分数
/**
* Launch the application.
*/
/**
* Create the frame.
*/
public GAME(int x,int y) {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(x, y, 232, 380);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
JPanel panel = new JPanel();
panel.setBounds(0, 0, 214, 37);
contentPane.add(panel);
panel.setLayout(null);
JButton btnExit = new JButton("");
btnExit.setIcon(new ImageIcon(GAME.class.getResource("/image/leftj.jpg")));
btnExit.setBounds(0, 0, 34, 34);
btnExit.setBorder(BorderFactory.createRaisedBevelBorder());
btnExit.addActionListener(new ActionListener() { // 为按钮添加监听事件
public void actionPerformed(ActionEvent e) {
START_GAME frame_start = new START_GAME(getX(),getY());
frame_start.setVisible(true);
dispose();
mythread.tosuspend();
//游戏结束,则重置方向
head.allFalse();
head.right=true;
//重置食物
food.food_live=false;
//重置蛇
snake_border.len=0;
p=head;
last=head;
Score=0; //分数重置
}
});
panel.add(btnExit);
JButton btnStop = new JButton("stop");
btnStop.setIcon(new ImageIcon(GAME.class.getResource("/image/stop.jpg")));
btnStop.setHideActionText(false);
btnStop.setBounds(180, 0, 34, 34);
btnStop.setBorder(BorderFactory.createRaisedBevelBorder());
btnStop.addActionListener(new ActionListener() { // 为按钮添加监听事件
public void actionPerformed(ActionEvent e) {
if(btnStop.getText().equals("stop")) { //当没有暂停,点击按钮的时候
btnStop.setIcon(new ImageIcon(GAME.class.getResource("/image/start.jpg")));
btnStop.setText("start");
mythread.tosuspend();
}
else { //当暂停,点击按钮,开始
btnStop.setIcon(new ImageIcon(GAME.class.getResource("/image/stop.jpg")));
btnStop.setText("stop");
mythread.toresume();
}
}
});
panel.add(btnStop);
JLabel Score = new JLabel("Score:");
Score.setFont(new Font("微软雅黑", Font.PLAIN, 20));
Score.setBounds(44, 0, 59, 34);
panel.add(Score);
scoreLabel.setFont(new Font("微软雅黑", Font.PLAIN, 20));
scoreLabel.setBounds(113, 0, 44, 34);
panel.add(scoreLabel);
JPanel panel_1 = new JPanel();
panel_1.setBackground(Color.WHITE);
panel_1.setBounds(10, 47, 196, 196);
contentPane.add(panel_1);
panel_1.setLayout(null);
JPanel panel_2 = new JPanel();
panel_2.setBounds(10, 251, 196, 80);
contentPane.add(panel_2);
panel_2.setLayout(null);
JButton up = new JButton("");
up.setIcon(new ImageIcon(GAME.class.getResource("/image/up.jpg")));
up.setBounds(73, 5, 50, 30);
up.addActionListener(new ActionListener() { // 为按钮添加监听事件
public void actionPerformed(ActionEvent e) {
if(!head.down) { //不能往反方向前进
head.allFalse();
head.up=true;
}
}
});
panel_2.add(up);
JButton left = new JButton("");
left.setIcon(new ImageIcon(GAME.class.getResource("/image/left.jpg")));
left.setBounds(23, 25, 50, 30);
left.addActionListener(new ActionListener() { // 为按钮添加监听事件
public void actionPerformed(ActionEvent e) {
if(!head.right) {
head.allFalse();
head.left=true;
}
}
});
panel_2.add(left);
JButton right = new JButton("");
right.setIcon(new ImageIcon(GAME.class.getResource("/image/right.jpg")));
right.setBounds(123, 25, 50, 30);
right.addActionListener(new ActionListener() { // 为按钮添加监听事件
public void actionPerformed(ActionEvent e) {
if(!head.left) {
head.allFalse();
head.right=true;
}
}
});
panel_2.add(right);
JButton down = new JButton("");
down.setIcon(new ImageIcon(GAME.class.getResource("/image/down.jpg")));
down.setBounds(73, 45, 50, 30);
down.addActionListener(new ActionListener() { // 为按钮添加监听事件
public void actionPerformed(ActionEvent e) {
if(!head.up) {
head.allFalse();
head.down=true;
}
}
});
panel_2.add(down);
mythread.start();
}
food foodo=new food();
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2=(Graphics2D)g;
g2.setColor(Color.BLUE);
if(head.nowx==foodo.foodx&&head.nowy==foodo.foody) {
//设置标志食物死亡
food.food_live=false;
p=new snake_border();
last.next=p; //指向新增加的身体
p.prior=last;
//为新加的节点设置坐标
p.nowx=last.oldx;
p.nowy=last.oldy;
//重新定义指针指向
last=p;
p=head;
//增加长度
snake_border.len++;
//增加分数
Score+=10;
}
scoreLabel.setText(String.valueOf(Score));
if(!food.food_live) { //如果食物死亡,创建新食物
foodo.foodxy();
while(p.next!=null) {
if(foodo.foodx==p.nowx&&foodo.foody==p.nowy) { //如果新食物的坐标与蛇身坐标相同,则重新随机坐标
foodo=new food();
foodo.foodxy();
p=head;
}
p=p.next;
}
food.food_live=true;
}
g2.fillRect(foodo.foodx, foodo.foody, 7, 7);
p=head; //指向头节点
g2.setColor(Color.GREEN);
for(int i=0;i<snake_border.len;i++) { //绘制蛇身
if(i==0) { //头节点移动
p.move();
}
if(i>0) { //其他节点跟随前一个节点
p.oldtonow();
p.nowx=p.prior.oldx;
p.nowy=p.prior.oldy;
}
if(p.next!=null) {
p=p.next;
}
}
p=head;
//如果头超出边界
if(head.nowx<19||head.nowx>12+196||head.nowy<80||head.nowy>73+196) {
GAMEOVER frame_start = new GAMEOVER(getX(),getY());
frame_start.setVisible(true);
dispose();
//游戏结束,则重置方向
head.allFalse();
head.right=true;
//重置食物
food.food_live=false;
//重置蛇
snake_border.len=0;
p=head;
last=head;
mythread.tosuspend();
}
//指向头节点的下一个节点
if(p.next!=null) {
p=head.next;
}
//如果蛇吃到自己的身体
for(int i=1;i<snake_border.len;i++) {
if(head.nowx==p.nowx&&head.nowy==p.nowy) {
GAMEOVER frame_start = new GAMEOVER(getX(),getY());
frame_start.setVisible(true);
dispose();
//游戏结束,则重置方向
head.allFalse();
head.right=true;
//重置食物
food.food_live=false;
//重置蛇
snake_border.len=0;
p=head;
last=head;
mythread.tosuspend();
}
if(p.next!=null) {
p=p.next;
}
}
p=head;
for(int i=0;i<snake_border.len;i++) { //绘制蛇身
g2.fillRect(p.nowx, p.nowy, 7, 7);
if(p.next!=null) {
p=p.next;
}
}
p=head;
}
class MyThread extends Thread{
private boolean suspend=false;
public synchronized void tosuspend() {
suspend=true;
}
public synchronized void toresume() {
suspend=false;
notify(); //唤醒线程
}
public void run() {
while(true){
synchronized(this){
while(suspend) {
try {
wait(); //使线程进入等待状态
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
repaint();// 调用paint方法,重绘
try {
sleep(300/START_GAME.speed);//每300/START_GAME.speed毫秒重绘一次
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
GAME_START类
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JButton;
import javax.swing.JLayeredPane;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.ImageIcon;
import java.awt.Color;
import javax.swing.JLabel;
import java.awt.CardLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.UIManager;
import java.awt.SystemColor;
import javax.swing.JComboBox;
import javax.swing.SwingConstants;
public class START_GAME extends JFrame {
private JPanel contentPane;
static int speed=1;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
START_GAME frame_start = new START_GAME();
frame_start.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public START_GAME() { //第一次创建的窗口
setTitle("\u8D2A\u5403\u86C7");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 250, 330);
contentPane = new JPanel();
contentPane.setBackground(SystemColor.activeCaption);
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
JButton btnStart = new JButton("\u6E38\u620F\u5F00\u59CB");
btnStart.setFont(new Font("微软雅黑", Font.PLAIN, 13));
btnStart.setBackground(SystemColor.menu);
btnStart.setForeground(Color.BLACK);
btnStart.setBounds(70, 195, 93, 40);
contentPane.add(btnStart);
JLabel welcome = new JLabel("\u6B22\u8FCE\u6E38\u73A9\u8D2A\u5403\u86C7");
welcome.setFont(new Font("微软雅黑", Font.PLAIN, 20));
welcome.setBounds(48, 50, 147, 53);
contentPane.add(welcome);
JComboBox<String> comboBox = new JComboBox<>(); //添加下拉框,用来设置速度
String [] speedarr= {"1","2","3"};
ComboBoxModel speedcm=new DefaultComboBoxModel<>(speedarr);
comboBox.setModel(speedcm);
comboBox.setBounds(98, 113, 65, 23);
contentPane.add(comboBox);
JLabel speedLabel = new JLabel("\u901F\u5EA6\uFF1A");
speedLabel.setHorizontalAlignment(SwingConstants.RIGHT);
speedLabel.setBounds(34, 113, 54, 23);
contentPane.add(speedLabel);
btnStart.addActionListener(new ActionListener() { // 为按钮添加监听事件
public void actionPerformed(ActionEvent e) {
GAME frame_game = new GAME(getX(),getY());
frame_game.setVisible(true);
snake_border.len++;
speed=Integer.valueOf((String) comboBox.getSelectedItem());
dispose();
}
});
}
public START_GAME(int x,int y) { //在游戏界面退出来时,定位创建的窗口
setTitle("\u8D2A\u5403\u86C7");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(x, y, 250, 330);
contentPane = new JPanel();
contentPane.setBackground(SystemColor.activeCaption);
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
JButton btnStart = new JButton("\u6E38\u620F\u5F00\u59CB");
btnStart.setFont(new Font("微软雅黑", Font.PLAIN, 13));
btnStart.setBackground(SystemColor.menu);
btnStart.setForeground(Color.BLACK);
btnStart.setBounds(70, 195, 93, 40);
contentPane.add(btnStart);
JLabel welcome = new JLabel("\u6B22\u8FCE\u6E38\u73A9\u8D2A\u5403\u86C7");
welcome.setFont(new Font("微软雅黑", Font.PLAIN, 20));
welcome.setBounds(48, 50, 147, 53);
contentPane.add(welcome);
JComboBox<String> comboBox = new JComboBox<>(); //添加下拉框,用来设置速度
String [] speedarr= {"1","2","3"};
ComboBoxModel speedcm=new DefaultComboBoxModel<>(speedarr);
comboBox.setModel(speedcm);
comboBox.setBounds(98, 113, 65, 23);
contentPane.add(comboBox);
JLabel speedLabel = new JLabel("\u901F\u5EA6\uFF1A");
speedLabel.setHorizontalAlignment(SwingConstants.RIGHT);
speedLabel.setBounds(34, 113, 54, 23);
contentPane.add(speedLabel);
btnStart.addActionListener(new ActionListener() { // 为按钮添加监听事件
public void actionPerformed(ActionEvent e) {
int x=getX();
int y=getY();
GAME frame_game = new GAME(x,y);
frame_game.setVisible(true);
snake_border.len++;
speed=Integer.valueOf((String) comboBox.getSelectedItem());
dispose();
}
});
}
}
GAMEOVER类
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JLabel;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.SwingConstants;
import javax.swing.JTextField;
import javax.swing.JButton;
public class GAMEOVER extends JFrame {
private JPanel contentPane;
/**
* Launch the application.
*/
// public static void main(String[] args) {
// EventQueue.invokeLater(new Runnable() {
// public void run() {
// try {
// GAMEOVER frame = new GAMEOVER();
// frame.setVisible(true);
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
// });
// }
/**
* Create the frame.
*/
public GAMEOVER(int x,int y) {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(x, y, 232, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
JLabel gameoverLabel = new JLabel("\u6E38\u620F\u7ED3\u675F");
gameoverLabel.setHorizontalAlignment(SwingConstants.CENTER);
gameoverLabel.setFont(new Font("微软雅黑", Font.PLAIN, 20));
gameoverLabel.setBounds(5, 5, 206, 61);
contentPane.add(gameoverLabel);
JLabel scoreLabel = new JLabel("Score:");
scoreLabel.setFont(new Font("微软雅黑", Font.PLAIN, 20));
scoreLabel.setBounds(58, 86, 70, 37);
contentPane.add(scoreLabel);
JButton btntostart = new JButton("\u786E\u5B9A");
btntostart.setFont(new Font("微软雅黑", Font.PLAIN, 20));
btntostart.setBounds(64, 171, 93, 37);
btntostart.addActionListener(new ActionListener() { // 为按钮添加监听事件
public void actionPerformed(ActionEvent e) {
START_GAME frame_start = new START_GAME(getX(),getY());
frame_start.setVisible(true);
GAME.Score=0;
dispose();
}
});
contentPane.add(btntostart);
JLabel Score = new JLabel("");
Score.setHorizontalAlignment(SwingConstants.CENTER);
Score.setFont(new Font("微软雅黑", Font.PLAIN, 20));
Score.setBounds(127, 86, 30, 37);
Score.setText(String.valueOf(GAME.Score));
contentPane.add(Score);
}
}
food类
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.Random;
public class food {
static boolean food_live=false; //表示食物是否存活
int foodx; //食物的横坐标
int foody; //食物的纵坐标
public void foodxy() {
Random rand = new Random(); //随机对象
foodx=rand.nextInt(27)*7+19; //随机间隔为7的随机数
foody=rand.nextInt(27)*7+80;
}
}
snake_border类
public class snake_border {
int nowx=19,nowy=80; //现在的坐标
int oldx=0,oldy=0; //前一格的坐标
static int len=0; //蛇的长度
boolean left=false; //如果为true,蛇的方向为左
boolean right=true; //如果为true,蛇的方向为右
boolean up=false; //如果为true,蛇的方向为上
boolean down=false; //如果为true,蛇的方向为下
snake_border next=null; //指向下一个节点(尾节点不需要)
snake_border prior;//指向前一个节点(头节点不需要)
public void move() {
if(left) {
oldtonow();
nowx-=7;
}
if(right) {
oldtonow();
nowx+=7;
}
if(up) {
oldtonow();
nowy-=7;
}
if(down) {
oldtonow();
nowy+=7;
}
}
public void allFalse() {
left=false;
right=false;
up=false;
down=false;
}
public void oldtonow() { //将移动前的坐标记录下来
oldx=nowx;
oldy=nowy;
}
}