贪吃蛇 Java

从b站找了视频,试着写了以下,但是还是有些问题,以下是代码:

package snake.com.qust;

import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.LinkedList;
import javax.swing.*;
import java.util.Random;
import java.util.TimerTask;
import java.util.Timer;
//蛇是由节点构成的集合,每个节点由横纵坐标确定
//先创建节点类
class Jiedian{
private int x;
private int y;
public Jiedian(){}
public Jiedian(int x,int y) {
this.x = x;
this.y = y;
}
public void setX(int x) {
this.x = x;
}
public int getX() {
return x;
}
public void setY(int y) {
this.y = y;
}
public int getY() {
return y;
}
public void random(){//随机生成位置
Random r=new Random();
//随机生成横纵坐标
this.x=r.nextInt(30);
this.y=r.nextInt(30);
}
}
//枚举:用几个固定的单词来表示一些常量
enum Direction{
UP,DOWN,LEFT,RIGHT; //上下左右
}
class Snake{
//用LinkedList集合存放节点,构成蛇身
private LinkedList<Jiedian> body;
//默认蛇的运动方向是朝左运动
private Direction direction = Direction.LEFT;
//定义蛇是否活着
public boolean isLiving = true;
private Demo_game game; // 能让Snake类引用Demo_game类
public Snake(Demo_game game) {
this.game = game;
initSnake();
}
public Snake() {
//初始化蛇的身体
initSnake();
}

private void initSnake() {
//创建集合
body = new LinkedList<>();
//先创建6个节点,添加到集合中
body.add(new Jiedian(11, 15));
body.add(new Jiedian(12, 15));
body.add(new Jiedian(13, 15));
body.add(new Jiedian(14, 15));
body.add(new Jiedian(15, 15));
body.add(new Jiedian(16, 15));
}

public LinkedList<Jiedian> getBody() {
return body;
}

public void setBody(LinkedList<Jiedian> body) {
this.body = body;
}
public boolean isLiving() {
return isLiving;
}
public Direction getDirection() {
return direction;
}

public void setDirection(Direction direction) {
this.direction = direction;
}

//移动:沿着蛇头的方向进行移动
public void move() {
if(!isLiving){
return;
}
if (isLiving) {
Jiedian head = body.getFirst();
switch (direction) {
case UP:
//在蛇头的上面添加一个节点
body.addFirst(new Jiedian(head.getX(), head.getY() - 1));
break;
case DOWN:
body.addFirst(new Jiedian(head.getX(), head.getY() + 1));
break;
case LEFT:
body.addFirst(new Jiedian(head.getX() - 1, head.getY()));
break;
case RIGHT:
body.addFirst(new Jiedian(head.getX() + 1, head.getY()));
break;
}
//删除最后一个节点
body.removeLast();
//碰撞检测

//判断蛇是否撞墙
head = body.getFirst();
if (head.getX() < 0 || head.getY() < 0 || head.getX() >= 30 || head.getY() >= 30) {
isLiving = false;
}
//判断蛇是否碰到自己的身体
for (int i = 1; i < body.size(); i++) {
Jiedian jiedian = body.get(i);
if (head.getX() == jiedian.getX() && head.getY() == jiedian.getY()) {
isLiving = false;
}
}
}
}

public void eat(Jiedian food) {
Jiedian head = body.getFirst();
switch (direction) {
case UP:
//在蛇头的上面添加一个节点
body.addFirst(new Jiedian(head.getX(), head.getY() - 1));
break;
case DOWN:
body.addFirst(new Jiedian(head.getX(), head.getY() + 1));
break;
case LEFT:
body.addFirst(new Jiedian(head.getX() - 1, head.getY()));
break;
case RIGHT:
body.addFirst(new Jiedian(head.getX() + 1, head.getY()));
break;
}

}
}
class Score{
//记录得分
private int score; // 定义玩家得分
public Score() {
score = 0;
}
public void increaseScore() {
score++;
}
public int getScore() {
return score;
}
// 绘制得分的方法
public void drawscore(Graphics g, int x, int y) {
g.drawString("Score: " + score, x, y);
}
}
class GameState{
//管理游戏的开始、暂停、结束;重新开始游戏
private boolean isStarted;
private boolean isPaused;
public GameState() {
isStarted = false;
isPaused = false;
}
public void startGame() {
isStarted = true;
isPaused = false;
}
public void pauseGame() {
isPaused = true;
}
public void resumeGame() {
isPaused = false;
}
public void endGame() {
isStarted = false;
isPaused = false;
}
public boolean isGameStarted() {
return isStarted && !isPaused;
}
public boolean isGamePaused() {
return isPaused;
}

}
//添加音效
public class Demo_game extends JFrame{//继承窗口类
private Snake snake=new Snake();//成员变量 蛇
private JPanel jPanel;//游戏棋盘
private Timer timer;//定时器:让蛇进行移动
private Jiedian food;//食物
private Score score=new Score();//玩家得分
private GameState gameState=new GameState();//游戏状态
private JButton restartButton;//添加按钮来重新开始游戏
public Demo_game() throws HeadlessException {//构造方法进行初始化
//初始化窗口参数
initFrame();
//初始化游戏棋盘
initGamePanel();
//初始化蛇
initSnake();
//初始化食物
initFood();
//初始化游戏状态
gameState.startGame();
//初始化定时器
initTimer();
//设置键盘监听
setKeyListener();
//添加重新开始按钮
addRestartButton();
}
private void initFood(){
food=new Jiedian();
food.random();
}
private void setKeyListener(){
addKeyListener(new KeyAdapter() {
//当键盘按下时,会自动调用此方法
@Override
public void keyPressed(KeyEvent e) {
super.keyPressed(e);
//键盘中的一个键都有一个编号 左37 上40 右39 下38,根据编号确定上下左右键
switch(e.getKeyCode()){
case KeyEvent.VK_UP:
if(snake.getDirection()!=Direction.DOWN) {
snake.setDirection(Direction.UP);
}
break;
case KeyEvent.VK_DOWN:
if(snake.getDirection()!=Direction.UP) {
snake.setDirection(Direction.DOWN);
}
break;
case KeyEvent.VK_LEFT:
if(snake.getDirection()!=Direction.RIGHT) {
snake.setDirection(Direction.LEFT);
}
break;
case KeyEvent.VK_RIGHT:
if(snake.getDirection()!=Direction.LEFT) {
snake.setDirection(Direction.RIGHT);
}
break;
}
}
});
}
//初始化定时器
private void initTimer(){
timer = new Timer();
//初始化定时任务
TimerTask timerTask=new TimerTask() {
@Override
public void run() {
//判断蛇头是否和食物重合
if(gameState.isGameStarted()){
snake.move();
if(snake.getBody().getFirst().getX()== food.getX()&&snake.getBody().getFirst().getY()==food.getY() ){
score.increaseScore();//增加分数
snake.eat(food);
food.random();
}
if(!snake.isLiving()){
timer.cancel();
gameState.endGame();
}
//重绘游戏棋盘
jPanel.repaint();
}
}
};
//每200毫秒调用定时任务,改变蛇的运动速度,时间越长,速度越慢
timer.scheduleAtFixedRate(timerTask,0,200);
}
//初始化蛇
private void initSnake(){
snake=new Snake();
}
//初始化窗口参数
private void initFrame(){
//设置窗口的宽高大小
setSize(630,630);
//设置窗口的位置
setLocation(400,100);
//设置关闭按钮
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//设置窗口大小不变动
setResizable(false);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
timer.cancel();
gameState.endGame();
System.exit(0);
}
});
}
//初始化游戏棋盘
private void initGamePanel(){
jPanel=new JPanel(){
//绘制棋盘内容
@Override
public void paintComponent(Graphics g) {//Graphics g可看作是一个画笔,用来绘制游戏中的蛇和食物等
super.paintComponent(g);
if (gameState.isGameStarted()) {
g.clearRect(0, 0, 620, 630);

//清空棋盘
g.clearRect(0, 0, 620, 620);
//绘制棋盘网格,每一格是20小方格
//绘制31条横线,0-30共31条
for (int i = 0; i <= 30; i++) {
g.drawLine(0, i * 20, 620, i * 20);
}
//绘制31条竖线
for (int i = 0; i <= 30; i++) {
g.drawLine(i * 20, 0, i * 20, 620);
}
//绘制蛇
LinkedList<Jiedian> body = snake.getBody();
for (Jiedian jiedian : body) {
g.fillRect(jiedian.getX() * 20, jiedian.getY() * 20, 20, 20);
}
//绘制食物
g.fillRect(food.getX() * 20, food.getY() * 20, 20, 20);
//绘制分数
score.drawscore(g, 30, 20);
}else{
g.setColor(Color.RED);
g.setFont(new Font("Serif",Font.BOLD,24));
g.drawString("Game Over",250,200);
drawRestartButton(g);
}
}
};
add(jPanel);
}
public void drawRestartButton(Graphics g){
int buttonWidth = 100;
int buttonHeight = 30;
int buttonX = 250;//按钮位置
int buttonY = 300;
g.setColor(Color.WHITE);
g.fillRect(buttonX, buttonY, buttonWidth, buttonHeight);
g.setColor(Color.BLACK);
g.drawString("Restart", buttonX+15 , buttonY +15);
}
public void addRestartButton(){
restartButton=new JButton("Restart");
restartButton.addActionListener(e -> restartGame());
jPanel.add(restartButton);
restartButton.setVisible(false);
}
public void restartGame() {
snake = new Snake(this); // 重置蛇
food = new Jiedian(); // 重置食物位置
food.random();
score = new Score(); // 重置得分
gameState.endGame();
gameState.startGame();
jPanel.remove(restartButton); // 移除旧的按钮
add(jPanel); // 重新添加 jPanel 以清除旧的绘制内容
addRestartButton(); // 添加新的按钮
jPanel.repaint();
}
public static void main(String[]args){
//创建窗口对象,并显示运行
new Demo_game().setVisible(true);
}
}

这段代码写的过程有挺多问题的,但最后都解决了,但我想加一个贪吃蛇死后重新开始的按钮,但怎么也不行。

最后的主要问题是最后重新开始的按钮不能点击,想问问到底是哪里出的问题,应该具体怎么解决?我认为是这一块出的问题:public void addRestartButton(){
restartButton=new JButton("Restart");
restartButton.addActionListener(e -> restartGame());
jPanel.add(restartButton);
restartButton.setVisible(false);
}
public void restartGame() {
snake = new Snake(this); // 重置蛇
food = new Jiedian(); // 重置食物位置
food.random();
score = new Score(); // 重置得分
gameState.endGame();
gameState.startGame();
jPanel.remove(restartButton); // 移除旧的按钮
add(jPanel); // 重新添加 jPanel 以清除旧的绘制内容
addRestartButton(); // 添加新的按钮
jPanel.repaint();
}
有运行结果的截图:

 

 

  • 14
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值