JAVA游戏项目之图层遮盖算法

举报
tea_year 发表于 2025/05/28 17:19:57 2025/05/28
【摘要】 图层遮盖算法0、课程回顾final关键字的用法模板方法设计模式适配器设计模式匿名内部类 一、本章目标实现图层遮盖算法问题1:假定我们有9个图层,最顶层为第1层,最下层为第9层,那么此时第6层当中有一张牌,它应该显示正常还是显示灰色的状态呢?问题2:第一层的牌呢?最后一层第9层的牌呢?判定第6层的某一张牌和他的上层5层的所有牌进行一个比较,是否有交集。如果有,则说明盖住了,显示灰色。不用再判断...

图层遮盖算法

0、课程回顾

final关键字的用法

模板方法设计模式

适配器设计模式

匿名内部类

一、本章目标

实现图层遮盖算法

问题1:假定我们有9个图层,最顶层为第1层,最下层为第9层,那么此时第6层当中有一张牌,它应该显示正常还是显示灰色的状态呢?

问题2:第一层的牌呢?最后一层第9层的牌呢?

判定第6层的某一张牌和他的上层5层的所有牌进行一个比较,是否有交集。如果有,则说明盖住了,显示灰色。

不用再判断6层的这张牌和上层的其他牌的遮盖问题。

如果没有,则说明第5层的牌并没有盖住它(6层的这张票),则继续和第四层的比较,如果还没有,继续比较更高层的牌,直到最高层1层,全部比较完毕。都没有交集,那么显示未正常颜色。

特殊情况:

  • 第一层的牌没有遮盖的问题,都是显示正常

  • 消除的游戏,所以牌在减少,某一层的牌为0了,或者某个单元格为空,说明什么:底层的牌不用再给改单元格进行比较。所以牌在消除的时候,要修改Cell单元格的状态为:0 无牌,还要修改brand属性为null。

image-20221216212203194.png

  1. 图层建立时,同时也建立链式的结构,更方便的找到上一层,Layer类当中增加parentLayer属性,也就是当前图层的上层。

  2. 实现compare函数,比较一张牌和一个图层的遮盖问题。

  3. 递归实现:如果和当前图层没有遮盖,继续比较上一层,直到顶层。

  4. 把map当中所有牌都调用一遍compare函数,从而判断是否置灰, 默认加载彩色图片。

二、涉及知识点

static 关键字: 静态的,对象无关的,和某一个类型有关。

递归方法调用: 渲染map的时候调用,让所有的牌和上一层的牌进行比较,如果上一层没有遮盖继续上一层。

矩阵交集方法: 如何判断遮盖。

三、知识点讲解

static 关键字

生活中的案例:

package cn.yunhe.demo;
class ICBC{  //这是什么银行? CCB  存存吧 ABC 农业 俺不存
    private  int total;//总存款数,公共厕所公共医院
    private String name;//银行的名称public ICBC(String name) {
        this.name = name;
    }public int saveMoney(int money){
        this.total += money;
        return this.total;
    }public int getTotal() {
        return total;
    }public String getName() {
        return name;
    }
}public class TestStatic {
    public static void main(String[] args) {
        ICBC icbc1 = new ICBC("高新区支行");
        icbc1.saveMoney(1000);
        System.out.println(icbc1.getName()+"总存款"+icbc1.getTotal());
        ICBC icbc2 = new ICBC("中原区支行");
        icbc2.saveMoney(2000);
        System.out.println(icbc2.getName()+"总存款"+icbc2.getTotal());
        ICBC icbc3 = new ICBC("金水区支行");
        icbc3.saveMoney(3000);
        System.out.println(icbc3.getName()+"总存款"+icbc3.getTotal());
    }
}


image-20230105103738577.png

static中文意思:静态的,static是和对象无关的。 PI 圆周率与某个对象又关吗?

