【JAVA学习笔记】67 - 坦克大战1.5 - 1.6,防止重叠,记录成绩,选择是否开新游戏或上局游戏,播放游戏音乐

项目代码

https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter20/src

增加功能

1.防止敌人坦克重叠运动

2.记录玩家的成绩,存盘退出

3.记录当时的敌人坦克坐标,存盘退出

4.玩游戏时,可以选择是开新游戏还是继续上局游戏

1.防止敌人坦克重叠运动 

这个功能想蛮久的。因为一开始的想法是判断矩形有没有进去,但是这样判断的话,左右的矩形和上下的矩形都是一样,所以判断方向会把02或者13直接判断,后面看了老师的改用方向的角判断

1.判断是否碰撞

该方法完成了是否碰撞的判断,传入的tank和tank分别为this和enemy,testDirect代表测试方向是否可行,因为总感觉就当前方向不太合适。返回的int代表当前方向为错误方向,即走不过去

    public static int tankScopeIf(Tank tank, Tank tank1, int testDirect) {
        if (testDirect == 0) {
            switch (tank1.getDirect()) {
                case 0:
                case 2:
                    //左上角坐标[tank.getX - 20 ,tank.getY - 30]
                    if (tank.getX() - 20 >= tank1.getX() - 20
                            && tank.getX() - 20 <= tank1.getX() + 20
                            && tank.getY() - 30 >= tank1.getY() - 30
                            && tank.getY() - 30 <= tank1.getY() + 30) {
                        return 0;
                    }
                    //右上角坐标[tank.getX + 20 , tank.getY - 30]
                    if (tank.getX() + 20 >= tank1.getX() - 20
                            && tank.getX() + 20 <= tank1.getX() + 20
                            && tank.getY() - 30 >= tank1.getY() - 30
                            && tank.getY() - 30 <= tank1.getY() + 30) {
                        return 0;
                    }
                    break;
                case 1:
                case 3:
                    //左上角坐标[tank.getX - 20 ,tank.getY - 30]
                    if (tank.getX() - 20 >= tank1.getX() - 30
                            && tank.getX() - 20 <= tank1.getX() + 30
                            && tank.getY() - 30 >= tank1.getY() - 20
                            && tank.getY() - 30 <= tank1.getY() + 20) {
                        return 0;
                    }
                    //右上角坐标[tank.getX + 20 , tank.getY - 30]
                    if (tank.getX() + 20 >= tank1.getX() - 30
                            && tank.getX() + 20 <= tank1.getX() + 30
                            && tank.getY() - 30 >= tank1.getY() - 20
                            && tank.getY() - 30 <= tank1.getY() + 20) {
                        return 0;
                    }
                    break;
            }
        } else if (testDirect == 2) {
            switch (tank1.getDirect()) {
                case 0:
                case 2:
                    //左下角坐标[tank.getX - 20 ,tank.getY + 30]
                    if (tank.getX() - 20 >= tank1.getX() - 20
                            && tank.getX() - 20 <= tank1.getX() + 20
                            && tank.getY() + 30 >= tank1.getY() - 30
                            && tank.getY() + 30 <= tank1.getY() + 30) {
                        return 2;
                    }
                    //右下角坐标[tank.getX + 20 , tank.getY + 30]
                    if (tank.getX() + 20 >= tank1.getX() - 20
                            && tank.getX() + 20 <= tank1.getX() + 20
                            && tank.getY() + 30 >= tank1.getY() - 30
                            && tank.getY() + 30 <= tank1.getY() + 30) {
                        return 2;
                    }
                    break;
                case 1:
                case 3:
                    //左下角坐标[tank.getX - 20 ,tank.getY + 30]
                    if (tank.getX() - 20 >= tank1.getX() - 30
                            && tank.getX() - 20 <= tank1.getX() + 30
                            && tank.getY() + 30 >= tank1.getY() - 20
                            && tank.getY() + 30 <= tank1.getY() + 20) {
                        return 2;
                    }
                    //右下角坐标[tank.getX + 20 , tank.getY + 30]
                    if (tank.getX() + 20 >= tank1.getX() - 30
                            && tank.getX() + 20 <= tank1.getX() + 30
                            && tank.getY() + 30 >= tank1.getY() - 20
                            && tank.getY() + 30 <= tank1.getY() + 20) {
                        return 2;
                    }
                    break;
            }
        } else if (testDirect == 1) {
            switch (tank1.getDirect()) {
                case 0:
                case 2:
                    //右上角坐标[tank.getX + 30 ,tank.getY - 20]
                    if (tank.getX() + 30 >= tank1.getX() - 20
                            && tank.getX() + 30 <= tank1.getX() + 20
                            && tank.getY() - 20 >= tank1.getY() - 30
                            && tank.getY() - 20 <= tank1.getY() + 30) {
                        return 1;
                    }
                    //右下角坐标[tank.getX + 30 , tank.getY + 20]
                    if (tank.getX() + 30 >= tank1.getX() - 20
                            && tank.getX() + 30 <= tank1.getX() + 20
                            && tank.getY() + 20 >= tank1.getY() - 30
                            && tank.getY() + 20 <= tank1.getY() + 30) {
                        return 1;
                    }
                    break;
                case 1:
                case 3:
                    //右上角坐标[tank.getX + 30 ,tank.getY - 20]
                    if (tank.getX() + 30 >= tank1.getX() - 30
                            && tank.getX() + 30 <= tank1.getX() + 30
                            && tank.getY() - 20 >= tank1.getY() - 20
                            && tank.getY() - 20 <= tank1.getY() + 20) {
                        return 1;
                    }
                    //右下角坐标[tank.getX + 30 , tank.getY + 20]
                    if (tank.getX() + 30 >= tank1.getX() - 30
                            && tank.getX() + 30 <= tank1.getX() + 30
                            && tank.getY() + 20 >= tank1.getY() - 20
                            && tank.getY() + 20 <= tank1.getY() + 20) {
                        return 1;
                    }
                    break;
            }
        } else if (testDirect == 3) {
            switch (tank1.getDirect()) {
                case 0:
                case 2:
                    //左上角坐标[tank.getX - 30 ,tank.getY - 20]
                    if (tank.getX() - 30 >= tank1.getX() - 20
                            && tank.getX() - 30 <= tank1.getX() + 20
                            && tank.getY() - 20 >= tank1.getY() - 30
                            && tank.getY() - 20 <= tank1.getY() + 30) {
                        return 3;
                    }
                    //左下角坐标[tank.getX - 30 , tank.getY + 20]
                    if (tank.getX() - 30 >= tank1.getX() - 20
                            && tank.getX() - 30 <= tank1.getX() + 20
                            && tank.getY() + 20 >= tank1.getY() - 30
                            && tank.getY() + 20 <= tank1.getY() + 30) {
                        return 3;
                    }
                    break;
                case 1:
                case 3:
                    //左上角坐标[tank.getX - 30 ,tank.getY - 20]
                    if (tank.getX() - 30 >= tank1.getX() - 30
                            && tank.getX() - 30 <= tank1.getX() + 30
                            && tank.getY() - 20 >= tank1.getY() - 20
                            && tank.getY() - 20 <= tank1.getY() + 20) {
                        return 3;
                    }
                    //左下角坐标[tank.getX - 30 , tank.getY + 20]
                    if (tank.getX() - 30 >= tank1.getX() - 30
                            && tank.getX() - 30 <= tank1.getX() + 30
                            && tank.getY() + 20 >= tank1.getY() - 20
                            && tank.getY() + 20 <= tank1.getY() + 20) {
                        return 3;
                    }
                    break;
            }
        }
        return -1;
    }
}

