MIKU MOE

Java_GUI及贪吃蛇案例

GUI及贪吃蛇案例



组件 : 窗口 弹窗 面板 文本框 列表框 按钮 图片 监听事件 鼠标键盘 事件

 

学习内容 :

Gui的核心技术:

Swing

Awt

了解MVC架构,了解监听!

1. AWT

1.1 Frame

 Frame frame = new Frame("title");
 //设置可见性
 frame.setVisible(true);
 //设置窗口大小
 frame.setSize(400,400);
 //设置背景颜色
 frame.setBackground(new Color(85,150,68));
 //弹出初始化位置
 frame.setLocation(200,200);
 //设置大小固定,不可拉伸
 frame.setResizable(false);

 public class MyFrame extends Frame{ //包装成类调用
     static int id = 0;
     public MyFrame(int x,int y,int w,int h,Color color){
         super("MyFrame"+(++id));
         setBackground(color);
         setBounds(x,y,w,h);
         setVisible(true);
         setResizable(false);
     }
 }

注意,此时关闭键不起作用!!

1.2 面板 - Panel

 Frame frame = new Frame();
 //布局的概念
 Panel panel = new Panel();
 //设置布局  布局管理器
 frame.setLayout(null);
 //坐标 背景
 frame.setBounds(300, 300, 500, 500);
 frame.setBackground(new Color(181, 252, 238));
 //panel设置坐标  相对于frame
 panel.setBounds(50, 50, 400, 400);
 panel.setBackground(new Color(190, 131, 255));
 //frame.add(panel);
 frame.add(panel);
 //可见性
 frame.setVisible(true);
 ​
 /*
 解决关闭问题!
 ​
 监听事件  关闭窗口  System.exit(0);
     frame.addWindowListener(new WindowListener()
     需要重写7个方法
 ​
 适配器模式:
     frame.addWindowListener(new WindowAdapter()
     选择性重写方法
 */
 frame.addWindowListener(new WindowAdapter() {
     @Override
     public void windowClosing(WindowEvent e) {
         System.exit(0);
     }
 });

1.3 布局管理器 - Layout

  • 流式布局

Frame frame = new Frame();
 //组件 - 按钮
 Button button1 = new Button("button1");
 Button button2 = new Button("button2");
 Button button3 = new Button("button3");
 //流式布局 - 默认居中
 //frame.setLayout(new java.awt.FlowLayout());
 frame.setLayout(new FlowLayout(FlowLayout.LEFT));
 frame.setSize(400,200);
 //添加按钮 - FlowLayout.LEFT 按钮从左顺序排列
 frame.add(button1);
 frame.add(button2);
 frame.setVisible(true);
  • 东西南北中

Frame frame = new Frame(); 
 Button east = new Button("East");  //定义东南西北中
 Button west = new Button("West");
 Button south = new Button("South");
 Button north = new Button("North");
 Button center = new Button("Center");
 frame.add(east,BorderLayout.EAST);  //添加
 frame.add(west,BorderLayout.WEST);
 frame.add(south,BorderLayout.SOUTH);
 frame.add(north,BorderLayout.NORTH);
 frame.add(center,BorderLayout.CENTER);
 //设置大小 可见
 frame.setSize(400,400);
 frame.setVisible(true);
  • 表格布局

Frame frame = new Frame();
 Button bth1 = new Button("bth1");
 ....
 Button bth6 = new Button("bth6");
 //表格布局 3行两列
 frame.setLayout(new GridLayout(3,2));
 frame.add(bth1);
 ....
 frame.add(bth6);
 frame.pack(); //Java函数:自动布局
 frame.setVisible(true);

  - 案例 布局

