之前学习了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);
}
}
}