Java GUI实现贪吃蛇游戏

news2024/11/26 20:35:52

贪吃蛇是一款经典的游戏,玩法相对简单但富有挑战性。以下是贪吃蛇游戏的基本玩法说明:

  1. 目标:控制一条蛇,在游戏区域内吃到尽可能多的食物,使蛇身变长,同时避免撞到自己的身体或游戏区域的边界。

  2. 控制:通常使用方向键(上、下、左、右)或滑动屏幕来控制蛇的移动方向,使其朝着食物的方向前进。

  3. 食物和增长:在游戏区域内随机生成食物。当蛇头接触到食物时,蛇身增长一个单位,并且得分会增加。

  4. 增加难度:随着蛇身不断增长,游戏会变得更加困难。蛇的身体会占据更多的空间,同时移动速度可能加快。

  5. 失败条件:游戏结束的条件包括蛇头撞到自己的身体或者撞到游戏区域的边界。

  6. 计分:游戏通常会记录你的得分,即吃到的食物数量或者游戏时长。

贪吃蛇是一款简单而又令人上瘾的游戏,你可以在各种平台上找到不同版本的贪吃蛇游戏。希望你能享受这个经典游戏带来的乐趣!

以下是Java实现的基本贪吃蛇游戏代码,你可以根据自己的需求进行修改和完善:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;

public class SnakeGame extends JFrame implements KeyListener {

    private static final long serialVersionUID = 1L;

    private JPanel panel;
    private static JLabel scoreLabel, gameOverLabel;
    private static int score = 0;
    private static int highScore = 0;
    private static boolean gameOver = false;

    private static final int ROWS = 30, COLS = 30;
    private static final int CELL_SIZE = 20;

    private Snake snake;
    private Food food;
    private Timer timer;

    public static void main(String[] args) {
        new SnakeGame().setVisible(true);
    }

    public SnakeGame() {
        setTitle("贪吃蛇游戏");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(false);

        panel = new JPanel();
        panel.setPreferredSize(new Dimension(ROWS * CELL_SIZE, COLS * CELL_SIZE));
        getContentPane().add(panel);
        addKeyListener(this);

        scoreLabel = new JLabel("得分: 0  最高分: " + highScore);
        panel.add(scoreLabel);

        gameOverLabel = new JLabel("游戏结束");
        gameOverLabel.setForeground(Color.RED);
        gameOverLabel.setVisible(false);
        panel.add(gameOverLabel);

        snake = new Snake();
        food = new Food(snake);
        food.generate();

        timer = new Timer(100, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                snake.update();
                checkGameOver();
                panel.repaint();
            }
        });
        timer.start();
        pack();
        setLocationRelativeTo(null);
    }

    private void checkGameOver() {
        if (snake.checkCollision()) {
            gameOver = true;
            gameOverLabel.setVisible(true);
            timer.stop();

            if (score > highScore) {
                highScore = score;
                scoreLabel.setText("得分: " + score + "  最高分: " + highScore);
            }
        }
    }

    @Override
    public void keyPressed(KeyEvent e) {
        if (!gameOver) {
            int keyCode = e.getKeyCode();
            if (keyCode == KeyEvent.VK_UP) {
                snake.changeDirection(Snake.UP);
            } else if (keyCode == KeyEvent.VK_DOWN) {
                snake.changeDirection(Snake.DOWN);
            } else if (keyCode == KeyEvent.VK_LEFT) {
                snake.changeDirection(Snake.LEFT);
            } else if (keyCode == KeyEvent.VK_RIGHT) {
                snake.changeDirection(Snake.RIGHT);
            }
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }

    public class Snake {

        private LinkedList<Point> segments;
        private int direction;

        public static final int UP = 1, DOWN = -1, LEFT = 2, RIGHT = -2;

        public Snake() {
            segments = new LinkedList<Point>();
            segments.add(new Point(3, 0));
            segments.add(new Point(2, 0));
            segments.add(new Point(1, 0));
            segments.add(new Point(0, 0));
            direction = RIGHT;
        }

        public void changeDirection(int newDirection) {
            if (direction + newDirection != 0) {
                direction = newDirection;
            }
        }

        public void update() {
            Point head = segments.getFirst();
            Point newHead = (Point) head.clone();

            if (direction == UP) {
                newHead.translate(0, -1);
            } else if (direction == DOWN) {
                newHead.translate(0, 1);
            } else if (direction == LEFT) {
                newHead.translate(-1, 0);
            } else if (direction == RIGHT) {
                newHead.translate(1, 0);
            }

            segments.addFirst(newHead);
            if (!food.checkCollision(newHead.x, newHead.y)) {
                segments.removeLast();
            } else {
                score++;
                scoreLabel.setText("得分: " + score + "  最高分: " + highScore);
                food.generate();
            }
        }

        public boolean checkCollision() {
            Point head = segments.getFirst();
            if (head.x < 0 || head.x >= COLS || head.y < 0 || head.y >= ROWS) {
                return true;
            }
            for (int i = 1; i < segments.size(); i++) {
                if (segments.get(i).equals(head)) {
                    return true;
                }
            }
            return false;
        }

        public void draw(Graphics g) {
            for (Point p : segments) {
                g.setColor(Color.GREEN);
                g.fillRect(p.x * CELL_SIZE, p.y * CELL_SIZE, CELL_SIZE, CELL_SIZE);
            }
        }
    }

    public class Food {
        private int x, y;
        private Snake snake;
        private Random rand;

        public Food(Snake snake) {
            this.snake = snake;
            rand = new Random();
        }

        public void generate() {
            do {
                x = rand.nextInt(COLS);
                y = rand.nextInt(ROWS);
            } while (snake.segments.contains(new Point(x, y)));
        }

        public boolean checkCollision(int x, int y) {
            if (this.x == x && this.y == y) {
                return true;
            }
            return false;
        }

        public void draw(Graphics g) {
            g.setColor(Color.RED);
            g.fillRect(x * CELL_SIZE, y * CELL_SIZE, CELL_SIZE, CELL_SIZE);
        }
    }

    @Override
    public void paint(Graphics g) {
        g.setColor(Color.LIGHT_GRAY);
        g.fillRect(0, 0, getWidth(), getHeight());
        snake.draw(g);
        food.draw(g);
    }
}

