基于JAVA实现的贪吃蛇小游戏

news2024/11/25 7:09:07

JAVA贪吃蛇小游戏实现:

     贪吃蛇曾经在我们的童年给我们带来了很多乐趣。贪吃蛇这款游戏现在基本上没人玩了,甚至在新一代人的印象中都已毫无记忆了。。。但是,这款游戏可以在一定程度上锻炼自己的编程能力。

     目前这个版本只是一个测试版本,所以只有一些基本功能,实现了移动,吃食物身体增长,分数增长,判断撞墙和撞自己的身体

代码展示

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.ArrayList;
import java.util.Random;

/**
 * 贪吃蛇实现类,
 * 可运行main方法查看效果
 */
public class SnakeGame extends JFrame implements ActionListener, KeyListener {
    private static final long serialVersionUID = 1L;
    private JPanel mainPanel, scorePanel, gamePanel;
    private JButton startButton, pauseButton, resumeButton;
    private JLabel scoreLabel;
    private Timer timer;
    private int score, headX, headY, headDirection, foodX, foodY, speed;
    private final int GAME_WIDTH = 400, GAME_HEIGHT = 400, GRID_SIZE = 10;
    private ArrayList<Integer> bodyX, bodyY;

    public SnakeGame() {
        super("贪吃蛇");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setFocusable(true);
        addKeyListener(this);

        // 创建主面板
        mainPanel = new JPanel(new BorderLayout());
        getContentPane().add(mainPanel);

        // 创建分数面板
        scorePanel = new JPanel();
        scoreLabel = new JLabel("分数: " + score);
        startButton = new JButton("开始");
        pauseButton = new JButton("暂停");
        resumeButton = new JButton("继续");
        startButton.addActionListener(this);
        pauseButton.addActionListener(this);
        resumeButton.addActionListener(this);
        pauseButton.setEnabled(false);
        resumeButton.setEnabled(false);
        scorePanel.add(scoreLabel);
        scorePanel.add(startButton);
        scorePanel.add(pauseButton);
        scorePanel.add(resumeButton);
        mainPanel.add(scorePanel, BorderLayout.NORTH);

        // 创建游戏面板
        gamePanel = new GamePanel();
        mainPanel.add(gamePanel, BorderLayout.CENTER);

        // 初始化
        headX = GAME_WIDTH / 2;
        headY = GAME_HEIGHT / 2;
        headDirection = KeyEvent.VK_DOWN;
        bodyX = new ArrayList<Integer>();
        bodyY = new ArrayList<Integer>();
        bodyX.add(headX);
        bodyY.add(headY - GRID_SIZE);
        bodyX.add(headX);
        bodyY.add(headY - 2 * GRID_SIZE);
        speed = 200;//移动速度 值越小速度越快,值越大速度越慢

        // 显示窗口
        pack();
        setLocationRelativeTo(null); // 居中
        setResizable(false); // 禁止调整大小
        setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == startButton) { // 开始游戏
            startGame();
        } else if (e.getSource() == pauseButton) { // 暂停游戏
            pauseGame();
        } else if (e.getSource() == resumeButton) { // 继续游戏
            resumeGame();
        }
    }

    @Override
    public void keyPressed(KeyEvent e) {
        int keyCode = e.getKeyCode();
        if (keyCode == KeyEvent.VK_UP && headDirection != KeyEvent.VK_DOWN) {
            headDirection = KeyEvent.VK_UP;
        } else if (keyCode == KeyEvent.VK_DOWN && headDirection != KeyEvent.VK_UP) {
            headDirection = KeyEvent.VK_DOWN;
        } else if (keyCode == KeyEvent.VK_LEFT && headDirection != KeyEvent.VK_RIGHT) {
            headDirection = KeyEvent.VK_LEFT;
        } else if (keyCode == KeyEvent.VK_RIGHT && headDirection != KeyEvent.VK_LEFT) {
            headDirection = KeyEvent.VK_RIGHT;
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {}

    @Override
    public void keyTyped(KeyEvent e) {}

    private void startGame() {
        startButton.setEnabled(false);
        pauseButton.setEnabled(true);
        timer = new Timer(speed, new TimerHandler());
        timer.start();
        newFood();
    }

    private void pauseGame() {
        timer.stop();
        pauseButton.setEnabled(false);
        resumeButton.setEnabled(true);
    }

    private void resumeGame() {
        timer.start();
        pauseButton.setEnabled(true);
        resumeButton.setEnabled(false);
    }

    private class GamePanel extends JPanel {
        private static final long serialVersionUID = 1L;

        public GamePanel() {
            setBackground(Color.WHITE);
            setPreferredSize(new Dimension(GAME_WIDTH, GAME_HEIGHT));
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);

            // 画食物
            g.setColor(Color.BLUE);
            g.fillOval(foodX, foodY, GRID_SIZE, GRID_SIZE);

            // 画蛇头
            g.setColor(Color.gray);
            g.fillOval(headX, headY, GRID_SIZE, GRID_SIZE);

            // 画蛇身体
            g.setColor(Color.BLACK);
            for (int i = 0; i < bodyX.size(); i++) {
                g.fillOval(bodyX.get(i), bodyY.get(i), GRID_SIZE, GRID_SIZE);
            }
        }
    }

    private class TimerHandler implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            // 移动蛇身体
            for (int i = bodyX.size() - 1; i > 0; i--) {
                bodyX.set(i, bodyX.get(i - 1));
                bodyY.set(i, bodyY.get(i - 1));
            }
            bodyX.set(0, headX);
            bodyY.set(0, headY);

            // 移动蛇头
            if (headDirection == KeyEvent.VK_UP) {
                headY -= GRID_SIZE;
            } else if (headDirection == KeyEvent.VK_DOWN) {
                headY += GRID_SIZE;
            } else if (headDirection == KeyEvent.VK_LEFT) {
                headX -= GRID_SIZE;
            } else if (headDirection == KeyEvent.VK_RIGHT) {
                headX += GRID_SIZE;
            }

            // 碰到边界或自身,游戏结束
            if (headX < 0 || headX + GRID_SIZE > GAME_WIDTH || headY < 0 || headY + GRID_SIZE > GAME_HEIGHT) {
                gameOver();
                return;
            }
            for (int i = 0; i < bodyX.size(); i++) {
                if (headX == bodyX.get(i) && headY == bodyY.get(i)) {
                    gameOver();
                    return;
                }
            }

            // 吃到食物,增加分数和身体长度
            if (headX == foodX && headY == foodY) {
                score += 10;
                scoreLabel.setText("分数: " + score);
                bodyX.add(bodyX.get(bodyX.size() - 1));
                bodyY.add(bodyY.get(bodyY.size() - 1));
                newFood();
            }

            // 重绘游戏面板
            gamePanel.repaint();
        }
    }

    private void newFood() {
        Random rand = new Random();
        foodX = rand.nextInt(GAME_WIDTH / GRID_SIZE) * GRID_SIZE;
        foodY = rand.nextInt(GAME_HEIGHT / GRID_SIZE) * GRID_SIZE;
        for (int i = 0; i < bodyX.size(); i++) {
            if (foodX == bodyX.get(i) && foodY == bodyY.get(i)) {
                newFood();
                return;
            }
        }
    }

    private void gameOver() {
        timer.stop();
        JOptionPane.showMessageDialog(this, "游戏结束,分数:" + score);
        startButton.setEnabled(true);
        pauseButton.setEnabled(false);
        resumeButton.setEnabled(false);
        score = 0;
        scoreLabel.setText("分数: " + score);
        headX = GAME_WIDTH / 2;
        headY = GAME_HEIGHT / 2;
        headDirection = KeyEvent.VK_DOWN;
        bodyX.clear();
        bodyY.clear();
        bodyX.add(headX);
        bodyY.add(headY - GRID_SIZE);
        bodyX.add(headX);
        bodyY.add(headY - 2 * GRID_SIZE);
    }

    //运行游戏
    public static void main(String[] args) {
        new SnakeGame();
        System.out.println("");
    }
}

