java贪吃蛇难度设计_Java贪吃蛇应用的设计与实现

今天来实现一个简单的贪吃蛇应用,效果如下:

GameController的作用

你已经可以根据一个Grid画出来游戏界面了,接下来就要开始处理用户的按键输入了。

还记得总体设计概览图吗们已经实现了大部分的类,也增加了一些新的类,现在应该是这个样子了:

这里要再次提高MVC模式,系统可以分为三个部分,模型(Model)、视图(View)和控制器(Controller):Model:业务功能、核心数据结构与算法,对应蓝色部分

View:负责界面显示,对应黄色部分

Controller:负责转发用户操作事件,对事件进行处理,对应红色部分

模型和视图已经基本完成了,我们在界面中画出了贪吃蛇以及它的食物,现在,让我们学习如何通过键盘操作让贪吃蛇动起来。这就需要GameController粉墨登场了。

接收键盘事件

首先我们需要一个按键监听器,当玩家敲击键盘的时候,就可以通过按键监听器知道玩家敲击了什么按键。

Java已经为我们提供好了键盘监听的接口,其接口定义如下:

public interface KeyListener extends EventListener {

public void keyPressed(KeyEvent e);

public void keyReleased(KeyEvent e);

public void keyTyped(KeyEvent e);

}

Java将键盘输入分成了三个步骤,按下(press),释放(release),键入(type),对应了KeyListener的三个方法:keyPressed: 按下某个键时会调用该方法

keyReleased: 释放某个键时会调用该方法

keyTyped: 键入某个键时会调用该方法

我们只需要让GameController实现该接口,即可完成一个按键监听器的实现:

public class GameController implements KeyListener {

@Override

public void keyPressed(KeyEvent e) {

// 这里处理按键

}

@Override

public void keyReleased(KeyEvent e) {

}

@Override

public void keyTyped(KeyEvent e) {

}

}

keyReleased()和keyTyped()方法不需要用到,我们只需要在keyPressed()方法中进行事件处理。

这样GameController就可以我们的游戏控制中心,我们可以通过它监听键盘并实现对界面的控制,

当然,我们需要通过下列语句在SnakeApp进行init()初始化时将GameController注册进window中:

SnakeApp.java

window.addKeyListener(gameController);

处理键盘事件

现在贪吃蛇还不能自动动起来,因此我们先让贪吃蛇接收到一个方向键时,就进行移动。所以keyPressed()方法的核心逻辑是:收到按键事件

根据按键情况,做一次移动

移动后重现显示界面

比如处理向上移动的代码逻辑如下:

public class GameController implements KeyListener {

@Override

public void keyPressed(KeyEvent e) {

int keyCode = e.getKeyCode();

if (keyCode == KeyEvent.VK_UP) {

grid.changeDirection(Direction.UP);

}

// repaint the canvas

}

}

处理好所有影响游戏状态的事件,你已经拥有了一只跟着你按键移动的贪吃蛇,不过你不按键它是静止不动的,你离完成一个完整的贪吃蛇游戏只差最后一步了。

如何让贪吃蛇移动起来

让贪吃蛇不断地移动,一个直观的处理方式是,在一个while循环中不断调用Grid.nextRound()方法:

while (running) {

grid.nextRound();

}

不过每次调用nextRound()之间需要有一个时间间隔,需要给游戏玩家反应时间来在下一次移动之前进行操作,比如改变方向。

这时就可以使用Thread.sleep()方法来让当前的执行暂时停止:

while (running) {

try {

Thread.sleep(Settings.DEFAULT_MOVE_INTERVAL);

} catch (InterruptedException e) {

break;

}

grid.nextRound();

}

Settings.DEFAULT_MOVE_INTERVAL的值为200,这样玩家每一次移动有0.2秒的时间来进行操作。

上面这段代码显然需要在一个新的线程中跑,否则其他线程就可能被影响,比如在接收用户输入的线程中跑这段代码的话,就无法接收用户输入了,因为都在那Sleep了。

实现游戏线程

要实现游戏线程,其实就是把第一节中的while循环代码放入到一个线程类的run()方法中。

