java坦克大战(1.0)

news2024/11/17 9:27:20

坦克大战

后面开始学习怎么使用java制造一个坦克大战游戏
但是不是直接开始做,而是随着这个游戏程序的制造,一边学习新知识融入到游戏中。包括多线程,反射,IO流…

Java坐标体系

在几乎所有的坐标中都有一个x轴和y轴,根据x,y的不同数据可以从x轴和y轴出发一条线,而这两条线就会形成一个交叉点。
x轴和y轴的出发点交叉点,叫做原点。如图所示

在这里插入图片描述

像素

计算机在屏幕上显示的内容都是由像素组成的,例如1080*1920,表示每行有1920个像素,每列有1080个像素。所以整个屏幕有2073600个像素,所以像素是密度单位,不是长度单位。

例如:你在1080的显示屏上使用x,y轴画了两条线,再使用2k的显示屏打开时,你会发现缩小了。
这里就是因为屏幕能显示的像素变多了,所以整体看着就觉得缩小了

Java绘图

使用Java画一个圆
在现实中绘画,需要{ 画框,画板,笔},在java中也有对应的类

  1. 定义一个自己的面板类,继承Java的面板类JPanel相当于画板。
    JPanel有个方法paint,可以使用画笔Graphics类对象的方法进行绘制
  2. 定义一个自己的框架类,也就是显示的窗口,继承Java的框架类JFrame
    在框架类的无参构造器中 把画板添加到框架里,且设置框架的尺寸和什么时候关闭程序
    JFrame有add方法可以将画板添加到框架里,setDefaultCloseOperation方法觉得啥时候关闭框架,结束程序
    还可以设置框架的尺寸,
public class test {
    public static void main(String[] args) {
        //11.实例化一个框架(框架的无参构造器,已经创建了面板和画笔了)
        new CircleFrame();
    }
}
//1.先定义一个自己的面板类(画板),继承Java的面板类,画画就是在画板上画
class MyPanel extends JPanel{
    //2.重写JPanel的paint方法(画笔方法),这里编写你要用画笔干啥,Graphics g可以理解为画笔
    @Override
    public void paint(Graphics g) {
        super.paint(g);//调用父类的方法,完成初始化
        System.out.println("paint方法运行");
        //3.画一个圆
        g.drawOval(20,20,100,100);//画圆的方法,x,y定义圆的起始位置,后面定义圆的宽和高
    }
}

