观察者模式 (模仿贪吃蛇)代码(上)

之前学习了23种模式,就找了个相关的案例,模仿贪吃蛇的。

2.与蛇关联的对象-食物
类的属性:蛇类的对象,整型数x,y表示食物的坐标位置,表示食物有无被吃的标志flag

类的方法:构造函数来初始化x,y坐标和flag标志,当蛇的头部碰到食物,也就是蛇的头或者身体的坐标和事物的坐标一样时,就表示食物被吃掉了。

class Food{
    Snake snake;
    int x,y;
    boolean flag;
    Food(Snake snake){
        this.snake = snake;
        flag = true;
        int x = 0;
        int y = 0;
        while(flag){
            flag = false;
            x = Math.abs(new Random().nextInt()%30);
            y = Math.abs(new Random().nextInt()%30);
            if(snake.head.x==x && snake.head.y==y) flag = true;
            for(Point it:snake.body) if(it.x==x && it.y==y) flag = true;
        }
        this.x = x;
        this.y = y;
    }
     
}

3.被观察者和地图-窗口组件与键盘事件 (MyPanel类)
类的介绍:该类继承了Jpanel ,实现了 KeyListener,Runnable接口
类的属性:蛇类的对象snake,食物类的对象food,蛇移动的速度speed,
类的方法:构造函数初始化snake ,food,speed,并且设置背景颜色;
paint函数为蛇的头部,身体,食物填充颜色,调用的是Graphics类中的fillRect 和setColor函数;
keyPressed、keyReleased、keyTyped都是对应的键盘监听器事件,分别是按下按键,释放按键,键入按键触发事件的监听器。这里用到了两次监听器,第一次把按键事件转化成蛇头的表示方向的改变,第二次把蛇头的表示方向的改变转化为蛇头实际方向的改变。第一次时按键的上下左右分别对应dir的1,2,3,4,第二次时dir的1,2,3,4分别对应蛇头坐标点的x,y方向上的移动,即通过坐标点的x,y数值的改变来表示蛇头的方向改变和移动。

class MyPanel extends JPanel implements KeyListener,Runnable{
    Snake snake;
    Food food;
    int speed;
    MyPanel(Snake snake,Food food){
        this.snake = snake;
        this.food = food;
        speed = 526;
        this.setBackground(Color.black);

    }
    public void paint(Graphics g){
        super.paint(g);
        g.fillRect(0,0,400,400);
        g.setColor(Color.GREEN);//设置头部颜色
        g.fillRect(snake.head.x*snake.size,snake.head.y*snake.size,snake.size,snake.size);
        g.setColor(Color.GRAY);//设置身体颜色
        for(Point it:snake.body) 
        g.fillRect(it.x*snake.size,it.y*snake.size,snake.size,snake.size);
        g.setColor(Color.PINK); //设置食物颜色
        g.fillRect(food.x*snake.size,food.y*snake.size,snake.size,snake.size);
    }
   
    public void keyPressed(Integer dir){ //键盘监听器
         
        Point oxy = new Point(snake.head);
            if(dir==3){//把dir转化为x,y方向上坐标数值的大小变化,
                snake.head.x--;
            }
            else if(dir==4){
                snake.head.x++;
            }
            else if(dir==1){
                snake.head.y--;
            }
            else if(dir==2){
                snake.head.y++;
            }else return;
         
        if(snake.isOut()) 
        	snake.dead(1);
        snake.body.add(0,oxy);
        
        if(snake.isEat(food)){
            snake.length++;
            if(speed >= 50) speed-=25;
            food = new Food(snake);
            
        }else snake.body.remove(snake.length-1);
         
        if(snake.isPitch()) snake.dead(2);
        
        repaint();
    }
       
 public void keyPressed(KeyEvent e){  //按下按键触发事件 相当于监听器

        int key = e.getKeyCode(); //观察者是蛇的方向,被观察者是被按下的按键

    
        if(((key==KeyEvent.VK_LEFT && snake.dir==4)||(key==KeyEvent.VK_UP && snake.dir==2)||(key==KeyEvent.VK_DOWN && snake.dir==1)||(key==KeyEvent.VK_RIGHT && snake.dir==3))){
            return;
        }
            if(key == KeyEvent.VK_LEFT){ 
                                 //把按键的上下左右转化为dir的1,2,3,4
                snake.dir = 3;
            }
            else if(key == KeyEvent.VK_RIGHT){
                snake.dir = 4;
            }
            else if(key == KeyEvent.VK_UP){
                snake.dir = 1;
            }
            else if(key == KeyEvent.VK_DOWN){
                snake.dir = 2;
            }else return;
         
         
    }
    public void keyReleased(KeyEvent e){}//释放按键触发事件
    public void keyTyped(KeyEvent e){}//键入按键触发事件
     
    public synchronized void run(){ //防止多个进程同时访问这个函数
         while(true){
            try{Thread.sleep(speed);
            }catch(Exception e){}
            keyPressed(snake.dir);
        }
    }
}

posted @ 2017-08-15 14:25  七月kirino  阅读(309)  评论(0编辑  收藏  举报