/*
 ┌──┬───────┬──┐
 │  ├───────┤  │
 ├──┼───┬───┼──┤
 │  ├───┼───┤  │
 └──┴───┴───┴──┘
 */
 public class Test {
     public static void main(String[] args) {
         Frame frame = new Frame();
         frame.setBounds(300,50,400,300);
         frame.setBackground(Color.cyan);
         frame.setVisible(true);
         frame.setLayout(new GridLayout(2,1));
         //panel
         Panel p1 =new Panel(new BorderLayout());//上  东西南北中
         Panel p2 =new Panel(new BorderLayout());//下  东西南北中
         Panel p3 =new Panel(new GridLayout(2,1));//上 - 中  表格布局
         Panel p4 =new Panel(new GridLayout(2,2));//下 - 中  表格布局
 ​
         p1.add(new Button("East-1"),BorderLayout.EAST);
         p1.add(new Button("West-1"),BorderLayout.WEST);
         p3.add(new Button("Center1-1"));
         p3.add(new Button("Center1-2"));
         p1.add(p3,BorderLayout.CENTER);
 ​
         p2.add(new Button("East-2"),BorderLayout.EAST);
         p2.add(new Button("West-2"),BorderLayout.WEST);
         for (int i = 0; i < 4; i++) {
             p4.add(new Button("Center2-"+(i+1)));
         }
         p2.add(p4,BorderLayout.CENTER);
 ​
         frame.add(p1);
         frame.add(p2);
         frame.addWindowListener(new WindowAdapter() {  //监听关闭
             @Override
             public void windowClosing(WindowEvent e) {
                 System.exit(0);
             }
         });
     }
 }

1.4 事件监听 - Listener

/*************按钮监听************/
 Frame frame = new Frame();
 Button button = new Button();
 //addActionListener()需要一个ActionListener,构造一个
 //  --可以直接new ActionListener(),使用匿名内部类,不推荐
 MyActionListener myActionListener = new MyActionListener();
 button.addActionListener(myActionListener);
 ​
 frame.add(button,BorderLayout.CENTER);
 frame.pack();
 windowClose(frame);
 frame.setVisible(true);
 ​
 /************关闭窗口************/
     private static void windowClose(Frame frame) {
         frame.addWindowListener(new WindowAdapter() {
             @Override
             public void windowClosing(WindowEvent e) {
                 System.exit(0);
             }
         });
     }
 /************监听事件************/
 class MyActionListener implements ActionListener{
     @Override
     public void actionPerformed(ActionEvent e) {
         System.out.println("点击输出 ");
     }
 }

/*************多个按钮共享一个事件*************/
 Frame frame = new Frame("开始-停止");
 Button button1 = new Button("Start");
 Button button2 = new Button("Stop");
 //可以显示的定义触发返回命令,不定义则默认值Stop
 //可以多个按钮只写一个监听类
 button2.setActionCommand("buttom2-stop");
 MyMonitor myMonitor = new MyMonitor();
 button1.addActionListener(myMonitor);
 button2.addActionListener(myMonitor);
 ​
 frame.add(button1,BorderLayout.NORTH);
 frame.add(button2,BorderLayout.SOUTH);
 frame.pack();
 frame.setVisible(true);
 /************监听事件************/
 class MyMonitor implements ActionListener {
     @Override
     public void actionPerformed(ActionEvent e) {
         //e.getActionCommand() 获得按钮信息
         System.out.println("按钮被点击:msg=>"+e.getActionCommand());
         /*if (e.getActionCommand().equals("Start")) {
             //定义具体执行的操作  ..... 
         }*/
     }
 }

 /*************输入框*************/
 public class TestT {
     public static void main(String[] args) {
         new MyFrame();  //启动!
     }
 }
 class MyFrame extends Frame {
     public MyFrame() {
         TextField textField = new TextField();
         add(textField);
         //监听文本框文字
         MyActionListener2 myActionListener2 = new MyActionListener2();
         //按下Enter,触发事件:(以下事件为获取文本框数据并输出,清空)
         textField.addActionListener(myActionListener2);
         //体换编码 - password: ******
         textField.setEchoChar('*');
         pack();
         setVisible(true);
     }
 }
 /************监听事件************/
 class MyActionListener2 implements ActionListener {
     @Override
     public void actionPerformed(ActionEvent e) {
         TextField field = (TextField) e.getSource();//获得输入框文本
         System.out.println(field.getText());//.....
         field.setText("");//清空文本框
     }
 }

  - 案例 简易加法计算器