2.接收错误方向

该方法先调用了地图范围判断,如果判断错误就把该方向计入有墙的方向,随后判断tank之间是否相互碰撞,如果传入四个值0123代表四个方向,如果返回的不是-1代表该方向无法前进,随后该方法返回一个列表

 public Vector<Integer> getSafeDirect() {
        Vector<Integer> safeDirects = new Vector<>();
        Vector<Integer> wrongDirects = new Vector<>();
        int direct;
        int cantMove;
        int haveHellDirect = -1;
        for (int i = 0; i < 4; i++) {
            safeDirects.add(i);
        }
        for (int i = 0; i < 4; i++) {
            if (Map.scopeIf(this, i)) {
                haveHellDirect = i;
                wrongDirects.add(haveHellDirect);
            }
        }

        for (int i = 0; i < enemies.size(); i++) {

            Enemy enemy = enemies.get(i);
            if (this == enemy) {
                continue;
            }
            for (int j = 0; j < 4; j++) {
                if ((cantMove = Map.tankScopeIf(this, enemy, j)) != -1) {
                    wrongDirects.add(cantMove);
                }
            }
        }
        safeDirects.removeAll(wrongDirects);
        System.out.println("不能移动的方向" + wrongDirects);
        return safeDirects;
    }

3.设置坦克方向

