JSD-2204-面向对象-成员内部类-匿名内部类-潜艇游戏--Day13

1.内部类

1.1 成员内部类:了解

   - 类中套类,外面的称为外部类,里面的称为内部类

   - 内部类通常只服务于外部类,对外不具备可见性

   - 内部类对象需要在外部类中创建

   - 内部类中可以直接访问外部类的成员(包括私有的),

     内部类中有个隐式的引用指向了创建它的外部类对象:外部类名.this-----API用

     public class InnerClassDemo {
         public static void main(String[] args) {
             Mama m = new Mama();
             //Baby b = new Baby(); //编译错误,内部类对外不具备可见性
         }
     }
     
     class Mama { //外部类
         private String name;
         void create(){
             Baby b = new Baby(); //正确,内部类对象通常在外部类中创建
         }
         class Baby{ //内部类
             void showName(){
                 System.out.println(name);
                 //Mama.this指代当前对象的外部类对象
                 System.out.println(Mama.this.name);
                 //System.out.println(this.name); //编译错误,this指代当前Baby对象
             }
         }
     }

1.2. 匿名内部类:-------大大简化代码

   - 何时用:若想创建一个类(派生类)的对象,并且对象只创建一次,可以设计为匿名内部类

   - 匿名内部类中不能修改外面局部变量的值,因为该变量在此处会默认为final的-----API用

   - 小面试题:内部类有独立的.class吗?     答:有

     public class NstInnerClassDemo {
         public static void main(String[] args) {
             //1)创建了Aoo的一个派生类,但是没有名字
             //2)为该派生类创建了一个对象,名为o1
             //  ---new Aoo(){}是在创建派生类对象,而后向上造型为Aoo类型
             //3)大括号中的为派生类的类体
             Aoo o1 = new Aoo(){
             };
     
             //1)创建了Aoo的一个派生类,但是没有名字
             //2)为该派生类创建了一个对象,名为o2
             //3)大括号中的为派生类的类体
             Aoo o2 = new Aoo(){
             };
     
             int num = 5;
             num = 55; //正确
             //1)创建了Boo的一个派生类,但是没有名字
             //2)为该派生类创建了一个对象,名为o3
             //3)大括号中的为派生类的类体
             Boo o3 = new Boo(){
                 void show(){
                     System.out.println("showshow");
                     //num = 88; //编译错误,在此处num会默认为final的
                 }
             };
             o3.show();
     
         }
     }
     
     abstract class Boo{
         abstract void show();
     }
     
     abstract class Aoo{
     }

2.潜艇游戏第七天:

2.1. 潜艇入场:

   - 潜艇对象是由窗口产生的,所以在World中设计nextSubmarine()生成潜艇对象

   - 潜艇入场为定时发生的,所以在run中调用submarineEnterAction()实现潜艇入场

     在submarineEnterAction()中:

     ​    每400毫秒,获取潜艇对象obj,submarines扩容,将obj添加到submarines末尾

     > 注意: run()中调用submarineEnterAction()之后必须调用repaint()来重画

2.2. 水雷入场:

   - 水雷对象是由水雷潜艇发射出来的,所以在MineSubmarine中设计shootMine()生成水雷对象

   - 水雷入场为定时发生的,所以在run中调用mineEnterAction()实现水雷入场

     在mineEnterAction()中:

     ​    每1000毫秒,......---------暂时搁置

2.3. 海洋对象移动:

   - 海洋对象移动为对象所共有的行为,所以在SeaObject中设计抽象方法move()实现移动,在6个派生类中重写

   - 海洋对象移动为定时发生的,所以在run中调用moveAction()实现海洋对象移动

     在moveAction()中:

     ​    遍历所有潜艇-潜艇动,遍历所有水雷-水雷动,遍历所有炸弹-炸弹动

2.4代码展示

2.4.1Battleship类

package cn.tedu.submarine;

import javax.swing.*;
import java.util.Objects;

/**
 * 战舰
 */
public class Battleship extends SeaObject{
    /**
     * 命
     */
    private int life;


    public Battleship() {
        super(66,26,270,124,5);
        this.life = 5;
    }


    @Override
    public void move() {

    }

    @Override
    public ImageIcon getImage() {
        return Images.battleship;
    }


    /**
     * 发射炸弹的方法
     */
    public void shootBomb(){

    }


}


2.4.2Bomb类

package cn.tedu.submarine;

import javax.swing.*;
import java.util.Objects;

/**
 * 炸弹
 */
public class Bomb extends SeaObject{

    public Bomb(int x , int y) {
        super(9,12,x,y,3);
    }


    /**
     * 炸弹移动的方法
     */
    @Override
    public void move() {
        y += speed;
    }

