基于Java的贪吃蛇游戏


链接: 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;
 }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值