当前位置: 首页 > article >正文

Java坦克大战

画图基础

先定义画板类, 用于画图

// 定义画板类画板,用于画图
class MyPanel extends JPanel{

    // Graphics g是一只画笔
    // Graphics 提供了绘画方法
    public void paint(Graphics g){
        super.paint(g);
        g.drawOval(0,0,100,100);
    }

}

定义窗口类,用于显示画板

// public类继承JFrame,用于定义窗口
public class Painting extends JFrame {
    public static void main(String[] args) {
        new Painting();
    }

    private MyPanel myPanel = null;

    public Painting(){
        myPanel = new MyPanel();
        // 窗口加入画布
        this.add(myPanel);
        this.setSize(500,500);
        // 设置窗口退出方式
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // 显示窗口
        this.setVisible(true);
    }
}

paint方法被调用情况

  1. 组件第一次在屏幕显示的时候
  2. 窗口大小改变的时候
  3. repaint()方法被调用的时候

Graphics类常用方法

// 画直线
drawLine(int x1, int y1, int x2, int y2)
// 画矩形边框
drawRect(int x, int y, int width, int height)
// 画椭圆边框
drawOval(int x, int y, int width, int height)
// 填充矩形
fillRect(int x, int y, int width, int height)
// 填充椭圆
fillOval(int x, int y, int width, int height)
// 画图片
drawImage(Image img, int x, int y, ImageObserver observer)
g.drawImage(imgae, 0 , 0,889,500,this);
// 获得图片资源
Image image = Toolkit.getDefaultToolkit().getImage(MyPanel.class.getResource("/vertin.png"));
// 画字符串
drawString(String str, int x, int y)
// 设置画笔颜色
setColor(Color c)
// 设置字体
setFont(Font font)
setFont(new Font("宋体",Font.BOLD,20))
// 设置背景色
setBackground(Color c)

Java事件处理

事件源:产生事件的对象,比如按钮,窗口,文本框等
事件监听器:负责监听事件源所发生的事件,当事件发生时,事件监听器会自动调用相应的方法来处理事件
事件:事件源上发生的事情,比如单击,双击,键盘按下,鼠标移动等
事件发生时,事件源创建对象交给事件监听器,事件监听器调用相应的方法处理事件

事件处理流程:

  1. 组件.addXXXListener(监听器对象)
  2. 监听器对象实现接口
  3. 重写接口中的方法

事件监听器接口

  1. 鼠标事件监听器接口:MouseListener
  2. 键盘事件监听器接口:KeyListener
  3. 窗口事件监听器接口:WindowListener

事件监听器适配器

  1. 鼠标事件监听器适配器:MouseAdapter
  2. 键盘事件监听器适配器:KeyAdapter

坦克大战

MyPanel类,用于完成游戏界面绘制

package TankGame;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Vector;

public class MyPanel extends JPanel implements KeyListener {
    public Player player = null;
    static Vector<RedEnemy> enemies = new Vector<>();
    private int enemiesNum = 6;
    private int points = 0;
    private int startMode = 0;
    private String saveAddress  = "d:\\save.dat";

    public int getPoints() {
        return points;
    }

    public void setPoints(int points) {
        this.points = points;
    }

    public static Vector<RedEnemy> getEnemies() {
        return enemies;
    }

    public static void setEnemies(Vector<RedEnemy> enemies) {
        MyPanel.enemies = enemies;
    }

    public MyPanel(){
        player = new Player(500, 500);

        for (int i = 0; i < enemiesNum; ++i) {
            RedEnemy e = new RedEnemy(10 + 100 * i, 10);
            enemies.add(e);
        }

    }

    public MyPanel(int startMode){
        File file = new File(saveAddress);
        if(startMode == 1 && file.exists()){
            try {
                ObjectInputStream oi = new ObjectInputStream(new FileInputStream(saveAddress));
                this.points = oi.readInt();
                player = (Player)oi.readObject();
                int N = oi.readInt();
                for(int i = 0;i < N;++i){
                    RedEnemy e = (RedEnemy) oi.readObject();
                    enemies.add(e);
                }
            } catch (IOException | ClassNotFoundException e) {
                throw new RuntimeException(e);
            } finally {
            }
        }else if(startMode == 0){
            player = new Player(500, 500);

            for (int i = 0; i < enemiesNum; ++i) {
                RedEnemy e = new RedEnemy(10 + 100 * i, 10);
                enemies.add(e);
            }

        }

    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);

