hello

// snakemodel

package mvctest;

 

import javax.swing.*;

 

import java.util.Arrays;

import java.util.LinkedList;

import java.util.Observable;

import java.util.Random;

 

 

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[i] = new boolean[maxy];

                 Arrays.fill(matrix[i], 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;//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]

                 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;

         }

      }

 

 

 

 

 

 

 

 

 

 

 

 

 

 

// snakeview

 

package mvctest;

 

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;

 

   JMenuBar jMenuBar = new JMenuBar();

   JMenu jMenu = new JMenu("menu");

   JMenuItem reset = new JMenuItem("reset");

   JMenuItem newgame = new JMenuItem("newgame");

  

  

 

  

   public snakeview(snakemodel model, snakecontrol control) {

       this.model = model;

       this.control = control;

 

       mainframe = new JFrame("greedsnake");

 

       Container cp = mainframe.getContentPane();

       jMenuBar.add(jMenu);

       jMenu.add(reset);

       jMenu.add(newgame);

      

       // 创建顶部的分数显示

       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();

   }

}

 

 

 

// snakecontrol

package mvctest;

 

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;

   }

 

@Override

public void keyPressed(KeyEvent e) {

      // TODO Auto-generated method stub

       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();

     }

}

 

@Override

public void keyReleased(KeyEvent e) {

      // TODO Auto-generated method stub

     

}

 

@Override

public void keyTyped(KeyEvent e) {

      // TODO Auto-generated method stub

     

}

}

 

 

 

// greedSnake

package mvctest;

 

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的观察者

            model.addObserver(view);

           

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

 

      }

}

 

posted @ 2017-02-26 23:17  梁伟雄的博客  阅读(155)  评论(0编辑  收藏  举报