JAVA游戏项目之消除区域和背景音乐

举报
tea_year 发表于 2025/05/29 17:22:23 2025/05/29
【摘要】 消除区域和背景音乐一、本章目标绘制消除区域添加背景图片添加背景音乐二、涉及知识点集合的排序: 名称相同的牌在一起,准备消除集合的Stream操作: 三个一组可以执行删除,Stream流,水流集合的删除:并发删除异常, 如果是三个执行删除操作集合的遍历: map集合的遍历方式,list和set都比较简单jdk8的新特性: lamda表达式、方法引用三、知识点讲解集合的排序实现牌的排序功能pac...

消除区域和背景音乐

一、本章目标

绘制消除区域

添加背景图片

添加背景音乐

二、涉及知识点

集合的排序: 名称相同的牌在一起,准备消除

集合的Stream操作: 三个一组可以执行删除,Stream流,水流

集合的删除:并发删除异常, 如果是三个执行删除操作

集合的遍历: map集合的遍历方式,list和set都比较简单

jdk8的新特性: lamda表达式、方法引用


三、知识点讲解

集合的排序

实现牌的排序功能

package cn.yunhe.demo;
​
import cn.yunhe.model.Brand;
​
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
​
public class TestArrayList {
    public static void main(String[] args) {
        Brand brand1 = new Brand("刷子");
        Brand brand2 = new Brand("剪刀");
        Brand brand3 = new Brand("水桶");
        Brand brand4 = new Brand("剪刀");
        Brand brand5 = new Brand("剪刀");
        Brand brand6 = new Brand("水桶");
        List<Brand> list = new ArrayList<Brand>();
        list.add(brand1);
        list.add(brand2);
        list.add(brand3);
        list.add(brand4);
        list.add(brand5);
        list.add(brand6);
        //要想排序:第一元素自身是可以比较的,每个人的身高,可以比较的;
        //第二种容器是有序的:高铁车厢座位都是有序的,电影院的座位也是有序的
        //第一种比较方法使用Collections工具类,Brand类需要实现Comparable接口,并实现其方法
        //Collections.sort(list);
        //第二种比较方法,直接调用list接口的sort方法,给他传入一个比较器,定义比较的规则
        /*
        list.sort(new Comparator<Brand>() {
            @Override
            public int compare(Brand o1, Brand o2) {
                return o1.getName().compareTo(o2.getName());
            }
        });
        */
        //第三种方式使用lamda表达式
        //list.sort((o1, o2) -> o1.getName().compareTo(o2.getName()));
        //第四种方式直接调用接口的静态方法,比较的是牌的名称
        list.sort(Comparator.comparing(Brand::getName));
        for (Brand brand : list) {
            System.out.print(brand.getName()+"--");
        }
    }
}

在面向对象里,如何具备某个能力?直接调用Collections.sort方法出错。原因元素自身不可以比较。

java: 对于sort(java.util.List<cn.yunhe.model.Brand>), 找不到合适的方法
    方法 java.util.Collections.<T>sort(java.util.List<T>)不适用
      (推论变量 T 具有不兼容的限制范围
        等式约束条件: cn.yunhe.model.Brand
        上限: java.lang.Comparable<? super T>)
    方法 java.util.Collections.<T>sort(java.util.List<T>,java.util.Comparator<? super T>)不适用
      (无法推断类型变量 T
        (实际参数列表和形式参数列表长度不同))

==第一种比较方法使用Collections工具类,Brand类需要实现Comparable接口,让元素具备比较性==

你的电脑功能强大吗?功能丰富吗?你的手机功能强大吗?功能丰富吗?你的电视等等。

package cn.yunhe.model;
​
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
​
//继承组件类
public class Brand extends JComponent implements Comparable<Brand>{
    private String name;//牌的名称
    private boolean isGray;//是否灰色
    private Image image;//正常图片
    private Image grayImage;//灰色图片
​
    //省略代码......
​
    @Override
    public int compareTo(Brand obj) {
        // obj是要比较的对象, 和谁比较,和当前对象,this
        int i = this.getName().compareTo(obj.getName());
        return i;
    }
}