        g.fillRect(0,0,1000,750);

        g.setColor(Color.CYAN);
        g.setFont(new Font("宋体",Font.BOLD,20));
        g.drawString("当前得分:" + points,  800, 700);
        // 绘制坦克
        if(player.isAlived())
            drawTank(player.getX(),player.getY(),g,player.getDir(),0);
        synchronized (player.getBullets()){
            // 绘制子弹
            Vector<Bullet> bullets = player.getBullets();
            for(Bullet b : bullets){
                switch (b.getType()){
                    case 0:
                        g.setColor(Color.yellow);
                        break;
                    case 1:
                        g.setColor(Color.RED);
                        break;
                }

                g.fillOval(b.getX(),b.getY(),10,10);
            }
        }

        synchronized (enemies) {
            for (Tank e : enemies) {
                drawTank(e.getX(), e.getY(), g, e.getDir(), 1);
            }
        }

    }


    public void drawTank(int x,int y,Graphics g,int dir, int type){
        // type决定颜色
        switch (type){
            case 0:// 玩家坦克
                g.setColor(Color.cyan);
                break;
            case 1:// 敌人坦克
                g.setColor(Color.magenta);
                break;
            default:
                g.setColor(Color.GRAY);
        }

        // dir决定方向 0上,1左,2右,3下
        switch (dir){
            case 0:
                g.fill3DRect(x,y,10,60,false);
                g.fill3DRect(x + 30,y,10,60,false);
                g.fill3DRect(x + 10,y + 10,20,40,false);
                g.fillOval(x + 10,y + 20,20,20);
                g.drawLine(x + 20,y + 30,x + 20,y);
                break;
            case 1:
                g.fill3DRect(x,y,60,10,false);
                g.fill3DRect(x,y + 30,60,10,false);
                g.fill3DRect(x + 10,y + 10,40,20,false);
                g.fillOval(x + 20,y + 10,20,20);
                g.drawLine(x + 30,y + 20,x ,y + 20);
                break;
            case 2:
                g.fill3DRect(x,y,60,10,false);
                g.fill3DRect(x,y + 30,60,10,false);
                g.fill3DRect(x + 10,y + 10,40,20,false);
                g.fillOval(x + 20,y + 10,20,20);
                g.drawLine(x + 30,y + 20,x + 60,y + 20);
                break;
            case 3:
                g.fill3DRect(x,y,10,60,false);
                g.fill3DRect(x + 30,y,10,60,false);
                g.fill3DRect(x + 10,y + 10,20,40,false);
                g.fillOval(x + 10,y + 20,20,20);
                g.drawLine(x + 20,y + 30,x + 20,y + 60);
        }

    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    @Override
    public void keyPressed(KeyEvent e) {
        if(!player.isAlived())
            return;
        if(e.getKeyCode() == KeyEvent.VK_J){
            //System.out.println("射击!");
            player.shoot();
        }


        //dir决定方向 0上,1左,2右,3下
        if(e.getKeyCode() == KeyEvent.VK_LEFT || e.getKeyCode() == KeyEvent.VK_A){
            player.setDir(1);
            player.moveLeft();
        }
        if(e.getKeyCode() == KeyEvent.VK_RIGHT || e.getKeyCode() == KeyEvent.VK_D){
            player.setDir(2);
            player.moveRight();
        }
        if(e.getKeyCode() == KeyEvent.VK_UP || e.getKeyCode() == KeyEvent.VK_W){
            player.setDir(0);
            player.moveUp();
        }
        if(e.getKeyCode() == KeyEvent.VK_DOWN || e.getKeyCode() == KeyEvent.VK_S){
            player.setDir(3);
            player.moveDown();
        }

        this.repaint();
    }

    @Override
    public void keyReleased(KeyEvent e) {

    }
}