/*
 简易加法计算器 - 案例
 文本框 "+" 文本框 按钮("=") 文本框
 */

 public class Calculator {
     public static void main(String[] args) {
         new Cal().loadFrame();
     }
 }
 /************计算器类************/
 class Cal extends Frame {
     //属性
     TextField t1,t2,t3;
     //方法
     public void loadFrame() {
         //组件
         t1 = new TextField(10);
         t2 = new TextField(10);
         t3 = new TextField(10);
         Label label = new Label("+"); //标签
         Button button = new Button("="); //按钮
         //监听
         button.addActionListener(new MyCalculator(this));
         //布局
         setLayout(new FlowLayout());
         add(t1);
         add(label);
         add(t2);
         add(button);
         add(t3);
         pack();
         setVisible(true);
     }
 }
 /************监听器类************/
 class MyCalculator implements ActionListener {
     Cal cal = null;
     //获取计算器这个对象,在一个类中组合另外一个类
     public MyCalculator(Cal cal) {
         this.cal = cal;
     }
     @Override
     public void actionPerformed(ActionEvent e) {
         //获得相加的数
         int n1 = Integer.parseInt(cal.t1.getText());
         int n2 = Integer.parseInt(cal.t2.getText());
         //加法运算
         cal.t3.setText(""+(n1+n2));
         //清除加法框
         cal.t1.setText("");
         cal.t2.setText("");
     }
 }
******

改进(内部类) :

内部类最大的好处,就是可以畅通无阻的访问外部的属性和方法!

public class Calculator_2 {
     public static void main(String[] args) {
         new Cal_2().loadFrame();
     }
 }
 class Cal_2 extends Frame { //计算器类
     //属性
     TextField t1,t2,t3;
     //方法
     public void loadFrame() {
         //组件
         t1 = new TextField(10);
         t2 = new TextField(10);
         t3 = new TextField(10);
         Label label = new Label("+"); //标签
         Button button = new Button("="); //按钮
         //监听
         button.addActionListener(new MyCalculator());
         //布局
         setLayout(new FlowLayout());
         add(t1);
         add(label);
         add(t2);
         add(button);
         add(t3);
         pack();
         setVisible(true);
     }
     //监听类作为内部类,简化代码
     private class MyCalculator implements ActionListener {
         @Override
         public void actionPerformed(ActionEvent e) {
             //获得相加的数
             int n1 = Integer.parseInt(t1.getText());
             int n2 = Integer.parseInt(t2.getText());
             //加法运算
             t3.setText(""+(n1+n2));
             //清除加法框
             t1.setText("");
             t2.setText("");
         }
     }
 }

1.5画笔 - paint

class MyPaint extends Frame {
     public void loadFrame() {
         setBounds(200,200,600,500);
         setVisible(true);
     }
     @Override  //画笔
     public void paint(Graphics g) {
         g.setColor(Color.red); //设置颜色
         /*drawOval空心圆
           fillOval实心圆
           fillRect实心方块
          */
         g.drawOval(100, 100, 100, 100);
         //用完还原颜色  养成习惯
     }
 }

1.6 鼠标监听

案例 : 鼠标画点

 /*鼠标监听 - 画画 - 单机画点*/
 public class Mouse {
     public static void main(String[] args) {
         new MyFrame("Pic");
     }
 }
 ​
 class MyFrame extends Frame {
     ArrayList points; //存储鼠标点击的点
     public MyFrame(String title) {
         super(title);
         setBounds(800,200,400,250);
         points = new ArrayList<>();
         this.addMouseListener(new MyMouseListener()); //鼠标监听器
         setVisible(true); //设置可见
     }
     /************画笔************/
     @Override
     public void paint(Graphics g) {
         //画画,监听鼠标事件
         Iterator iterator = points.iterator();
         while (iterator.hasNext()) {
             Point point = (Point) iterator.next();
             g.setColor(Color.blue);
             g.fillOval(point.x, point.y, 10, 10);
         }
     }
     public void addPoint(Point point) {
         points.add(point);
     }
     //不直接使用implements MouseListener,需要重写所有方法
     //使用适配器模式extends MouseAdapter
     private class MyMouseListener extends MouseAdapter {
         //鼠标 单击
         @Override
         public void mousePressed(MouseEvent e) {
             MyFrame frame = (MyFrame) e.getSource();
             //点击时产生点
             frame.addPoint(new Point(e.getX(),e.getY()));
             //每次点击鼠标重新画一边
             frame.repaint(); //刷新  帧
         }
     }
 }

