swing实现贪吃蛇

工程文件

在这里插入图片描述

Data类

package Final_traning.snake;
import java.net.*;
import javax.swing.*;

//存放外部数据
public class Data {

    public static URL upURL = Data.class.getResource("/Final_traning/snake/statics/up.png");
    public static URL downURL = Data.class.getResource("/Final_traning/snake/statics/down.png");
    public static URL leftURL = Data.class.getResource("/Final_traning/snake/statics/left.png");
    public static URL rightURL = Data.class.getResource("/Final_traning/snake/statics/right.png");
    public static ImageIcon up = new ImageIcon(upURL);
    public static ImageIcon down = new ImageIcon(downURL);
    public static ImageIcon left = new ImageIcon(leftURL);
    public static ImageIcon right = new ImageIcon(rightURL);

    public static URL bodyURL = Data.class.getResource("/Final_traning/snake/statics/body.png");
    public static ImageIcon body = new ImageIcon(bodyURL);
    public static URL foodURL = Data.class.getResource("/Final_traning/snake/statics/food.png");
    public static ImageIcon food = new ImageIcon(foodURL);


}


游戏面板

package Final_traning.snake;

import javax.sql.DataSource;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Date;
import java.util.Random;

//游戏面板
public class GamewPanel extends JPanel implements KeyListener, ActionListener {

    //定义蛇的数据结构
    int length;
    int []snakeX = new int[600];  //蛇的X坐标
    int []snakeY = new int[600];  //蛇的Y坐标
    String fx;
    int foodX,foodY; //食物坐标
    boolean isStart = false;
    boolean isFail = false;
    Random random = new Random();

    //定时器
    Timer timer = new Timer(100,this);//100ms刷新一次

    //构造器
    public GamewPanel(){
        init();
        //获得焦点事件
        this.setFocusable(true);
        this.addKeyListener(this);
    }
    //初始化方法
    public void init(){
        length = 3;
        snakeX[0] = 100;snakeY[0] = 100;
        snakeX[1] = 75;snakeY[1] = 100;
        snakeX[2] = 50;snakeY[2] = 100;
        fx = "R";//初始方向向右
        timer.start();//游戏一开始定时器启动

        //食物随机分配在页面上
        foodX = 25 + 25*random.nextInt(34);
        foodY = 75 + 25*random.nextInt(24);
    }

    //绘制面板,游戏中的所有东西都是用这个画笔
    @Override
    protected void paintComponent(Graphics g) {
        //绘制静态面板
        super.paintComponent(g); // 清屏
        this.setBackground(Color.BLACK);

        //画食物
        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 == false){
            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.getKeyCode();

        if(keycode == KeyEvent.VK_SPACE){ //按下的是空格
            if(isFail){
                isFail = false;
                init();
            }else{
                isStart = !isStart;
            }
            repaint();
        }
        //小蛇移动
        if(keycode == KeyEvent.VK_UP){
            fx = "U";
        }else if(keycode == KeyEvent.VK_DOWN){
            fx = "D";
        }else if (keycode == KeyEvent.VK_LEFT){
            fx = "L";
        }else if (keycode == KeyEvent.VK_RIGHT){
            fx = "R";
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {

    }
    @Override
    public void keyTyped(KeyEvent e) {

    }

    //事件监听--固定的时间刷新
    @Override
    public void actionPerformed(ActionEvent e) {
        if(isStart && isFail==false){
            //吃食物
            if(snakeX[0] == foodX && snakeY[0] == foodY){
                length++;
                //再次随机食物
                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("U"))
            {
                snakeY[0]=snakeY[0]-25;
                if(snakeY[0]<70){ snakeY[0]=650; }
            }else if (fx.equals("D"))
            {
                snakeY[0]=snakeY[0]+25;
                if(snakeY[0]>650){ snakeY[0]=75; }
            }

            //如果小蛇的头和food坐标重合
            if(snakeX[0] == foodX && snakeY[0]==foodY)
            {
                length++;
                //重新生成food
                foodX = 25+25*random.nextInt(34);
                foodY = 75+25*random.nextInt(24);
            }
            //结束panduan
            for(int i=1;i<length;i++)
            {
                if(snakeX[0]==snakeX[i] && snakeY[0]==snakeY[i])
                    isFail = true;
            }

            //重画
            repaint();
        }
        timer.start(); //定时器开始
    }
}



主页面

package Final_traning.snake;

import javax.swing.*;

/**
 * 2021.1.13
 * 贪吃蛇游戏开发
 */
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 GamewPanel());
        frame.setLocation(100,100);
        frame.setVisible(true);
    }
}

  • 游戏用到的素材:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    ps:模仿b站阿婆主 遇见狂神说所写

热门文章

编程学习 ·

spring注解式开发

一、@Configuration 声明一个类相当于配置类似于xml的配置文件,声明一个或者多个@Bean方法,并由spring容器管理,以便于在运行中为这些bean生成BeanDefinition和服务请求。 @Configuration //包扫描 @ComponentScan(value = "com.alibaba") }) public class MyConf…
编程学习 ·

创新实训(10)-提取式文本摘要之bert聚类