TankGame类,用于创建坦克大战游戏的窗口,并让用户在控制台选择是新游戏还是继续上一局游戏

package TankGame;

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

public class TankGame extends JFrame {
    MyPanel myPanel = null;
    Timer timer = null;
    Checker checker = null;
    Saver saver = null;
    int startMode = 0;

    public TankGame(int startMode){
        myPanel = new MyPanel(startMode);
        timer = new Timer(myPanel.player.getBullets(),myPanel);
        checker = new Checker(myPanel.player.getBullets(),myPanel);
        saver = new Saver(myPanel);
        saver.setDaemon(true);
        timer.setDaemon(true);
        checker.setDaemon(true);
        timer.start();
        checker.start();
        saver.start();
        // 窗口加入画布
        this.add(myPanel);
        this.setSize(1000,750);
        // 设置窗口退出方式
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.addKeyListener(myPanel);
        // 显示窗口
        this.setVisible(true);
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        //while(true){
            System.out.println("选择你想要开始的方式:");
            System.out.println("1. 新游戏");
            System.out.println("2. 上一次自动存档游戏");
            int input = scanner.nextInt();
            switch (input){
                case 1:
                    new TankGame();
                    break;
                case 2:
                    new TankGame(1);
                    break;
                default:
                    new TankGame();
                    break;
            }
        //}

    }

    public TankGame(){
        myPanel = new MyPanel();
        timer = new Timer(myPanel.player.getBullets(),myPanel);
        checker = new Checker(myPanel.player.getBullets(),myPanel);
        saver = new Saver(myPanel);
        saver.setDaemon(true);
        timer.setDaemon(true);
        checker.setDaemon(true);
        timer.start();
        checker.start();
        saver.start();
        // 窗口加入画布
        this.add(myPanel);
        this.setSize(1000,750);
        // 设置窗口退出方式
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.addKeyListener(myPanel);
        // 显示窗口
        this.setVisible(true);
    }
}

Tank类,用于实现坦克有关的所有行为,包括坦克的移动、发射子弹、判断是否碰撞等

package TankGame;

import java.io.Serializable;
import java.util.Vector;

public class Tank implements Collied , Serializable {
    private int x;
    private int y;
    private int dir = 3;     dir决定方向 0上,1左,2右,3下
    private int speed = 3;
    private int shootType = 0;
    private boolean isAlived = true;
    private boolean restricted = false;

    public boolean isRestricted() {
        return restricted;
    }

    public void setRestrict(boolean restricted) {
        this.restricted = restricted;
    }

    public boolean isAlived() {
        return isAlived;
    }

    public void setAlived(boolean alived) {
        isAlived = alived;
    }

    public boolean AinB(Tank t1, Tank t2){
        if(t1.getX() < t2.getX() || t1.getY() < t2.getY()){
            return false;
        }

        int t1x = t1.getX() + (t1.dir == 1 || t1.dir == 2 ? 0 : 20);
        int t1y = t1.getY() + (t1.dir == 1 || t1.dir == 2 ? 20 : 0);
        if(t2.dir == 0 || t2.dir == 3){
            return ((t1x - t2.getX() < 40 && t1y - t2.getY() < 60));
        }else{
            return t1x - t2.getX() < 60 &&  t1y - t2.getY() < 40;
        }
    }

    @Override
    public boolean onCollision(Object o1, Object o2) {
        if(o1 instanceof Tank && o2 instanceof Tank){
            Tank t1 = (Tank) o1;
            Tank t2 = (Tank) o2;

            return AinB(t1,t2) || AinB(t2,t1);
        }

        return false;
    }

    public int getShootType() {
        return shootType;
    }



    public void setShootType(int shootType) {
        this.shootType = shootType;
    }

    private static Vector<Bullet> bullets= new Vector<>();

    public static Vector<Bullet> getBullets() {
        return bullets;
    }