第一种完整代码:

package cn.yunhe.demo;
​
import cn.yunhe.model.Brand;
​
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
​
public class Demo1 {
​
    public static void main(String[] args) {
        Brand brand1 = new Brand("刷子");
        Brand brand2 = new Brand("剪刀");
        Brand brand3 = new Brand("水桶");
        Brand brand4 = new Brand("剪刀");
        Brand brand5 = new Brand("剪刀");
        Brand brand6 = new Brand("水桶");
        List<Brand> list = new ArrayList<>();//普通的集合类,有序不允许重复
        list.add(brand1);
        list.add(brand2);
        list.add(brand3);
        list.add(brand4);
        list.add(brand5);
        list.add(brand6);
        System.out.println("排序之前: ");
        for (Brand brand : list){
            System.out.print(brand.getName() + "\t");
        }
        //1. 第一种排序方式:默认出错,Collections不知道排序的依据
        Collections.sort(list);
        System.out.println("\n排序之后:");
        for (Brand brand : list){
            System.out.print(brand.getName() + "\t");
        }
    }
}
​

==第二种比较方法,直接调用list接口的sort方法,给他传入一个比较器,定义比较的规则,让容器具备排序功能==

首先把Brand类实现的接口注释掉,Demo1出错,注释:Collections.sort(list);

package cn.yunhe.demo;
​
import cn.yunhe.model.Brand;
​
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
​
public class Demo2 {
​
    public static void main(String[] args) {
        Brand brand1 = new Brand("刷子");
        Brand brand2 = new Brand("剪刀");
        Brand brand3 = new Brand("水桶");
        Brand brand4 = new Brand("剪刀");
        Brand brand5 = new Brand("剪刀");
        Brand brand6 = new Brand("水桶");
        List<Brand> list = new ArrayList<>();//普通的集合类,有序不允许重复
        list.add(brand1);
        list.add(brand2);
        list.add(brand3);
        list.add(brand4);
        list.add(brand5);
        list.add(brand6);
        System.out.println("排序之前: ");
        for (Brand brand : list){
            System.out.print(brand.getName() + "\t");
        }
        //第2种排序方法,调用list的sort方法,需要一个比较器
        //告诉容器按照什么方式进行比较,高铁车厢有编号,电影院也是一个容器,具备排序功能,几排几号。
        list.sort(new Comparator<Brand>() {
            @Override
            public int compare(Brand o1, Brand o2) {
                return o1.getName().compareTo(o2.getName());
            }
        });
​
        System.out.println("\n排序之后:");
        for (Brand brand : list){
            System.out.print(brand.getName() + "\t");
        }
    }
}
​

==第三种比较方法,直接调用list接口的sort方法,使用Lamda表达式简化代码而已==

//第2种排序方法,调用list的sort方法,需要一个比较器
//告诉容器按照什么方式进行比较,
/*
list.sort(new Comparator<Brand>() {
    @Override
    public int compare(Brand o1, Brand o2) {
        return o1.getName().compareTo(o2.getName());
    }
});
*/
//第3种比较方式实用lambda表达式
list.sort((o1, o2) -> o1.getName().compareTo(o2.getName()));

==第四种比较方法,使用jdk8的新特性,比使用Lamda表达式还要简单==

