java 编写贪吃蛇小游戏

前段时间用Android编写了一个贪吃蛇的小游戏,感觉还不错,就想着能不能用java编写有个贪吃蛇的游戏,在电脑上面运行。于是就开始动手写了。

编写贪吃蛇游戏的博客或文档特别多,有些写的挺好的,都是一个共同的思想。都是通过没吃到食物时,头加尾减。吃到食物时头加尾不减。

我们看看通过java写这个游戏,要使用到哪些知识点,有可能写的不全面或不是最好的方法,希望在下面留言,指正下。

1:java里面关于swing的知识需要了解。图形化界面编程会用到里面的一些控件,例如 JFram,JPanel,JButton,JSpinner等。所以想学的同学,余姚了解swing。

2:java里面画布的知识了解下,类似于Canvas的。在java里面是通过Graphics 进行绘图的,以为我们需要将蛇体的当前状态和食物的当前位置绘制在面板上面。

3:了解下java里面关于键盘事件的监听,以为我们是通过键盘操作游戏的。

好了基本需要的知识就这些,剩下的就需要自己去实现逻辑代码,把整个游戏完成。来看看怎么写。

我在定义了三个类,主类 MyClass ,JFramDemo,Snake。

主类就不讲,java代码是从主类里面的main方法开始运行的。在这我把主要代码放在JFramDemo与Snake里面。主类比较少,知识让整个代码运行起来的。

public class MyClass {
    public static void main(String[] strings) {
        JFarmDemo mJFarmDemo = new JFarmDemo();
    }
}

这上面就是我的主类,是不是比较少。所以重点在JFarmDemo 类里面。

 

JFarmDemo 类:

 

package com.example.lib.java;


import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.FlowLayout;
import java.awt.Image;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;


import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JTabbedPane;
import javax.swing.SpinnerListModel;
import javax.swing.SpinnerModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class JFarmDemo {
    /**
     * mJFrame第一次显示的窗体,游戏开始前选择游戏难度的窗体
     * jFrame 点击开始按钮后显示的窗体,游戏正在运行的窗体
     *
     */
    private static JFrame mJFrame, jFrame;
    private static JLabel mJLabel, mJLabel1;
    private static JPanel mJPanel, mJPanel2;
    private static JButton mJButton, mJButton2;
    private static JSpinner mJSpinner;
    private static String[] strings;
    private static int number = 20;

    public JFarmDemo() {
        init_J();
        mJFrame.setBounds(500, 200, 300, 450);
        mJFrame.setBackground(Color.BLUE);
        mJFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        mJFrame.setLayout(new BorderLayout(10, 10));
        mJPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10));
        mJPanel.add(mJButton);
        mJPanel.add(mJLabel1);
        SpinnerModel model = new SpinnerListModel(strings);
        mJSpinner = new JSpinner(model);
        mJSpinner.setSize(50, 50);
        mJPanel.add(mJSpinner);
        mJPanel.add(mJButton2);
        ImageIcon mIcon = new ImageIcon("image/snakeback.png");
        mJLabel = new JLabel(mIcon);
        mJPanel2.add(mJLabel);
        mJFrame.add(mJPanel, BorderLayout.SOUTH);
        mJFrame.add(mJPanel2, BorderLayout.CENTER);
        mJFrame.setResizable(false);
        mJFrame.setVisible(true);
        Listen();
    }

    private void init_J() {
        mJFrame = new JFrame("贪吃蛇");
        jFrame = new JFrame("游戏界面");
        mJPanel = new JPanel();
        mJPanel2 = new JPanel();
        mJButton = new JButton("开始");
        mJLabel1 = new JLabel("选择难度");
        mJButton2 = new JButton("退出");
        strings = new String[]{"简单", "一般", "困难"};
    }

    private void Listen() {
        mJButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                mJFrame.setVisible(false);
                jFrame.getContentPane().setBackground(Color.CYAN);
                Snake snake = new Snake(number, 300, 440);
                snake.setBackground(Color.BLUE);
                jFrame.add(snake);
                jFrame.setBounds(500, 200, 320, 480);
                jFrame.setResizable(false);
                jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                jFrame.setVisible(true);

            }
        });
        mJSpinner.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent changeEvent) {
                switch (mJSpinner.getValue().toString()) {
                    case "简单":
                        number = 20;
                        break;
                    case "一般":
                        number = 15;
                        break;
                    case "困难":
                        number = 10;
                        break;
                    default:
                        break;
                }

            }
        });
        mJButton2.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                mJFrame.dispose();
            }
        });
    }
}

Snake类:

 

package com.example.lib.java;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;


import javax.swing.JComponent;


public class Snake extends JComponent implements KeyListener {

