坦克大战2.0,3.0,4.0版本

news2024/9/23 19:29:14

1.坦克大战 0.3

在坦克大战游戏(0.2版)基础上添加如下功能:当玩家按一下j键,就发射一颗子弹.

1672660265805

编写Shot类

1672665042333

package com.yt.tankgame03;

/**
 * 射击子弹
 */
public class Shot implements Runnable{
    int x;//子弹的x坐标
    int y;//子弹的y坐标
    int direct;//子弹的方向
    int speed = 2;//子弹的速度
    boolean isLive = true;//子弹是否存活

    //构造器
    public Shot(int x, int y, int direct) {
        this.x = x;
        this.y = y;
        this.direct = direct;
    }

    @Override
    public void run() {//射击行为
        while (true){

            //线程休眠
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //根据方向改变x,y坐标
            switch (direct){
                case 0://表示方向向上
                    y -= speed;
                    break;
                case 1://表示方向向右
                    x += speed;
                    break;
                case 2://表示方向向下
                    y += speed;
                    break;
                case 3://表示方向向zuo
                    x -= speed;
                    break;

            }
            //测试下,输出x,y的坐标
            System.out.println("子弹 x=" + x + " y=" + y);
            //子弹出边界了
            if (!(x>= 0 && x <=1000 && y>=0 && y<=750)){
                isLive = false;
                break;
            }
        }

    }
}

在坦克中编写射击地方坦克的方法

1672665167793

1672665143463