运行效果如图:

完整素材及全部代码

代码已上传csdn,0积分下载,觉得这片博文有用请留下你的点赞。

基于JAVA实现的贪吃蛇小游戏

      感谢大家的阅读,希望对大家有所帮助!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1626669.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AI:162-如何使用Python进行图像识别与处理深度学习与卷积神经网络的应用

本文收录于专栏:精通AI实战千例专栏合集 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 每一个案例都附带关键代码,详细讲解供大家学习,希望可以帮到大家。正在不断更新中~ 一.如何使用Python进行图像识别与处理…

在Windows 10中如何关闭BitLocker加密?这里提供详细步骤

序言 BitLocker加密将有助于保持卷或闪存驱动器处于安全模式。但是&#xff0c;如果你不再需要BitLocker加密&#xff0c;你可以在Windows 10计算机上轻松删除BitLocker加密。在这里&#xff0c;我们将向你展示在Windows 10上删除/禁用BitLocker驱动器加密的四种方法。 通过控…

Qt/C++音视频开发71-指定mjpeg/h264格式采集本地摄像头/存储文件到mp4/设备推流/采集推流

一、前言 用ffmpeg采集本地摄像头&#xff0c;如果不指定格式的话&#xff0c;默认小分辨率比如640x480使用rawvideo格式&#xff0c;大分辨率比如1280x720使用mjpeg格式&#xff0c;当然前提是这个摄像头设备要支持这些格式。目前市面上有一些厂家做的本地设备支持264格式&am…

