java学习之贪吃蛇(1)

snake  包括几个属性

1.move       移动   

2.draw       画出自己

3.changeDirection  改变方向

4.isEatBody 吃到了自己

5.isEatFood 迟到了食物

6.isEatRock 吃到了石头

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

Food    包括几个属性

1.draw       画出自己 

2.isSnakeEatFood 蛇迟到了自己

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

Ground    包括几个属性

1.draw       画出自己

2.isSnakeEatRock 蛇迟到了自己

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

GamePanel   包括几个属性

1.redisplay    重新画出蛇,食物,石头

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

自己定义的监听器部分 分为4部分,

1 建立侦听接口,例如下边的snakelistener

2 控制继承接口,后实现接口类中定义的方法 ,例如下边的controller

3 在第三个类中添加监听器,并且定义添加监听器的方法addactivelistener123(snakelistener l),例如下边的snake

4 为其他的类中addactivelistener123(controller)


1.监听接口 SnakeListener 

public interface SnakeListener {
void snakeMoveddisplay();                //接口只定义方法,没有方法体
}

2.控制类 controller   implements SnakeListener 

@Override

public void snakeMoveddisplay() {                    //实现方法体
// TODO Auto-generated method stub
gamepanel.display(snake,food,ground);
}

-------------------------------------------------------------------------------------------------------------------------------------------------------------------
3.Snake

             private Set<SnakeListener> listeners = new HashSet<SnakeListener>();      //定义一个监听器集合,add

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

             public void addSnakeListener(SnakeListener l){                                               //定义向监听器集合中添加监听器的方法

                   if(l!=null)
                      this.listeners.add(l);
            }

             --------------------------------------------------------------------------------------------------------------------------------
             for(SnakeListener l :listeners){                                       //遍历监听器集合,如果有就触发,执行如下方法
l.snakeMoveddisplay();
}
  

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

4.GameFrame 主窗体

sanke.addSnakeListener(controller)


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

snake

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


package com;


import java.awt.Graphics;
import java.awt.Point;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;