package cn.yunhe.demo;
​
import cn.yunhe.model.Brand;
​
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
​
public class Demo4 {
​
    public static void main(String[] args) {
        Brand brand1 = new Brand("刷子");
        Brand brand2 = new Brand("剪刀");
        Brand brand3 = new Brand("水桶");
        Brand brand4 = new Brand("剪刀");
        Brand brand5 = new Brand("剪刀");
        Brand brand6 = new Brand("水桶");
        List<Brand> list = new ArrayList<>();//普通的集合类,有序不允许重复
        list.add(brand1);
        list.add(brand2);
        list.add(brand3);
        list.add(brand4);
        list.add(brand5);
        list.add(brand6);
        System.out.println("排序之前: ");
        for (Brand brand : list){
            System.out.print(brand.getName() + "\t");
        }
        //第4种排序方法,
        //①jdk8的第一个新特性:接口的默认方法,静态方法
        //②jdk8的第二个新特性:方法引用,本质是调用方法
        list.sort(Comparator.comparing(Brand::getName));
​
        System.out.println("\n排序之后:");
        for (Brand brand : list){
            System.out.print(brand.getName() + "\t");
        }
    }
}

字符串怎么进行比较的?普通的英语单词比较的字母的ASCII,汉字比较的编码对应的数字,GBK编码和UTF-8编码是不一样的。

ASCII码 字符 ASCII码 字符 ASCII码 字符 ASCII码 字符
0 NUT 32 (space) 64 @ 96
1 SOH 33 65 A 97 a
2 STX 34 66 B 98 b
3 ETX 35 # 67 C 99 c
4 EOT 36 $ 68 D 100 d
5 ENQ 37 % 69 E 101 e
6 ACK 38 & 70 F 102 f
7 BEL 39 , 71 G 103 g
8 BS 40 ( 72 H 104 h
9 HT 41 ) 73 I 105 i
10 LF 42 * 74 J 106 j
11 VT 43 + 75 K 107 k
12 FF 44 , 76 L 108 l
13 CR 45 - 77 M 109 m
14 SO 46 . 78 N 110 n
15 SI 47 / 79 O 111 o
16 DLE 48 0 80 P 112 p
17 DCI 49 1 81 Q 113 q
18 DC2 50 2 82 R 114 r
19 DC3 51 3 83 X 115 s
20 DC4 52 4 84 T 116 t
21 NAK 53 5 85 U 117 u
22 SYN 54 6 86 V 118 v
23 TB 55 7 87 W 119 w
24 CAN 56 8 88 X 120 x
25 EM 57 9 89 Y 121 y
26 SUB 58 : 90 Z 122 z
27 ESC 59 ; 91 [ 123 {
28 FS 60 < 92 \ 124 |
29 GS 61 = 93 ] 125 }
30 RS 62 > 94 ^ 126 ~
31 US 63 ? 95 127 DEL

集合的Stream操作

实现牌的三个一组,如果一组有三个可以消除了。

package cn.yunhe.demo;
​
import cn.yunhe.model.Brand;
​
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
​
public class TestStream {
    public static void main(String[] args) {
        Brand brand1 = new Brand("刷子");
        Brand brand2 = new Brand("剪刀");
        Brand brand3 = new Brand("水桶");
        Brand brand4 = new Brand("剪刀");
        Brand brand5 = new Brand("剪刀");
        Brand brand6 = new Brand("水桶");
        List<Brand> list = new ArrayList<Brand>();
        list.add(brand1);
        list.add(brand2);
        list.add(brand3);
        list.add(brand4);
        list.add(brand5);
        list.add(brand6);
        //需要存储:牌的名称----牌的数量 键值对
        Map<String,Integer> map = new HashMap<String, Integer>();
        for (Brand b : list) {
            //如果包括牌的名称
            if (map.containsKey(b.getName())) {
                Integer num = map.get(b.getName());
                map.put(b.getName(), ++num);
            } else {
                map.put(b.getName(), 1);
            }
        }
        System.out.println(map);
    }
}

stream的操作,流的概念,水流就要有水库(水源),蓄水池,电流要有输变电站(电源)。也可以理解为流水线,富士康的生产线。FileInputStream

实体类:

package cn.yunhe.demo;
​
public class Employee {
    private int id;
    private String name;
    private int age;
    private double salary;
    private Status status;
​
    public Employee(String name, int age, double salary) {
        this.name = name;
        this.age = age;
        this.salary = salary;
    }
​
    public Employee(int id,String name, int age, double salary, Status status) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
        this.status = status;
    }