1.7 窗口监听

 class WindowFrame extends Frame {
     public WindowFrame() {
         setBackground(Color.blue);
         setBounds(500, 300, 400, 200);
         setVisible(true);
         //内部类 方式
         //addWindowListener(new MyWindowListenter());
         //匿名内部类 方式 推荐
         this.addWindowListener(
                 new WindowAdapter() {
                     /************常用:关闭 激活************/
                     @Override
                     public void windowClosing(WindowEvent e) {
                         System.out.println("窗口正在关闭...");
                         System.exit(0);
                     }
                     @Override
                     public void windowActivated(WindowEvent e) {
                         WindowFrame source = (WindowFrame) e.getSource();
                         source.setTitle("获得焦点 - 修改TiTle");
                         System.out.println("激活窗口 获得焦点");
                     }
                 }
         );
 ​
     }
 }

1.8 键盘监听

class KeyBoard extends Frame {
     public KeyBoard() {
         setBounds(500,200,400,200);
         setVisible(true);
 ​
         this.addKeyListener(new KeyAdapter() {
             @Override
             public void keyPressed(KeyEvent e) {
                 //获得键盘的键
                 int keyCode = e.getKeyCode();
                 System.out.println(keyCode); //keyCode不需要记,使用VK.XXX
                 if (keyCode == KeyEvent.VK_UP) {
                     System.out.println("KeyEvent.VK_UP : 小键盘上键");
                 }
             }
         });
     }
 }

 


2. Swing

2.1 窗口、面板

/*窗口 面板*/
 public class JFrameT {
     //init() 初始化
     public void init() {
         //顶级窗口
         JFrame jf = new JFrame("JFrame");
         jf.setVisible(true);
         jf.setBounds(400,200,400,200);
         //设置文字 JLabel
         JLabel label = new JLabel("text");
         jf.add(label);
         //文本居中
         label.setHorizontalAlignment(SwingConstants.CENTER);
         //获得一个容器 设置背景颜色
         Container container = jf.getContentPane();
         container.setBackground(Color.RED);
         //关闭事件
         jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
     }
     public static void main(String[] args) {
         //建立窗口
         new JFrameT().init();
     }
 }
******

2.2 弹窗 - JDialog

 /*弹窗 主窗口*/
 public class DiologT extends JFrame {
     public DiologT() {
         this.setVisible(true);
         this.setSize(700,500);
         this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
         //JFrame容器
         Container contenter = this.getContentPane();
         //绝对布局
         contenter.setLayout(null);
         //按钮
         JButton button = new JButton("点击弹框");
         button.setBounds(30,30,200,50);
         //按钮事件监听 点击弹出弹窗
         button.addActionListener(new ActionListener() {
             @Override
             public void actionPerformed(ActionEvent e) {
                 new MyDiolog(); //弹窗
             }
         });
         contenter.add(button);
     }
 ​
     public static void main(String[] args) {
         new DiologT();
     }
 }
 //弹窗窗口  默认有关闭事件
 class MyDiolog extends JDialog {
     public MyDiolog() {
         this.setVisible(true);
         this.setBounds(100,100,500,500);
         Container container = this.getContentPane();
         container.setLayout(null);
         JLabel label = new JLabel("title");
         label.setBounds(50,50,100,100);
         container.add(label);
     }
 }
******

