Java贪吃蛇大作战

作为Java新手小白,渴望学习一些好玩有趣的java程序

废话不多说,接下来我会一步一步实现java小程序:贪吃蛇大作战哦! 

实现 Java贪吃蛇一共分四个步骤:

1、画出窗体对象
2、绘制静态ui
3、使用鼠标监听器事件和定时器事件让小蛇动起来
4、实现吃食物的功能

关于代码中的数值,因为小蛇的素材图片像素为25*25 ,游戏区域灰色方格为850*600

 1、绘制窗体对象

        使用JFrame这个类,分别设置界面标题、宽度、高度、位置、退出界面以及位置固定,最后将界面显示出来:

public class Main {
    public static void main(String[] args) {
	// write your code here
        JFrame frame = new JFrame("贪吃蛇大作战");//界面标题
        frame.setSize(900, 720);//设置宽高
        frame.setLocationRelativeTo(null);//布局正中间
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//退出
        frame.setResizable(false);//大小固定,不能变化
        frame.setVisible(true);//显示
    }
}

界面如下:

 2、绘制静态Ui

         新建Panel.java文件,添加如下绘制标题代码,并在Main.java中调用显示:

public class Panel extends JPanel {           //由Panel继承JPanel,创建一个画布类

    @Override
    protected void paintComponent(Graphics g) {         //方法:绘制,Graphics g是画笔对象
        super.paintComponent(g);
        //绘制顶部标题
        //paintIcon()函数可将图片放到对应的容器中去:对象、画笔工具、位置坐标
        new ImageIcon("img/title.png").paintIcon(this,g,20,11);
    }
}


调用部分
frame.add(new Panel());   //显示顶部标题

绘制游戏区域,在Panel.java文件中protected void paintComponent(Graphics g)函数中继续添加绘制游戏区域代码:

//绘制游戏区域
g.fillRect(20,75,850,600);//参数为绘制矩形窗口的顶点x,y坐标,矩形的宽、高

 运行结果如下:

3、鼠标监听时间与定时器

设置键盘监听事件以及定时器的启动,实现键盘与游戏界面的交互,定时器的作用是保证每隔一段时间刷新物体的坐标位置,以便实时更新游戏界面。具体代码在Panel.java文件中编辑如下:

游戏初始界面: 

 当按下空格键开始游戏后,小蛇开始运动,我们可以通过键盘上的上下左右键对小蛇的运动方向进行控制!(注:实现图是动态的这里就不展示,你们可以自行试试,如果有问题可以重复检查一下代码是否敲错)

具体实现代码在Panel.java文件中编辑如下:

package com.company;

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;

public class Panel extends JPanel implements KeyListener, ActionListener {           //由Panel继承JPanel,创建一个画布类,加入键盘监听
    int length;//小蛇长度
    int[] snakeX = new int[500];
    int[] snakeY = new int[500];
    String fx; //小蛇朝向
    boolean isStart = false;  //游戏开始或者暂停

    //定时器(保证每隔一段时间就调用paintComponent()方法,保证游戏时小蛇移动页面的刷新)
    Timer timer = new Timer(100,this);//定时器时间100ms,监听对象是

    public Panel(){
        init();
        //添加监听事件
        this.setFocusable(true);//使得一直聚焦在游戏区域
        this.addKeyListener(this);
    }