    @Override
    public ImageIcon getImage() {
        return Images.bomb;
    }


}


2.4.3Images类

package cn.tedu.submarine;

import javax.swing.ImageIcon;


public class Images {
    /**
     * 背景图
     */
    public static ImageIcon sea;
    /**
     * 战舰图
     */
    public static ImageIcon battleship;
    /**
     * 炸弹图片
     */
    public static ImageIcon bomb;
    /**
     * 游戏结束
     */
    public static ImageIcon gameover;
    /**
     * 水雷图片
     */
    public static ImageIcon mine;
    /**
     * 水雷潜艇
     */
    public static ImageIcon minesubm;
    /**
     * 侦察潜艇
     */
    public static ImageIcon obsersubm;
    /**
     * 鱼类潜艇
     */
    public static ImageIcon torpesubm;

    /**
     * 初始化图片
     */
    static {
        battleship = new ImageIcon("img/battleship.png");
        sea = new ImageIcon("img/sea.png");
        bomb = new ImageIcon("img/bomb.png");
        gameover = new ImageIcon("img/gameover.png");
        mine = new ImageIcon("img/mine.png");
        minesubm = new ImageIcon("img/minesubm.png");
        obsersubm = new ImageIcon("img/obsersubm.png");
        torpesubm = new ImageIcon("img/torpesubm.png");
    }

//    /**
//     * 测试图片
//     * @param args
//     */
//    public static void main(String[] args) {
//        //返回8表示成功了
//        System.out.println(battleship.getImageLoadStatus());
//    }

}


2.4.4Mine类

package cn.tedu.submarine;

import javax.swing.*;
import java.util.Objects;

/**
 * 水雷
 */
public class Mine extends SeaObject{

    public Mine(int x , int y) {
        super(11,11,x,y,1);
    }


    /**
     * 水雷移动的方法
     */
    @Override
    public void move() {
        y-=speed;
    }

    @Override
    public ImageIcon getImage() {
        return Images.mine;
    }


}


2.4.5MineSubMarine类

package cn.tedu.submarine;

import javax.swing.*;
import java.util.Objects;
import java.util.Random;

/**
 * 水雷潜艇
 */
public class MineSubmarine extends SeaObject{


    public MineSubmarine() {
        super(63,19);
    }


    /**
     * 水雷潜艇移动
     */
    @Override
    public void move() {
        x+=speed;
    }

    @Override
    public ImageIcon getImage() {
        return Images.minesubm;
    }

    /**
     * 发射水雷---生成水雷对象
     * @return
     */
    public Mine shootMine(){
        return new Mine(this.x+this.width,this.y-11);
    }
}


2.4.6ObserverSubMarine类

package cn.tedu.submarine;

import javax.swing.*;
import java.util.Objects;
import java.util.Random;

/**
 * 侦察潜艇
 */
public class ObserverSubmarine extends SeaObject{


    public ObserverSubmarine() {
        super(63,19);
    }


    /**
     * 侦察潜艇移动
     */
    @Override
    public void move() {
        x+=speed;
    }

    @Override
    public ImageIcon getImage() {
        return Images.obsersubm;
    }
}


2.4.7SeaObject类

package cn.tedu.submarine;

import javax.swing.*;
import java.awt.*;
import java.util.Random;

/**
 * 海洋对象
 */
public abstract class SeaObject {
    public static final int LIVE = 0;//或者的
    public static final int DEAL = 1;//死了的
    protected int state = LIVE;//当前状态(默认是活着的)
    /**
     * 成员变量一般都要private的
     * 此处设计为protected
     * 因为还没有讲到getter/setter
     */
    /**
     * 宽
     */
    protected int width;
    /**
     * 高
     */
    protected int height;
    /**
     * x轴
     */
    protected int x;
    /**
     * y轴
     */
    protected int y;
    /**
     * 速度
     */
    protected int speed;


    public SeaObject(int width,int height,int x , int y,int speed){
        this.width = width;
        this.height = height;
        this.x = x;
        this.y = y;
        this.speed = speed;
    }

    public SeaObject(int width,int height){
        this.width = width;
        this.height = height;
        Random rand = new Random();
        x = -width;
        y = rand.nextInt(World.HEIGHT-height-150+1 ) +150;
        this.speed = rand.nextInt(3)+1;
    }

    /**
     * 移动的方法
     */
    public abstract void move();

    /**
     * 获取对象的图片
     */
    public abstract ImageIcon getImage();

    /**
     * 判断是活着的
     * @return
     */
    public boolean isLive(){
        return state == LIVE;
    }

    /**
     * 判断是死的吗
     * @return
     */
    public boolean isDeal(){
        return  state == DEAL;
    }