//射击
public void shotEnemyTank(){
    //创建Shot对象,根据当前Hero对象的位置和方向来创建Shot对象
    switch (getDirect()){//得到坦克的方向
        case 0://向上
            shot = new Shot(getX()+20,getY(),0);
            break;
        case 1://向右
            shot = new Shot(getX()+60,getY()+20,1);
            break;
        case 2://向下
            shot = new Shot(getX()+20,getY()+60,2);
            break;
        case 3://向左
            shot = new Shot(getX(),getY()+20,3);
            break;
    }
    //启动射击的线程
    new Thread(shot).start();

绘制射击的子弹

1672665270885

将面板设置成线程

1672665311805

1672665330559

启动线程

1672665371693

2.坦克大战 0.4 版

  1. 让敌人的坦克也能够发射子弹(可以有多颗子弹)
  2. 当我方坦克击中敌人坦克时,敌人的坦克就消失,如果能做出爆炸效果更好
  3. 让敌人的坦克也可以自由随机的上下左右移动
  4. 控制我方的坦克和敌人的坦克在规定的范围移动分析->解决

让敌人的坦克也能够发射子弹(可以有多颗子弹)

  1. 在敌人坦克类,使用Vector保存多个Shot
  2. 当每创建一个敌人坦克对象,给该敌人坦克对象初始化一个Shot对象,同时启动Shot
  3. 在绘制敌人坦克时,需要遍历敌人坦克对象Vector,绘制所有的子弹,当子弹isLive == false时,就从Vector移除.

当我方坦克击中敌人坦克时,敌人的坦克就消失,如果能做出爆炸效果更好

1672708284085

1672710589458

1672710765063

编写炸弹类

1672712110073

1672712637370

1672712894280

1672713151203

1672713615102

坦克大战为什么第一个坦克不显示爆炸效果?增加休眠时间之后反而变好了呢?

1672716191612

让敌人的坦克也可以自由随机的上下左右移动

让敌人的坦克也可以自由随机的上下左右移动思路分析

  1. 因为要求敌人的坦克,可以自由移动,因此需要将敌人坦克当做线程使用
  2. 我们需要Enemy Tank implements Runnable
  3. 在run方法写上我们相应的业务代码
  4. 在创建敌人坦克对象时,启动线程

写多线程一定要考虑什么时候退出多线程

将敌人的坦克设置为多线程

1672717411549

启动线程

1672717558262

3.坦克大战0.5

  1. 我方坦克在发射的子弹消亡后,才能发射新的子弹.=>扩展(发多颗子弹怎么办,控制在我们的面板上,最多只有5颗)-》在课后完善..
  2. 让敌人坦克发射的子弹消亡后,可以再发射子弹.[口头说.]
  3. 当敌人的坦克击中我方坦克时,我方坦克消失,并出现爆炸效果. 思路:编写方法,判断敌人的坦克是否击中我的坦克
  4. 让敌人坦克可以最多发射3颗(在面板E),我们的坦克可以发射3颗.并且能够出现正常的爆炸效果即可.

我方坦克在发射的子弹消亡后,才能发射新的子弹.=>扩展(发多颗子弹怎么办)

  1. 在按下J键,我们判断当前hero对象的子弹,是否已经销毁
  2. 如果没有销毁,就不去触发shotEnemyTank
  3. 如果已经销毁,才去触发shotEnemyTank
  4. 如果要发射多颗子弹,就使用Vector保存
  5. 在绘制我方子弹时,需要遍历该Vector集合

1672732761333

我方坦克发射多颗子弹

1672733079617

1672733420698

1672733558494

控制只能发射5颗子弹

1672733838276

多颗子弹打多个坦克

1672734703463

1672734727896

让敌人坦克发射的子弹消亡后,可以再发射子弹

1672736216664

当敌人的坦克击中我方坦克时,我方坦克消失,并出现爆炸效果.

1672737230425

1672737297989

4.项目目录

1672737709194

Bomb类

package com.yt.tankgame04;

/**
 * 炸弹
 */
public class Bomb {
    int x,y;//炸弹的x,y坐标
    int life = 9;//炸弹的生命周期
    boolean isLive = true;

    public Bomb(int x, int y) {
        this.x = x;
        this.y = y;
    }
    //减少生命值
    public void lifeDown(){//配合出现图片的爆炸效果
        if (life>0){
            life--;
        } else {
            isLive = false;
        }
    }
}

EnemyTank类

package com.yt.tankgame04;

import java.util.Vector;

public class EnemyTank extends Tank implements Runnable{
    //在敌人坦克类,使用Vector保存多个Shot
    Vector<Shot> shots = new Vector<>();
    boolean isLive = true;
    public EnemyTank(int x, int y) {
        super(x, y);
    }

    @Override
    public void run() {
        while (true){

            //判断如果shots的size()==0,说明集合已经没有子弹了
            //创建一颗子弹,放入的集合中,并启动
            if (isLive && shots.size() < 3){
                Shot s = null;
                //判读坦克的方向,创建对应的子弹
                switch (getDirect()){
                    case 0:
                        s = new Shot(getX()+20,getY(),0);
                        break;
                    case 1:
                        s = new Shot(getX()+60,getY()+20,1);
                        break;
                    case 2://向下
                        s = new Shot(getX()+20,getY()+60,2);
                        break;
                    case 3://向左
                        s = new Shot(getX(),getY()+20,0);
                        break;
                }
                shots.add(s);
                //启动
                new Thread(s).start();
            }

            //根据坦克的方向来继续移动
            switch (getDirect()){
                case 0://向上
                    //让坦克保持一个方向,走30步
                    for (int i = 0; i < 30; i++) {
                        if (getY()>0) {
                            moveUp();
                        }
                        //休眠50ms,不休眠会到处乱窜
                        try {
                            Thread.sleep(50);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    break;
                case 1://向右
                    //让坦克保持一个方向,走30步
                    for (int i = 0; i < 30; i++) {
                        if (getX()+60 < 1000){
                            moveRight();
                        }
                        //休眠50ms,不休眠会到处乱窜
                        try {
                            Thread.sleep(50);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    break;
                case 2://向下
                    //让坦克保持一个方向,走30步
                    for (int i = 0; i < 30; i++) {
                        if (getY()+60 < 750) {
                            moveDown();
                        }
                        //休眠50ms,不休眠会到处乱窜
                        try {
                            Thread.sleep(50);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    break;
                case 3://向左
                    //让坦克保持一个方向,走30步
                    for (int i = 0; i < 30; i++) {
                        if (getX() > 0) {
                            moveLeft();
                        }
                        //休眠50ms,不休眠会到处乱窜
                        try {
                            Thread.sleep(50);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    break;
            }

            //然后随机的改变坦克方向,0-3的一个整数
            setDirect((int)(Math.random()*4));
            //一旦写并发程序,一定要考虑什么时候结束
            if (!isLive){
                break;//退出线程
            }
        }
    }
}

Hero类

package com.yt.tankgame04;

import java.util.Vector;

//创建自己的坦克
public class Hero extends Tank {
    //定义一个Shot对象,表示射击的行为(线程)
    Shot shot = null;
    //可以发射多颗子弹
    Vector<Shot> shots = new Vector<>();

    public Hero(int x, int y) {
        super(x, y);
    }

    //射击
    public void shotEnemyTank(){

        //控制在面板上只能有5颗子弹
        if (shots.size() == 5){
            return;
        }

        //创建Shot对象,根据当前Hero对象的位置和方向来创建Shot对象
        switch (getDirect()){//得到坦克的方向
            case 0://向上
                shot = new Shot(getX()+20,getY(),0);
                break;
            case 1://向右
                shot = new Shot(getX()+60,getY()+20,1);
                break;
            case 2://向下
                shot = new Shot(getX()+20,getY()+60,2);
                break;
            case 3://向左
                shot = new Shot(getX(),getY()+20,3);
                break;
        }
        //把新创建的shot放入到shots中
        shots.add(shot);
        //启动射击的线程
        new Thread(shot).start();

    }
}

MyPanel类

package com.yt.tankgame04;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Vector;

//坦克大战的绘图区域
//为了监听键盘事件,实现KeyListener
//为了让Panel不停的重绘子弹,需要将MyPanel实现Runable,当做一个线程使用
public class MyPanel extends JPanel implements KeyListener ,Runnable{
    //定义我的坦克
    Hero hero = null;
    //定义敌人的坦克,放入到Vector中,敌人的坦克不止一个
    Vector<EnemyTank> enemyTanks = new Vector<>();
    int enemyTankSize = 3;
    //定义一个Vector,用于存放炸弹
    //说明当子弹击中坦克时,就加入一个Bomb对象到bombs
    Vector<Bomb> bombs = new Vector<>();

    //定义三张炸弹,用于显示爆炸的效果
    Image image1 = null;
    Image image2 = null;
    Image image3 = null;


    public MyPanel(){
        hero = new Hero(500,100);//初始化自己的坦克
        hero.setSpeed(5);
        //初始化敌人的坦克
        for (int i = 0; i < enemyTankSize; i++) {
            //创建敌人的坦克
            EnemyTank enemyTank = new EnemyTank((100 * (i + 1)), 0);
            //设置方向
            enemyTank.setDirect(2);
            //启动敌人坦克线程,让它动起来
            new Thread(enemyTank).start();
            //给该enemyTank加入一颗子弹
            Shot shot = new Shot(enemyTank.getX()+20,enemyTank.getY()+60,enemyTank.getDirect());
            //加入到enemyTank的Vector成员
            enemyTank.shots.add(shot);
            //启动shot对象
            new Thread(shot).start();
            //加入
            enemyTanks.add(enemyTank);
        }

        //初试化图片对象
        image1 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb1.png"));
        image2 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb2.png"));
        image3 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb3.png"));
        //


    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        g.fillRect(0,0,1000,750);//填充矩形,默认是黑色

        if (hero != null && hero.isLive) {
            //画出坦克-封装到方法
            drawTank(hero.getX(), hero.getY(), g, hero.getDirect(), 1);
        }

        //画出敌人的坦克,遍历Vector
        for (int i=0; i< enemyTanks.size(); i++){
            //从Vector中取出坦克
            EnemyTank enemyTank = enemyTanks.get(i);
            //判断当前坦克是否还存活
            if (enemyTank.isLive) {//当敌人坦克是存活的才画出该坦克
                drawTank(enemyTank.getX(), enemyTank.getY(), g, enemyTank.getDirect(), 0);
                //画出enemyTank 的所有子弹
                for (int j = 0; j < enemyTank.shots.size(); j++) {
                    //取出子弹,准备绘制
                    Shot shot = enemyTank.shots.get(j);
                    //绘制
                    if (shot.isLive) {
                        g.draw3DRect(shot.x, shot.y, 2, 1, false);
                    } else {
                        //从Vector移除,否则一直画
                        enemyTank.shots.remove(shot);
                    }
                }
            }
            //当坦克被打爆之后,将其重从集合中移除
//            if (!enemyTank.isLive){
//                enemyTanks.remove(i);
//            }

        }

        //画出hero射击的子弹
        /*
        if (hero.shot != null && hero.shot.isLive == true){
//            System.out.println("子弹被绘制。。。");
//            g.fill3DRect(hero.shot.x,hero.shot.y,1,1,false);
            g.draw3DRect(hero.shot.x,hero.shot.y,1,2,false);
        }
         */
        //将hero的子弹集合shots遍历取出绘制
        for (int i = 0; i < hero.shots.size(); i++) {
            Shot shot = hero.shots.get(i);
            if (shot != null && shot.isLive == true){
                g.draw3DRect(shot.x,shot.y,1,2,false);
            } else {//如果该shot对象已经无效,就从shot集合中移除
                hero.shots.remove(shot);
            }
        }

        //如果bombs集合中有对象,就画出
        for (int i = 0; i < bombs.size(); i++) {
            //取出炸弹
            Bomb bomb = bombs.get(i);
            //根据当前这个bomb对象的life值去画出对应的图片
            if (bomb.life > 6){
                //为什么休眠一下第一个坦克才会显示爆炸效果呢?
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                g.drawImage(image1,bomb.x,bomb.y,60,60,this);
            } else if (bomb.life>3){
                g.drawImage(image2,bomb.x,bomb.y,60,60,this);
            } else {
                g.drawImage(image3,bomb.x,bomb.y,60,60,this);
            }
            //让炸弹的生命值减少
            bomb.lifeDown();
            //如果bomb life为0,就从bombs的集合中删除
            if (bomb.life == 0){
                bombs.remove(bomb);
            }
        }


    }

    //编写方法,画出坦克

    /**
     *
     * @param x 坦克的左上x坐标
     * @param y 坦克的左上y坐标
     * @param g 画笔
     * @param direction 方向 ,上下左右
     * @param type 我们的坦克,还是敌方坦克
     */
    public void drawTank(int x, int y,Graphics g, int direction,int type){
        //根据不同类型的坦克,设置不同的颜色
        switch (type){
            case 0://我们的坦克
                g.setColor(Color.cyan);
                break;
            case 1://敌方的坦克
                g.setColor(Color.yellow);
                break;
        }

        //根据坦克的方向来绘制对应形状的坦克
        //direction表示方向,0:向上  1向右 2向下 3向左
        switch (direction){
            case 0://0表示向上
                g.fill3DRect(x,y,10,60,false);//画出坦克左边的轮子
                g.fill3DRect(x+10,y+10,20,40,false);//画出坦克中间
                g.fill3DRect(x+30,y,10,60,false);//画出坦克右边的轮子
                g.drawOval(x+10,y+20,20,20);//画出坦克中间的盖子
                g.drawLine(x+20,y+30,x+20,y);//画出炮筒
                break;
            case 1://1表示向右
                g.fill3DRect(x,y,60,10,false);//画出坦克上边的轮子
                g.fill3DRect(x+10,y+10,40,20,false);//画出坦克中间
                g.fill3DRect(x,y+30,60,10,false);//画出坦克下边的轮子
                g.drawOval(x+20,y+10,20,20);//画出坦克中间的盖子
                g.drawLine(x+30,y+20,x+60,y+20);//画出炮筒
                break;
            case 2://2表示向下
                g.fill3DRect(x,y,10,60,false);//画出坦克左边的轮子
                g.fill3DRect(x+10,y+10,20,40,false);//画出坦克中间
                g.fill3DRect(x+30,y,10,60,false);//画出坦克右边的轮子
                g.drawOval(x+10,y+20,20,20);//画出坦克中间的盖子
                g.drawLine(x+20,y+30,x+20,y+60);//画出炮筒
                break;
            case 3://3表示向左
                g.fill3DRect(x,y,60,10,false);//画出坦克上边的轮子
                g.fill3DRect(x+10,y+10,40,20,false);//画出坦克中间
                g.fill3DRect(x,y+30,60,10,false);//画出坦克下边的轮子
                g.drawOval(x+20,y+10,20,20);//画出坦克中间的盖子
                g.drawLine(x+30,y+20,x,y+20);//画出炮筒
                break;
            default:
                System.out.println("暂时没有处理");
        }
    }

    //编写方法,判断敌人坦克是否击中我的坦克
    public void hitHero(){
        //遍历所有敌人的坦克
        for (int i = 0; i < enemyTanks.size(); i++) {
            //取出敌人坦克,
            EnemyTank enemyTank = enemyTanks.get(i);
            //遍历enemyTank 对象的所有子弹
            for (int j = 0; j < enemyTank.shots.size(); j++) {
                //取出一颗子弹
                Shot shot = enemyTank.shots.get(j);
                //判断shot 是否击中我的坦克
                if (hero.isLive && shot.isLive){
                    hitTank(shot,hero);
                }
            }
        }
    }

    //如果我们的坦克可以发射多个子弹
    //在判断我方子弹是否击中敌人坦克时,就需要把我们的子弹集合中所有的子弹都取出
    //和敌人的所有坦克进行判断
    public void hitEnemyTank(){
        //遍历我们的子弹
        for (int j = 0; j < hero.shots.size(); j++) {
            Shot shot = hero.shots.get(j);
            //判断是否击中了敌人坦克
            if (shot != null && hero.shot.isLive) {//当我的子弹还存活
                //遍历敌人所有的坦克
                for (int i = 0; i < enemyTanks.size(); i++) {
                    EnemyTank enemyTank = enemyTanks.get(i);
                    hitTank(hero.shot, enemyTank);
                }
            }
        }
    }


    //编写方法,判断我反子弹是否击中敌人坦克
    //什么时候判断击中坦克呢?run方法
    public void hitTank(Shot s, Tank Tank){
       //判断s击中坦克
       switch (Tank.getDirect()){
           case 0://坦克向上
           case 2://坦克向下
               if (s.x >Tank.getX() && s.x < Tank.getX()+40
                    && s.y > Tank.getY() && s.y < Tank.getY()+60){
                   s.isLive = false;
                   Tank.isLive = false;
                   //当我的子弹击中敌人坦克之后,将enemyTank重Vector中去掉
                   enemyTanks.remove(Tank);
                   //创建Bomb对象,加入到bombs集合中
                   Bomb bomb = new Bomb(Tank.getX(), Tank.getY());
                   bombs.add(bomb);
               }
               break;
           case 1://坦克向右
           case 3://坦克向左
               if (s.x > Tank.getX() && s.x<Tank.getX()+60 &&
                    s.y> Tank.getY() && s.y< Tank.getY()+40){
                   s.isLive = false;
                   Tank.isLive = false;
                   //当我的子弹击中敌人坦克之后,将enemyTank重Vector中去掉
                   enemyTanks.remove(Tank);
                   //创建Bomb对象,加入到bombs集合中
                   Bomb bomb = new Bomb(Tank.getX(), Tank.getY());
                   bombs.add(bomb);
               }
               break;

       }
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    //处理w s a d 键的按下情况
    @Override
    public void keyPressed(KeyEvent e) {
        if(e.getKeyCode() == KeyEvent.VK_W){
            //按下w键,改变坦克方向
            hero.setDirect(0);
            if (hero.getY() > 0) {
                hero.moveUp();
            }
        } else if (e.getKeyCode() == KeyEvent.VK_D){
            hero.setDirect(1);
            if (hero.getX()+60 < 1000){
                hero.moveRight();
            }
        } else if (e.getKeyCode() == KeyEvent.VK_S){
            hero.setDirect(2);
            if (hero.getY()+60 < 750) {
                hero.moveDown();
            }
        } else if (e.getKeyCode() == KeyEvent.VK_A){
            hero.setDirect(3);
            if (hero.getX() > 0){
                hero.moveLeft();
            }
        }
        //如果用户按下j,就表示发射子弹
        if (e.getKeyCode() == KeyEvent.VK_J){
//            System.out.println("用户按下了J,开始射击。");

            //判断hero子弹是否已经销毁,shot != null 不意味着 shot对象被销毁了
            //if (hero.shot == null || !hero.shot.isLive) {
            //    hero.shotEnemyTank();
            //}
            //发射多颗子弹
            hero.shotEnemyTank();
        }

        //务必要重绘,才能显示出变化
        this.repaint();
    }

    @Override
    public void keyReleased(KeyEvent e) {

    }

    @Override
    public void run() {//每隔100ms,重绘绘图区域,子弹就移动起来了
        while (true) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            //是否击中敌人坦克
            hitEnemyTank();
            //敌人坦克是否击中我们
            hitHero();
            this.repaint();
        }
    }
}

Shot类

package com.yt.tankgame04;

/**
 * 射击子弹
 */
public class Shot implements Runnable{
    int x;//子弹的x坐标
    int y;//子弹的y坐标
    int direct;//子弹的方向
    int speed = 2;//子弹的速度
    boolean isLive = true;//子弹是否存活

    //构造器
    public Shot(int x, int y, int direct) {
        this.x = x;
        this.y = y;
        this.direct = direct;
    }

    @Override
    public void run() {//射击行为
        while (true){

            //线程休眠
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //根据方向改变x,y坐标
            switch (direct){
                case 0://表示方向向上
                    y -= speed;
                    break;
                case 1://表示方向向右
                    x += speed;
                    break;
                case 2://表示方向向下
                    y += speed;
                    break;
                case 3://表示方向向zuo
                    x -= speed;
                    break;

            }
            //测试下,输出x,y的坐标
            System.out.println("子弹 x=" + x + " y=" + y);
            //子弹出边界了
            //当子弹碰到敌人坦克是也应该结束线程
            if (!(x>= 0 && x <=1000 && y>=0 && y<=750 && isLive)){
                isLive = false;
                break;
            }
        }

    }
}

Tank类

package com.yt.tankgame04;

public class Tank {
    private int x;//指定坦克的横坐标
    private int y;//指定坦克的纵坐标
    private int direct;//表示坦克方向 0上 1右 2下 3左
    private int speed = 1;
    boolean isLive = true;

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

    //上右下左移动方法
    public void moveUp(){
        y -= speed;
    }

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

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

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

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

    public int getDirect() {
        return direct;
    }

    public void setDirect(int direct) {
        this.direct = direct;
    }

    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;
    }
}

YtTankGame04类

package com.yt.tankgame04;

import javax.swing.*;

public class YtTankGame04 extends JFrame {
    //定义MyPanel
    MyPanel mp = null;

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

    public YtTankGame04(){
        mp = new MyPanel();
        //将mp放入到Thread,并启动
        Thread thread = new Thread(mp);
        thread.start();
        this.add(mp);//将面板(就是绘制游戏的区域)添加到窗口中
        this.addKeyListener(mp);//让JFrame监听mp的键盘事件
        this.setSize(1000,750);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }

}

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

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

相关文章

Python 做了一个 ChatGPT 机器人,表妹玩了一下午

大家好&#xff0c;我是毕加锁。 毫无疑问&#xff0c;ChatGPT 已经是当下编程圈最火的话题之一&#xff0c;它不仅能够回答各类问题&#xff0c;甚至还能执行代码&#xff01; 或者是变成一只猫 因为它实在是太好玩&#xff0c;我使用Python将ChatGPT改造&#xff0c;可以实现…

【回答问题】ChatGPT上线了!给我推荐20个比较流行的知识蒸馏模型/方法/源码

目录给我推荐20个比较流行的知识蒸馏模型给我推荐10个比较流行的知识蒸馏模型源码给我推荐20个比较流行的深度学习知识蒸馏方法给我推荐20个比较流行的深度学习知识蒸馏方法源码给我推荐20个比较流行的深度学习知识蒸馏实现源码给我推荐20个比较流行的知识蒸馏模型 好的&#…

VSCode配置并连接远程服务器 并设置免密登录

文章目录1 前言PyCharm与VSCode2 VSCode配置远程开发环境3 VSCode配置远程免密登录4 推荐插件参考1 前言 PyCharm与VSCode 最近由于许多深度学习的项目需要在服务器上跑&#xff0c;之前一直使用PyCharm进行开发&#xff0c;使用习惯之后觉得还行&#xff0c;配置稍微有点复杂…

(七)Docker上安装常用软件说明(tomcat,mysql)

目录 一、总体步骤 二、安装tomcat 三、安装mysql&#xff08;简易版&#xff09; 四、安装mysql&#xff08;实战版&#xff09; 一、总体步骤 1、搜索镜像 2、拉取镜像 3、查看镜像 4、启动镜像 5、停止容器 6、移除容器 二、安装tomcat 1、dockerhub官网搜索tom…

福利来了~Python内置函数最全总结,建议收藏

喜迎2023&#xff0c;希望所有人都幸福安康&#xff01;小编在这里给大家放烟花了&#xff0c;希望新的一年疫情嗝屁&#xff0c;霉运全跑&#xff01; 开始正文。 1 abs() 绝对值或复数的模 In [1]: abs(-6) Out[1]: 6 2 all() 接受一个迭代器&#xff0c;如果迭代器的所有…

前端bug每次都比后端多,我总结了5点原因

最近总有朋友跟我吐槽说&#xff0c;每次一汇报&#xff0c;就说前端bug多&#xff0c;前端能力有问题&#xff0c;几乎每次都是前端bug比后端多&#xff0c;还好几次导致项目延期。 我其实听的挺不是滋味的&#xff0c;前端bug比后端多&#xff0c;可能是这么几点原因吧 目录 …

Shiro历史漏洞复现 - Shiro-550

文章目录Shiro简介Shiro历史漏洞Shiro-550Shiro-721漏洞发现Shiro组件识别Shiro漏洞搜索Shiro漏洞检测工具Shiro rememberMe反序列化漏洞&#xff08;Shiro-550&#xff09;漏洞原理影响版本漏洞利用Shiro-721 (未完待续......&#xff09;Shiro简介 Apache Shiro是一种功能强…

LeetCode刷题复盘笔记—一文搞懂动态规划之115. 不同的子序列问题(动态规划系列第三十九篇)

今日主要总结一下动态规划的一道题目&#xff0c;115. 不同的子序列 题目&#xff1a;115. 不同的子序列 Leetcode题目地址 题目描述&#xff1a; 给定一个字符串 s 和一个字符串 t &#xff0c;计算在 s 的子序列中 t 出现的个数。 字符串的一个 子序列 是指&#xff0c;通…

spring boot 日志

目录 什么是日志呢 ? 日志有什么作用呢? 什么是日志呢 ? 日志的作用是什么呢 ? 我们需要学会日志的什么 ? 自定义输出日志 日志持久化 为什么要将日志持久化呢? 如何进行日志的持久化 设置日志级别 日志级别有什么用呢 ? 日志都有哪些级别呢 ? 如何设置日志…

十二、Express接口编写 —— 跨域问题

在前面的HTTP模块内容内容当中讲到这个跨域的问题&#xff0c;跨域就涉及到浏览器的同源策略&#xff0c;跨域只出现在浏览器当中&#xff0c;在浏览器当中去执行脚本的时候会进行一个同源检测&#xff0c;只有是同源的脚本才会被浏览器执行&#xff0c;不同源就是跨域&#xf…

MySQL高级 SQL优化【order bygroup by优化】

目录 1&#xff1a;SQL优化 1.1&#xff1a;order by优化 A. 数据准备 B. 执行排序SQL C. 创建索引 D. 创建索引后&#xff0c;根据age, phone进行升序排序 E. 创建索引后&#xff0c;根据age, phone进行降序排序 F. 根据phone&#xff0c;age进行升序排序&#xff…

STM32MP157驱动开发——Linux 网络设备驱动

STM32MP157驱动开发——Linux 网络设备驱动一、简介STM32MP1 GMAC 接口简介YT8511C 详解二、驱动开发1.网络外设的设备树2.设备驱动三、测试网速测试参考文章&#xff1a;【正点原子】I.MX6U嵌入式Linux驱动开发——Linux 网络驱动 一、简介 网络驱动是 linux 驱动三巨头之一&…

[C语言]三种方法实现n的k次方(递归/调用math库函数/实现pow函数)[含递归图解说明]

目录 1.调用math库函数中的pow函数实现n的k次方 2.创造pow函数实现n的k次方 3.递归实现n的k次方&#xff08;含图解&#xff09; 1.调用math库函数中的pow函数实现n的k次方 pow函数的功能&#xff1a;计算n的k次幂 pow格式&#xff1a;pow(n,k) #include <stdio.h>#in…

@NotEmpty、@NotBlank、@NotNull 区别和使用

这种注解通常使用场景在前端发送过来的数据&#xff0c;先进行校验处理&#xff0c;在进行逻辑判断的&#xff0c;所以在进行校验处理的时候&#xff0c;我们通常会使用这三种注解来进行判断传过来的值 1NotNull 适用于基本数据类型(Integer&#xff0c;Long&#xff0c;Doubl…

回收租赁商城系统功能拆解01讲-产品架构

回收租赁系统适用于物品回收、物品租赁、二手买卖交易等三大场景。 可以快速帮助企业搭建类似闲鱼回收/爱回收/爱租机/人人租等回收租赁商城。 回收租赁系统支持智能评估回收价格&#xff0c;后台调整最终回收价&#xff0c;用户同意回收后系统即刻放款&#xff0c;用户微信零…

【谷粒商城基础篇】基础环境搭建

谷粒商城笔记合集 分布式基础篇分布式高级篇高可用集群篇简介&环境搭建项目简介与分布式概念&#xff08;第一、二章&#xff09;基础环境搭建&#xff08;第三章&#xff09;整合SpringCloud整合SpringCloud、SpringCloud alibaba&#xff08;第四、五章&#xff09;前端知…

关于yum源的总结

博客主页&#xff1a;https://tomcat.blog.csdn.net 博主昵称&#xff1a;农民工老王 主要领域&#xff1a;Java、Linux、K8S 期待大家的关注&#x1f496;点赞&#x1f44d;收藏⭐留言&#x1f4ac; 目录1 相关概念1.1 rpm与yum1.2 yum源与repo文件2 yum源的种类2.1 官方源2.…

【HTML】耗时一下午,整理出了一个精美的响应式登陆注册表单(附源码)

&#x1f482;作者简介&#xff1a; THUNDER王&#xff0c;一名热爱财税和SAP ABAP编程以及热爱分享的博主。目前于江西师范大学会计学专业大二本科在读&#xff0c;同时任汉硕云&#xff08;广东&#xff09;科技有限公司ABAP开发顾问。在学习工作中&#xff0c;我通常使用偏后…

【OpenDDS开发指南V3.20】第八章:opendds_idl

opendds_idl是构建opendds和opendds应用程序过程中使用的代码生成器之一。 它可以用多种不同的方式定制如何从IDL文件生成源代码。 有关默认使用模式的概述,请参见第2.1.2节。 OpenDDS IDL编译器是使用位于$DDS_ROOT/bin/(PATH上)的OpenDDS_IDL可执行文件调用的。 它解析…

SpringBoot+RabbitMQ(官方案例)

在线文档项目结构 1.源码克隆&#xff1a;git clone https://github.com/spring-guides/gs-messaging-rabbitmq.git 2.包含两个项目initial和complete&#xff0c;initial可以根据文档练习完善&#xff0c;complete是完整项目 3.功能描述&#xff1a;构建应用程序&#xff0c;S…