基于java实现贪吃蛇小游戏,主要通过绘制不同的图片并以一定速度一帧一帧地在窗体上进行展示。
开发工具:eclipse
java工具包:jdk1.8
代码地址:https://gitee.com/jay_musu/games-and-tools.git
一、创建新项目
创建一个新的项目,并命名。创建一个名为images的文件夹用来存放游戏相关图片。然后再在项目的src文件下创建一个com.xxx.view的包用来存放所有的图形界面类,创建一个com.xxx.controller的包用来存放启动的入口类(控制类)。如下所示;
二、主要的游戏界面
1.代码
package com.snake.view;import java.awt.Color;import java.awt.EventQueue;import java.awt.Font;import java.awt.Frame;import java.awt.Graphics;import java.awt.Image;import java.util.ArrayList;import java.util.List;import java.util.Random;import javax.swing.ImageIcon;import javax.swing.JFrame;import javax.swing.JOptionPane;import javax.swing.JPanel;import javax.swing.Timer;import javax.swing.border.EmptyBorder;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.KeyAdapter;import java.awt.event.KeyEvent;public class SnakeJPanel extends JPanel implements ActionListener{private boolean start;//当前游戏状态private int speed;//速度private boolean exist;//当前是否存在食物private int foodType;//食物种类private int x;//豆子的横坐标private int y;//豆子的纵坐标private ArrayList localList;//蛇public String direction;//方向private String direction2;//引导方向public boolean flag;Random rand = new Random();private ImageIcon up;private ImageIcon down;private ImageIcon right;private ImageIcon left;private ImageIcon body;private ImageIcon food;private ImageIcon title;Timer time;private int score;//当前得分情况private int num;//吃到的食物个数//private Image offScreenImage;//图形缓存//图片绘制@Overridepublic void paint(Graphics g) {direction = direction2;g.setColor(Color.WHITE);g.fillRect(0, 0, 900, 700);//绘制游戏框//标题框//g.drawRect(25, 30, 800, 75);title.paintIcon(this, g, 25, 10);//内容框g.setColor(Color.black);g.fillRect(25, 75, 850, 600);//绘制食物的坐标位置if(!exist) {//如果当前不存在豆子,随机绘制一个豆子if(num % 5 == 0) {foodType = 1;}else {foodType = 0;}boolean isProduce = true;while(isProduce) {isProduce = false;x = rand.nextInt(33) * 25 + 25;y = rand.nextInt(23) * 25 + 75;for (int[] arr:localList) {if(x == arr[0] && y == arr[1]) {isProduce = true;break;}}}System.out.println(x + "---" + y);} if(eat()) {exist = false; }else {exist = true; }if(foodType == 0) {//绘制食物g.setColor(Color.blue);//g.fillRect(x, y, 25, 25);g.drawImage(food.getImage(),x, y, 25, 25,null);}else {//绘制食物g.setColor(Color.WHITE);g.fillRect(x, y, 25, 25);//g.drawImage(food.getImage(),x, y, 25, 25,null);}//绘制头g.setColor(Color.red);//g.fillRect(localList.get(0)[0], localList.get(0)[1], 25, 25);ImageIcon head = null;//判断当前方向if(direction.equals("R")) { head = right;}else if(direction.equals("L")) { head = left;}else if(direction.equals("U")) { head = up;}else if(direction.equals("D")) { head = down;}//g.drawImage(head.getImage(), localList.get(0)[0], localList.get(0)[1], 25, 25,null);head.paintIcon(this, g,localList.get(0)[0], localList.get(0)[1]);//绘制身体g.setColor(Color.white);for (int i = 1; i 0; i--) {//从蛇尾开始,每节身体移动到前一节身体的位置上localList.set(i,new int[] {localList.get(i - 1)[0],localList.get(i - 1)[1]});}//记录头位置int[] local = localList.get(0);//判断当前方向,并进行模拟移动,判断是否与边界重合if(direction.equals("R")) {if(local[0] >= 850) {local[0] = 25;}else {local[0] += 25;}}else if(direction.equals("L")) {if(local[0] <= 25) {local[0] = 850;}else {local[0] -= 25;}}else if(direction.equals("U")) {if(local[1] = 650) {local[1] = 75;}else {local[1] += 25;}}//更改头的位置localList.set(0, local);}}//判断下一步是否为蛇身private boolean isbody() {// TODO 自动生成的方法存根//记录头位置int x = localList.get(0)[0];int y = localList.get(0)[1];//判断当前方向,并进行模拟移动,判断是否与边界重合if(direction.equals("R")) {x += 25;}else if(direction.equals("L")) {x -= 25;}else if(direction.equals("U")) {y -= 25;}else if(direction.equals("D")) {y += 25;}for (int i = 1; i < localList.size(); i++) {if(localList.get(i)[0] == x && localList.get(i)[1] == y) {return true;}}return false;}////判断下一步是否为边界//private boolean isborder() {//// TODO 自动生成的方法存根////记录头位置//// TODO 自动生成的方法存根////记录头位置//int x = localList.get(0)[0];//int y = localList.get(0)[1];//////判断当前方向,并进行模拟移动,判断是否与边界重合//if(direction.equals("R")) {//x += 25;//}else if(direction.equals("L")) {//x -= 25;//}else if(direction.equals("U")) {//y -= 25;//}else if(direction.equals("D")) {//y += 25;//}////if(x (33 * 25 + 25)) {//return true;//当x坐标超出边界,则返回true//}//if(y (23 * 25 + 105)) {//return true;//当y坐标超出边界,则返回true//}//return false;//蛇头移动后未超出边界,返回false////}/** * Create the frame. */public SnakeJPanel(int speed) {this.speed = speed; //初始化速度//初始化游戏面板的基本信息this.setSize(900, 700);this.setLocation(0, 30);this.setFocusable(true);init();//初始化界面drawImage();//绘制图片moveByKey();//给界面添加一个键盘监听}/* * 键盘监听 * 通过键盘输入上下左右来控制当前蛇头移动的方向 * 先判断当前蛇头方向,再来改变引导方向 * 当进行绘制时再修改蛇的方向 * 保证不会因为在短时间内快速变换方向导致蛇头逆向转向 */private void moveByKey() {addKeyListener(new KeyAdapter() {@Overridepublic void keyPressed(KeyEvent e) {int key = e.getKeyCode();//边界值判断switch(key) {case 65:case 37:{//向左走if(!direction.equals("R")) {direction2 = "L";}break;}case 87:case 38:{//向上走if(!direction.equals("D")) {direction2 = "U";}break;}case 68:case 39:{//向右走if(!direction.equals("L")) {direction2 = "R";}break;}case 83:case 40:{//向下走if(!direction.equals("U")) {direction2 = "D";}break;}case KeyEvent.VK_SPACE:{//如果当前键盘输入为空格start = !start;//调整游戏状态System.out.println("暂停/开始");repaint();//重绘}}//任意键开始if(!start && key != KeyEvent.VK_SPACE) {//如果当前状态为暂停状态,且键盘输入不是空格start = true;repaint();//重绘}}});}/** * 初始化游戏基本信息 */private void init() {start = false;exist = true;direction2 = "U";flag = true;localList = new ArrayList();localList.add(0,new int[] {75,125});//蛇头localList.add(1,new int[] {75,150});//蛇身1localList.add(2,new int[] {75,175});//蛇身2//创建第一个食物的位置//通过循环保证当前生成的食物不在身体所在的坐标上boolean isProduce = true;while(isProduce) {//循环生成食物坐标isProduce = false;//结束本次循环x = rand.nextInt(33) * 25 + 25;y = rand.nextInt(23) * 25 + 75;for (int[] arr:localList) {//循环遍历蛇头及蛇身的坐标if(x == arr[0] && y == arr[1]) {//如果食物坐标和蛇的某一节坐标重合isProduce = true;//跳转循环状态,继续下一次食物生成break;}}//蛇身遍历完成,没有重合坐标,结束食物坐标生成}time = new Timer(speed, this);setLayout(null);score = 0;num = 0;foodType = 0;//repaint();}}
三、构造启动类
package com.snake.controller;import javax.swing.JFrame;import javax.swing.JOptionPane;import com.snake.view.SnakeJPanel;public class SnakeStart {public static void main(String[] args) {int speed = 0;String showInputDialog = null;//初始化时间//得到速度while(true) {showInputDialog = JOptionPane.showInputDialog("蛇移动速度(1 - 5)","3");if(showInputDialog == null) {showInputDialog = "3";//默认速度break;}if(showInputDialog.length() > 1) {continue;}char[] a = showInputDialog.toCharArray();if(a[0] >= '1' && a[0] <= '5') {break;}}speed = Integer.parseInt(showInputDialog) * 50;SnakeJPanel snakeJPanel = new SnakeJPanel(speed);//创建一个JFrame窗口,将游戏面板添加进行窗口中JFrame jFrame = new JFrame();//设置窗口的某些属性jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);jFrame.setSize(920, 750);jFrame.add(snakeJPanel);jFrame.setLocationRelativeTo(null);jFrame.setVisible(true);}}
四、游戏测试
设置贪吃蛇运行速度
游戏界面