    /**
     * 画图片
     * @param g
     */
    public void paintImage(Graphics g){
        if (isLive()){//若或者的
            //不要求掌握
            this.getImage().paintIcon(null,g,this.x,this.y);
        }
    }
}


2.4.8TorpedoSubmarine类

package cn.tedu.submarine;

import javax.swing.*;
import java.util.Objects;
import java.util.Random;

/**
 * 鱼类潜艇
 */
public class TorpedoSubmarine extends SeaObject{


    public TorpedoSubmarine() {
        super(64,20);
    }


    /**
     * 鱼类潜艇移动的方法
     */
    @Override
    public void move() {
        x+=speed;
    }

    @Override
    public ImageIcon getImage() {
        return Images.torpesubm;
    }

}


2.4.9World(测试类)

package cn.tedu.submarine;

import javax.swing.*;
import java.awt.Graphics;
import java.util.Arrays;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

/**
 * 整个游戏世界
 */
public class World extends JPanel {
    public static final int WIDTH = 641;//窗口的宽
    public static final int HEIGHT = 479;//窗口的高

    private Battleship ship = new Battleship();//战舰
    private SeaObject[] submarines = {};//潜艇数组(侦察潜艇,鱼雷潜艇,水雷潜艇)
    private Mine[] mines = {
            new Mine(200, 300)
    };//水雷数组
    private Bomb[] bombs = {
            new Bomb(180, 130)
    };//炸弹数组

    public void action() {
        Timer timer = new Timer();
        int interval = 10;
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                submarineEnterAction();//敌人入场
                minesEnterAction();//水雷入场
                submarineMove();//潜艇移动
                repaint();//重新画一下
            }
        }, interval, interval);
    }

    /**
     * 潜艇移动
     */
    public void submarineMove() {
        for (int i = 0; i < submarines.length; i++) {
            submarines[i].move();
        }

        for (int i = 0; i < bombs.length; i++) {
            bombs[i].move();
        }

        for (int i = 0; i < mines.length; i++) {
            mines[i].move();
        }
    }

    private int mineEnterIndex = 0;//水雷入场计数
    /**
     * 水雷入场
     */
    public void minesEnterAction() {//没10个毫秒走一次
        mineEnterIndex++;//没10毫秒增1
        if (mineEnterIndex % 100 == 0){

        }
    }


    private int subEnterIndex = 0;
    /**
     * 敌人入场
     */
    public void submarineEnterAction() {
        subEnterIndex++;
        if (subEnterIndex%40 == 0){
            SeaObject obj = nextSubmarine();
            submarines = Arrays.copyOf(submarines,submarines.length+1);
            submarines[submarines.length-1]=obj;
        }
    }

    /**
     * 生成潜艇对象
     */
    public SeaObject nextSubmarine() {
        Random random = new Random();
        int type = random.nextInt(20);
        if (type < 10) {
            return new ObserverSubmarine();
        } else if (type < 15) {
            return new TorpedoSubmarine();
        } else {
            return new MineSubmarine();
        }
    }


    /**
     * 重写JPanel中的paint()画  g 画笔
     *
     * @param g
     */
    @Override
    public void paint(Graphics g) {
        Images.sea.paintIcon(null, g, 0, 0);//海洋图片
        ship.paintImage(g);
        //画敌人
        for (int i = 0; i < submarines.length; i++) {
            submarines[i].paintImage(g);
        }
        //画水雷
        for (int i = 0; i < mines.length; i++) {
            mines[i].paintImage(g);
        }
        //画炸弹
        for (int i = 0; i < bombs.length; i++) {
            bombs[i].paintImage(g);
        }
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        World world = new World();
        world.setFocusable(true);
        frame.add(world);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(WIDTH + 16, HEIGHT + 39);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

        world.action();


    }


}

3.补充

3.1隐式的引用:

   - this:指代当前对象
   - super:指代当前对象的超类对象
   - 外部类名.this:指代当前对象的外部类对象 

3.2做功能的套路:

   - 先写行为/方法:
     - 若为某个对象所特有的行为,就将方法设计在特定的类中
     - 若为所有对象所共有的行为,就将方法设计在超类中
   - 窗口调用:
     - 若为定时发生的,就在定时器run中调用
     - 若为事件触发的,就在侦听器中调用-------------------明天讲

3.3如何调错:

   - 打桩:System.out.println(数据);-----------需要慢慢来,调得多了就有经验了

3.4明日单词:

   1)interface:接口
   2)implements:实现
   3)enemy:敌人
   4)nuclear:核武器
   5)left:左
   6)right:右
   7)out of bounds:超出界限
   8)Key:键盘
   9)Adapter:适配器
   10)release:松开/弹起
   11)code:编码
   12)space:空白
   13)listener:监听

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值