​
    @Override
    public String toString() {
        return "Employee{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", salary=" + salary +
                ", status=" + status +
                '}';
    }
​
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    public int getAge() {
        return age;
    }
​
    public void setAge(int age) {
        this.age = age;
    }
​
    public double getSalary() {
        return salary;
    }
​
    public void setSalary(double salary) {
        this.salary = salary;
    }
​
    public int getId() {
        return id;
    }
​
    public void setId(int id) {
        this.id = id;
    }
​
    public Status getStatus() {
        return status;
    }
​
    public void setStatus(Status status) {
        this.status = status;
    }
​
    public enum Status {
        FREE, BUSY, VOCATION;
    }
}
​

stream的操作:

package cn.yunhe.demo;
​
import cn.yunhe.model.Brand;
​
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
​
public class TestStream {
    private static List<Employee> list = new ArrayList<>();
    static {
        list.add( new Employee("张三",38,5500.00) );
        list.add( new Employee("李四",30,4500.00) );
        list.add( new Employee("王五",48,6500.00) );
        list.add( new Employee("赵六",28,8500.00) );
        list.add( new Employee("赵六",28,8500.00) );
        list.add( new Employee("赵六",28,8500.00) );
        list.add( new Employee("赵六",28,8500.00) );
    }
    public static void main(String[] args) {
        demo3();
    }
    public static void demo3() {
        //获取集合的所有对象的姓名,再组成一个List集合
        List<String> listName = list.stream().
            map(Employee::getName).collect(Collectors.toList());
        listName.forEach(System.out::println);
        //过滤薪水大于5000,只取前3名,limit
        list.stream().filter(e -> e.getSalary()>5000).limit(3)
            .forEach(System.out::println);
    }
    //净水器是干什么的?
    public static void demo2() {
        Stream<Employee> employeeStream = list.stream().filter(e -> e.getAge() > 35);
        employeeStream.forEach(System.out::println);
    }
}
​

Stream的收集collect操作:

package cn.yunhe.demo;
​
import cn.yunhe.model.Brand;
​
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
​
public class TestBrandGroup {
    public static void main(String[] args) {
        Brand brand1 = new Brand("刷子");
        Brand brand2 = new Brand("剪刀");
        Brand brand3 = new Brand("水桶");
        Brand brand4 = new Brand("剪刀");
        Brand brand5 = new Brand("剪刀");
        Brand brand6 = new Brand("水桶");
        List<Brand> list = new ArrayList<Brand>();
        list.add(brand1);
        list.add(brand2);
        list.add(brand3);
        list.add(brand4);
        list.add(brand5);
        list.add(brand6);
        //牌的分组,满足3张调用删除方法
        Map<String,List<Brand>>  map= list.stream()
            .collect(Collectors.groupingBy(Brand::getName));
        Set<String> brandName = map.keySet();
        for (String name : brandName) {
            System.out.println(name + map.get(name).size());
        }
    }
   
    public void test(){
        List<String> list = emps.stream().map(Employee::getName)
            .collect(Collectors.toList());
        list.forEach(System.out::println);
        System.out.println("====================");
        Set<String> set = emps.stream().map(Employee::getName)
            .collect(Collectors.toSet());
        set.forEach(System.out::println);
        System.out.println("====================");
        HashSet<String> hashSet = emps.stream().map(Employee::getName)
            .collect(Collectors.toCollection(HashSet::new));
        hashSet.forEach(System.out::println);
    }
}
​

集合的删除

实现牌的删除

不能在遍历的时候删除集合中的元素,会出现并发修改异常:

package cn.yunhe.demo;
​
import cn.yunhe.model.Brand;
​
import java.util.ArrayList;
import java.util.List;
​
public class TestBrandDelete {
    public static void main(String[] args) {
        Brand brand1 = new Brand("刷子");
        Brand brand2 = new Brand("剪刀");
        Brand brand3 = new Brand("水桶");
        Brand brand4 = new Brand("剪刀");
        Brand brand5 = new Brand("剪刀");
        Brand brand6 = new Brand("水桶");
        List<Brand> list = new ArrayList<Brand>();
        list.add(brand1);
        list.add(brand2);
        list.add(brand3);
        list.add(brand4);
        list.add(brand5);
        list.add(brand6);
        //剪刀超过3张,怎么删除
        for (Brand brand : list) {
            if (brand.getName().equals("剪刀")){
                list.remove(brand);
            }
        }
        System.out.println("===========删除之后==============");
        System.out.println(list);
    }
}

执行之后的异常:

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
    at java.util.ArrayList$Itr.next(ArrayList.java:859)
    at cn.yunhe.demo.TestBrandDelete.main(TestBrandDelete.java:24)
​
进程已结束,退出代码1

怎么删除?使用迭代器的方式遍历和删除。

package cn.yunhe.demo;
​
import cn.yunhe.model.Brand;
​
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
​
public class TestBrandDelete {
    public static void main(String[] args) {
        Brand brand1 = new Brand("刷子");
        Brand brand2 = new Brand("剪刀");
        Brand brand3 = new Brand("水桶");
        Brand brand4 = new Brand("剪刀");
        Brand brand5 = new Brand("剪刀");
        Brand brand6 = new Brand("水桶");
        List<Brand> list = new ArrayList<Brand>();
        list.add(brand1);
        list.add(brand2);
        list.add(brand3);
        list.add(brand4);
        list.add(brand5);
        list.add(brand6);
        //剪刀超过3张,怎么删除
        //相当于小朋友上学在校门口排队,老师一个一个扒拉学生,看看有没有恐怖分子,冒牌货,不是学校的学生
        Iterator<Brand> it =  list.iterator();//iterator 迭代器可以理解为这个老师
        while (it.hasNext()) {
            Brand brand = it.next();//看下一个学生
            if (brand.getName().equals("剪刀")){
                it.remove();
            }
        }
​
        /*for (Brand brand : list) {
            if (brand.getName().equals("剪刀")){
                list.remove(brand);
            }
        }*/
        System.out.println("===========删除之后==============");
        list.forEach(e -> System.out.println(e.getName()));
    }
}
​

map集合的遍历

实现牌的名称和数量的遍历

Map<String,List<Brand>>  map = list.stream().collect(Collectors.groupingBy(Brand::getName));
Set<String> brandName = map.keySet();
for (String name : brandName) {  //遍历所有的key
    System.out.println(name + map.get(name).size());
}

jdk8的新特性

实现代码的简化

四、代码实现

1、绘制消除区域

把点击的牌放到一起list容器里,所谓绘制消除区域就是把list容器中的牌依次绘制到窗体上。

package cn.yunhe.model;
​
import java.util.ArrayList;
import java.util.List;
​
/**
 * 消除区域
 */