这个代码实现的贪吃蛇游戏界面为:

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

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

相关文章

SQL题

[极客大挑战 2019]EasySQL 进行简单的尝试&#xff0c;就知道是单引号的字符型注入 万能密码进行一个简单的尝试 结果就出来了 还是要了解一下原理 输入的是1&#xff0c;形成的sql语句是错误的SELECT*FROM table_name WHERE username1and password123; 第一个单引号和第二个…

[代码实战和详解]VGG16

VGG16 详解 我的github代码实现&#xff1a;vgg16 我们在vgg16神经网络上训练了SIGNS数据集&#xff0c;这是一个分类的数据集&#xff0c;在我的github上有介绍怎么下载数据集以及如何训练。 VGG16是一个卷积神经网络&#xff08;CNN&#xff09;架构&#xff0c;它在2014年…

国内领先的五大API接口供应商

API&#xff08;Application Programming Interface&#xff09;接口&#xff0c;现在很多应用系统中常用的开放接口&#xff0c;对接相应的系统、软件功能&#xff0c;简化专业化的程序开发。作者用过的国内比较稳定的API接口供应商有如下几家&#xff0c;大家可以参考选择&am…

论文学习——THE USTC SYSTEM FOR ADRESS-M CHALLENGE

文章目录 引言正文Abstract模型基本结构模型效果汇总 Introduction介绍跨语言任务的独特性思路启发和变化如何使用预定义好的音频特征如何使用预定义好的语言模型——语言模型中获取韵律信息结果说明 Dataset数据集Mthods方法使用设计好的特征进行AD检测使用的特征分类和训练方…

【原创】java+swing+mysql通讯录管理系统设计与实现

前言&#xff1a; 通讯录管理系统是一个设计和实现个人或组织之间联系人信息管理的系统。该系统可能涵盖了联系人的详细信息&#xff0c;如姓名、电话号码、电子邮件地址、地址等&#xff0c;并提供了对联系人信息进行添加、删除、修改、查询等操作的功能。通讯录管理系统旨在…

Android设计模式--状态模式

真知即所以为行&#xff0c;不行不足谓之知 一&#xff0c;定义 当一个对象的内在状态改变时&#xff0c;允许改变其行为&#xff0c;这个对象看起来像是改变了其类。 这么说可能很难理解&#xff0c;通俗来讲就是当一个对象它有多种状态的时候&#xff0c;把每一种状态的行为…

【科普】储能EMS的嵌入式系统该如何选择?

来源&#xff1a;飞凌嵌入式官网 引言 储能EMS&#xff08;能源管理系统&#xff09;是专门针对储能系统设计和实施的管理系统&#xff0c;它在新型储能系统领域起到了至关重要的作用。储能EMS能够帮助企业或者机构实现储能设备的高效、安全和可靠管理&#xff0c;优化能源的储…

