Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 342|回复: 0

[Java游戏学习]我MVC改写的贪食蛇小游戏

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-10-14 19:59:41 | 显示全部楼层 |阅读模式
    程序运行图:
      
      
       
       
         
       

       
       
      
      // GreedSnake.java
    /**
      * 程序名称:贪食蛇
      * 原作者:BigF
      * 修改者:algo
      * 说明:我以前也用C写过这个程序,现在看到BigF用Java写的这个,发现虽然作者自称是Java的初学者,
      *      但是明显编写程序的素养不错,程序结构写得很清晰,有些细微得地方也写得很简洁,一时兴起之
      *      下,我认真解读了这个程序,发现数据和表现分开得很好,而我近日正在学习MVC设计模式,
      *      因此尝试把程序得结构改了一下,用MVC模式来实现,对源程序得改动不多。
      *      我同时也为程序增加了一些自己理解得注释,希望对大家阅读有帮助。
      */
    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);
             model.addObserver(view);
             (new Thread(model)).start();
         }
    }

    //----------------------------------------------------------------------
    // SnakeModel.java
    import javax.swing.*;
    import java.util.Arrays;
    import java.util.LinkedList;
    import java.util.Observable;
    import java.util.Random;

    /**
      * 游戏的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) {
             this.maxX = maxX;
             this.maxY = maxY;

             reset();
         }

         public void reset(){
             direction = SnakeModel.UP;                          // 蛇运行的方向
             timeInterval = 200;                     // 时间间隔,毫秒
             paused = false;                     // 暂停标志
             score = 0;                              // 得分
             countMove = 0;                          // 吃到食物前移动的次数

             // initial matirx, 全部清0
             matrix = new boolean[maxX][];
             for (int i = 0; i < maxX; ++i) {
                 matrix = new boolean[maxY];
                 Arrays.fill(matrix, false);
             }

             // initial the snake
             // 初始化蛇体,如果横向位置超过20个,长度为10,否则为横向位置的一半
             int initArrayLength = maxX > 20 ? 10 : maxX / 2;
             nodeArray.clear();
             for (int i = 0; i < initArrayLength; ++i) {
                 int x = maxX / 2 + i;
                 int y = maxY / 2;
                 nodeArray.addLast(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) nodeArray.getFirst();
             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) {       // 吃到食物,成功
                         nodeArray.addFirst(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 {                        // 如果新坐标的点上没有东西(蛇体),移动蛇体
                     nodeArray.addFirst(new Node(x, y));
                     matrix[x][y] = true;
                     n = (Node) nodeArray.removeLast();
                     matrix[n.x][n.y] = false;
                     countMove++;
                     return true;
                 }
             }
             return false;                                   // 触到边线,失败
         }

         public void run() {
             running = true;
             while (running) {
                 try {
                     Thread.sleep(timeInterval);
                 } catch (Exception e) {
                     break;
                 }

                 if (!paused) {
                     if (moveOn()) {
                         setChanged();           // Model通知View数据已经更新
                         notifyObservers();
                     } else {
                         JOptionPane.showMessageDialog(null,
                                 "you failed",
                                 "Game Over",
                                 JOptionPane.INFORMATION_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 < nodeArray.size(); ++i) {
                 Node n = (Node) nodeArray.get(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;
         }
    }

    //---------------------------------------------------------------------
    // SnakeControl.java
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;

    /**
      * MVC中的Controler,负责接收用户的操作,并把用户操作通知Model
      */
    public class SnakeControl  implements KeyListener{
         SnakeModel model;

         public SnakeControl(SnakeModel model){
             this.model = model;
         }

         public void keyPressed(KeyEvent e) {
             int keyCode = e.getKeyCode();
             if (model.running){                // 运行状态下,处理的按键
                 switch (keyCode) {
                     case KeyEvent.VK_UP:
                         model.changeDirection(SnakeModel.UP);
                         break;
                     case KeyEvent.VK_DOWN:
                         model.changeDirection(SnakeModel.DOWN);
                         break;
                     case KeyEvent.VK_LEFT:
                         model.changeDirection(SnakeModel.LEFT);
                         break;
                     case KeyEvent.VK_RIGHT:
                         model.changeDirection(SnakeModel.RIGHT);
                         break;
                     case KeyEvent.VK_ADD:
                     case KeyEvent.VK_PAGE_UP:
                         model.speedUp();
                         break;
                     case KeyEvent.VK_SUBTRACT:
                     case KeyEvent.VK_PAGE_DOWN:
                         model.speedDown();
                         break;
                     case KeyEvent.VK_SPACE:
                     case KeyEvent.VK_P:
                         model.changePauseState();
                         break;
                     default:
                 }
             }

             // 任何情况下处理的按键,按键导致重新启动游戏
             if (keyCode == KeyEvent.VK_R ||
                     keyCode == KeyEvent.VK_S ||
                     keyCode == KeyEvent.VK_ENTER) {
                 model.reset();
             }
         }

         public void keyReleased(KeyEvent e) {
         }

         public void keyTyped(KeyEvent e) {
         }
    }

    //----------------------------------------------------------------------
    // SnakeView.java
    import javax.swing.*;
    import java.awt.*;
    import java.util.Iterator;
    import java.util.LinkedList;
    import java.util.Observable;
    import java.util.Observer;

    /**
      * 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) {
             this.model = model;
             this.control = control;

             mainFrame = new JFrame("GreedSnake");

             Container cp = mainFrame.getContentPane();

             // 创建顶部的分数显示
             labelScore = new JLabel("Score:");
             cp.add(labelScore, BorderLayout.NORTH);

             // 创建中间的游戏显示区域
             paintCanvas = new Canvas();
             paintCanvas.setSize(canvasWidth + 1, canvasHeight + 1);
             paintCanvas.addKeyListener(control);
             cp.add(paintCanvas, BorderLayout.CENTER);

             // 创建底下的帮助栏
             JPanel panelButtom = new JPanel();
             panelButtom.setLayout(new BorderLayout());
             JLabel labelHelp;
             labelHelp = new JLabel("PageUp, PageDown for speed;", JLabel.CENTER);
             panelButtom.add(labelHelp, BorderLayout.NORTH);
             labelHelp = new JLabel("ENTER or R or S for start;", JLabel.CENTER);
             panelButtom.add(labelHelp, BorderLayout.CENTER);
             labelHelp = new JLabel("SPACE or P for pause", JLabel.CENTER);
             panelButtom.add(labelHelp, BorderLayout.SOUTH);
             cp.add(panelButtom, BorderLayout.SOUTH);

             mainFrame.addKeyListener(control);
             mainFrame.pack();
             mainFrame.setResizable(false);
             mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
             mainFrame.setVisible(true);
         }

         void repaint() {
             Graphics g = paintCanvas.getGraphics();

             //draw background
             g.setColor(Color.WHITE);
             g.fillRect(0, 0, canvasWidth, canvasHeight);

             // draw the snake
             g.setColor(Color.BLACK);
             LinkedList na = model.nodeArray;
             Iterator it = na.iterator();
             while (it.hasNext()) {
                 Node n = (Node) it.next();
                 drawNode(g, n);
             }

             // draw the food
             g.setColor(Color.RED);
             Node n = model.food;
             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: " + model.score;
             labelScore.setText(s);
         }

         public void update(Observable o, Object arg) {
             repaint();
         }
    }  

      
      
       
       

         
       

         
       
      


      



                            function TempSave(ElementID)
                            {
                                    CommentsPersistDiv.setAttribute("CommentContent",document.getElementById(ElementID).value);
                                    CommentsPersistDiv.save("CommentXMLStore");
                            }
                            function Restore(ElementID)
                            {
                                    CommentsPersistDiv.load("CommentXMLStore");
                                    document.getElementById(ElementID).value=CommentsPersistDiv.getAttribute("CommentContent");
                            }
                   
                      











    源码下载:http://file.javaxxz.com/2014/10/14/195941371.zip
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-6-16 09:55 , Processed in 0.342848 second(s), 38 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表