该方法完成了对安全方向的接受,接收到安全的方向后判断是否为空,为空代表没有方向安全,直接return,然后判断当前方向是否安全,安全就移动,然后移动的次数计数器count++,如果没有安全的方向,在安全方向里随机一个出来设置为该坦克的方向。

最后判断移动的次数,如果是5次以上就随机转向,然后重置计数

public void randomMove() {
        Vector<Integer> safeDirects = getSafeDirect();
        if (safeDirects.isEmpty()) {
            System.out.println("该敌人无法移动");
            return;
        }

        if (safeDirects.contains(this.getDirect())) {
            move();
            count++;
        }else {
            int index = (int) (Math.random() * safeDirects.size());//0-size
            setDirect(safeDirects.get(index));
        }
        if (count >= (int) (Math.random() * 40) && count > 5) {//当移动的次数大于某个值的时候,改变方向,0-39的范围
            int index = (int) (Math.random() * safeDirects.size());//0-size
            setDirect(safeDirects.get(index));
            count = 0;//计数为0
        }
    }

2.记录玩家的成绩,存盘退出

创建一个记录类,该类内实现记录击毁数量,输出字符流写入硬盘。

public class Recorder  {
    //定义变量,记录击毁坦克数量
    private static int destroyEnemy = 0;
    private static FileWriter fileWriter = null;
    private static BufferedWriter bufferedWriter = null;
    private static String recordPath = "src\\com\\yinhai\\tankgame1_5\\DestroyEnemyCount.txt";

    public static int getDestroyEnemy() {
        return destroyEnemy;
    }