public class Snake {
private Set<SnakeListener> listeners = new HashSet<SnakeListener>();


public void changeDirection(){
System.out.println("snake 's changedirection");
}

public void isEatBody(){
System.out.println("snake's isEatBody");
}

public void eatFood(){
System.out.println("snake's eatfood");
}

public void move(){
System.out.println("snake move");

}

//定义一个线程,让蛇不停的移动
private class SnakeDriver implements Runnable{
public void run(){
while(true){
move();
//触发监听事件
for(SnakeListener l :listeners){
l.snakeMoveddisplay();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

public void addSnakeListener(SnakeListener l){
if(l!=null)
this.listeners.add(l);

}

public void draw(){
System.out.println("my name is a snake");
}

//启动线程的方法,让蛇开始走
public void start(){
new Thread(new SnakeDriver()).start();
}

}

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

food

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

package com;


public class Food {


public boolean isSnakeEatFood(Snake snake){
System.out.println("food's issnakeeatfood");
return false;
}

public void draw(){
System.out.println("food draw");
}
}

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

ground

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

package com;


public class Ground {



public boolean isSnakeEatRock(Snake snake){
System.out.println("Ground's issankeeatrock");
return false;
}

public void draw(){
System.out.println("rock 's drawME");
}
}

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

gamepanel

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

package com;


import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;


import javax.swing.JPanel;
import javax.swing.border.EtchedBorder;


import cn.snake;




/**
 * 游戏的显示界面<BR>
 * 可以用 setBackgroundColor() 设置游戏的背景色
 * 
 * @version 1.0, 15/04/18
 * 
 * @author 刘洋
 * 
 */
public class GamePanel extends JPanel {


   //先定义,然后通过display传参对sanke等赋值,使整个程序的snake food等统一。
private Snake snake;
  private Food food;
  private Ground ground;
 
  //display 后边更的是参数,目的是为了给上边的private snake等赋值,
  //由于display是在controller中用到,所以通过赢引用参数赋值后的,本类中的snake,food,
  //就是controller中定义的snake,food
public void display(Snake snake,Food food,Ground ground){
System.out.println("gamepanel's display");

this.snake = snake;
this.food = food;
this.ground = ground;
this.repaint();


@Override
protected void paintComponent(Graphics g) {
// TODO Auto-generated method stub
this.snake.draw();
this.food.draw();
System.out.println("repaint");
this.ground.draw();
}

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

SnakeListener 

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

package com;


public interface SnakeListener {
void snakeMoveddisplay();
}

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

controller 

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

package com;


import com.Food;
import com.GamePanel;
import com.Ground;
import com.Snake;
import com.SnakeListener;


public class controller implements SnakeListener{

//controller这里我们也定义了snake,food等,但是在本类里没有被new,或赋值,我们还需要将已经复制或new的snake,food传进来。
private Snake snake ;
  private Food food ;
  private Ground ground ;
GamePanel gamepanel;


@Override
public void snakeMoveddisplay() {
// TODO Auto-generated method stub
gamepanel.display(snake,food,ground);
}

//测试的时候主窗口中new sanke 、new food,而且在主窗口中调用controller(snake,。。)这里就是通过controller进行传参。
public controller(Snake snake, Food food, Ground ground, GamePanel gamepanel) {
super();
this.snake = snake;
this.food = food;
this.ground = ground;
this.gamepanel = gamepanel;
}


public void newgame(){
//定义什么时候为开始游戏呢?蛇开始走的时候。
snake.start();
}



}

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

gameframe                  测试的窗体,如果不用frame和add(gamepanel,B),那么gamepanel的repain()重绘图就不好使。记住

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

package com;


import java.awt.BorderLayout;


import javax.swing.JFrame;


public class gameframe  {




public static void main(String[] args){

Snake snake = new Snake();
Food food = new Food();
Ground ground = new Ground();
   GamePanel gamepanel= new GamePanel();
controller cont = new controller(snake,food,ground,gamepanel);
snake.addSnakeListener(cont);

javax.swing.JFrame frame= new  JFrame();
frame.setSize(300,300);
frame.add(gamepanel,BorderLayout.CENTER);
frame.setVisible(true);
cont.newgame();
}
}

以上仅是一个简单的思路还需要进一步的扩展,实现效果为

执行gameframe后会打出如下内容

snake move
gamepanel's display
my name is a snake
food draw
repaint
rock 's drawME
my name is a snake
food draw
repaint
rock 's drawME
snake move
gamepanel's display
my name is a snake
food draw
repaint

实现蛇每移动一次,gamepanel就重新显示一遍snake food ground

可以运行! (以下代码只是其中的一个类) package chy.snake.entities; import java.awt.Color; import java.awt.Graphics; import java.awt.Point; import java.util.HashSet; import java.util.LinkedList; import java.util.Set; import chy.snake.listener.SnakeListener; import chy.snake.util.Global; public class Snake { public static final int up = 1; public static final int down = -1; public static final int left = -2; public static final int right = 2; private int oldDirection,newDirection; //newDirection:一次时间 间隔内输入的最后方向 private Point oldTail; private boolean life; //life 为 true或者false,初始为true, 用于118行 private LinkedList<Point> body = new LinkedList<Point> (); //需要经常访问蛇的第一个和最后一个节点,使用链表LinkedList存放蛇的身体节点,因为它有getFirst(),getLast(),removeLast(),方法 private Set<SnakeListener> listeners = new HashSet<SnakeListener>(); public Snake(){ init(); } public void init(){ //初始化 int x = Global.WIDTH/2; int y = Global.HEIGHT/2; for(int i=0;i<3;i++){ //初始长度3 body.addLast(new Point(x-i,y)); //是addLast } oldDirection = newDirection = right; //初始方向 右 life = true; } public void die(){ life = false; } public void move(){ System.out.println("Snake's move"); if (!(oldDirection + newDirection == 0)){ oldDirection = newDirection; } //1.去尾 oldTail = body.removeLast(); int x = body.getFirst().x; int y = body.getFirst().y; //蛇头的x,y坐标 switch(oldDirection){ case up: y--; break; case down: y++; break; case left: x--; break; case right: x++; break; } Point newHead = new Point(x,y); //2.加头 body.addFirst(newHead); } public void changeDirection(int direction){ /*无效方向:在蛇的这一次移动之后和下一次移动之前的 这个时间间隔内输入了多个方向,只有最后一个方向 是 有效方向,其余的都为无效方向*/ System.out.println("Snake's changeDirection"); newDirection = direction; //将一个时间间隔内按得最后方向,赋给 newDirection } public void eatFood(){ System.out.println("Snake's eatFood"); body.addLast(oldTail); //后面的节点不去掉 } public boolean isEatFood(){ System.out.println("Snake's isEatFood"); return false; } public boolean isEatBody(Snake snake){ //比较蛇是否吃到身体 System.out.println("snake's isEatBody"); for(int i= 1;i<body.size();i++){ //i 从蛇头结点的下一个节点开始,排除蛇头结点 if(body.get(i).equals(this.getHead())){ //如果i 的节点 和 头结点 相同 return true; } } return false; } public void drawMe(Graphics g){ System.out.println("Snake's drawMe"); g.setColor(Color.GREEN); //设置蛇的颜色 for(Point p : body){ g.fill3DRect(p.x * Global.CELL_SIZE, p.y * Global.CELL_SIZE, Global.CELL_SIZE, Global.CELL_SIZE, true); } } public Point getHead(){ //得到蛇头节点,判断吃食物 return body.getFirst(); } private class SnakeDriver implements Runnable{ //线程,不停的调用move方法 @Override public void run() { // TODO 自动生成的方法存根 while(life){ // 42和46行,life为true 或者false move(); for(SnakeListener l : listeners){ l.snakeMoved(Snake.this); //循环,依次调用SnakeMoved方法 } try { Thread.sleep(300); } catch (InterruptedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } } } } public void start(){ new Thread(new SnakeDriver()).start(); //启动线程的方法 } public void addSnakeListener(SnakeListener l){ if(l != null){ this.listeners.add(l); } } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值