3.3 标签 - Icon

 new JLabel("xxx");

 public class ImageT extends JFrame {
     public ImageT() {
         JLabel label = new JLabel("Image");
         //获取图片地址 - 获取类目录同级图片
         URL url = ImageT.class.getResource("Pic.png");
         ImageIcon icon = new ImageIcon(url);
         label.setIcon(icon);
 ​
         label.setHorizontalAlignment(SwingConstants.CENTER);
 ​
         Container container = getContentPane();
         container.add(label);
 ​
         setVisible(true);
         setBounds(100,100,400,300);
         setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
     }
 ​
     public static void main(String[] args) {
         new ImageT();
     }
 }
******

3.4 面板 - JPanel

public JPanelT() {
     Container container = this.getContentPane();
     //内标布局  - 行距
     container.setLayout(new GridLayout(2,1,10,10));
     JPanel jPanel = new JPanel(new GridLayout(1, 3));
     jPanel.add(new JButton("1"));
     jPanel.add(new JButton("2"));
     jPanel.add(new JButton("3"));
     container.add(jPanel);
     this.setVisible(true);
     this.setBounds(100,100,400,300);
     this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
 }
******

- 滚动条 JScrollPanel

public JScrollT() {
     Container container = this.getContentPane();
     //文本域
     JTextArea area = new JTextArea();
     area.setText("/**内容超出文本框出现滚动条**/");
     //Scorll面板
     JScrollPane scrollPane = new JScrollPane(area);
     container.add(scrollPane);
 ​
     this.setVisible(true);
     this.setBounds(200,200,200,200);
     this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
 }

3.5 按钮 - Buttom

  • 图片按钮

public Buttom_1_T() {
     Container container = this.getContentPane();
     //将图片变为图标
     URL resource = Buttom_1_T.class.getResource("Pic.png");
     Icon icon = new ImageIcon(resource);
     //将图标放在按钮上
     JButton button = new JButton();
     button.setIcon(icon);
     button.setToolTipText("提示:图片按钮");
     container.add(button);
     this.setVisible(true);
     this.setSize(500,300);
     this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
 }
******
  • 单选 JRadioButton

public Buttom_R_T() {
     Container container = this.getContentPane();
     //将图片变为图标
     URL url = Buttom_R_T.class.getResource("Pic.png");
     Icon icon = new ImageIcon(url);
     //单选框 -- 每组只能选一个 需要分组
     JRadioButton radioButton1 = new JRadioButton();
     JRadioButton radioButton2 = new JRadioButton();
     JRadioButton radioButton3 = new JRadioButton();
     ButtonGroup group = new ButtonGroup(); // 分组
     group.add(radioButton1);
     group.add(radioButton2);
     group.add(radioButton3);
     container.add(radioButton1,BorderLayout.NORTH);
     container.add(radioButton2,BorderLayout.CENTER);
     container.add(radioButton3,BorderLayout.SOUTH);
     this.setVisible(true);
     this.setSize(500,300);
     this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
 }
******
  • 多选 JCheckBox

 public Buttom_C_T() {
     Container container = this.getContentPane();
     //将图片变为图标
     URL url = Buttom_R_T.class.getResource("Pic.png");
     Icon icon = new ImageIcon(url);
     //多选框
     JCheckBox checkBox1 = new JCheckBox("checkBox1");
     JCheckBox checkBox2 = new JCheckBox("checkBox2");
     container.add(checkBox1,BorderLayout.NORTH);
     container.add(checkBox2,BorderLayout.SOUTH);
     this.setVisible(true);
     this.setSize(500,300);
     this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
 }
******

3.6 列表 - JComboBox

  • 下拉框 - 选择,超出两个选项

 JComboBox box = new JComboBox();
 box.addItem("下拉框选项");
  • 列表框 - 展示信息,动态扩容

//动态添加
 Vector contents = new Vector();//String[] contents = {"1","2","3"};静态展示
 //列表放入内容
 JList list = new JList(contents);
 //动态添加
 contents.add("4");
 contents.add("5");
 contents.add("6");
 container.add(list);

3.7 文本框

  • 文本框 - JTextField

 JTextField textField = new JTextField("world",20);
 container.add(textField);
  • 密码框 - JPasswordField

 JPasswordField textField = new JPasswordField();
 container.add(textField);
  • 文本域 - JTextArea