    public static void setDestroyEnemy(int destroyEnemy) {
        Recorder.destroyEnemy = destroyEnemy;
    }
    public static void addDestroyEnemyCount(){
        destroyEnemy++;
    }
    public static void keepRecord() {
        try {
           bufferedWriter = new BufferedWriter(new FileWriter(recordPath,true));
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss E");
            String format = sdf.format(new Date()); // format:将日期转换成指定格式的字符串
           bufferedWriter.write( format + " 坦克大战游戏击毁数量为 " + destroyEnemy + "\n");

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(bufferedWriter != null){
                try {
                    bufferedWriter.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

3.记录当时的敌人坦克坐标/方向,存盘退出

在keepRecord增加功能,遍历敌人列表,保存X Y 和 方向,记得在开始游戏的时候在构造器或者能调用的地方使用set方法指向该enemies,不然一直都是null

            for (int i = 0; i < enemies.size(); i++) {
                Enemy enemy = enemies.get(i);
                if(enemy.isLive()){
                    //保存该信息
                    String record = "敌人信息" + i + " " + enemy.getX() + " "
                            + enemy.getY() + " " + enemy.getDirect() + "\r\n";
                    //写入到文件
                    bufferedWriter.write(record);
                }
            }

4.玩游戏时,可以选择是开新游戏还是继续上局游戏

可以使用对象流保存,但是最好不要更改已有的代码,所以新开一个类Node,该类拥有X Y direct,然后定义一个Vector列表保存Node,Node保存敌人的信息

该nodeHero类用于保存hero的基本信息,如击杀数等

public class Node implements Serializable {
    private int x;
    private int y;
    private int direct;
}
public class NodeHero extends Node{
    private int destroyEnemyCount;
    public NodeHero(int x, int y, int direct,int destroyEnemyCount) {
        super(x, y, direct);
        this.destroyEnemyCount = destroyEnemyCount;
    }

    public int getDestroyEnemyCount() {
        return destroyEnemyCount;
    }
}

接着在ReadCoder类内编写方法,记录信息。save方法用于保存数据到nodes内,定义输出流,将Vector<Node>(该类实现Serilizeable接口)直接输出为文件存盘。如果需要读取,调用recovery方法,该方法使用对象输入流,将该文件反序列化为对象,然后返回该nodes

    private static Vector<Enemy> enemies = null;
    private static Hero hero = null;
    private static Vector<Node> nodes = null;

    public static Vector<Node> recoveryEnemies() {
        try {
            nodes = new Vector<>();
            objectInputStream = new ObjectInputStream(new FileInputStream(recordEnemyInfoPath));
            nodes =(Vector<Node>)objectInputStream.readObject();
            System.out.println("读取完毕");
            return nodes;
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
            System.out.println("无上局游戏记录");
            System.exit(0);
        }
        finally {
            try {
                if (objectInputStream != null) {
                    objectInputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
    public static void saveNode() throws IOException {
        nodes = new Vector<>();
        if(hero.isLife()){
            nodes.add(0,new NodeHero(hero.getX(),hero.getY(), hero.getDirect(),Recorder.destroyEnemy));
        }else{
            nodes.add(0,null);
        }

        for (int i = 0; i < enemies.size(); i++) {
            Enemy enemy = enemies.get(i);
            if(enemy.isLive()){
                nodes.add(new Node(enemy.getX(),enemy.getY(),enemy.getDirect()));
            }
        }

        if (!nodes.isEmpty()){
            objectOutputStream.writeObject(nodes);
        }


    }

然后分别在程序关闭以及开始的地方调用这两个方法,例如save方法在程序关闭时调用

public class YinhaiTankGame01 extends JFrame {
    MyPanel myPanel = null;
    public static void main(String[] args) {
        YinhaiTankGame01 yinhaiTankGame01 = new YinhaiTankGame01();


    }

    public YinhaiTankGame01(){
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入1:新游戏 2:上一局游戏");
        String key = scanner.next();
        myPanel = new MyPanel(key);
        this.add(myPanel);
        this.setSize(1600,900);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
        this.addKeyListener(myPanel);
        new Thread(myPanel).start();
        //增加响应关闭窗口的处理
        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.out.println("检测到关闭窗口");
                Recorder.keepRecord();
                System.exit(0);
            }
        });
    }
}

使用了addWindowListener方法,当检测到关闭窗口时保存数据,在创建画板时传入key值,用于在画板的构造器内判断是否继续游戏,在该画板内如果为1,开始新游戏,将原先构造器的内容放入case语句块内即可,如果为1,调用获取记录方法,获得nodes,然后将nodes的属性分别赋给hero与enemy。

public MyPanel(String key) {
        switch (key){
            case "1":
                int xInitialize = 0;
                int yInitialize = 100;
                int count = 0;
                for (int i = 0; i < enemyNum; i++) {
                    count++;
                    if ((xInitialize = 100 * (count)) >= 1500) {
                        yInitialize += 100;
                        count = 0;
                    }
                    if (yInitialize >= 800) {
                        break;
                    }
                    Enemy enemy = new Enemy(xInitialize, yInitialize, 10);
                    hero = new Hero(800, 450, 10.0);//初始化位置
                    Thread thread = new Thread(enemy);
                    thread.start();
                    enemy.setHero(hero);
                    enemies.add(enemy);
                    enemy.setEnemies(enemies);
                    Recorder.setEnemies(enemies);
                    Recorder.setHero(hero);
                }
                break;
            case "2"://继续上次游戏
                nodes = Recorder.recoveryEnemies();
                if (nodes == null){
                    System.out.println("无上局游戏记录");
                    return;
                }
                if(nodes.get(0) == null){
                    System.out.println("hero 死亡上局游戏无法继续");
                }else{
                    NodeHero nodeHero =(NodeHero)nodes.get(0);
                    hero = new Hero(nodeHero.getX(),nodeHero.getY(),10);
                    hero.setDirect(nodeHero.getDirect());
                    Recorder.setDestroyEnemy(nodeHero.getDestroyEnemyCount());
                }
                for (int i = 1; i < nodes.size(); i++) {
                    Node node = nodes.get(i);
                    Enemy enemy = new Enemy(node.getX(),node.getY(),10);
                    enemy.setDirect(node.getDirect());
                    Thread thread = new Thread(enemy);
                    thread.start();
                    enemy.setHero(hero);
                    enemies.add(enemy);
                    enemy.setEnemies(enemies);
                    Recorder.setEnemies(enemies);
                    Recorder.setHero(hero);
                }
                break;
            default:
                System.out.println("错误的输入");
        }

5.在开始游戏的时候添加音乐

调用该API在画板绘图完成的时候启动该线程即可

package com.yinhai.tankgame1_5;

import javax.sound.sampled.*;
import java.io.File;
import java.io.IOException;

/**
 * @author 韩顺平
 * @version 1.0
 */
public class AePlayWave extends Thread {
    private String filename;

    public AePlayWave(String wavfile) { //构造器 , 指定文件
        filename = wavfile;

    }

    public void run() {

        File soundFile = new File(filename);

        AudioInputStream audioInputStream = null;
        try {
            audioInputStream = AudioSystem.getAudioInputStream(soundFile);
        } catch (Exception e1) {
            e1.printStackTrace();
            return;
        }

        AudioFormat format = audioInputStream.getFormat();
        SourceDataLine auline = null;
        DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);

        try {
            auline = (SourceDataLine) AudioSystem.getLine(info);
            auline.open(format);
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }

        auline.start();
        int nBytesRead = 0;
        //这是缓冲
        byte[] abData = new byte[512];

        try {
            while (nBytesRead != -1) {
                nBytesRead = audioInputStream.read(abData, 0, abData.length);
                if (nBytesRead >= 0)
                    auline.write(abData, 0, nBytesRead);
            }
        } catch (IOException e) {
            e.printStackTrace();
            return;
        } finally {
            auline.drain();
            auline.close();
        }

    }
}

6.增加判断,如果文件不存在不开启游戏

使用File类的文件查找即可

总结:

        思路还算清晰,但是在对象流是否能精准的拿到多个对象的最后一个对象上查了很久,结论是不行,所以改用列表的方式序列化。然后就是要多写,确实不写起来很难用好面向对象的理念。重叠的想了非常久,老师的方法更简洁一点,如果当前方向走不了就随机给个方向再判断。我的想法就是全部枚举出来错误的方向,然后不走那个方向即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/125919.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

尚硅谷大数据项目《在线教育之实时数仓》笔记007

视频地址&#xff1a;尚硅谷大数据项目《在线教育之实时数仓》_哔哩哔哩_bilibili 目录 第9章 数仓开发之DWD层 P053 P054 P055 P056 P057 P058 P059 P060 P061 P062 P063 P064 P065 第9章 数仓开发之DWD层 P053 9.6 用户域用户注册事务事实表 9.6.1 主要任务 读…

Facebook主页评分的优化建议

Facebook是全球最大的社交媒体平台之一&#xff0c;它拥有着超10亿的用户&#xff0c;那么在这个竞争激烈的平台上维护和优化你的Facebook主页评分对于增加曝光度以及吸引更多的粉丝和提升品牌形象是非常重要的&#xff0c;下面小编将讲讲Facebook主页评分的优化建议。 1、清楚…

《国产服务器操作系统发展报告(2023)》重磅发布

11月1日&#xff0c;《国产服务器操作系统发展报告&#xff08;2023&#xff09;》&#xff08;以下简称“报告”&#xff09;在 2023 云栖大会上正式发布&#xff0c;开放原子开源基金会理事长孙文龙、中国信息通信研究院副总工程师石友康、阿里云基础软件部副总裁马涛、浪潮信…

MathWorks Matlab R2023b ARM Mac报错 License Manager Error -8

MathWorks Matlab R2023b 23.2.0.2365128 ARM 版本安装激活后出现报错&#xff1a; License Manager Error -8 License checkout failed. License Manager Error -8 Make sure the HostID of the license file matches this machine, and that the HostID on the SERVER line m…

k8s存储卷 PV和PVC

目录 emptyDir存储卷 hostPath存储卷 nfs共享存储卷 PVC 和 PV 生命周期 一个PV从创建到销毁的具体流程如下&#xff1a; 静态pvc 动态pvc 3、定义PVC 4、测试访问 搭建 StorageClass NFS&#xff0c;实现 NFS 的动态 PV 创建 1、在stor01节点上安装nfs&#xff0…

VINS-Mono-后端优化 (二:预积分残差雅可比推导)

文章目录 对位置 δ α \delta\alpha δα 进行求导位置误差 δ α \delta\alpha δα 对平移 P b k w P^{w}_{b_{k}} Pbk​w​ 的求导位置 δ α \delta\alpha δα 对旋转 R w b k R^{b_{k}}_{w} Rwbk​​ 进行求导 对速度 δ β \delta\beta δβ 进行求导速度 δ β…

Vuex介绍

一、Vuex 概述 目标&#xff1a;明确Vuex是什么&#xff0c;应用场景以及优势 1.是什么 Vuex 是一个 Vue 的 状态管理工具&#xff0c;状态就是数据。 大白话&#xff1a;Vuex 是一个插件&#xff0c;可以帮我们管理 Vue 通用的数据 (多组件共享的数据)。例如&#xff1a;购…

创建多层级行索引,创建多层级行索引的DataFrameMultiIndex.from_product()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 创建多层级行索引, 创建多层级行索引的DataFrame MultiIndex.from_product() [太阳]选择题 使用pd.MultiIndex.from_product()&#xff0c;下列输出正确的是&#xff1a; import pandas as pd…

【操作系统】考研真题攻克与重点知识点剖析 - 第 2 篇:进程与线程

前言 本文基础知识部分来自于b站&#xff1a;分享笔记的好人儿的思维导图与王道考研课程&#xff0c;感谢大佬的开源精神&#xff0c;习题来自老师划的重点以及考研真题。此前我尝试了完全使用Python或是结合大语言模型对考研真题进行数据清洗与可视化分析&#xff0c;本人技术…

在Word中优雅的给公式编号,且自动更新

本文适用情景&#xff1a; 使用Word插入公式&#xff1b;需要给公式增加编号&#xff1b;且在正文中引用&#xff0c;支持自动更新序号。 Word自带公式编号 1 Word自带公式编辑器1.1 问题1.2 原因完美解决 2 MathType公式编辑器end: 后记&#xff1a; 1 Word自带公式编辑器 或…

卡尔曼滤波EKF

目录 一、概述 二、卡尔曼滤波的5个公式 三、应用案例&#xff1a;汽车运动 四、应用案例&#xff1a;温度估计 五、总结 一、概述 初学者对于卡尔曼滤波5个公式有点懵&#xff0c;本文先接地气地介绍5个公式&#xff0c;然后举两个常用例子加强理解&#xff0c;同时附有M…

【媒体邀约】媒体宣传——企业成长的催化剂

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 媒体宣传是企业成长的催化剂&#xff0c;它在各种方面对企业的成功和发展起到了关键作用。 1. 曝光和知名度&#xff1a; 媒体宣传可以将企业和其产品或服务推向广泛的受众&#xff0c;…

Vue脚手架学习笔记

视频 Vue脚手架学习笔记 1. 脚手架设置相关内容1.1 各文件的作用1.2 关闭语法检查 2. 组件的使用2.1 单文件组件的使用&#xff08;组件使用的三个步骤&#xff09;2.2 prop配置项&#xff1a;父向子传数据2.2.1 数组方式2.2.2 类型限制2.2.3 默认值、必要性 2.3 ref &#xf…

Hello Qt!

目录 1. 什么是Qt 2. Qt中的模块 3. 下载安装 4. QtCreator 4. Hello Qt 解释 .pro 解释 main.cpp 解释 mainwindow.ui 解释 mainwindow.h 解释 mainwindow.cpp 5. Qt 中的窗口类 5.1 基础窗口类 5.2 窗口的显示 6. Qt 的坐标体系 7. 内存回收 1. 什么是Qt 是一…

评估APP网页小程序代码UI开发H5估价师怎么评估开发精确研发价格?

作为一名应用程序开发评估师&#xff0c;可能涉及到的主要任务是为特定的应用程序提供估算开发成本和所需时间预测。为了为一个应用程序更准确地评估价格&#xff0c;须遵循以下几个步骤&#xff1a; 问: 如何让一个App更好、更精确地评估出价格&#xff1f; 答: 以下是一个可…

一款功能强大的web目录扫描器专业版

dirpro 简介 dirpro 是一款由 python 编写的目录扫描器&#xff0c;操作简单&#xff0c;功能强大&#xff0c;高度自动化。 自动根据返回状态码和返回长度&#xff0c;对扫描结果进行二次整理和判断&#xff0c;准确性非常高。 已实现功能 可自定义扫描线程 导入url文件进…

1. Collection,List, Map, Queue

1. java集合框架体系结构图 2. Collection派生的子接口 其中最重要的子接口是&#xff1a; 1&#xff09;List 表示有序可重复列表&#xff0c;重要的实现类有&#xff1a;ArrayList, LinkedList ArrayList特点&#xff1a;底层数组实现&#xff0c;随机查找快&#xff0c;增删…

centos 上redis以及远程连接工具rdm安装与使用

目录 一 安装包准备 二 安装 三 启动 redis 四 rdm 连接 redis 一 安装包准备 redis 6.2.4 网盘资源&#xff1a; 链接: https://pan.baidu.com/s/1R120Va9FEyraLdiPe9fBHg?pwdgq9i 提取码: gq9i rdm 网盘资源&#xff1a; 链接: https://pan.baidu.com/s/1GiYnfIuQdSUmM…

服装展示服务预约小程序的内容如何

互联网电商深入&#xff0c;很多服装商家开始线上卖货经营、会员管理及私域营销等&#xff0c;这也是当今商家们的一个优选项&#xff0c;当然除了直接卖货以外&#xff0c;展示和预约、客户交互也同样是不少商家需要的。 那么商家通过服装展示预约小程序能够实现什么效果呢&a…

19 数据中心详解

1、数据中心的概念 其实平时我们不管是看新闻&#xff0c;视频&#xff0c;下载文件等&#xff0c;最终访问的目的地都是在数据中心里面。数据中心存放的是服务器&#xff0c;区别于我们平时使用的笔记本或者台式机。 机架&#xff1a;数据中心的服务器被放在一个个叫作机架&…