前段时间用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 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 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 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 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) { } }
运行效果:
游戏开始界面:
游戏运行界面:
有问题欢迎在下方留言,相互讨论一下。