public final class Math {/**
     * Don't let anyone instantiate this class.
     */
    private Math() {}/**
     * The {@code double} value that is closer than any other to
     * <i>e</i>, the base of the natural logarithms.
     */
    public static final double E = 2.7182818284590452354;/**
     * The {@code double} value that is closer than any other to
     * <i>pi</i>, the ratio of the circumference of a circle to its
     * diameter.
     */
    public static final double PI = 3.14159265358979323846;
    public 说明该属性是公有的,可以在别的类直接访问,不属于某个对象,所以不用private修饰
    static 说明该属性和具体对象没有关系,可以直接通过类名.属性名进行访问
    final  说明定义的是常量,圆周率不会随意改变
    double 说明定义这个变量的类型是双精度浮点型
    PI     说明定义的常量名称,常量一般大写字母,MAX_AGE多个单词之间用下划线隔开
    3.14   说明常量的值

1.1 生活的角度来理解静态的资源

公共的资源的都属于静态的东西,对象可以使用静态的资源,但是和对象无关;

公共厕所就是静态资源,公立医院就是静态资源,不属于某一个对象, 共享单车。

1.2 Java中的静态

1.修饰成员变量:静态属性

2.修饰成员方法:静态方法

3.修饰代码块: 静态代码块,不属于某一个方法的,但是执行时机先于构造方法

class Man {
    static String name;//静态的属性  和对象无关的
    //静态方法
    public static void eat () {
        System.out.println("吃饭喝酒");
    }
    //静态代码块
    static {
        System.out.println("嘻嘻");
    }
}
public class Demo1 {
    public static void main(String[] args) {
        //咋使用 类.静态的属性
        Man.name = "狗蛋";
        System.out.println(Man.name);
        //使用  类.静态方法名字()
        Man.eat();   
    }
}

1.2.1 static修饰成员变量

静态成员变量:

static String name;

语法格式:

static 数据类型  变量名;

注意事项:

1.使用static修饰的变量叫静态变量

2.代码中对象还没有创建的时候,如果加载了类,static修饰的属性已经存在了,和对象没有关系。

class Person {
    String name;
    int age;
    static String country;
}
public class Demo2 {
    public static void main(String[] args) {
        Person sb = new Person();
        sb.name = "张三";
        sb.age = 23;
        Person.country = "中国";
        //The static field Person.country 
        //should be accessed in a static way
        System.out.println(sb.country);//中国
        System.out.println(Person.country);//in a static way
        sb.country = "PRC";
        System.out.println(Person.country);//PRC
    }
}

1.2.2 static修饰成员方法

静态方法,语法格式:

public static 返回值 方法的名字 (参数列表) {}

调用静态方法:类.方法名字();

class Dog {
    public void eat () {
        System.out.println("普通的成员方法");
    }
    public static void sleep () {
        System.out.println("睡吧不用看家了");
    }
}
public class Demo3 {
    public static void main(String[] args) {
        Dog.sleep();
        //Dog.eat();只能拿对象来调用这个方法eat
        Demo3.test();
    }
    public static void test () {
        System.out.println("嘻嘻");
    }
}

1.2.3 static修饰代码块

语法格式: 静态代码块

static {
    语句体
}

只要这个类加载,那么静态代码块一定会执行,

执行顺序: 静态代码块-》构造代码块-》构造方法

class Cat {
    public Cat () {
        System.out.println("无参构造方法");
    }
    {
        System.out.println("构造代码块");
    }
    static {
        System.out.println("静态的代码块");
    }
}
public class Demo4 {
    public static void main(String[] args) {
        Cat cat = new Cat();
    }
}

1.3 什么时候变量声明为实例的,什么时候声明为静态的?

如果这个类型的所有对象的某个属性值都是一样的,不建议定义为实例变量,浪费内存空间。 建议定义为类级别特征,定义为静态变量,在方法区中只保留一份,节省内存开销。

  • 一个对象一份的是实例变量。

  • 所有对象一份的是静态变量。

class Chinese{// 身份证号
    // 每一个人的身份证号不同,所以身份证号应该是实例变量,一个对象一份。
    String idCard;// 姓名
    // 姓名也是一个人一个姓名,姓名也应该是实例变量。
    String name;
    String girlFriend;
    String sex;
    int age;
    // 国籍
    // 重点重点五颗星:加static的变量叫做静态变量
    static String country = "中国";
    static String minzu = "汉";// 无参数
    public Chinese(){
    
    }// 有参数
    public Chinese(String s1,String s2){
        idCard = s1;
        name = s2;
    }
}

注意:

  1. 静态变量在类加载时初始化,不需要new对象,静态变量的空间就开出来了。

  2. 静态变量存储在方法区

  3. 静态代码块的案例:注意该代码不用练习,仅仅演示静态代码块的用法。

    package cn.yunhe.util;
     
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import java.io.InputStream;
     