    public void shoot(){
        //bullets.add(new Bullet(x,y,0,dir,10));
        switch (dir){
            case 0:
                bullets.add(new Bullet(x + 15,y,shootType,dir,10));
                break;
            case 1:
                bullets.add(new Bullet(x ,y + 15,shootType,dir,10));
                break;
            case 2:
                bullets.add(new Bullet(x + 60,y + 15,shootType,dir,10));
                break;
            case 3:
                bullets.add(new Bullet(x + 15,y + 60,shootType,dir,10));
                break;
        }
    }

     dir决定方向 0上,1左,2右,3下
    public void moveLeft(){
        x -= speed;
        if(x < 0 ){
            dir = 2;
            x += speed;
        }
        if(restricted){
            x += (int)(1.5 * speed);
        }
    }


    public void moveRight(){
        x += speed;
        if(x >= 930){
            dir = 1;
            x -= speed;
        }
        if(restricted){
            x -=  (int)(1.5 * speed);
        }
    }

    public void moveUp(){
        y -= speed;
        if(y < 0 ){
            dir = 3;
            y += speed;
        }
        if(restricted){
            y += (int)(1.5 * speed);
        }
    }
    public void moveDown(){
        y += speed;
        if(y >= 680 ){
            dir = 0;
            y -=  speed;
        }
        if(restricted){
            y -= (int)(1.5 * speed);
        }
    }

    public int getDir() {
        return dir;
    }

    public void setDir(int dir) {
        this.dir = dir;
    }

    public int getSpeed() {
        return speed;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }

    public Tank(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }
}

Player类,作为Tank类的子类,用于定义一些玩家坦克特有的属性和方法

package TankGame;

public class Player extends Tank{
    public Player(int x,int y){
        super(x,y);
        setSpeed(5);
    }
}

RedEnemy类,作为Tank类的子类,用于定义一些敌方坦克特有的属性和方法

package TankGame;

public class RedEnemy extends Tank{

    public RedEnemy(int x, int y) {
        super(x, y);
        setShootType(1);
    }


    public int moveTime = 500;
    public int shootTime = 1000;

    public final int MOVETIME = 500;
    public final int SHOOTTIME = 1000;
}

Bullet类,用于定义坦克发射的子弹的相关属性和方法

package TankGame;

public class Bullet implements Collied{
    private int x;
    private int y;
    private int type;
    private int dir;
    private int speed;

    @Override
    public boolean onCollision(Object o1, Object o2) {
        if(o2 instanceof Tank){
            Tank t = (Tank) o2;
            Bullet b = (Bullet) o1;
            if(b.getX() < t.getX() || b.getY() < t.getY()) return false;
            if(t.getDir() == 0 || t.getDir() == 3){
                return (b.getX() - t.getX() < 40 && b.getY() - t.getY() < 60);
            }else{
                return b.getX() - t.getX() < 60 && b.getY() - t.getY() < 40;
            }
        }
        return false;
    }

    public int getSpeed() {
        return speed;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }

    public Bullet(int x, int y, int type, int dir, int speed) {
        this.x = x;
        this.y = y;
        this.type = type;
        this.dir = dir; // dir决定方向 0上,1左,2右,3下
        this.speed = speed;
    }