//4.定义一个展示面板的框架(窗口,可以理解为画框),继承Java的JFrame框架类
class CircleFrame extends JFrame{
    //5.定义一个面板变量
    MyPanel myPanel = null;
    public CircleFrame(){//无参构造器
        //6.初始化面板,实例化面板
        myPanel = new MyPanel();
        //7.将面板放到框架(窗口)里面
        this.add(myPanel);
        //8.设置框架(窗口)的尺寸
        this.setSize(500,500);
        //9.让窗口显示出来
        this.setVisible(true);
        //10.当点击了窗口的关闭键后退出程序
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

Graphics类的常用方法

  1. 画直线-drawLine(int x,int,y,int x2,int y2)
  2. 画矩形边框-drawRect(int x,int y,int width,int height)
  3. 画椭圆-drawOval(int x,int y,int width,int height)
  4. 填充矩形fillRect((int x,int y,int width,int height)
  5. 填充椭圆fillOval(int x,int y,int width,int height)
  6. 画图片-drawImage(Image img,int,int y…)
  7. 画字符串drawString(String str,int x,int y)
  8. 设置画笔的字体setFont(Font font)
  9. 设置画笔的颜色 setColor(Color c )

使用演示:

public class test {
    public static void main(String[] args) {
        new CircleFrame();
    }
}
class MyPanel extends JPanel{
    @Override
    public void paint(Graphics g) {
        super.paint(g);
        System.out.println("paint方法运行");
//        1. 画直线-drawLine(int x,int,y,int x2,int y2)
        g.drawLine(10,10,50,50);
//        2. 画矩形边框-drawRect(int x,int y,int width,int height)
        g.drawRect(20,20,70,70);
//        3. 画椭圆-drawOval(int x,int y,int width,int height)
        g.drawOval(20,20,100,100);
//        4. 填充矩形fillRect((int x,int y,int width,int height)
        //需要先设置一下画笔的颜色
        g.setColor(Color.BLACK);
        g.fillRect(70,70,100,90);
//        5. 填充椭圆fillOval(int x,int y,int width,int height)
        //如果不改其他颜色,就不用再设置一下了,要换其他颜色,再重新调用setColor
        g.fillOval(30,30,60,60);
//        6. 画图片-drawImage(Image img,int,int y...)
        //需要先获取一下图片,需要提前把图片放在根目录,不然编译器找不到
        Image image = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/4.jpg"));
        g.drawImage(image,70,70,860,360,this);
//        7. 画字符串drawString(String str,int x,int y)
        //可以先设置一个颜色和设置一下字体
        g.setColor(Color.PINK);
        g.setFont(new Font("微软雅黑",Font.BOLD,30));//字体,加粗,字体大小
        g.drawString("Java",90,110);
//        8. 设置画笔的字体setFont(Font font)
//        9. 设置画笔的颜色 setColor(Color c )
    }
}
class CircleFrame extends JFrame{
    MyPanel myPanel = null;
    public CircleFrame(){
        myPanel = new MyPanel();
        this.add(myPanel);
        this.setSize(500,500);
        this.setVisible(true);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

绘制坦克大战的背景区域

思路:
按照前面的学习
定义画板类和画框类,然后直接在画板上新建一个和框架(窗口)大小一样的矩形(需要填充)即可

public class Tank {
    int x ;//坦克的横坐标
    int y ;//坦克的纵坐标
}
public class MyPanel extends Panel {
@Override
    public void paint(Graphics g){
        super.paint(g);
        g.fillRect(0,0,1000,950);
    }
}
public class myWindow extends JFrame {
    MyPanel  m = null;
    public myWindow(){
        m = new MyPanel();
        this.add(m);
        this.setSize(1000,950);
        this.setVisible(true);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public static void main(String[] args) {
        new myWindow();
    }
}

在这里插入图片描述

绘制坦克

可以坦克有两个特性

不同朝向
不同阵营
所以可以将绘制坦克封装到方法里,根据不同参数绘制不同的坦克

public class MyPanel extends Panel {
    Tank tank;
   @Override
    public void paint(Graphics g) {
        super.paint(g);
       System.out.println("调用paint");
       g.fillRect(0,0,500,600);
       drawTank(20,460,g,0,0);
       drawTank(90,350,g,0,1);

    }
    /**
    @param x 坦克的起始横坐标
    @param y 坦克的起始纵坐标
    @param g 画笔
    @param direct 根据方向绘制不同朝向的坦克
    @param type  根据0或者1 绘制不同颜色的坦克
    */
    public void drawTank(int x,int y,Graphics g,int direct,int type){
        switch (type){
            case 0:
                g.setColor(Color.PINK);//自己的坦克就粉色
                break;
            case 1:
                g.setColor(Color.RED);//敌人的坦克就红色
                break;
        }
            switch (direct){
                case 0://0表示绘制方向朝上的坦克
                    g.fill3DRect(x,y,10,50,false);
                    g.fill3DRect(x+10,y+5,25,40,false);
                    g.fill3DRect(x+35,y,10,50,false);
                    g.fillOval(x+10,y+15,25,25);
                    g.drawLine(x+22,y-5,x+22,y+25);
                    break;
                default://其他情况暂不考虑
                    break;
            }
    }
}

在这里插入图片描述

键盘监听

坦克大战肯定是要根据键盘的操作,坦克做出不同的动作
为了实现这个目标,需要了解一个接口

KeyListener接口,可以对键盘做出监听,获取到键盘的操作
KeyListener接口有三个方法

//字符输出时,该方法触发
public void keyTyped(KeyEvent e) {}

//有按键按下时,该方法触发
public void keyPressed(KeyEvent e) {}

//有按键松开时,该方法触发
public void keyReleased(KeyEvent e) { }

我们可以使用 e.getCode,获取到键盘对应的ASCII码
然后再根据ASCII码是对应的动作时 调用repaint方法,触发paint方法重绘画板

但是要在框架类 使用this.addKeyListener();方法把画板传进去

java事件处理机制

java事件处理是采取“委派事件模型”,当事件发生时,产生事件的对象,会把此“信息”,传递给“事件的监听者”处理,所谓“信息”实际上就是java.awt.event事件类库里某个类所创建的对象,把它称之为“事件的对象”

委派事件模型
什么是委派事件模型?

举例说明:
我通过微信向同学说“借我300块”,同学收到后,就发了红包给我

那么 事件源就是我要借钱,事件/对象,就是一条微信,同学就是事件监听者。他给我发红包就是对事件进行处理

在这里插入图片描述

在上面已经演示了键盘监听类 KeyEvent
java中还有其他的事件监听类

事件类说明
ActionEvent通常在按下按钮,或双击一个列表项或选中某个菜单时发生)
AdjustmentEvent当操作一个滚动条时发生。
ComponentEvent:当一个组件隐藏,移动,改变大小时发送。
ContainerEvent当一个组件从容器中加入或者删除时发生。
FocusEvent当一个组件获得或是失去焦点时发生。
ItemEvent当一个复选框或是列表项被选中时,当一个选择框或选择菜
KeyEvent当从键盘的按键被按下,松开时发生。
MouseEvent当鼠标被拖动,移动,点击,按下…2
TextEvento当文本区和文本域的文本发生改变时发生。
WindowEvent当一个窗口激活,关闭,失效,恢复,最小化.

事件监听器接口

  1. 当事件源产生一个事件,可以传送给事件监听者处理
  2. 事件监听者,实际上就是一个类,这个类实现了某个事件监听器接口
  3. 事件监听者接口可以有多种,不同的事件监听者接口可以监听不同事件,一个类可以实现多个监听接口
  4. 这些接口通常在java.awt.event包和javax.swing.event包中定义,

让坦克动起来

要让坦克动起来,得先画出不同朝向的坦克
首先前面已经画出了朝上的,那么横坐标和纵坐标其实不用动,将宽和高调整即可

朝上的:
g.fill3DRect(x,y,10,50,false);
g.fill3DRect(x+10,y+5,25,40,false);
g.fill3DRect(x+35,y,10,50,false);
g.fillOval(x+10,y+15,25,25);
g.drawLine(x+22,y-5,x+22,y+25);
朝右的:
g.fill3DRect(x,y+7,50,10,false);
g.fill3DRect(x+5,y+14,40,25,false);
g.fill3DRect(x,y+37,50,10,false);
g.fillOval(x+10,y+15,25,25);
g.drawLine(x+25,y+25,x+58,y+25);
朝下的:
g.fill3DRect(x,y,10,50,false);
g.fill3DRect(x+10,y+5,25,40,false);
g.fill3DRect(x+35,y,10,50,false);
g.fillOval(x+10,y+12,25,25);
g.drawLine(x+22,y+55,x+22,y+25);
朝左的:
g.fill3DRect(x,y+7,50,10,false);
g.fill3DRect(x+5,y+14,40,25,false);
g.fill3DRect(x,y+37,50,10,false);
g.fillOval(x+10,y+15,25,25);
g.drawLine(x+25,y+25,x-8,y+25);

不同的方向都制造了好后,由于前面绘制坦克的是由drawTank方法的direct来决定的
所以我们在Tank类把他变成一个属性,方便后面监听事件的更改

public class MyPanel extends Panel implements KeyListener {
    int speek = 1;
    Tank tank;
    public MyPanel(){
        tank = new Tank(20,460,0);
    }
   @Override
    public void paint(Graphics g) {
        super.paint(g);
       System.out.println("调用paint");
       g.fillRect(0,0,500,600);
       drawTank(tank.x,tank.y,g,tank.direct,0);
    }
    /**
    @param x 坦克的起始横坐标
    @param y 坦克的起始纵坐标
    @param g 画笔
    @param direct 根据方向绘制不同朝向的坦克
    @param type  根据0或者1 绘制不同颜色的坦克
    */
    public void drawTank(int x,int y,Graphics g,int direct,int type){
        switch (type){
            case 0:
                g.setColor(Color.PINK);//自己的坦克就粉色
                break;
            case 1:
                g.setColor(Color.RED);//敌人的坦克就红色
                break;
        }
            switch (direct){//0上,1右,2下,3左
                case 0://0表示绘制方向朝上的坦克
                    g.fill3DRect(x,y,10,50,false);
                    g.fill3DRect(x+10,y+5,25,40,false);
                    g.fill3DRect(x+35,y,10,50,false);
                    g.fillOval(x+10,y+15,25,25);
                    g.drawLine(x+22,y-5,x+22,y+25);
                    break;
                case 1://1表示绘制方向朝右的坦克
                    g.fill3DRect(x,y+7,50,10,false);
                    g.fill3DRect(x+5,y+14,40,25,false);
                    g.fill3DRect(x,y+37,50,10,false);
                    g.fillOval(x+10,y+15,25,25);
                    g.drawLine(x+25,y+25,x+58,y+25);
                    break;
                case 2://2表示绘制方向朝下的坦克
                    g.fill3DRect(x,y,10,50,false);
                    g.fill3DRect(x+10,y+5,25,40,false);
                    g.fill3DRect(x+35,y,10,50,false);
                    g.fillOval(x+10,y+12,25,25);
                    g.drawLine(x+22,y+55,x+22,y+25);
                    break;
                case 3://3表示绘制方向朝左的坦克
                    g.fill3DRect(x,y+7,50,10,false);
                    g.fill3DRect(x+5,y+14,40,25,false);
                    g.fill3DRect(x,y+37,50,10,false);
                    g.fillOval(x+10,y+15,25,25);
                    g.drawLine(x+25,y+25,x-8,y+25);
                    break;
                default://其他情况暂不考虑
                    break;
            }
    }

    @Override //字符输出时,该方法触发
    public void keyTyped(KeyEvent e) {

    }

    @Override//有按键按下时,该方法触发
    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == 87){//前进
            moveUp();
            tank.direct = 0;
        }else if(e.getKeyCode() == 83){
            moveDown();
            tank.direct = 2;
        }else if(e.getKeyCode() == 65){
            moveLeft();
            tank.direct = 3;
        }
        else if(e.getKeyCode() == 68){
            moveRight();
            tank.direct = 1;
        }else if(e.getKeyCode() == 32){
            System.out.println("氮气加速~");
            speek +=5;
        }else{
            System.out.println(e.getKeyCode());
        }
        repaint();
    }

    @Override//有按键松开时,该方法触发
    public void keyReleased(KeyEvent e) {

    }
    public void moveUp(){
        tank.y-=speek;
    }
    public void moveLeft(){
        tank.x-=speek;
    }
    public void moveRight(){
        tank.x+=speek;
    }
    public void moveDown(){
        tank.y+=speek;
    }
}

画出敌人坦克

因为敌人坦克后面肯定是有自己的特性的所以新建一个EnemyTanks类
敌人坦克肯定不止一个,所以需要集合
且后面会运用到多线程,所以使用Vector集合来存储敌人坦克,提高安全性
然后遍历集合绘制敌人坦克

public class MyPanel extends Panel implements KeyListener {
    int speek = 1;
    Tank tank;
    Vector<EnemyTanks> enemyTanks = new Vector<>();
    public MyPanel(){
        tank = new Tank(20,460,0);
        for (int i = 0; i < 3; i++) {
            EnemyTanks enemyTank = new EnemyTanks(100*(i+1),0,2);
            enemyTanks.add(enemyTank);
        }
    }
   @Override
    public void paint(Graphics g) {
        super.paint(g);
       System.out.println("调用paint");
       g.fillRect(0,0,500,600);
       //画我方坦克
       drawTank(tank.x,tank.y,g,tank.direct,0);
       for (int i = 0; i < enemyTanks.size(); i++) {
           EnemyTanks e = enemyTanks.get(i);
           //画敌方坦克
           drawTank(e.x,e.y,g,e.direct,1);
       }
    }
    /**
    @param x 坦克的起始横坐标
    @param y 坦克的起始纵坐标
    @param g 画笔
    @param direct 根据方向绘制不同朝向的坦克
    @param type  根据0或者1 绘制不同颜色的坦克
    */
    public void drawTank(int x,int y,Graphics g,int direct,int type){
        switch (type){
            case 0:
                g.setColor(Color.PINK);//自己的坦克就粉色
                break;
            case 1:
                g.setColor(Color.RED);//敌人的坦克就红色
                break;
        }
            switch (direct){//0上,1右,2下,3左
                case 0://0表示绘制方向朝上的坦克
                    g.fill3DRect(x,y,10,50,false);
                    g.fill3DRect(x+10,y+5,25,40,false);
                    g.fill3DRect(x+35,y,10,50,false);
                    g.fillOval(x+10,y+15,25,25);
                    g.drawLine(x+22,y-5,x+22,y+25);
                    break;
                case 1://1表示绘制方向朝右的坦克
                    g.fill3DRect(x,y+7,50,10,false);
                    g.fill3DRect(x+5,y+14,40,25,false);
                    g.fill3DRect(x,y+37,50,10,false);
                    g.fillOval(x+10,y+15,25,25);
                    g.drawLine(x+25,y+25,x+58,y+25);
                    break;
                case 2://2表示绘制方向朝下的坦克
                    g.fill3DRect(x,y,10,50,false);
                    g.fill3DRect(x+10,y+5,25,40,false);
                    g.fill3DRect(x+35,y,10,50,false);
                    g.fillOval(x+10,y+12,25,25);
                    g.drawLine(x+22,y+55,x+22,y+25);
                    break;
                case 3://3表示绘制方向朝左的坦克
                    g.fill3DRect(x,y+7,50,10,false);
                    g.fill3DRect(x+5,y+14,40,25,false);
                    g.fill3DRect(x,y+37,50,10,false);
                    g.fillOval(x+10,y+15,25,25);
                    g.drawLine(x+25,y+25,x-8,y+25);
                    break;
                default://其他情况暂不考虑
                    break;
            }
    }

    @Override //字符输出时,该方法触发
    public void keyTyped(KeyEvent e) {

    }

    @Override//有按键按下时,该方法触发
    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == 87){//前进
            moveUp();
            tank.direct = 0;
        }else if(e.getKeyCode() == 83){
            moveDown();
            tank.direct = 2;
        }else if(e.getKeyCode() == 65){
            moveLeft();
            tank.direct = 3;
        }
        else if(e.getKeyCode() == 68){
            moveRight();
            tank.direct = 1;
        }else if(e.getKeyCode() == 32){
            System.out.println("氮气加速~");
            speek +=5;
        }else{
            System.out.println(e.getKeyCode());
        }
        repaint();
    }

    @Override//有按键松开时,该方法触发
    public void keyReleased(KeyEvent e) {

    }
    public void moveUp(){
        tank.y-=speek;
    }
    public void moveLeft(){
        tank.x-=speek;
    }
    public void moveRight(){
        tank.x+=speek;
    }
    public void moveDown(){
        tank.y+=speek;
    }
}

在这里插入图片描述

1.0完成

至此坦克大战1.0完成,后面学习了多线程再制造2.0版本,让敌人坦克也动起来。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

大数据项目实战之数据仓库:用户行为采集平台——第1章 数据仓库概念

第1章 数据仓库概念 数据仓库&#xff08;Data Warehouse&#xff09;&#xff0c;是为企业制定决策&#xff0c;提供数据支持的。可以帮助企业改进业务流程、提高产品质量等。 数据仓库的输入数据通常包括&#xff1a;业务数据、用户行为数据和爬虫数据等 业务数据&#xf…

Java - 对象的比较

一、问题提出 前面讲了优先级队列&#xff0c;优先级队列在插入元素时有个要求&#xff1a;插入的元素不能是null或者元素之间必须要能够进行比较&#xff0c;为了简单起见&#xff0c;我们只是插入了Integer类型&#xff0c; 那优先级队列中能否插入自定义类型对象呢&#xf…

深入理解JDK动态代理原理,使用javassist动手写一个动态代理框架

文章目录一、动手实现一个动态代理框架1、初识javassist2、使用javassist实现一个动态代理框架二、JDK动态代理1、编码实现2、基本原理&#xff08;1&#xff09;getProxyClass0方法&#xff08;2&#xff09;总结写在后面一、动手实现一个动态代理框架 1、初识javassist Jav…

Dijkstra算法的入门与应用

目录 一、前言 二、Dijkstra算法 1、Dijkstra 算法简介 2、算法思想&#xff1a;多米诺骨牌 3、算法实现 4、例子 三、例题 1、蓝桥王国&#xff08;lanqiaoOJ题号1122&#xff09; 一、前言 本文主要讲了Dijkstra算法的概念、实现与一道模板例题。 二、Dijkstra算法…

RSTP基础要点(上)

RSTP基础RSTP引入背景STP所存在的问题RSTP对于STP的改进端口角色重新划分端口状态重新划分快速收敛机制&#xff1a;PA机制端口快速切换边缘端口的引入RSTP引入背景 STP协议虽然能够解决环路问题&#xff0c;但是由于网络拓扑收敛较慢&#xff0c;影响了用户通信质量&#xff…

分布式对象存储

参考《分布式对象存储----原理、架构以及Go语言实现》&#xff08;作者&#xff1a;胡世杰&#xff09; 对象存储简介 数据的管理方式 以对象的方式管理数据&#xff0c;一个对象包括&#xff1a;对象的数据、对象的元数据、对象的全局唯一标识符 访问数据的方式 可扩展的分…

useCallback、useMemo、React.memo

1、React.memo React.memo 是 React 中用于函数组件优化的高阶组件&#xff0c;可以在一定程度上减少组件的重渲染&#xff0c;提升应用性能。React.memo 的实现原理是对比组件的前后两次渲染传入的 props 是否相等&#xff0c;如果相等则不会触发重新渲染&#xff0c;否则会触…

使用 Nacos 搭建一个简单的微服务项目

Nacos Nacos 是阿里巴巴推出来的一个新开源项目&#xff0c;一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。 准备Nacos 将 nacos 安装成功之后&#xff0c;进入nacos的bin 目录下&#xff0c;通过命令sh startup.sh -m standalone启动nacos&#xff0c;然后…

ChatGPT概述:从模型训练到基本应用的介绍

ChatGPT概述&#xff1a;从模型训练到基本应用的介绍 目录 本文是对ChatGPT的由来、训练过程以及实际落地场景的解释&#xff0c;主要内容包括如下三个方面&#xff1a; 1、ChatGPT是什么 2、ChatGPT的原理 3、ChatGPT的思考 4、ChatGPT的应用 ChatGPT是什么 ChatGPT可能是近…

代码随想录算法训练营第四天| 24. 两两交换链表中的节点 、19.删除链表的倒数第N个节点、面试题 02.07. 链表相交 、142.环形链表II

24. 两两交换链表中的节点 24.两两交换链表中的节点介绍给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09;。思路上述是自己看到这道…

Zookeeper3.5.7版本——客户端命令行操作(命令行语法)

目录一、命令行语法二、help命令行语法示例一、命令行语法 命令行语法列表 命令基本语法功能描述help显示所有操作命令ls path使用 ls 命令来查看当前 znode 的子节点 [可监听]-w 监听子节点变化-s 附加次级信息create普通创建-s 含有序列-e 临时&#xff08;重启或者超时消失…

【3.5】单调栈、回文数、子序列、编辑距离问题,MySQL、Redis

文章目录单调栈总结子序列问题总结编辑距离问题总结回文串问题总结MySQL 执行流程是怎样的&#xff1f;第一步&#xff1a;连接器第二步&#xff1a;查询缓存第三步&#xff1a;解析器 解析SQL第四步&#xff1a;执行 SQL2.2 MySQL 一行记录是怎么存储的&#xff1f;MySQL 的数…

ChatGPT vs Bard 背后的技术对比分析和未来发展趋势

ChatGPT vs Bard 背后的技术对比分析和未来发展趋势 目录 ChatGPT vs Bard 背后的技术对比分析和未来发展趋势

Vulnhub系列:VulnOSv2

老样子&#xff0c;kali ip:192.168.56.104&#xff0c;靶机ip利用nmap或arp-scan -l进行查看靶机ip为&#xff1a;192.168.56.124&#xff0c;利用nmap进行端口探测发现了22、80、6667端口&#xff0c;下一步就是进行web探测&#xff0c;输入靶机ip后发现页面存在个链接&#…

Qt中调用gtest进行单元测试及生成覆盖率报告

一.环境配置 googletest地址:https://github.com/google/googletest 我下载的是1.12.1,这是最后一个支持C++11的版本。 首先编译gtest,在windows上的编译方式和编译gRPC一模一样,详见Qt中调用gRPC,编译完了会生成几个静态库,如下图所示 本文主要用到了libgtest.a 下载ms…

多线程二 多线程了解与使用

文章目录synchronized 锁有两种synchronized异常捕获主线程和子线程volatile的作用notify是随机启动等待线程中的一个synchronized 锁有两种 类对象类的实例 第一种&#xff1a;锁类对象&#xff0c;有两种方式&#xff0c;如下&#xff1a; // 方法一&#xff1a;synchroni…

Dubbo源码解析-——服务导出

前言 在之前我们讲过Spring和Dubbo的集成&#xff0c;我们在服务上标注了DubboService的注解&#xff0c;然后最终Dubbo会调用到ServiceBean#export方法中&#xff0c;本次我们就来剖析下服务导出的全流程。 一、前置回顾 由于ServiceBean实现了ApplicationListener接口&…

基于图像识别的数据处理系统

基于EASYDL模型的图像识别数据处理系统 需求分析 1.1软件背景分析 世界已经进入工业自动化的时代。随着图像识别、语音识别、机械稳定化的发展。自动化已经成为公司或者企业发展的重要方向。自动化是指机器设备或生产过程在不需要人工直接干预情况下&#xff0c;按照预期的目…

Java分布式解决方案(二)

文章目录&#x1f525;分布式事务处理_认识本地事务&#x1f525;关系型数据库事务基础_并发事务带来的问题&#x1f525;关系型数据库事务基础_MySQL事务隔离级别&#x1f525;MySQL事务隔离级别_模拟异常发生之脏读&#x1f525;MySQL事务隔离级别_模拟异常发生之不可重复读&…

浏览器渲染原理

阶段 - Parse 1、解析HTML&#xff0c;浏览器将从服务器获取到的HTML文件之后&#xff0c;会产生一个渲染任务&#xff0c;交给消息队列&#xff08;EventLoop/MessageLoop&#xff09;。 2、在事件循环机制的作用下&#xff0c;会将渲染任务交给主线程 3、主线程在获取到渲染…