LeetCode热题100——二分查找

二分查找 1. 搜索插入位置2. 搜素二维矩阵3. 在排序数组中查找第一个和最后一个元素位置 1. 搜索插入位置 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 // 题…

vue-router配置

1、路由安装 npm install vue-router4 2、创建router目录 3、编辑文件且引入router包 4、main.js引入

【C++面向对象】13. 接口 / 抽象类*

文章目录 【 1. 抽象类 】1.1 抽象类的定义1.2 抽象类的应用条件1.3 实例 【 2. 设计策略 】 接口描述了类的行为和功能&#xff0c;而不需要完成类的特定实现。C 接口是使用 抽象类&#xff08;abstract base class&#xff0c;也称为ABC&#xff09; 来实现的。 【 1. 抽象类…

《C++避坑神器·二十》C++智能指针简单使用

智能指针&#xff0c;自动释放所指向的对象。 头文件 #include <memory>shared_ptr 允许多个指针指向同一个对象 unique_ptr 独占所指向的对象 weak_ptr 指向shared_ptr所管理的对象 作用原理&#xff1a;在函数作用域结束时调用析构函数自动释放资源。 shared_ptr: …

数据结构-二叉树力扣题

目录 1.相同的树 2.二叉树中查找值为x的节点 3.单值二叉树 4.对称二叉树 5.二叉树的前序遍历 6.另一颗树的子树 层序遍历&#xff1a; 7.二叉树遍历 8.判断二叉树是否是完全二叉树 一个特殊的性质&#xff1a; 1.相同的树 题目链接&#xff1a;力扣&#xff08;LeetC…

基于操作系统讨论Java线程与进程、浅谈Go的线程与管程

文章目录 操作系统中的进程进程概念进程的状态 Java中的进程Java进程的概念Java进程的特性Java进程的状态Java进程与操作系统进程的通信 操作系统的进程和Java进程的区别联系操作系统进程Java 进程区别和联系 操作系统中的线程动机优点多核编程 Java中的线程定义&#xff1a;特…

ping命令使用示例解析

【一】ping命令简介 ping &#xff08;Packet Internet Groper&#xff09;是一种因特网包探索器&#xff0c;用于测试网络连接量的程序。ping的一般用途有&#xff1a; ①【测试网络物理链路是否正常】&#xff1a;通过将ICMP(Internet控制消息协议)回显数据包发送到网络终端&…

Unity中Shader图形流水线中的纹理

文章目录 前言一、图形流水线中的纹理1、我们的纹理一般用于&#xff1a;2、纹理的获取方式&#xff1a; 二、纹理的分类1、颜色纹理2、几何纹理 三、纹理管线四、纹理的作用1、纹理可以 替换 漫反射模型中的 漫反射系数Kd2、纹理还有的作用 前言 Unity中Shader图形流水线中的…

【入门篇】1.3 redis客户端之 jedis 高级使用示例

文章目录 0.前言1. 发布和订阅消息2. 事务操作3. 管道操作4. jedis 支持哨兵模式5. jedis 支持集群模式5. 参考链接 0.前言 Jedis是Redis的Java客户端&#xff0c;它支持所有的Redis原生命令&#xff0c;使用方便&#xff0c;且可以与Java项目无缝集成。 该库的最新版本支持Re…

C#创建并调用dll

文章目录 1.VS2019创建C#主程序2.编译主程序3.添加类库工程&#xff0c;并添加计算逻辑4.给主程序添加引用项5.重新编译主程序6.主程序添加测试逻辑 1.VS2019创建C#主程序 2.编译主程序 debug目录下生成exe&#xff1a; 3.添加类库工程&#xff0c;并添加计算逻辑 添加计算逻…

ROS 多机器人导航RVIZ环境的配置

文章目录 前言一、添加多个2D Pose Estimate/2D nav Goal二、RVIZ的其他配置1.RobotModel 总结 前言 前文ROS Turtlebot3多机器人编队导航仿真写了多机器人呢导航的代码实现&#xff0c;本文主要说明&#xff0c;RVIZ导航环境的配置&#xff0c;如何添加多个2D Pose Estimate/…

CODING DevOps产品认证笔记

1.敏捷&精益&瀑布概述 1.1 敏捷软件开发 第一章敏捷软件开发背景 背景&#xff1a;乌卡时代 易变性:当今世界的变化越来越多越来越快&#xff0c;越来越不可预测。不确定性:历史上的任何一个时代所带来的经验已经无法为当今世界的所有变化提供参照。复杂性:事物间的…