    public Bullet(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getDir() {
        return dir;
    }

    public void setDir(int dir) {
        this.dir = dir;
    }

    public Bullet(int x, int y, int type, int dir) {
        this.dir = dir;
        this.type = type;
        this.y = y;
        this.x = x;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    public void moveLeft(){
        x -= speed;
    }

    public void moveRight(){
        x += speed;
    }

    public void moveUp(){
        y -= speed;
    }
    public void moveDown(){
        y += speed;
    }
}

Checker类,用于实现碰撞检测、游戏资源回收等功能

package TankGame;

import java.util.Vector;

public class Checker extends Thread{
    private Vector<Bullet> bullets = null;
    private MyPanel panel = null;
    private Vector<Bullet> removeBulletArr = new Vector<>();
    private Vector<RedEnemy> removeEnemiesArr = new Vector<>();
    private Vector<RedEnemy> enemies;

    public Checker(Vector<Bullet> bullets) {
        this.bullets = bullets;
    }

    public Checker(Vector<Bullet> bullets,MyPanel panel) {
        this.bullets = bullets;
        this.panel = panel;
        this.enemies = panel.getEnemies();
    }

    @Override
    public void run() {
        while(true){
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            //碰撞判断
           synchronized (bullets){
               //System.out.print("A");
                synchronized (enemies){
                    //System.out.println("B");
                    //检查碰撞
                    for(Bullet b : bullets){
                        if(b.getType() != 0 && b.onCollision(b,panel.player)){
                            panel.player.setAlived(false);
                            //panel.setPoints(panel.getPoints());
                        }
                        if(b.getType() == 1) continue;
                        for(RedEnemy e : enemies) {
                            if (!e.isAlived()) continue;
                            if (b.onCollision(b, e)) {
                                removeBulletArr.add(b);
                                e.setAlived(false);
                                removeEnemiesArr.add(e);
                                panel.setPoints(panel.getPoints() + 10);
                            }
                        }

                    }
                }
           }

            synchronized (enemies){
                boolean plCanMove = true;
                for(int i = 0;i < enemies.size();++i){
                    RedEnemy e1 = enemies.get(i);
                    boolean e1CanMove = true;
                    for(int j = 0;j < enemies.size();++j) {
                        if(j == i) continue;
                        RedEnemy e2 = enemies.get(j);
                        if (e1.onCollision(e1, e2)) {
                            e1.setRestrict(true);
                            e2.setRestrict(true);
                            e1CanMove = false;
                        }
                    }
                    Tank t = panel.player;
                    if (e1.onCollision(e1, t)) {
                        e1.setRestrict(true);
                        t.setRestrict(true);
                        e1CanMove = false;
                        plCanMove = false;
                    }
                    if(e1CanMove){
                        e1.setRestrict(false);
                    }
                }
                if(plCanMove){
                    panel.player.setRestrict(false);
                }
            }

            synchronized (bullets){
                //System.out.println(bullets.size());
                for(Bullet b : removeBulletArr){
                    bullets.remove(b);
                }
                removeBulletArr.clear();
            }

            synchronized (enemies){
                //System.out.println(bullets.size());
                for(RedEnemy e : removeEnemiesArr){
                    enemies.remove(e);
                }
                removeEnemiesArr.clear();
            }




            //无敌
            //panel.player.setAlived(true);

            //检查子弹是否超出边界
            synchronized (bullets){
                //System.out.println(bullets.size());
                for(Bullet b : bullets){
                    if(b.getY() <= 0 || b.getY() >= 750 || b.getX() <= 0 || b.getX() >= 1000){
                        removeBulletArr.add(b);
                    }

                }
                for(Bullet b : removeBulletArr){
                    bullets.remove(b);
                }
                removeBulletArr.clear();
            }

            panel.repaint();
        }
    }
}

Collied类,用于定义一个碰撞检测的类,其中包含一个方法,可以检测两个对象是否碰撞

package TankGame;

public interface Collied {
    // 判断是否碰撞的方法
    boolean onCollision(Object o1,Object o2);
}

Timer类,用于模拟游戏时间流逝,然后根据时间的流逝更新子弹和坦克的位置

package TankGame;

import java.awt.*;
import java.util.Vector;

public class Timer extends Thread{
    private Vector<Bullet> bullets= new Vector<>();
    private MyPanel panel = null;
    private int deltaTime = 25;
    Vector<RedEnemy> enemies =  null;

    public Timer(Vector<Bullet> bullets) {
        this.bullets = bullets;
    }

    public Timer(Vector<Bullet> bullets,MyPanel panel) {
        this.bullets = bullets;
        this.panel = panel;
        enemies =  panel.enemies;
    }

    public int getDeltaTime() {
        return deltaTime;
    }

    public void setDeltaTime(int deltaTime) {
        this.deltaTime = deltaTime;
    }

    @Override
    public void run() {
        while(true){// 40帧左右
            try {
                Thread.sleep(deltaTime);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            // 子弹运动
            synchronized (bullets){
                for(Bullet b : bullets){
                    switch (b.getDir()){
                         dir决定方向 0上,1左,2右,3下
                        case 0:
                            b.moveUp();
                            break;
                        case 1:
                            b.moveLeft();
                            break;
                        case 2:
                            b.moveRight();
                            break;
                        case 3:
                            b.moveDown();
                            break;
                    }
                }
            }

            // 敌人运动
            int nextDir = 0;
            synchronized (bullets) {
                synchronized (enemies) {
                    for (RedEnemy t : enemies) {
                        if (!t.isAlived()) {
                            continue;
                        }
                        t.moveTime -= deltaTime;
                        t.shootTime -= deltaTime;
                        if (t.shootTime < 0) {
                            t.shoot();
                            t.shootTime = t.SHOOTTIME;
                        }
                        if (t.moveTime < 0) {
                            t.moveTime = t.MOVETIME;
                            nextDir = (int) (Math.random() * 4);
                        } else {
                            nextDir = t.getDir();
                        }
                        t.setDir(nextDir);

                        switch (nextDir) {
                            case 0:
                                t.moveUp();
                                break;
                            case 1:
                                t.moveLeft();
                                break;
                            case 2:
                                t.moveRight();
                                break;
                            case 3:
                                t.moveDown();
                                break;
                        }
                    }
                    //System.out.println("release e");
                }
            }

            panel.repaint();
        }
    }
}

Saver类,用于保存游戏状态到指定文件中去

package TankGame;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.PrintStream;
import java.util.Vector;

public class Saver extends Thread{
    private MyPanel panel = null;
    private int saveInterval = 10000;
    private String saveAddress  = "d:\\save.dat";
    private Tank player = null;
    private Vector<RedEnemy> enemies = null;

    public Saver(MyPanel panel) {
        this.panel = panel;
        this.player = panel.player;
        this.enemies = panel.getEnemies();
    }


    @Override
    public void run() {
        while(true){
            try {
                Thread.sleep(saveInterval);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            try {
                ObjectOutputStream op = new ObjectOutputStream(new FileOutputStream(saveAddress));
                op.writeInt(panel.getPoints());
                op.writeObject(player);
                op.writeInt(enemies.size());
                synchronized (enemies ){
                    for(int i = 0;i < enemies.size();++i){
                        op.writeObject(enemies.get(i));
                    }
                }
                op.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            } finally {
            }
        }
    }
}

项目源于视频:https://www.bilibili.com/video/BV1fh411y7R8?spm_id_from=333.788.videopod.episodes&vd_source=16bf0c507e4a78c3ca31a05dff1bee4e&p=569


http://www.kler.cn/a/524816.html

相关文章:

  • 17.Word:李楠-学术期刊❗【29】
  • CTFSHOW-WEB入门-命令执行29-32
  • Linux基础指令
  • 16届蓝桥杯寒假刷题营】第2期DAY5IOI赛
  • C++ unordered_map和unordered_set的使用,哈希表的实现
  • Ubuntu二进制部署K8S 1.29.2
  • 蛇年的第一篇博客:设想中的汉字编码
  • Sprintboot原理
  • VMware安装win10记录
  • MySQL备忘录
  • 上位机知识篇---Linux的shell脚本搜索、查找、管道
  • 【数据结构】初识链表
  • MongoDB常见的运维工具总结介绍
  • 《刚刚问世》系列初窥篇-Java+Playwright自动化测试-19- 操作鼠标悬停(详细教程)
  • 代码随想录|动态规划 300.最长递增子序列 674. 最长连续递增序列 718. 最长重复子数组
  • Go学习:格式化输入输出
  • solon-flow 你好世界!
  • C++传送锚点的内存寻址:内存管理
  • G. Rudolf and CodeVid-23
  • [250125] DeepSeek 发布开源大模型 R1,性能比肩 OpenAI o1 | 希捷推出高达 36TB 的硬盘
  • 【C++】STL容器使用与实现详解:vector
  • STM32 PWM驱动直流电机
  • 2024 CVPR Highlight Learning-Feedback
  • C# 环境:深入探讨与优化
  • Python中的函数(上)
  • 十大主流联邦学习框架:技术特性、架构分析与对比研究