那么哪个类适合作为线程类呢个线程里不断调用Grid.nextRun()方法,并且还要即时地更新界面,显然这也是术语GameController的职责,所以让GameController实现Runnable接口,让它成为一个线程类。

同时为了控制一次游戏是否结束,增加一个boolean类型的标志running。

public class GameController implements Runnable, KeyListener {

private final Grid grid;

private final GameView gameView;

private boolean running;

public GameController(Grid grid, GameView gameView) {

this.grid = grid;

this.gameView = gameView;

this.running = true;

}

@Override

public void run() {

while (running) {

try {

Thread.sleep(Settings.DEFAULT_MOVE_INTERVAL);

} catch (InterruptedException e) {

break;

}

// 进入游戏下一步

// 如果结束,则退出游戏

// 如果继续,则绘制新的游戏页面

}

running = false;

}

}

run()函数中的核心逻辑是典型的控制器(Controller)逻辑:修改模型(Model):调用Grid的方法使游戏进入下一步

更新视图(View):调用GameView的方法刷新页面

我们可以给GameView增加一个结束游戏时的处理方法,可以在run()方法中调用:

public void showGameOverMessage() {

JOptionPane.showMessageDialog(null, “游戏结束”, “游戏结束”, JOptionPane.INFORMATION_MESSAGE);

}

这里简单弹出一个显示游戏结束信息的对话框。

启动线程

如何启动线程呢nakeApp的init()方法中增加一条语句即可:

gameController = new GameController(grid, gameView);

window.addKeyListener(gameController);

// 启动线程

new Thread(gameController).start();

EDT(Event Dispatching Thread,字面上翻译成“事件分配线程”)是Java GUI应用中的一个线程,这个线程管理着所有SWING GUI事件和整个UI界面。我们对UI相关的修改都应该放到EDT中。

我们将SnakeApp也实现Runnable接口,init()方法更名为run()方法。

在main函数中添加启动代码:

public static void main(String[] args) {

SwingUtilities.invokeLater(new SnakeApp());

}

在GameController中对UI的修改也应该通过SwingUtilities.invokeLater()方法来完成。

至此,一个完整的贪吃蛇游戏就搞定了。

需要注意的是,多线程程序往往涉及到线程同步的问题,多个线程同时访问一个变量会影响业务逻辑时,就需要专门的同步处理。在贪吃蛇应用中,事件处理线程和现在实现的GameController线程都会访问Grid的direction变量,只不过访问和修改的顺序对游戏并没有什么影响,所以我们可以不做同步处理。

更进一步

如果你希望更进一步地优化贪吃蛇应用,现在的应用已经非常好扩展了,比如:积分功能:可以创建得分规则的类(模型类的一部分), 在GameController的run()方法中计算得分

变速功能:比如加速功能,减速功能,可以在GameController的keyPressed()方法中针对特定的按键设置每一次移动之间的时间间隔,将Thread.sleep(Settings.DEFAULT_MOVE_INTERVAL);替换为动态的时间间隔即可

更漂亮的游戏界面:修改GameView中的drawXXX方法,比如可以将食物渲染为一张图片,Graphics有drawImage方法

如果希望更多了解Swing编程,则可以在游戏界面上增加更多的组件,比如积分的Lable和启动结束的按钮等

所以贪吃蛇应用非常适合入门Java编程的同学。可以了解用面向对象的方式来编程解决问题,学习如何设计类,如何选择数据结构、Java Swing编程和多线程编程的基础知识。这中间也涉及很多Java编程经常碰到的问题,比如匿名类和回调方法等,你会发现你对于Java SE编程会有更深入的掌握。

想进一步深入了解贪吃蛇应用的更多细节知识,请阅读完整的教程

java贪吃蛇难度设计_Java贪吃蛇应用的设计与实现

小编重点推荐:

更多精彩内容请访问天码营 站

文章知识点与官方知识档案匹配,可进一步学习相关知识Java技能树首页概览93751 人正在系统学习中 相关资源:snake:蛇-恶意软件存储动物园-其它代码类资源-CSDN文库

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2020年11月16日
下一篇 2020年11月16日

相关推荐