创新实训(10)-提取式文本摘要之bert聚类 1. 思路 使用bert作为预训练模型,利用bert生成的词向量进行下游任务的处理,在这篇论文中使用的是k-means计算词向量分布的重心作为文本摘要的候选句子。可以看作是聚类的一种形式。 2.代码分析 基于Pytorch的Transformers框架,使用预…
编程学习 ·

单例和枚举原理

单例和枚举原理 枚举 简单介绍枚举类能够统一管理一些全局的变量,封装对于他们的逻辑与方法。还能和switch-case结合,简化大量的if-else,让代码更加优雅。直接Demo public enum Week {//本文的枚举类变量,枚举类实例,name属性指的就是MONDAY//这类的变量MONDAY(0,"星…
编程学习 ·

阿里热更新hotfix使用

一、SDK引入项目build中添加buildscript {repositories {google()jcenter()//添加这句maven {url "http://maven.aliyun.com/nexus/content/repositories/releases"}}dependencies {...}}allprojects {repositories {google()jcenter()maven { url "https://jit…
编程学习 ·

Explicit Model Predictive Control of a Magnetic Flexible Endoscope

对胶囊的动力学进行建模,能更好的对胶囊进行控制,在已知胶囊预定义轨迹的情况下,对胶囊进行预测控制和定位。 一个磁灵活内窥镜的显式模型预测控制 Explicit Model Predictive Control of a Magnetic Flexible Endoscope [1] Paper Link Authors: Scaglioni, Bruno, et al. …
编程学习 ·

遗传算法求解TSP问题python实现

文章目录1 遗传算法总体设计2 算子设计2.1 选择算子2.2 交叉算子2.3 变异算子2.4 将种群的个体按照里程排序,并返回当前种群中的最优个体及其里程2.5 设置种群数,变异概率及其进化次数2.6 主函数3 实验结果分析4 附python源码(完整版) 1 遗传算法总体设计Step1: 初始化参数(…
编程学习 ·

Tomcat 启动控制台乱码

Tomca 启动控制台乱码将tomcat用作web应用服务器,在tomcat的服务迭代中,服务漏洞是不可避免需要升级的来修复漏洞的。在修复漏洞的时候通常需要将原来的webapps下的文件复制到新tomcat中,并替换tomcat/conf/server.xml文件(小版本升级都可以用这种方式)。解决乱码 在tomca…
编程学习 ·

【Android开发--新手必看篇】Calendar类的使用

Android笔记 ​ ——其他 【若对该知识点有更多想了解的,欢迎私信博主~~】 Calendar类: 获取日期 注:在JDK1.0中,Date类是唯一处理时间的类,但是由于Date类中方法比较少并且有一些方法不便于实现国际化,所以从JDK1.1版本开始新增了Calendar类,增加了许多功能强大的方法…
编程学习 ·

Netty之WebSocket应用

1. 什么是Netty?Netty是一个高性能事件驱动,异步非阻塞的IO Java开源框架,由Jboss提供,用于建立Tcp等底层的链接,基于Netty可以建立高性能的Http服务器,快速开发高性能、高可靠的网络服务器和客户端程序。它支持Http,websocket,tcp,udp等协议。同时Netty又是基于NIO的…
编程学习 ·

【牛客网】写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。

题目 写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。 需要掌握 1、异或运算 两个数不相同,结果为1。两个数相同,结果为0。 2、与运算 两位同时为“1”,结果才为“1”,否则为0 3、左移 将一个二进制操作数对象按指定的移动位数向左移,左边溢…
编程学习 ·

Linux学习日记 7.1 (用户)

MOOC链接 一。什么是用户和用户组 1.用户 UID (User‘s ID)是识别用户权限的标识,用户登陆系统所处的角色是通过UID来实现的,而非用户名,因此,每个用户的UID必须是唯一的。 Linux中的用户分成三类 ※ 系统管理员用户:拥有整个系统所有的权限,只能有一个,即根用户root,…
编程学习 ·

顺序结构

顺序结构 1,if选择结构public static void main(String[] args) {Scanner scanner = new Scanner(System.in);System.out.println("请输入你的成绩:");int score = scanner.nextInt();if(score>=60 && score<70){System.out.println("及格&quo…
编程学习 ·

微信小程序 列表渲染多层嵌套循环

前言入门教程之列表渲染多层嵌套循环,目前官方的文档里,主要是一维数组列表渲染的案例,还是比较简单单一,给刚入门的童鞋还是无从入手的感觉。<view wx:for="{{items}}">{{index}}: {{item.message}} </view>123 还有一个九九乘法表把数据直接写到wx…
编程学习 ·

C语言指针笔记

C语言指针 一.地址与指针变量 程序在执行过程中需要有内存来存储需要用到的数据和程序代码,它们都占据一些内存单元,地址是这些内存单元的编号,同时包括它所指向的数据的类型信息。因此,可以把地址形象化地称为"指针"。 但不要把地址和指针混为一个概念,地址是数…
编程学习 ·

u-boot2020.04移植(1、u-boot的编译)

最近公司项目用到了xilinx的zynq7000 soc,开发方式有所不同,驱动的数据都是通过设备树来提供,以前没接触过,所以想系统的学习一下相关的内容,但是手头只有一块三星的s5pv210开发板,使用的u-boot和linux系统不支持设备树,只好自己移植,以此记录一下移植过程,加深理解与…