    private static List<Head> headList = new ArrayList<>();
    private static int mSecretion;
    private static boolean isRuning = true;
    private static boolean iseating = true;
    private static boolean isChange = false;
    private static int a, b, space ;
    private static int weight, high;

    public Snake(final int number, int weight, int high) {
        Snake.weight = weight;
        Snake.high = high;
        space = number;
        this.setFocusable(true);  // 获取焦点
        this.addKeyListener(this); // 监听键盘事件
        headList.add(new Head());
        a = 4;
        b = 5;
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (isRuning) {
                    try {
                        Thread.sleep(100);
                        repaint();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

            }
        }).start();

    }

    @Override
    protected void paintComponent(Graphics graphics) {
        super.paintComponent(graphics);
        for (int i = 1; i <= weight / space; i++) {
            graphics.drawLine(i * space, 0, i * space, high);
        }
        for (int i = 1; i <= high / space; i++) {
            graphics.drawLine(0, i * space, weight, i * space);
        }
        graphics.setColor(Color.BLUE);
        if (isChange) {
            isChange = false;
            a = new Random().nextInt(14) + 1;
            b = new Random().nextInt(21) + 1;
        }
        graphics.fillRect(a * space, b * space, space, space);
        graphics.setColor(Color.BLACK);

        for (int i = 0; i < headList.size(); i++) {
            if (i==0){
                graphics.setColor(Color.RED);
            }else {
                graphics.setColor(Color.BLACK);
            }
            graphics.fillRect(headList.get(i).x, headList.get(i).y, space, space);
        }
        snakeMove(headList, mSecretion);

        if (iseating) {
            headList.remove(headList.size() - 1);
        }
        iseating = true;

    }

    public void snakeMove(List<Head> heads, int mSnakedirection) {
        Head mOldHead = heads.get(0);
        Head mNewheads = new Head();
        switch (mSnakedirection) {
            //上
            case 1:
                mNewheads.x = mOldHead.x;
                mNewheads.y = mOldHead.y - space;
                break;
            //下
            case 2:
                mNewheads.x = mOldHead.x;
                mNewheads.y = mOldHead.y + space;
                break;
            //左
            case 3:
                mNewheads.x = mOldHead.x + space;
                mNewheads.y = mOldHead.y;
                break;
            //右
            case 4:
                mNewheads.x = mOldHead.x - space;
                mNewheads.y = mOldHead.y;
                break;
        }
        Crossing(mNewheads.x, mNewheads.y);
        EatMyself(heads);
        EatFood(mNewheads.x, mNewheads.y);
        Sanme(heads);
        heads.add(0, mNewheads);

    }

    /**
     * 越界
     *
     * @param x
     * @param y
     */
    private void Crossing(int x, int y) {
        if ((x < 0 || x > 280) || (y < 0 || y > 420)) {
            isRuning = false;
        }
    }

    /**
     * 碰到自己
     */
    private void EatMyself(List<Head> heads) {
        for (int i = 1; i < heads.size(); i++) {
            if (heads.get(0).x == heads.get(i).x && heads.get(0).y == heads.get(i).y) {
                isRuning = false;
            }
        }
    }

    /**
     * 吃到食物
     */
    private void EatFood(int x, int y) {
        if (x == a * space && y == b * space) {
            iseating = false;
            isChange = true;
        }
    }

    /**
     * 避免食物与蛇体重合
     */
    private void Sanme(List<Head> heads) {
        for (int i = 0; i < heads.size(); i++) {
            if (a == heads.get(i).x && b == heads.get(i).y) {
                a = new Random().nextInt(14) + 1;
                b = new Random().nextInt(21) + 1;
            }
        }
    }

    @Override
    public void keyTyped(KeyEvent keyEvent) {

    }

    @Override
    public void keyPressed(KeyEvent keyEvent) {
        int keyCode = keyEvent.getKeyCode();
//        System.out.print("键盘值:" + keyCode + "\n");
        //上
        if ((keyCode == 87 || keyCode == 38) && mSecretion != 2) {
            mSecretion = 1;
        }
        //下
        else if ((keyCode == 83 || keyCode == 40) && mSecretion != 1) {
            mSecretion = 2;
        }//左
        else if ((keyCode == 68 || keyCode == 39 )&& mSecretion != 4) {
            mSecretion = 3;

        }//右
        else if ((keyCode == 65 || keyCode == 37 )&& mSecretion != 3) {
            mSecretion = 4;

        }
    }

    @Override
    public void keyReleased(KeyEvent keyEvent) {

    }
}

运行效果:

游戏开始界面:

游戏运行界面:

有问题欢迎在下方留言,相互讨论一下。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章