96编辑器旗下产品
找图
终身
ID:0
到期时间:永久
退出登录
您的位置:首页 > 百科管理 > 详情

贪吃蛇素材图片java-java贪吃蛇原理

原创:找图网 2023-04-24 17:18:32
  • 我想求一个Java编写的贪吃蛇游戏,要有注释和流程图最好

  • 用MVC方式实现的贪吃蛇游戏,共有4个类。运行GreedSnake运行即可。主要是观察者模式的使用,我已经添加了很多注释了。

    1、

    /*

    * 程序名称:贪食蛇

    * 原作者:BigF

    * 修改者:algo

    * 说明:我以前也用C写过这个程序,现在看到BigF用Java写的这个,发现虽然作者自称是Java的初学者,

    * 但是明显编写程序的素养不错,程序结构写得很清晰,有些细微得地方也写得很简洁,一时兴起之

    * 下,我认真解读了这个程序,发现数据和表现分开得很好,而我近日正在学习MVC设计模式,

    * 因此尝试把程序得结构改了一下,用MVC模式来实现,对源程序得改动不多。

    * 我同时也为程序增加了一些自己理解得注释,希望对大家阅读有帮助。

    */

    package mvcTest;

    /**

    * @author WangYu

    * @version 1.0

    * Description:

    * </pre>

    * Create on :Date :2005-6-13 Time:15:57:16

    * LastModified:

    * History:

    */

    public class GreedSnake {

    public static void main(String[] args) {

    SnakeModel model = new SnakeModel(20,30);

    SnakeControl control = new SnakeControl(model);

    SnakeView view = new SnakeView(model,control);

    //添加一个观察者,让view成为model的观察者

    (view);

    (new Thread(model)).start();

    }

    }

    -------------------------------------------------------------

    2、

    package mvcTest;

    //

    import ;

    import ;

    /**

    * MVC中的Controler,负责接收用户的操作,并把用户操作通知Model

    */

    public class SnakeControl implements KeyListener{

    SnakeModel model;

    public SnakeControl(SnakeModel model){

    = model;

    }

    public void keyPressed(KeyEvent e) {

    int keyCode = e.getKeyCode();

    if (){ // 运行状态下,处理的按键

    switch (keyCode) {

    case _UP:

    ();

    break;

    case _DOWN:

    ();

    break;

    case _LEFT:

    ();

    break;

    case _RIGHT:

    ();

    break;

    case _ADD:

    case _PAGE_UP:

    ();

    break;

    case _SUBTRACT:

    case _PAGE_DOWN:

    ();

    break;

    case _SPACE:

    case _P:

    ();

    break;

    default:

    }

    }

    // 任何情况下处理的按键,按键导致重新启动游戏

    if (keyCode == _R ||

    keyCode == _S ||

    keyCode == _ENTER) {

    ();

    }

    }

    public void keyReleased(KeyEvent e) {

    }

    public void keyTyped(KeyEvent e) {

    }

    }

    -------------------------------------------------------------

    3、

    /*

    *

    */

    package mvcTest;

    /**

    * 游戏的Model类,负责所有游戏相关数据及运行

    * @author WangYu

    * @version 1.0

    * Description:

    * </pre>

    * Create on :Date :2005-6-13 Time:15:58:33

    * LastModified:

    * History:

    */

    //

    import .*;

    import ;

    import ;

    import ;

    import ;

    /**

    * 游戏的Model类,负责所有游戏相关数据及运行

    */

    class SnakeModel extends Observable implements Runnable {

    boolean[][] matrix; // 指示位置上有没蛇体或食物

    LinkedList nodeArray = new LinkedList(); // 蛇体

    Node food;

    int maxX;

    int maxY;

    int direction = 2; // 蛇运行的方向

    boolean running = false; // 运行状态

    int timeInterval = 200; // 时间间隔,毫秒

    double speedChangeRate = 0.75; // 每次得速度变化率

    boolean paused = false; // 暂停标志

    int score = 0; // 得分

    int countMove = 0; // 吃到食物前移动的次数

    // UP and DOWN should be even

    // RIGHT and LEFT should be odd

    public static final int UP = 2;

    public static final int DOWN = 4;

    public static final int LEFT = 1;

    public static final int RIGHT = 3;

    public SnakeModel( int maxX, int maxY) {

    = maxX;

    = maxY;

    reset();

    }

    public void reset(){

    direction = ; // 蛇运行的方向

    timeInterval = 200; // 时间间隔,毫秒

    paused = false; // 暂停标志

    score = 0; // 得分

    countMove = 0; // 吃到食物前移动的次数

    // initial matirx, 全部清0

    matrix = new boolean[maxX][];

    for (int i = 0; i < maxX; ++i) {

    matrix[i] = new boolean[maxY];

    (matrix[i], false);

    }

    // initial the snake

    // 初始化蛇体,如果横向位置超过20个,长度为10,否则为横向位置的一半

    int initArrayLength = maxX > 20 ? 10 : maxX / 2;

    ();

    for (int i = 0; i < initArrayLength; ++i) {

    int x = maxX / 2 + i;//maxX被初始化为20

    int y = maxY / 2; //maxY被初始化为30

    //nodeArray[x,y]: [10,15]-[11,15]-[12,15]~~[20,15]

    //默认的运行方向向上,所以游戏一开始nodeArray就变为:

    // [10,14]-[10,15]-[11,15]-[12,15]~~[19,15]

    (new Node(x, y));

    matrix[x][y] = true;

    }

    // 创建食物

    food = createFood();

    matrix[food.x][food.y] = true;

    }

    public void changeDirection(int newDirection) {

    // 改变的方向不能与原来方向同向或反向

    if (direction % 2 != newDirection % 2) {

    direction = newDirection;

    }

    }

    /**

    * 运行一次

    * @return

    */

    public boolean moveOn() {

    Node n = (Node) ();

    int x = n.x;

    int y = n.y;

    // 根据方向增减坐标值

    switch (direction) {

    case UP:

    y--;

    break;

    case DOWN:

    y++;

    break;

    case LEFT:

    x--;

    break;

    case RIGHT:

    x++;

    break;

    }

    // 如果新坐标落在有效范围内,则进行处理

    if ((0 <= x && x < maxX) && (0 <= y && y < maxY)) {

    if (matrix[x][y]) { // 如果新坐标的点上有东西(蛇体或者食物)

    if (x == food.x && y == food.y) { // 吃到食物,成功

    (food); // 从蛇头赠长

    // 分数规则,与移动改变方向的次数和速度两个元素有关

    int scoreGet = (10000 - 200 * countMove) / timeInterval;

    score += scoreGet > 0 ? scoreGet : 10;

    countMove = 0;

    food = createFood(); // 创建新的食物

    matrix[food.x][food.y] = true; // 设置食物所在位置

    return true;

    } else // 吃到蛇体自身,失败

    return false;

    } else { // 如果新坐标的点上没有东西(蛇体),移动蛇体

    (new Node(x, y));

    matrix[x][y] = true;

    n = (Node) ();

    matrix[n.x][n.y] = false;

    countMove++;

    return true;

    }

    }

    return false; // 触到边线,失败

    }

    public void run() {

    running = true;

    while (running) {

    try {

    (timeInterval);

    } catch (Exception e) {

    break;

    }

    if (!paused) {

    if (moveOn()) {

    setChanged(); // Model通知View数据已经更新

    notifyObservers();

    } else {

    (null,

    "you failed",

    "Game Over",

    _MESSAGE);

    break;

    }

    }

    }

    running = false;

    }

    private Node createFood() {

    int x = 0;

    int y = 0;

    // 随机获取一个有效区域内的与蛇体和食物不重叠的位置

    do {

    Random r = new Random();

    x = r.nextInt(maxX);

    y = r.nextInt(maxY);

    } while (matrix[x][y]);

    return new Node(x, y);

    }

    public void speedUp() {

    timeInterval *= speedChangeRate;

    }

    public void speedDown() {

    timeInterval /= speedChangeRate;

    }

    public void changePauseState() {

    paused = !paused;

    }

    public String toString() {

    String result = "";

    for (int i = 0; i < (); ++i) {

    Node n = (Node) (i);

    result += "[" + n.x + "," + n.y + "]";

    }

    return result;

    }

    }

    class Node {

    int x;

    int y;

    Node(int x, int y) {

    this.x = x;

    this.y = y;

    }

    }

    ------------------------------------------------------------

    4、

    package mvcTest;

    //

    import .*;

    import .*;

    import ;

    import ;

    import ;

    import ;

    /**

    * MVC模式中得Viewer,只负责对数据的显示,而不用理会游戏的控制逻辑

    */

    public class SnakeView implements Observer {

    SnakeControl control = null;

    SnakeModel model = null;

    JFrame mainFrame;

    Canvas paintCanvas;

    JLabel labelScore;

    public static final int canvasWidth = 200;

    public static final int canvasHeight = 300;

    public static final int nodeWidth = 10;

    public static final int nodeHeight = 10;

    public SnakeView(SnakeModel model, SnakeControl control) {

    = model;

    = control;

    mainFrame = new JFrame("GreedSnake");

    Container cp = ();

    // 创建顶部的分数显示

    labelScore = new JLabel("Score:");

    (labelScore, );

    // 创建中间的游戏显示区域

    paintCanvas = new Canvas();

    (canvasWidth + 1, canvasHeight + 1);

    (control);

    (paintCanvas, );

    // 创建底下的帮助栏

    JPanel panelButtom = new JPanel();

    (new BorderLayout());

    JLabel labelHelp;

    labelHelp = new JLabel("PageUp, PageDown for speed;", );

    (labelHelp, );

    labelHelp = new JLabel("ENTER or R or S for start;", );

    (labelHelp, );

    labelHelp = new JLabel("SPACE or P for pause", );

    (labelHelp, );

    (panelButtom, );

    (control);

    ();

    (false);

    (_ON_CLOSE);

    (true);

    }

    void repaint() {

    Graphics g = ();

    //draw background

    g.setColor();

    g.fillRect(0, 0, canvasWidth, canvasHeight);

    // draw the snake

    g.setColor();

    LinkedList na = ;

    Iterator it = ();

    while (()) {

    Node n = (Node) ();

    drawNode(g, n);

    }

    // draw the food

    g.setColor();

    Node n = ;

    drawNode(g, n);

    updateScore();

    }

    private void drawNode(Graphics g, Node n) {

    g.fillRect(n.x * nodeWidth,

    n.y * nodeHeight,

    nodeWidth - 1,

    nodeHeight - 1);

    }

    public void updateScore() {

    String s = "Score: " + ;

    (s);

    }

    public void update(Observable o, Object arg) {

    repaint();

    }

    }

  • 急啊!Java大神帮忙,我用Java做的贪吃蛇,但是方向键不可以控制,怎么回事啊

  • 从你的代码来看,方向键的监听是正常的,可以控制,只是你没有创建一个线程来执行蛇的移动,使得整个执行为单线程,所以蛇移动时按键是不会有反应,只有结束后才在控制台显示。

  • java贪吃蛇原理

  • 楼主没有看到蛇移动的本质,蛇虽然是分成很多块,但他们还是一个整体,每一块的移动都和上一块有关,所以不需要对每一块都进行判断。

    原理:

    把蛇身体的每一块看成一个对象(对象存储该块的坐标和相关信息),作为节点存储在线性链表中,再设置一个变量标志蛇的方向(通过按键可以改变)。一般人都是让每一个节点等于他指向的下一个节点,并让头节点改变位置来实现转弯和移动,这个算法复杂度太高(O(n)),实际上只要做两步操作,插入一个头节点,删除一个尾节点就可以了,新插入的头节点位置根据蛇当前的方向决定

    最新文章 更多
    最新素材 更多
    公司介绍 网站地图 图片资讯
    Copyright © 2010-2022 山东找图网络科技有限公司  鲁ICP备18007836号-3  邮箱:15653358549@163.com