1688获得店铺所有商品API接口技术解析与应用实践

在电商领域&#xff0c;快速获取店铺所有商品信息对于商家和开发者来说至关重要。1688作为国内领先的B2B电商平台&#xff0c;提供了丰富的API接口供开发者使用&#xff0c;其中获得店铺所有商品API接口是其中之一。本文将深入解析该API接口的技术实现&#xff0c;并探讨其在实…

嵌入式中全栈工程师是怎么样的?

这两天有小伙伴问我,如何才能做到嵌入式全栈?我用visio软件画了一张图,为大家讲解。 此图为博主认为的嵌入式全栈,从硬件到软件全套技术栈,我们“从下往上”讲解。 1、首先是需要有原理图库,可以自己画,也可以从别人那里拷贝。有了原理图库,就开始画原理图。画原理图需…

​「Python大数据」词频数据渲染词云图导出HTML

前言 本文主要介绍通过python实现数据聚类、脚本开发、办公自动化。词频数据渲染词云图导出HTML。 一、业务逻辑 读取voc数据采集的数据批处理,使用jieba进行分词,去除停用词词频数据渲染词云图将可视化结果保存到HTML文件中二、具体产出 三、执行脚本 python wordCloud.p…

基于模糊控制的电动汽车锂电池SOC主动均衡电路MATLAB仿真模型

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 模型简介 模型在 Matlab/Simulink仿真平台中搭建16节电芯锂电池电路模型&#xff0c;主要针对电动车锂电池组SOC差异性&#xff0c;采用模糊控制算法动态调节均衡电流&#xff0c;以减少均衡时间和能量损耗。…

OpenStack 云平台管理

目录 一、案例分析 1.1、案例概述 1.2、案例前置知识点 1&#xff09;关于浮动 IP 地址 2&#xff09;关于快照 1.3、案例环境 1&#xff09;本案例实验环境 2&#xff09;案例需求 3&#xff09;案例实现思路 二、案例实施 2.1、部署 OpenStack 2.2、创建…

WSL2无法ping通本地主机ip的解决办法

刚装完WSL2的Ubuntu子系统时&#xff0c;可能无法ping通本地主机的ip&#xff1a; WSL2系统ip&#xff1a; 本地主机ip&#xff1a; 在powershell里输入如下的命令&#xff1a; New-NetFirewallRule -DisplayName "WSL" -Direction Inbound -InterfaceAlias &quo…