    public class MyBatisUtil {
        //获得SqlSession工厂
        private static SqlSessionFactory factory;
        //创建ThreadLocal绑定当前线程中的SqlSession对象
        private static final ThreadLocal<SqlSession> THREAD_LOCAL = new ThreadLocal<SqlSession>();
        //静态代码块
        static {
            try {
                //读取配置文件,数据库的配置信息 url driverClass username password
                InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
                factory = new SqlSessionFactoryBuilder().build(is);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
     
        //获得连接(从THREAD_LOCAL中获得当前线程SqlSession)
        private static SqlSession openSession(){
            SqlSession session = THREAD_LOCAL.get();
            if(session == null){
                session = factory.openSession();
                THREAD_LOCAL.set(session);
            }
            return session;
        }
     
        /**
         * 释放连接(释放当前线程中的SqlSession)
         */
        public static void closeSession(){
            SqlSession session = THREAD_LOCAL.get();
            session.close();
            THREAD_LOCAL.remove();
        }
     
        /**
         *  提交事务(提交当前线程中的SqlSession所管理的事务)
         */
        public static void commit(){
            SqlSession session = openSession();
            session.commit();
            closeSession();
        }
     
        /**
         * 回滚事务(回滚当前线程中的SqlSession所管理的事务)
         */
        public static void rollback(){
            SqlSession session = openSession();
            session.rollback();
            closeSession();
        }
        /**
         * 获得接口实现类对象
         * @param clazz 泛型对象
         * @param <T> 泛型
         * @return
         */
        public static <T> T getMapper(Class<T> clazz){
            SqlSession session = openSession();
            return session.getMapper(clazz);
        }
    }

递归方法调用

1、基本说明

递归调用就是在当前的函数中调用当前的函数并传给相应的参数,这是一个动作,这一动作是层层进行的,直到满足一般情况的的时候,才停止递归调用,开始从最后一个递归调用返回。

简单的说:递归就是方法自己调用自己,每次调用是传入不同的变量,递归有助于编程者解决复杂的问题,同时可以让代码变得整洁。

递归本质:程序调用自身的编程技巧叫做递归。AlphaGo 李世石, 自己和自己下棋

老顽童周伯通被困在桃花岛洞中的日子,相当无聊,对武功痴迷的他,竟然在无聊中悟出了一套绝世武功——左右互搏术。简单说,就是自己和自己打架玩,复杂点说,这是一套上等的绝妙武学,相当于将人一分为二,分心二用,左手和右手可以同时出不同的招数,相当于,一个人的战斗力可以成倍增加。

e850352ac65c10387d30be019deb2c1bb27e89ad.jpeg


2、递归需要满足三个条件:

  1. 边界条件

  2. 递归前进段: 递推

  3. 递归返回段: 回归

当边界条件不满足时,递归前进;当边界条件满足时,递归返回。

3、递归能解决什么问题?

  • 各种数学问题:8皇后问题,汉诺塔,阶乘问题,迷宫问题,球和篮子的问题(google编程大赛)

  • 各种算法中也会使用到递归,比如快排,并归排序,二分查找,分治算法等。

  • 调用栈解决的问题--->递归代码比较简洁

4、递归举例

4.1打印问题
package cn.yunhe.demo;public class TestRecursion {
    public static void main(String[] args) {
        a a = new a();
        a.test(4);
    }
}
 
class a {
    public void test(int n) {
        if (n >2) {
            test(n - 1);
        }
        System.out.println("n=" + n);
    }
}

打印问题在JVM内存中的执行过程,栈的特点是先进后出,队列的特点:先进先出。 栈帧

image-20230105112259038.png

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pi85aSc5peg6Laj,size_20,color_FFFFFF,t_70,g_se,x_16.png

4.2阶乘问题
public class TestRecursion {
    public static void main(String[] args) {
        int res = a.factorial(5);
        System.out.println("res=" + res);
    }
}
// 5! = 4!*5   4! = 4*3!  3! = 3 *2!  2 = 1!*2; 1! = 1*1
class a {
    //阶乘问题
    public int factorial(int n) {
        if (n == 1) {
            return 1;
        } else {
            return factorial(n - 1) * n;
        }
    }
 
}

阶乘问题分析:

此题中,按照递归的三个条件来分析: (1)边界条件:阶乘,乘到最后一个数,即1的时候,返回1,程序执行到底; (2)递归前进段:当前的参数不等于1的时候,继续调用自身; (3)递归返回段:从最大的数开始乘,如果当前参数是5,那么就是54,即5(5-1),即n*(n-1)

5、递归方法进阶练习(求斐波那契数

请使用递归的方式求出斐波那契数1,1,2,3,5,8,13....

给你一个整数n,求出他的值是多少

思路分析

  1. 当n = 1 斐波那契数是 1

  2. 当n = 2斐波那契数是 1

  3. 当n >= 3 斐波那契数是前两个数的和

  4. 这里就是一个递归的思路

代码实现

public class TestRecursion {
    public static void main(String[] args) {
        T t1 = new T();
        System.out.println("当n=7 对应的斐波那契数=" + t1.fibonacci(7));
    }
}
 
class T {
    public int fibonacci(int n) {
        if (n >= 1) {
            if (n == 1 || n == 2) {
                return 1;
            } else {
                return fibonacci(n - 1) + fibonacci(n - 2);
            }
        } else {
            System.out.println("要求输入的n>=1的整数");
            return -1;
        }
    }
}

控制台输出结果:当n=7时,对应的斐波那契数= 13;

6、递归重要规则

  1. 执行一个方法时,就创建一个新的受保护的独立空间(栈空间)

  2. 方法的局部变量是独立的,不会相互影响,比如n变量

  3. 如果方法中使用的是引用类型变量(比如数组,对象),就会共享该引用类型的数据。

  4. 递归必须向退出递归的条件逼近,否则就是无限递归(龟死了)

  5. 当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者放回时,该方法也就执行完毕。

矩阵交集方法

判断两个组件是否覆盖的方法。

package cn.yunhe.demo;import javax.swing.*;
import java.awt.*;public class AbsoluteLayoutTest {public static void main(String[] args) {
        JFrame jf = new JFrame("学籍管理系统");
        jf.setSize(300,250);
        jf.setLayout(null);
        jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        //放两个按钮
        JButton addBtn = new JButton("添加");
        JButton updBtn = new JButton("更新");
        addBtn.setBounds(10,10,60,25);
        updBtn.setBounds(50,10,60,25);//改成80再测试一下
​
        jf.getContentPane().add(addBtn);
        jf.getContentPane().add(updBtn);//判断两个矩形是否有交集 intersects 交集
        Rectangle addRect = addBtn.getBounds();
        Rectangle updRect = updBtn.getBounds();
        boolean b = addRect.intersects(updRect);
        System.out.println("是否有交集:" + b);
​
        jf.setVisible(true);
    }
}

四、代码实现

  1. Layer类增加自身类型的 parent 属性,存储上一层对象的引用

  public class Layer {
  
      private int offsetx;//偏移量 x轴
      private int offsety;//偏移量 y轴
  
      private int rowNum;//行
      private int colNum;//列
      private int capacity;//最大容量
      private int size;//目前有多少牌,当牌添加和消失的时候改变
  
      //中间大部分代码都省略......
      
      private Layer parent;//上一层图层对象
      //生成getter、setter方法
      
      public Layer getParent() {
          return parent;
      }
  
      public void setParent(Layer parent) {
          this.parent = parent;
      }
  }
  1. 在MapUtil工具类增加建立链式结构的代码和比较的方法

  package cn.yunhe.util;
  
  import cn.yunhe.model.Brand;
  import cn.yunhe.model.Cell;
  import cn.yunhe.model.Layer;
  import cn.yunhe.model.Map;
  
  import java.awt.*;
  
  public class MapUtil {
  
      public static Map buildMap(int floorHeight){
          Map map = new Map();
          map.setFloorHeight(floorHeight);
  
          Layer layer1 = LayerUtil.buildLayer(floorHeight,floorHeight);
          Layer layer2 = LayerUtil.buildLayer(floorHeight,floorHeight);
          Layer layer3 = LayerUtil.buildLayer(floorHeight,floorHeight);
  
          //构建图层的链式关系
          layer3.setParent(layer2);
          layer2.setParent(layer1);
          //parent==null说明当前这一层已经是顶层,
          //这是循环或者递归结束的重要条件
          layer1.setParent(null);
  
          map.getList().add(layer1);
          map.getList().add(layer2);
          map.getList().add(layer3);
  
          return map;
      }
  
      /**
       * 函数的作用:判断当前牌和某一图层内所有牌是否有矩阵交集。
       * true  有交集,当前牌显示灰色牌
       * false 无交集,当前牌显示正常牌
       */
      public static boolean compare(Brand brand,Layer layer){
          Cell[][] cells = layer.getCells();
          for (int row = 0; row < cells.length; row++) {
              for (int col = 0; col < cells[row].length; col++) {
                  //如果当前的单元格是空的,不用比较
                  Cell cell = cells[row][col];
                  if (cell.getState() == 1) {
                      //单元格有牌,可以比较
                      Rectangle temp = cell.getBrand().getBounds();
                      Rectangle rect = brand.getBounds();
                      boolean result = rect.intersects(temp);
                      if (result) {
                          //有交集,说明上层的牌被盖住了,判定结束,所以使用return
                          return result;
                      }
  
                  }
              }
          }
          //此时我们需要和更上层的牌进行比较判定,
          //假如当前有9层,正在比较6层当中的某个牌,比较5层
          if (layer.getParent() != null){
              return compare(brand,layer.getParent());
          } else {
              //如果parent == null 说明已经到最顶层啦
              return false;//显示正常牌
          }
  
      }
  }

以上方法只是判定是否有交集,还需要在渲染Map的时候调用。

  1. 在Map类中增加compareAll方法,判断Map中的所有牌是否为灰色

  package cn.yunhe.model;
  
  import cn.yunhe.util.MapUtil;
  
  import java.util.ArrayList;
  import java.util.List;
  
  /**
   * 一个地图有多个图层,层层之间遮盖
   */
  public class Map {
      //层高,有几张图层,游戏难度相关
      private int floorHeight;
  
      private List<Layer> list = new ArrayList<>();
  
      public int getFloorHeight() {
          return floorHeight;
      }
  
      public void setFloorHeight(int floorHeight) {
          this.floorHeight = floorHeight;
      }
  
      public List<Layer> getList() {
          return list;
      }
  
      public void setList(List<Layer> list) {
          this.list = list;
      }
  
      /**
       * 判断当前map中所有(每一张)牌,是否置灰
       */
      public void compareAll(){
          //i=0,最顶层Layer不需要判断
          for (int i = 1; i < list.size(); i++) {
              Layer layer = list.get(i);
              Cell[][] cells = layer.getCells();
              for (int row = 0; row < cells.length; row++) {
                  for (int col = 0; col < cells[row].length; col++) {
                      Cell cell = cells[row][col];
                      if (cell.getState() == 1){ //有牌
                          Brand brand = cell.getBrand();
                          //注意是给上一层,i=1,layer.getParent就是上一层 i=0
                          boolean result = MapUtil.compare(brand,layer.getParent());
                          brand.setGray(result);//设置为灰色
                      }
                  }
              }
          }
      }
  }
  1. 修改Brand类事件处理的代码,如果是灰色单击事件不用响应

  public Brand(String name){
      this.name = name;
      this.image = Toolkit.getDefaultToolkit().getImage("imgs//"+name + ".png");
      this.grayImage = Toolkit.getDefaultToolkit().getImage("imgs//"+name+"_gray.png");
      this.addMouseListener(new MouseAdapter() {
          @Override
          public void mouseClicked(MouseEvent e) {
              System.out.println("Brand. mouseClicked 响应鼠标单击事件");
              Brand brand = (Brand) e.getSource();//获取事件源
              if (brand.getGray()) {//灰色  true
                  return;//  return num; 只有return表示结束当前方法的执行
              }else {
                  //通过父容器删除自己,一般树形结构使用这种方式
                  brand.getParent().remove(brand);
              }
  
          }
      });
  }
  1. 在TestRenderMap类中调用compareAll方法

  public TestRenderMap() {
      //1.初始化基本信息
      init();
      //2.渲染图层:添加组件的方法,可以添加自己定义的组件都当前的窗口中
      List<Layer> list = map.getList();
      for (Layer layer : list) {
          renderLayer(layer);
      }
      map.compareAll();//游戏开始时调用
  
      //3.自动刷新
      autoRefresh();
  }
  1. 测试执行效果

被遮盖的牌显示未灰色,点击也没有响应。

image-20221216221753184.png

但是点击完正常颜色的牌后,灰色的牌并没有变成彩色的。

image-20221216221920649.png

  1. 说明:在删除一张牌的时候,需要调用Map的比较方法,重新计算是否遮盖显示灰色牌,问题是Brand类中没有Map对象,如何解决?也就是在删除牌的时候我们需要调用一次map的comapareAll方法,这时需要把map对象声明为共有全局对象。代码如下:

  public class TestRenderMap extends JFrame {
      public static final Map map = MapUtil.buildMap(3);//把private改为public
  	//以下代码略
  1. 在Brand类中调用map的comapareAll方法,修改Brand类的事件监听方法。

  public Brand(String name){
  		//代码略...
          this.addMouseListener(new MouseAdapter() {
              @Override
              public void mouseClicked(MouseEvent e) {
                  System.out.println("Brand. mouseClicked 响应鼠标单击事件");
                  Brand brand = (Brand) e.getSource();//获取事件源
                  if (brand.getGray()) {//灰色
                      return;
                  }else {
                      //通过父容器删除自己,一般树形结构使用这种方式
                      brand.getParent().remove(brand);
                      //调用比较的方法
                      //TestRenderMap类,map是公有静态属性,compareAll方法
                      TestRenderMap.map.compareAll();
                      //System.out.println()
                  }
              }
          });
      }

运行测试,发现漏出的灰色图片还是不能点击,还是灰色的,如下图所示:

image-20221216224550336.png

  1. 如何解决以上问题?通过brand.getParent().remove(brand);只是在UI树中删除了brand对象,但是在Cell当中的状态state和brand并没有删除。界面删除了,但是在我们构建的数据结构中没有删除,内存中的引用没有删除。如何修改这个Bug?

  2. 既要删除UI树中的组件,还要删除数据模型中的数据和对应的状态,这是两套体系。如何删除呢?我们需要把cell对象的内容做个修改:

  cell.setState(0);//置为无牌状态
  cell.setBrand(null);//引用对象为null

但是Brand类中没有单元格对象,我们需要在Brand类中增加单元格对象的属性,也就是Brand对象要知道自己属于哪个单元格。单元格包括那张牌,他们两个应该互通的。

  1. 修改Brand类,增加Cell属性,并生成getter、setter方法

   public class Brand extends JComponent{
   	//代码略....
       //宽高
       private int width = 50;
       private int height = 50;
       
       private Cell cell;
       //代码略....
       public Cell getCell() {
           return cell;
       }
   
       public void setCell(Cell cell) {
           this.cell = cell;
       }
   }

问题:Brand对象如何获取Cell对象? 先思考Cell对象什么时候绑定的Brand对象?

  1. 修改LayerUtil工具类的代码

   package cn.yunhe.util;
   
   import cn.yunhe.model.Brand;
   import cn.yunhe.model.Cell;
   import cn.yunhe.model.Layer;
   
   public class LayerUtil {
       public static Layer buildLayer(int rowNum,int colNum){
           Layer layer = new Layer(rowNum,colNum);
   
           Brand[] brands = BrandUtil.buildBrands(layer.getCapacity());
   
           Cell[][] cells = layer.getCells();
           int flag = 0;
           for (int row = 0; row < cells.length; row++) {
               for (int col = 0; col < cells[row].length; col++) {
                   Brand brand = brands[flag++];//不是创建新对象,
   
                   Cell cell = new Cell();
                   cell.setState(1);
                   cell.setBrand(brand);//把牌放到单元格
   				cells[row][col] = cell;
                   
                   brand.setCell(cell);//把单元格赋值给牌
               }
           }
   
           return  layer;
       }
   }
  1. 再修改Brand类对象,在删除牌的时候,把单元格的数据修改一下

   public Brand(String name){
       this.name = name;
       this.image = Toolkit.getDefaultToolkit().getImage("imgs//"+name + ".png");
       this.grayImage = Toolkit.getDefaultToolkit().getImage("imgs//"+name+"_gray.png");
       this.addMouseListener(new MouseAdapter() {
           @Override
           public void mouseClicked(MouseEvent e) {
               System.out.println("Brand. mouseClicked 响应鼠标单击事件");
               Brand brand = (Brand) e.getSource();//获取事件源
               if (brand.getGray()) {//灰色
                   return;
               }else {
                   //通过父容器删除自己,一般树形结构使用这种方式
                   brand.getParent().remove(brand);
                   cell.setState(0);//无牌状态
                   cell.setBrand(null);//无牌引用
                   //调用比较的方法
                   TestRenderMap.map.compareAll();
               }
   
           }
       });
   }

再次运行测试类,可以看到第2层、第3层可以正常显示了。

image-20221216230606697.png

  1. 至此完成遮盖算法的全部实现。

五、本章总结

static 关键字

递归方法调用

矩阵交集方法

六、本章作业

  1. static 关键字的案例

  2. 递归方法调用的案例

  3. 矩阵交集的案例

  4. 本章的项目

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。