JTextArea area = new JTextArea();
 area.setText("/**内容超出文本框出现滚动条**/");
 //Scorll面板
 JScrollPane scrollPane = new JScrollPane(area);
 container.add(scrollPane);

 




# 实例 - 贪吃蛇

键盘监听

定时器 Timer

1.定义数据

2.画

3.监听事件 : 键盘 事件

完整代码:

  数据中心

/*数据中心 - 定义图片路径*/
 public class Data {
     //绝对路径   xxx.jpg
     //相对路径   /xx.jpg 相当于当前项目
     public static URL upURL = Data.class.getResource("statics/up.png");
     public static URL leftURL = Data.class.getResource("statics/left.png");
     public static URL downURL = Data.class.getResource("statics/down.png");
     public static URL rightURL = Data.class.getResource("statics/right.png");
     public static URL bodyURL = Data.class.getResource("statics/body.png");
     public static URL foodURL = Data.class.getResource("statics/food.png");
     public static URL headerURL = Data.class.getResource("statics/header.png");
 ​
     public static ImageIcon up =new ImageIcon(upURL);
     public static ImageIcon left =new ImageIcon(leftURL);
     public static ImageIcon down =new ImageIcon(downURL);
     public static ImageIcon right =new ImageIcon(rightURL);
     public static ImageIcon body =new ImageIcon(bodyURL);
     public static ImageIcon food =new ImageIcon(foodURL);
     public static ImageIcon header =new ImageIcon(headerURL);
 }
Data.java

   启动器

 /*游戏启动程序*/
 public class StartGame {
     public static void main(String[] args) {
         JFrame frame = new JFrame("贪吃蛇");
         frame.setBounds(10,10,900,720);
         frame.setResizable(false);//窗口大小不可变
         frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
         frame.add(new PanelG()); //***
         frame.setVisible(true);//设置可见
     }
 }
StartGame
  *****
/*面板*/
 public class PanelG extends JPanel implements KeyListener, ActionListener {
     /*定义需要用到的所有数据*/
     int source; //积分
     int length; //长度
     int foodx;  //食物坐标X
     int foody;  //食物坐标Y
     String fx;  //初始方向
     int[] snakeX = new int[600]; //存储身体X坐标
     int[] snakeY = new int[600]; //存储身体Y坐标
     boolean isFail = false;      //游戏失败判定
     boolean isStart = false;     //游戏状态判定:开始 停止
     Random random = new Random();//随机数生成食物
     //定时器 - 100ms刷新一次
     Timer timer = new Timer(100, this);
 ​
     /*构造器*/
     public PanelG() {
         init(); //初始化函数
         this.setFocusable(true);    //获得焦点事件
         this.addKeyListener(this);//获得监听事件
         timer.start(); //定时器启动
     }
 ​
     /*初始化*/
     public void init() {
         length = 3;
         source = 0; //初始化长度积分
         snakeX[0] = 100;
         snakeY[0] = 100; //脑袋坐标
         snakeX[1] = 75;
         snakeY[1] = 100; //身体1
         snakeX[2] = 50;
         snakeY[2] = 100; //身体2
         fx = "R";        //初始化方向 - 右
         //食物随机分布 - 获得食物坐标
         foodx = 25 + 25 * random.nextInt(34);
         foody = 75 + 25 * random.nextInt(24);
     }
 ​
     /*绘制面板*/
     @Override
     protected void paintComponent(Graphics g) {
         super.paintComponent(g); //清屏
         //绘制静态面板 - 背景色:白色
         this.setBackground(Color.WHITE);
         //头部广告栏 (组件:当前面板,画笔:当前画笔,X边距,Y边距)
         Data.header.paintIcon(this, g, 25, 11);
         //默认游戏界面 - (画笔默认黑色)
         g.fillRect(25, 75, 850, 600);
         //积分展示
         g.setColor(Color.white);
         g.setFont(new Font("微软雅黑", Font.BOLD, 18));
         g.drawString("长度 " + length, 750, 35);
         g.drawString("分数 " + source, 750, 50);
         //绘制食物
         Data.food.paintIcon(this, g, foodx, foody);
         //******移动******
         if (fx.equals("R")) {
             Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
         } else if (fx.equals("L")) {
             Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);
         } else if (fx.equals("U")) {
             Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);
         } else if (fx.equals("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]);
         }  //绘制身体
         //游戏状态判定
         if (!isStart) {
             g.setColor(Color.white);
             g.setFont(new Font("微软雅黑", Font.BOLD, 40));
             g.drawString("按下空格开始游戏", 300, 300);
         }
         //游戏失败判定
         if (isFail) {
             g.setColor(Color.RED);
             g.setFont(new Font("微软雅黑", Font.BOLD, 40));
             g.drawString("失败,按空格重新开始", 300, 300);
         }
     }
 ​
     /*键盘监听事件 - 继承键盘监听接口*/
     @Override
     public void keyPressed(KeyEvent e) {
         int keyCode = e.getExtendedKeyCode(); //获得键盘按键
         //暂停 开始
         if (keyCode == KeyEvent.VK_SPACE) {//判断是否空格
             if (isFail) {
                 //重新开始
                 isFail = false;
                 init();//初始化
             } else {
                 isStart = !isStart; //取反
             }
             repaint();//刷新
         }
         //******转向******
         if (keyCode == KeyEvent.VK_UP) {
             if (!fx.equals("D")) {
                 fx = "U";
             }
         } else if (keyCode == KeyEvent.VK_LEFT) {
             if (!fx.equals("R")) {
                 fx = "L";
             }
         } else if (keyCode == KeyEvent.VK_DOWN) {
             if (!fx.equals("U")) {
                 fx = "D"; 
            } 
        } else if (keyCode == KeyEvent.VK_RIGHT) { 
            if (!fx.equals("L")) { 
                fx = "R"; 
            } 
        } 
    } 