反映工业发展质量与效益的主要指标有哪些

我国经济已由高速增长阶段转向高质量发展阶段&#xff0c;这是新时代我国经济发展的基本特征。推动高质量发展&#xff0c;是保持经济持续健康发展的必然要求&#xff0c;是适应我国社会主要矛盾变化和全面建成小康社会、全面建设社会主义现代化国家的必然要求&#xff0c;是遵…

解决Gson转Map时数值int、long等转为Double

今天尝试使用Gson&#xff0c;发现转Map时数值都转成了Double&#xff0c;百度无果后&#xff0c;通过查看源码&#xff0c;尝试可以通过自定义对象转数值策略来解决&#xff0c;特地记录一下&#xff1b; Gson默认采取将数值转换到Double的策略ToNumberPolicy.DOUBLE&#xf…

mysql的多表查询和子查询

多表查询&#xff1a;查询数据时&#xff0c;需要使用多张表来查询 多表查询分类&#xff1a; 1.内连接查询 2.外连接查询 3.子查询 笛卡尔积&#xff1a; create table class (id int primary key auto_increment,name varchar(10) ); create table student (id int primar…

2024软件测试面试题总结

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号【互联网杂货铺】&#xff0c;回复 1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 测试技术面试题 1、什么是兼容性测试&#xff1f;兼容性测试侧…

2024年Java JDK下载安装教程,附详细图文

文章目录 简介一、JDK的下载二、JDK的安装三、设置环境变量(不一定需要执行&#xff09; 简介 博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f34…

打印机连接电脑后打印无反应解决小方法

测试页打印失败是否参阅打印疑难解答已或得帮助 一台刚购买的新惠普打印机&#xff0c;拆箱后正常安装&#xff0c;接通电源、USB线连接电脑&#xff0c;正常安装驱动光盘&#xff1b;然后打印测试页来测试打印机&#xff0c;这个时候你点打印测试页&#xff0c;在打印任务里会…

国家级会议报道:贝锐蒲公英异地组网高效实现前方数据回传

作为市委宣传部的国有新闻媒体&#xff0c;在日常工作中会派遣大量人员外出进行采访、报道&#xff0c;还经常面临国家级重要会议或活动的报道任务。 在这些工作中&#xff0c;前方人员往往需要和后方人员协同、保证内容的时效性&#xff0c;及时反馈现场的相关资料和信息、访…

docker入门级命令

基本概念 docker的连个基本概念&#xff1a;镜像、容器。 docker镜像可以理解为是存储docker安装包的地方&#xff0c;比如&#xff1a;mcr.microsoft.com/mssql/server:2017-latest是sqlserver的docker镜像。 可以通过docker pull命令拉取远程镜像到本地。比如&#xff1a;…

JWT原理解析

一、概述 虽然现在很多的开发框架会支持JWT的使用&#xff0c;但是对JWT还是没有一个详细的了解&#xff0c;有很多疑惑&#xff1a; JWT比之前的session或者token有什么好处&#xff1f;JWT的构成元素是什么&#xff1f;JWT从生成到使用的详细流程&#xff1f; 二、 JWT 2…

PLL深度解析第一篇——PLL的知识图谱

在硬件电路中&#xff0c;时钟就像心脏一样&#xff0c;在时钟的节拍下&#xff0c;不同的芯片、不同的电路、不同的接口都可以有序的进行工作或者通信&#xff08;类似流水线一样&#xff0c;必须有节奏的运行&#xff09;。 但是在芯片中&#xff0c;不同的模块和接口工作的频…

chrome浏览器安装elasticsearch的head可视化插件

head插件简介 elasticsearch-head被称为是弹性搜索集群的web前端&#xff0c;head插件主要是用来和elastic Cluster交互的Web前端 head插件历史 elasticsearch-head插件在0.x-2.x版本的时候是集成在elasticsearch内的&#xff0c;由elasticsearch的bin/elasticsearch-plugin…