    //初始化方法
    public void init(){
        length = 3;
        fx = "r";
        //初始化小蛇位置
        snakeX[0] = 100; snakeY[0] = 100;
        snakeX[1] = 75; snakeY[1] = 100;
        snakeX[2] = 50; snakeY[2] = 100;
        timer.start();
    }
    @Override
    protected void paintComponent(Graphics g) {         //方法:绘制,Graphics g是画笔对象
        super.paintComponent(g);
        //绘制顶部标题
        //paintIcon()函数可将图片放到对应的容器中去:对象、画笔工具、位置坐标
        new ImageIcon("img/title.png").paintIcon(this,g,20,11);
        //绘制游戏区域
        g.fillRect(20,75,850,600);//参数为绘制矩形窗口的顶点x,y坐标,矩形的宽、高
        //绘制小蛇
        //蛇头
        if(fx.equals("r")){
            new ImageIcon("img/right.png").paintIcon(this,g,snakeX[0],snakeY[0]);
        }else if(fx.equals("l")){
            new ImageIcon("img/left.png").paintIcon(this,g,snakeX[0],snakeY[0]);
        }else if(fx.equals("u")){
            new ImageIcon("img/up.png").paintIcon(this,g,snakeX[0],snakeY[0]);
        }else if(fx.equals("d")) {
            new ImageIcon("img/down.png").paintIcon(this, g, snakeX[0], snakeY[0]);
        }
        //蛇身
        for(int i = 1; i < length; i++){
            new ImageIcon("img/body.png").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);
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {    //点击

    }

    @Override
    public void keyPressed(KeyEvent e) {   //按压
        int KeyCode = e.getKeyCode();
        if(KeyCode == KeyEvent.VK_SPACE){   //监听空格键
            isStart = !isStart;
        }
        if(isStart){
            if(KeyCode == KeyEvent.VK_LEFT){
                fx = "l";
            }else if(KeyCode == KeyEvent.VK_RIGHT){
                fx = "r";
            }else if(KeyCode == KeyEvent.VK_UP){
                fx = "u";
            }else if(KeyCode == KeyEvent.VK_DOWN){
                fx = "d";
            }
        }


        repaint();
    }

    @Override
    public void keyReleased(KeyEvent e) {    //释放

    }

    @Override
    public void actionPerformed(ActionEvent e) {
        //改变蛇的位置坐标
        if(isStart){     //头部位置遍历
            for(int i = length-1;i > 0; i--){
                snakeX[i] = snakeX[i-1];
                snakeY[i] = snakeY[i-1];
            }
            if(fx.equals("l")){
                snakeX[0] = snakeX[0] - 25;
            }else if(fx.equals("r")){
                snakeX[0] = snakeX[0] + 25;
            }else if(fx.equals("u")){
                snakeY[0] = snakeY[0] - 25;
            }else if(fx.equals("d")){
                snakeY[0] = snakeY[0] + 25;
            }
            repaint();
        }
        timer.start();//启动定时器
    }
}

处理小蛇触及边界问题(小蛇在左边边界出去则从右边边界出来,上下同理),以小蛇的头部位置为基准判断小蛇的运动方向,在相应运行方向的判断函数中加入边界判断:

左边
//边界判断
if(snakeX[0] < 25){
   snakeX[0] = 850;
}

右边
//边界判断
if(snakeX[0] > 850){
   snakeX[0] = 25;
}

上面
//边界判断
if(snakeY[0] < 75){
   snakeY[0] = 658;
}

下面
 //边界判断
if(snakeY[0] > 650){
  snakeY[0] = 75;
}

初始化食物位置,在小蛇吃掉当前食物后小蛇身体长度+1,并再随机产生食物

在public class Panel extends JPanel implements KeyListener, ActionListener中定义食物变量
int foodx;
int foody;
Random random = new Random(); //生成随机位置


在public void init()初始化函数中加入
//初始化食物位置
 foodx = 25 + 25*random.nextInt(34);
 foody = 25 + 25*random.nextInt(75);


在画笔函数protected void paintComponent(Graphics g)中画出食物
 //画出食物的位置
 new ImageIcon("img/food.png").paintIcon(this, g, foodx, foody);


在小蛇运动actionPerformed(ActionEvent e) 函数中
//判断是否小蛇吃了食物(重合)
if(snakeX[0] == foodx && snakeY[0] == foody){
    length++;
    foodx = 25 + 25*random.nextInt(34);//食物被吃后重新产生随机食物
    foody = 75 + 25*random.nextInt(24);
 }

最后实现功能如下:

1、简单的贪吃蛇小游戏;

2、按下空格键开始游戏,小蛇开始运动,键盘的上下左右键控制小蛇的运动方向;

3、小蛇吃掉一个食物后随机产生下一个食物,同时小蛇的身体长度加1

4、再按下空格键游戏停止。

项目资源:Java实现贪吃蛇小游戏-Java文档类资源-优快云下载

可以运行! (以下代码只是其中的一个类) package chy.snake.entities; import java.awt.Color; import java.awt.Graphics; import java.awt.Point; import java.util.HashSet; import java.util.LinkedList; import java.util.Set; import chy.snake.listener.SnakeListener; import chy.snake.util.Global; public class Snake { public static final int up = 1; public static final int down = -1; public static final int left = -2; public static final int right = 2; private int oldDirection,newDirection; //newDirection:一次时间 间隔内输入的最后方向 private Point oldTail; private boolean life; //life 为 true或者false,初始为true, 用于118行 private LinkedList<Point> body = new LinkedList<Point> (); //需要经常访问蛇的第一个和最后一个节点,使用链表LinkedList存放蛇的身体节点,因为它有getFirst(),getLast(),removeLast(),方法 private Set<SnakeListener> listeners = new HashSet<SnakeListener>(); public Snake(){ init(); } public void init(){ //初始化 int x = Global.WIDTH/2; int y = Global.HEIGHT/2; for(int i=0;i<3;i++){ //初始长度3 body.addLast(new Point(x-i,y)); //是addLast } oldDirection = newDirection = right; //初始方向 右 life = true; } public void die(){ life = false; } public void move(){ System.out.println("Snake's move"); if (!(oldDirection + newDirection == 0)){ oldDirection = newDirection; } //1.去尾 oldTail = body.removeLast(); int x = body.getFirst().x; int y = body.getFirst().y; //蛇头的x,y坐标 switch(oldDirection){ case up: y--; break; case down: y++; break; case left: x--; break; case right: x++; break; } Point newHead = new Point(x,y); //2.加头 body.addFirst(newHead); } public void changeDirection(int direction){ /*无效方向:在蛇的这一次移动之后和下一次移动之前的 这个时间间隔内输入了多个方向,只有最后一个方向 是 有效方向,其余的都为无效方向*/ System.out.println("Snake's changeDirection"); newDirection = direction; //将一个时间间隔内按得最后方向,赋给 newDirection } public void eatFood(){ System.out.println("Snake's eatFood"); body.addLast(oldTail); //后面的节点不去掉 } public boolean isEatFood(){ System.out.println("Snake's isEatFood"); return false; } public boolean isEatBody(Snake snake){ //比较蛇是否吃到身体 System.out.println("snake's isEatBody"); for(int i= 1;i<body.size();i++){ //i 从蛇头结点的下一个节点开始,排除蛇头结点 if(body.get(i).equals(this.getHead())){ //如果i 的节点 和 头结点 相同 return true; } } return false; } public void drawMe(Graphics g){ System.out.println("Snake's drawMe"); g.setColor(Color.GREEN); //设置蛇的颜色 for(Point p : body){ g.fill3DRect(p.x * Global.CELL_SIZE, p.y * Global.CELL_SIZE, Global.CELL_SIZE, Global.CELL_SIZE, true); } } public Point getHead(){ //得到蛇头节点,判断吃食物 return body.getFirst(); } private class SnakeDriver implements Runnable{ //线程,不停的调用move方法 @Override public void run() { // TODO 自动生成的方法存根 while(life){ // 42和46行,life为true 或者false move(); for(SnakeListener l : listeners){ l.snakeMoved(Snake.this); //循环,依次调用SnakeMoved方法 } try { Thread.sleep(300); } catch (InterruptedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } } } } public void start(){ new Thread(new SnakeDriver()).start(); //启动线程的方法 } public void addSnakeListener(SnakeListener l){ if(l != null){ this.listeners.add(l); } } }
### 回答1: 这里提供一个基于Java Swing开发的简单贪吃蛇游戏代码: ``` import java.awt.Color; import java.awt.Graphics; import java.awt.Point; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.util.LinkedList; import java.util.Random; import javax.swing.JFrame; import javax.swing.JPanel; public class SnakeGame extends JPanel implements Runnable, KeyListener { private static final long serialVersionUID = 1L; // 游戏宽度 private static final int WIDTH = 500; // 游戏高度 private static final int HEIGHT = 500; // 方格小 private static final int BLOCK_SIZE = 20; // 蛇的长度 private int snakeLength = 3; // 蛇的坐标 private LinkedList<Point> snake = new LinkedList<Point>(); // 蛇的方向 private int direction = KeyEvent.VK_RIGHT; // 食物坐标 private Point food = new Point(); // 随机种子 private Random random = new Random(); // 游戏是否结束 private boolean gameOver = false; public SnakeGame() { // 初始化界面 JFrame frame = new JFrame("贪吃蛇作战"); frame.setSize(WIDTH, HEIGHT); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLocationRelativeTo(null); frame.setResizable(false); frame.addKeyListener(this); frame.add(this); frame.setVisible(true); // 初始化蛇 snake.add(new Point(2, 0)); snake.add(new Point(1, 0)); snake.add(new Point(0, 0)); // 初始化食物 generateFood(); // 启动游戏线程 Thread thread = new Thread(this); thread.start(); } @Override public void paint(Graphics g) { // 清空画布 g.clearRect(0, 0, WIDTH, HEIGHT); // 画蛇 g.setColor(Color.GREEN); for (Point p : snake) { g.fillRect(p.x * BLOCK_SIZE, p.y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE); } // 画食物 g.setColor(Color.RED); g.fillRect(food.x * BLOCK_SIZE, food.y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE); // 画分数 g.setColor(Color.BLACK); g.drawString("分数:" + (snakeLength - 3), 10, 20); // 画游戏结束提示 if (gameOver) { g.setColor(Color.RED); g.drawString("游戏结束!", WIDTH / 2 - 30, HEIGHT / 2); } } @Override public void run() { while (!gameOver) { try { // 控制游戏速度 Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } // 移动蛇 moveSnake(); // 判断是否吃到食物 if (snake.getFirst().equals(food)) { snakeLength++; generateFood(); } // 判断是否撞到墙或自己 if (snake.getFirst().x < 0 || snake.getFirst().x >= WIDTH / BLOCK_SIZE || snake.getFirst().y < 0 || snake.getFirst().y >= HEIGHT / BLOCK_SIZE || snake.contains(snake.getFirst())) { gameOver = true; } // 重绘界面 repaint(); } } @Override public void keyPressed(KeyEvent e) { // 更新蛇的方向 if (e.getKeyCode() == KeyEvent.VK_UP && direction != KeyEvent.VK_DOWN) { direction = KeyEvent.VK_UP; } else if (e.getKeyCode() == KeyEvent.VK_DOWN && direction != KeyEvent.VK_UP) { direction = KeyEvent.VK_DOWN; } else if (e.getKeyCode() == KeyEvent.VK_LEFT && direction != KeyEvent.VK_RIGHT) { direction = KeyEvent.VK_LEFT; } else if (e.getKeyCode() == KeyEvent.VK_RIGHT && direction != KeyEvent.VK_LEFT) { direction = KeyEvent.VK_RIGHT; } } @Override public void keyTyped(KeyEvent e) { } @Override public void keyReleased(KeyEvent e) { } // 移动蛇 private void moveSnake() { int x = snake.getFirst().x; int y = snake.getFirst().y; switch (direction) { case KeyEvent.VK_UP: y--; break; case KeyEvent.VK_DOWN: y++; break; case KeyEvent.VK_LEFT: x--; break; case KeyEvent.VK_RIGHT: x++; break; } snake.addFirst(new Point(x, y)); if (snake.size() > snakeLength) { snake.removeLast(); } } // 生成食物 private void generateFood() { while (true) { int x = random.nextInt(WIDTH / BLOCK_SIZE); int y = random.nextInt(HEIGHT / BLOCK_SIZE); food.setLocation(x, y); if (!snake.contains(food)) { break; } } } public static void main(String[] args) { new SnakeGame(); } } ``` 以上代码仅提供参考,可以根据自己的需求进行修改和完善。 ### 回答2: Java贪吃蛇作战代码是一段用Java语言编写的程序,实现了经典游戏“贪吃蛇作战”。 首先,程序需要定义蛇的属性,比如蛇的位置、尺寸、速度以及方向等信息。通过一个数组或者链表来保存蛇的身体坐标,每个节点表示蛇身体的一个部分。还需要定义食物的属性,比如食物的位置和小。 接下来,程序需要监听玩家的输入,根据玩家的操作来改变蛇的方向:向上、向下、向左或向右移动。可以使用键盘事件监听,通过按键的keyCode来确定操作。 然后,程序需要实现蛇的移动逻辑。蛇向前移动时,身体的每一节都要跟着移动,并且新增加的食物会被蛇吃掉,使得蛇的身体变长。当蛇的头部与身体相撞或者撞墙时,游戏结束。 在游戏进行时,程序需要不断更新屏幕上的蛇和食物的位置,以及判断蛇是否吃到食物,如果吃到了则生成新的食物。可以使用定时器或者循环来实现游戏的更新和渲染。 最后,当游戏结束时,可以显示游戏结束的提示信息,比如游戏得分、最高分等。 总结来说,Java贪吃蛇作战代码是通过定义蛇和食物的属性,监听玩家输入,实现蛇的移动逻辑,并在游戏进行时不断更新屏幕上的内容,最后展示游戏结束信息的一段Java程序。编写这样的代码可以锻炼编程能力,并且可以在游戏中体验到程序设计的乐趣。 ### 回答3: 在Java贪吃蛇作战代码中,首先需要创建一个贪吃蛇的类。这个类包含贪吃蛇的身体坐标、移动方向和长度等属性。在游戏开始时,需要初始化贪吃蛇的位置和长度。 然后,我们需要实现游戏的主循环。在每一轮循环中,根据用户输入或者预设的策略改变贪吃蛇的移动方向,并且根据贪吃蛇当前位置和移动方向计算下一步的位置。如果下一步的位置是食物的位置,那么贪吃蛇的长度加一,并且在地图上生成一个新的食物。如果下一步的位置是地图边界或者贪吃蛇自身的位置,那么游戏结束。 游戏的地图可以使用二维数组来表示,每个元素的值表示该位置的状态,比如空白、贪吃蛇的身体或者食物。 为了让游戏有更好的可玩性,我们可以添加一些额外的功能。比如,在地图上随机生成障碍物,让贪吃蛇在遇到障碍物时无法通过。我们还可以设计多个关卡和不同的游戏模式,让玩家可以选择不同的难度或者挑战各种挑战。此外,我们还可以添加一些特殊道具,比如加速、减速或者变换方向等,让游戏更加有趣。 最后,我们需要实现一些图形界面交互,比如显示地图和贪吃蛇,监听键盘事件来改变贪吃蛇的移动方向。如果有条件的话,我们还可以将游戏进行网络化,实现多人联机对战,让玩家可以与其他玩家进行对战和竞争。 总之,Java贪吃蛇作战代码需要实现贪吃蛇的移动、长度增加、判断游戏结束等基本功能,并可以通过添加障碍物、地图关卡、道具等来增加游戏的可玩性和趣味性。同时,还可以实现图形界面和网络对战等功能来提供更好的游戏体验。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值