​ 
    /*事件监听 - 通过固定时间刷新Timer*/ 
    @Override 
    public void actionPerformed(ActionEvent e) { 
        if (isStart && !isFail) { 
            //吃食物 
            if (snakeX[0] == foodx && snakeY[0] == foody) { 
                length++; //长度+1 
                source += 10; 
                //再次随机生成食物 
                foodx = 25 + 25 * random.nextInt(34); 
                foody = 75 + 25 * random.nextInt(24); 
            } 
            //移动 - 后一格向前移 
            for (int i = length - 1; i > 0; i--) { 
                snakeX[i] = snakeX[i - 1]; 
                snakeY[i] = snakeY[i - 1]; 
            } 
            //方向 - 边界判断 
            if (fx.equals("R")) { 
                snakeX[0] = snakeX[0] + 25; 
                if (snakeX[0] > 850) { 
                    snakeX[0] = 25; 
                } 
            } else if (fx.equals("L")) { 
                snakeX[0] = snakeX[0] - 25; 
                if (snakeX[0] < 25) { 
                    snakeX[0] = 850; 
                } 
            } else if (fx.equals("D")) { 
                snakeY[0] = snakeY[0] + 25; 
                if (snakeY[0] > 650) { 
                    snakeY[0] = 75; 
                } 
            } else if (fx.equals("U")) { 
                snakeY[0] = snakeY[0] - 25; 
                if (snakeY[0] < 75) { 
                    snakeY[0] = 650; 
                } 
            } 
            //失败判定 
            for (int i = 1; i < length; i++) { 
                if (snakeX[0] == snakeX[i] && snakeY[0] == snakeY[i]) { 
                    isFail = true; 
                } 
            } 
            repaint(); 
        } 
    } 
​ 
    @Override 
    public void keyReleased(KeyEvent e) { 
​ 
    } 
​ 
    @Override 
    public void keyTyped(KeyEvent e) { 
​ 
    } 
}
PanelG

 

后续优化:特殊食物 难度分级 鼠标控制 续盘(数据库 登录) 联机对战 ....



posted @ 2021-08-15 17:26  miku_moe  阅读(83)  评论(0)    收藏  举报