public class EliminateBox {
    //注意加static关键字
    private static List<Brand> slot = new ArrayList<>();
​
    public void addSlot(Brand brand){
        slot.add(brand);
        //调用绘制方法
        paint();
    }
​
    //绘制消除框
    public void paint(){
        for (int i = 0; i <slot.size(); i++){
            Brand brand = slot.get(i);
            int x = i * brand.getWidth() + 10; //宽度50,第1张牌x=10,第2张:60,110
            brand.setBounds(x,600,50,50);
        }
    }
}
  1. 在Brand类中增加EliminateBox属性,调用消除牌的方法

  public class Brand extends JComponent{
    //省略代码
      private int width = 50;
      private int height = 50;
  
      private Cell cell;
    //增加消除框属性
      private EliminateBox eliminateBox = new EliminateBox();
      public Brand(String name) {
        //省略部分代码
          //添加事件处理机制
          this.addMouseListener(new MouseAdapter() {
              @Override
              public void mouseClicked(MouseEvent e) {
                  Brand brand  = (Brand) e.getSource();
                  if (brand.isGray()) {
                      return;// 表示的结束方法的执行,直接返回
                  }
                  System.out.println("你点击了" + brand.getName());
                  //brand.getParent().remove(brand);
                  eliminateBox.addSlot(brand);//调用消除框方法
                  //删除数据结构中的数据
                  cell.setStatus(0);//无牌状态,你必须设置是当前牌所在的单元格
                  cell.setBrand(null);
                  TestRenderMap.map.compareAll();//每次点击之后都要重新计算一下图层的遮盖
              }
          });
      }
      //下面代码省略

执行效果:

image-20221220162114224.png

  1. 增加牌的排序功能,名称相同的牌放在一起

  public void addSlot(Brand brand){
      slot.add(brand);
      //牌的排序,根据牌的名称
      slot.sort(Comparator.comparing(Brand::getName));
      //调用绘制方法
      paint();
  }
  1. 问题:牌的消除条件是什么?如果达到这个条件就要消除牌,下面实现牌的删除方法。

  package cn.yunhe.model;
  
  import java.util.*;
  import java.util.Map;
  import java.util.stream.Collectors;
  
  /**
   * 消除区域
   */
  public class EliminateBox {
      private static List<Brand> slot = new ArrayList<>();
  
      public void addSlot(Brand brand){
          slot.add(brand);
          //牌的排序,根据牌的名称
          slot.sort(Comparator.comparing(Brand::getName));
          Map<String, List<Brand>> map = slot.stream().collect(Collectors.groupingBy(Brand::getName));
          Set<String> keySet = map.keySet();
          for (String key : keySet) {
              List<Brand> brands = map.get(key);
              if (brands.size() == 3){
                  deleteBrand(key);
              }
          }
          //调用绘制方法
          paint();
      }
  
      /**
       * 迭代器清空集合方法
       */
      public void deleteBrand(String name){
          Iterator<Brand> iterator = slot.iterator();
          while (iterator.hasNext()) {
              Brand brand = iterator.next();
              if (brand.getName().equals(name)) {
                  brand.getParent().remove(brand);//ui界面删除
                  iterator.remove();//数据结构删除
              }
          }
      }
  
      //绘制消除框
      public void paint(){
          for (int i = 0; i <slot.size(); i++){
              Brand brand = slot.get(i);
              int x = i * brand.getWidth() + 10;
              brand.setBounds(x,600,50,50);
          }
      }
  }

image-20230110104935458.png

  1. 游戏退出的条件是什么?

在EliminateBox类中添加游戏退出的方法,在添加牌的同时调用该方法。

  package cn.yunhe.model;
  
  import javax.swing.*;
  import java.util.*;
  import java.util.Map;
  import java.util.stream.Collectors;
  
  /**
   * 消除区域
   */
  public class EliminateBox {
      private static List<Brand> slot = new ArrayList<>(); //注意静态的属性
  
      public void addSlot(Brand brand){
          slot.add(brand);
          //省略部分代码
          //调用绘制方法
          paint();
          //调用游戏结束的方法
          gameOver();
      }
  
        //游戏退出的方法
      public void gameOver(){
          if (slot.size() == 7){
              JOptionPane.showMessageDialog(null,"Game Over!!");
              System.exit(0);
          }
      }
  }
  1. 添加音乐和背景

在项目目录下创建music和lib文件夹,并把音乐文件和jar包复制到对应的文件夹;注意把jar把添加到构建路径。点击File — Project Structre菜单,弹出项目结构对话框:

image-20221220165648578.png

image-20221220165717646.png

image-20221220165830299.png


最终效果截图:

image-20221220165940527.png

  1. 添加播放音乐的工具类

  package cn.yunhe.model;
  
  import javazoom.jl.decoder.JavaLayerException;
  import javazoom.jl.player.Player;
  
  import java.io.BufferedInputStream;
  import java.io.FileInputStream;
  import java.io.FileNotFoundException;
  
  public class Music {
      public void play()  {
          try {
              String str = System.getProperty("user.dir") +"/music/music.mp3";
              BufferedInputStream bis = new BufferedInputStream(new FileInputStream(str));
              Player player = new Player(bis);
              player.play();//播放音乐
          }catch (FileNotFoundException|JavaLayerException e) {
              e.printStackTrace();
          }
      }
  }
  1. 在TestRenderMap类中调用播放方法

  public class TestRenderMap extends JFrame {
      public static final Map map = MapUtil.buildMap(3);
      public TestRenderMap() {
          //1. 初始化窗体
          init();
          //2.渲染图层:问题图层在哪里???
          List<Layer> layerList = map.getList();
          for (int i = 0; i <layerList.size(); i++) {
              renderLayer(layerList.get(i));
          }
          //3.调用compareAll方法,判定是否为正常图片
          map.compareAll();
          //4.自动刷新线程
          autoRefresh();
          //5.调用播放音乐的方法
          new Music().music();
      }
      //下面代码略
  }

测试一下是否可以播放音乐。

  1. 添加背景和消除框图片,==注意删除Brand类的width和height的getter、setter方法==

修改TestRenderMap类增加两个属性:

  public class TestRenderMap extends JFrame {
      public static final Map map = MapUtil.buildMap(3);
      private Brand bj = new Brand("背景草地");//背景图片
      private Brand xc = new Brand("消除区域");//消除背景图片
      public TestRenderMap() {
          //1. 初始化窗体
          init();
  
          //绘制背景和消除区域
          xc.setBounds(0,575,450,800);
          this.getContentPane().add(xc);
  
          bj.setBounds(0,0,450,800);
          this.getContentPane().add(bj);
  
          //2.渲染图层:问题图层在哪里???
          List<Layer> layerList = map.getList();
          for (int i = 0; i <layerList.size(); i++) {
              renderLayer(layerList.get(i));
          }
          //3.调用compareAll方法,判定是否为正常图片
          map.compareAll();
          //4.自动刷新线程
          autoRefresh();
          //5.调用播放音乐的方法
          new Music().music();
      }
          /**
       * 渲染的图层的数据
       */
      public void renderLayer(Layer layer ){
          //获取单元格
          Cell[][] cells = layer.getCells();
          for (int row = 0; row < cells.length; row++) {
              for (int col = 0; col < cells[row].length; col++) {
                  Brand brand = cells[row][col].getBrand();
                  int x = col * 50 + layer.getOffsetx(); 
                  int y = row * 50 + layer.getOffsety(); 
                  brand.setBounds(x,y,50,50);
                  this.getLayeredPane().add(brand);//注意改为LayeredPane否则出现遮盖
              }
          }
      }
      //后面代码.....
  }


  1. 再次调试运行,如下图所示, 点背景草地和消除区域出现bug,两个牌也隐藏了,如何解决:

image-20221220181858067.png

在Brand类的事件处理机制加如下代码:

public Brand(String name) {
        //给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) {
                Brand brand  = (Brand) e.getSource();
                if (brand.isGray() || brand.getName().equals("背景草地") || brand.getName().equals("消除区域")) {
                    return;// 表示的结束方法的执行,直接返回
                }
                System.out.println("你点击了" + brand.getName());
                //brand.getParent().remove(brand);//自杀方式
                eliminateBox.addSlot(brand);
                brand.removeMouseListener(this);//消除框的牌移除事件
                //删除数据结构中的数据
                cell.setStatus(0);//无牌状态,你必须设置是当前牌所在的单元格
                cell.setBrand(null);
                TestRenderMap.map.compareAll();//每次点击之后都要重新计算一下图层的遮盖
            }
        });
    }

再次测试运行即可。

五、本章总结

集合的排序

集合的Stream操作

集合的删除:并发删除异常

map集合的遍历

jdk8的新特性

六、本章作业

集合的排序

集合的Stream操作

集合的删除:并发删除异常

map集合的遍历

jdk8的新特性

项目案例的代码

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

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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