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

经典游戏,用java实现的坦克大战小游戏

今天给大家分享一个使用java编写的坦克大战小游戏,整体还是挺好玩的,通过对这款游戏的简单实现,加深对java基础的深刻理解。

一、设计思路
1.坦克大战小游戏通过java实现,其第一步需要先绘制每一关对应的地图,地图包括河流、草地、砖块、铁块等。
2.需要绘制玩家坦克、敌方坦克、以及坦克移动过程中使用到的碰撞算法,子弹与坦克之间的碰撞,
包括击中敌方坦克后的爆炸效果,通过重绘实现坦克的移动,以及各种道具的随机生成算法。

实际运行效果如下:

在这里插入图片描述
二、代码实现
1.首先需要将游戏中涉及到的各种对象梳理清楚,由于Java面向对象的特征,可以将一些对象公共特性抽象出来,比如将坦克抽象出一个超类,代码如下:

public abstract class Tank{int x=0;int y=0;int tempX=0;int tempY=0;int size=32;int direct=Constant.UP;int speed=1;int lives=1;int frame=0;//控制敌方坦克切换方向的时间boolean isAI=false;//是否自动boolean hit;boolean isShooting=false;boolean isDestroyed=false;boolean isProtected=false;Map map;GameMain gameMain;Collision collision;Bullet bullet;int starNum=0; //星星数public Tank(int size,int speed,Collision collision,Map map,GameMain gameMain) {this.size=size;this.collision=collision;this.map=map;this.gameMain=gameMain;this.speed=speed;	}public void move() {//如果是AI坦克,在一定时间或碰撞后切换方法if(this.isAI && gameMain.enemyStopTime>0) {return;}this.tempX=this.x;this.tempY=this.y;if(this.isAI) {this.frame++;if(this.frame%100==0 || this.hit) {this.direct=(int)(Math.random()*4);this.hit=false;this.frame=0;}}if(this.direct==Constant.UP) {this.tempY-=this.speed;}else if(this.direct==Constant.DOWN) {this.tempY+=this.speed;}else if(this.direct==Constant.LEFT) {this.tempX-=this.speed;}else if(this.direct==Constant.RIGHT) {this.tempX+=this.speed;}isHit();if(!this.hit) {this.x=this.tempX;this.y=this.tempY;}}public void isHit() {if(this.direct==Constant.LEFT) {if(this.x<=map.offsetX) {this.x=map.offsetX;this.hit=true;}}else if(this.direct==Constant.RIGHT) {if(this.x>=map.offsetX+map.mapWidth-this.size) {this.x=map.offsetX+map.mapWidth-this.size;this.hit=true;}}else if(this.direct==Constant.UP) {if(this.y<=map.offsetY) {this.y=map.offsetY;this.hit=true;}}else if(this.direct==Constant.DOWN) {if(this.y>=map.offsetY+map.mapHeight-this.size) {this.y=map.offsetY+map.mapHeight-this.size;this.hit=true;}}if(!this.hit) {if(collision.tankMapCollision(this, map)) {this.hit=true;}}}public abstract void drawTank(Graphics2D ctx2);public void shoot(int type,Graphics2D ctx2) {if(this.isAI && gameMain.enemyStopTime>0) {return;}if(this.isShooting) {return;}int tempX=this.x;int tempY=this.y;this.bullet=new Bullet(tempX, tempY, this.direct, gameMain, type, map, this, collision);if(!this.isAI) {if(this.starNum==0) {this.bullet.speed=3;this.bullet.fireNum=1;}if(this.starNum>0 && this.starNum<=3) {this.bullet.speed+=this.starNum;this.bullet.fireNum+=(this.starNum-1);}if(this.starNum>3) {this.bullet.speed+=3;this.bullet.fireNum+=3;}}if(this.direct==Constant.UP) {tempX = this.x + this.size/2 - this.bullet.size/2;tempY=this.y-this.bullet.size;}else if(this.direct==Constant.DOWN) {tempX = this.x + this.size/2 - this.bullet.size/2;tempY=this.y+this.bullet.size;}else if(this.direct==Constant.LEFT) {tempX=this.x-this.bullet.size;tempY=this.y + this.size/2 - this.bullet.size/2;}else if(this.direct==Constant.RIGHT) {tempX=this.x+this.bullet.size;tempY=this.y + this.size/2 - this.bullet.size/2;}this.bullet.x=tempX;this.bullet.y=tempY;if(!this.isAI) {//音乐Constant.executor.execute(new Runnable() {@Overridepublic void run() {Constant.ATTACK_AUDIO.play();}});}this.bullet.drawBullet(ctx2);gameMain.bulletArr.add(this.bullet);this.isShooting=true;}public void distroy() {this.isDestroyed=true;gameMain.crackArr.add(new CrackAnimation(gameMain, Constant.CRACK_TYPE_TANK, this));if(this.isAI) {Constant.executor.execute(new Runnable() {@Overridepublic void run() {Constant.TANK_DESTROY_AUDIO.play();}});gameMain.appearEnemy--;}else {Constant.executor.execute(new Runnable() {@Overridepublic void run() {Constant.PLAYER_DESTROY_AUDIO.play();}});this.starNum=0;}}
}

2.坦克子类实现

public class PlayTank extends Tank{int protectedTime = 0;//保护时间int offsetX=0; //坦克2与坦克1的距离int type; //玩家类型public PlayTank(int type,Collision collision, Map map, GameMain gameMain) {super(32, 2, collision, map, gameMain);this.lives = 3;//生命值this.isProtected = true;//是否受保护this.protectedTime = 500;//保护时间this.type=type;}@Overridepublic void drawTank(Graphics2D ctx2) {this.hit = false;if(this.type==1) {ctx2.drawImage(Constant.RESOURCE_IMAGE, this.x, this.y,this.x+this.size,this.y+this.size,Constant.POS.get("player").x+this.offsetX+this.direct*this.size, Constant.POS.get("player").y,Constant.POS.get("player").x+this.offsetX+this.direct*this.size+this.size, Constant.POS.get("player").y+this.size, null);}else {ctx2.drawImage(Constant.RESOURCE_IMAGE, this.x, this.y,this.x+this.size,this.y+this.size,Constant.POS.get("player").x+128+this.offsetX+this.direct*this.size, Constant.POS.get("player").y,Constant.POS.get("player").x+128+this.offsetX+this.direct*this.size+this.size, Constant.POS.get("player").y+this.size, null);}if(this.isProtected) {int temp=((500-protectedTime)/5)%2;ctx2.drawImage(Constant.RESOURCE_IMAGE, this.x, this.y,this.x+this.size,this.y+this.size,Constant.POS.get("protected").x, Constant.POS.get("protected").y+32*temp,Constant.POS.get("protected").x+this.size, Constant.POS.get("protected").y+this.size, null);this.protectedTime--;if(this.protectedTime==0) {this.isProtected=false;}}}/*** 玩家坦克复活* @param player*/public void renascenc(int playerType) {this.lives--;this.direct=Constant.UP;this.isProtected=true;this.protectedTime=500;this.isDestroyed = false;int temp=0;if(playerType==1) {temp=129;}else {temp=256;}this.x = temp + map.offsetX;this.y = 385 + map.offsetY;}}

3.通过子类继承父类实现玩家坦克和敌方坦克的创建,创建完后,接下来就可让坦克动起来,如下:

public void addEnemyTank(Graphics2D ctx2) {if(enemyArr == null || enemyArr.size() >= maxAppearEnemy || maxEnemy == 0){return;}appearEnemy++;Tank objTank=null;int rand=(int) (Math.random()*4);if(rand==0) {objTank=new TankEnemy0(collision, map, this);}else if(rand==1) {objTank=new TankEnemy1(collision, map, this);}else if(rand==2) {objTank=new TankEnemy2(collision, map, this);}else if(rand==3) {objTank=new TankEnemy3(collision, map, this);}enemyArr.add(objTank);this.maxEnemy--;map.clearEnemyNum(maxEnemy, appearEnemy,ctx2);}

4.在移动过程中,涉及到坦克与子弹,坦克与地图之间的碰撞问题,实现如下:

/**
* 坦克与地图间的碰撞
**/
public boolean tankMapCollision(Tank tank,Map map) {//移动检测,记录最后一次的移动方向,根据方向判断+-overlap;int tileNum=0;int rowIndex=0;int colIndex=0;int overlap=3; //允许重叠的大小//根据tank的x、y计算map的row和colif(tank.direct==Constant.UP) {rowIndex=(tank.tempY+overlap-map.offsetY)/map.tileSize;colIndex=(tank.tempX+overlap-map.offsetX)/map.tileSize;}else if(tank.direct==Constant.DOWN) {rowIndex=(tank.tempY-overlap-map.offsetY+tank.size)/map.tileSize;colIndex=(tank.tempX+overlap-map.offsetX)/map.tileSize;}else if(tank.direct==Constant.LEFT) {rowIndex=(tank.tempY+overlap-map.offsetY)/map.tileSize;colIndex=(tank.tempX+overlap-map.offsetX)/map.tileSize;}else if(tank.direct==Constant.RIGHT){rowIndex=(tank.tempY+overlap-map.offsetY)/map.tileSize;colIndex=(tank.tempX-overlap-map.offsetX+tank.size)/map.tileSize;}if(rowIndex>=map.hTileCount || rowIndex<0 || colIndex>=map.wTileCount || colIndex<0) {return true;}if(tank.direct==Constant.UP || tank.direct==Constant.DOWN) {int tempWidth=tank.tempX-map.offsetX-colIndex*map.tileSize+tank.size-overlap;if(tempWidth%map.tileSize==0) {tileNum=tempWidth/map.tileSize;}else {tileNum=tempWidth/map.tileSize+1;}for(int i=0;i<tileNum && colIndex+i<map.wTileCount;i++) {int mapContent=map.mapLevel[rowIndex][colIndex+i];if(mapContent==Constant.WALL || mapContent==Constant.GRID || mapContent==Constant.WATER || mapContent==Constant.HOME || mapContent==Constant.ANOTHER_HOME) {if(tank.direct==Constant.UP) {tank.y=map.offsetY+rowIndex*map.tileSize+map.tileSize-overlap;}else {tank.y=map.offsetY+rowIndex*map.tileSize-tank.size+overlap;}return true;}}}else {int tempHeight=tank.tempY-map.offsetY-rowIndex*map.tileSize+tank.size-overlap;if(tempHeight%map.tileSize==0) {tileNum=tempHeight/map.tileSize;}else {tileNum=tempHeight/map.tileSize+1;}for(int i=0;i<tileNum && rowIndex+i<map.hTileCount;i++) {int mapContent=map.mapLevel[rowIndex+i][colIndex];if(mapContent==Constant.WALL || mapContent==Constant.GRID || mapContent==Constant.WATER || mapContent==Constant.HOME || mapContent==Constant.ANOTHER_HOME) {if(tank.direct==Constant.LEFT) {tank.x=map.offsetX+colIndex*map.tileSize+map.tileSize-overlap;}else {tank.x=map.offsetX+colIndex*map.tileSize-tank.size+overlap;}return true;}}}return false;}

5.绘制界面,通过定时重绘实现,具体代码如下:

public class GameMain extends JPanel{//int enemyNum=12;Map map;Num num;int level=1;Level tankLevel;int gameState=Constant.GAME_STATE_MENU;private boolean isGameOver=false;int maxEnemy = 12;//敌方坦克总数int maxAppearEnemy = 5;//屏幕上一起出现的最大数int appearEnemy = 0; //已出现的敌方坦克int enemyStopTime=0;List<Bullet> bulletArr;List<Tank> enemyArr;List<CrackAnimation> crackArr;List<Integer> keys;Tank player1 = null;//玩家1Tank player2 = null;//玩家2Collision collision;int mainframe = 0;Image offScreenImage;Menu menu;Stage stage;Prop prop;Graphics2D ctx2;int overX = 176;int overY = 384;int propTime = 300; //道具出现频次int homeProtectedTime = -1;int winWaitTime=80;public void initGame(GameMain gameMain) {this.num=new Num(gameMain);this.tankLevel=new Level();this.collision=new Collision(gameMain);}public void initObject() {this.map=new Map(this, num, tankLevel, level);player1=new PlayTank(1,collision, map, this);player1.x = 129 + map.offsetX;player1.y = 385 + map.offsetY;player2 = new PlayTank(2,collision, map, this);player2.x = 256 + map.offsetX;player2.y = 385 + map.offsetY;bulletArr=new ArrayList<>();enemyArr=new ArrayList<>();crackArr=new ArrayList<>();keys=new ArrayList<>();menu=new Menu();stage=new Stage(level, this,this.num);this.isGameOver=false;this.propTime=400;this.homeProtectedTime = -1;this.maxEnemy=12;this.winWaitTime=50;this.appearEnemy=0;this.overY=384;}public void goGameOver() {this.isGameOver=true;}@Overridepublic void paint(Graphics g) {//创建和容器一样大小的Image图片if(offScreenImage==null) {offScreenImage=this.createImage(Constant.SCREEN_WIDTH,Constant.SCREEN_HEIGHT);}//获得该图片的画布Graphics gImage=offScreenImage.getGraphics();//填充整个画布gImage.fillRect(0,0,Constant.SCREEN_WIDTH,Constant.SCREEN_HEIGHT);if(ctx2==null) {ctx2=(Graphics2D)gImage;}if(gameState==Constant.GAME_STATE_MENU) {menu.drawMenu(ctx2);}if(gameState==Constant.GAME_STATE_INIT) {stage.setNum(ctx2);stage.drawStage(ctx2);}if(gameState==Constant.GAME_STATE_START || gameState==Constant.GAME_STATE_OVER) {drawAll(ctx2);}if(gameState==Constant.GAME_STATE_OVER) {gameOver();}if(gameState==Constant.GAME_STATE_WIN) {this.winWaitTime--;drawAll(ctx2);if(this.winWaitTime==0) {nextLevel();}}//将缓冲区绘制好的图形整个绘制到容器的画布中g.drawImage(offScreenImage,0,0,null);}public void initMap(Graphics2D ctx2) {map.setNum(ctx2);map.drawMap(ctx2);}public void drawAll(Graphics2D ctx2) {map.setNum(ctx2);map.drawMap(ctx2);if(player1.lives>0) {player1.drawTank(ctx2);}if(player2.lives>0) {player2.drawTank(ctx2);}if(appearEnemy<maxEnemy){if(mainframe % 100 == 0){addEnemyTank(ctx2);mainframe = 0;}mainframe++;}drawLives(ctx2);drawEnemyTanks(ctx2);map.drawGrassMap(ctx2);drawBullet(ctx2);drawCrack(ctx2);keyEvent();if(propTime<=0){drawProp(ctx2);}else{propTime --;}if(homeProtectedTime > 0){homeProtectedTime --;}else if(homeProtectedTime == 0){homeProtectedTime = -1;homeNoProtected(ctx2);}}public void addEnemyTank(Graphics2D ctx2) {if(enemyArr == null || enemyArr.size() >= maxAppearEnemy || maxEnemy == 0){return;}appearEnemy++;Tank objTank=null;int rand=(int) (Math.random()*4);if(rand==0) {objTank=new TankEnemy0(collision, map, this);}else if(rand==1) {objTank=new TankEnemy1(collision, map, this);}else if(rand==2) {objTank=new TankEnemy2(collision, map, this);}else if(rand==3) {objTank=new TankEnemy3(collision, map, this);}enemyArr.add(objTank);this.maxEnemy--;map.clearEnemyNum(maxEnemy, appearEnemy,ctx2);}public void drawEnemyTanks(Graphics2D ctx2) {if(enemyArr!=null && enemyArr.size()>0) {Iterator<Tank> it=enemyArr.iterator();while(it.hasNext()) {Tank enemyTank=it.next();if(enemyTank.isDestroyed) {it.remove();}else {enemyTank.drawTank(ctx2);}}}if(enemyStopTime > 0){enemyStopTime --;}}/*** 绘制玩家生命数*/public void drawLives(Graphics2D ctx2) {map.drawLives(player1.lives, 1,ctx2);map.drawLives(player2.lives, 2,ctx2);}/*** 绘制子弹* @param ctx2*/public void drawBullet(Graphics2D ctx2) {if(bulletArr != null && bulletArr.size() > 0){Iterator<Bullet> it=bulletArr.iterator();while(it.hasNext()) {Bullet bullet=it.next();if(bullet.isDestroyed) {it.remove();bullet.owner.isShooting=false;}else {//绘制子弹bullet.drawBullet(ctx2);}}}}public void drawCrack(Graphics2D ctx2) {if(crackArr != null && crackArr.size() > 0){Iterator<CrackAnimation> it=crackArr.iterator();while(it.hasNext()) {CrackAnimation crackAnimation=it.next();if(crackAnimation.isOver) {it.remove();if(crackAnimation.crackObj instanceof Tank) {Tank tank=(Tank)crackAnimation.crackObj;if(tank==player1) {PlayTank playerTank1=(PlayTank)player1;playerTank1.renascenc(1);}else if(tank==player2) {PlayTank playerTank2=(PlayTank)player2;playerTank2.renascenc(2);}}}else {//绘制爆炸效果crackAnimation.draw(ctx2);}}}}public void drawProp(Graphics2D ctx2) {double rand=Math.random();if(rand<=0.4 && prop==null) {prop=new Prop(this, map, collision);prop.initProp();}if(prop!=null) {prop.drawProp(ctx2);if(prop.isDestroyed) {prop=null;propTime=600;}}}public void nextLevel() {level++;if(level==17) {level=1;}int oldPlayerNum=menu.playNum;initObject();menu.playNum = oldPlayerNum;//只有一个玩家if(menu.playNum == 1){player2.lives = 0;}map.first=0;stage.init(level);gameState = Constant.GAME_STATE_INIT;}public void preLevel() {level--;if(level == 0){level = 16;}//保存玩家数int oldPlayerNum = menu.playNum;initObject();menu.playNum = oldPlayerNum;//只有一个玩家if(menu.playNum == 1){player2.lives = 0;}stage.init(level);gameState = Constant.GAME_STATE_INIT;}public void gameLoop() {switch (gameState) {case Constant.GAME_STATE_MENU:repaint();break;case Constant.GAME_STATE_INIT://stage.draw();if(stage.isReady == true){gameState = Constant.GAME_STATE_START;}repaint();break;case Constant.GAME_STATE_START://drawAll();if(isGameOver ||(player1.lives <=0 && player2.lives <= 0)){gameState = Constant.GAME_STATE_OVER;map.homeHit(ctx2);Constant.executor.execute(new Runnable() {@Overridepublic void run() {Constant.PLAYER_DESTROY_AUDIO.play();}});}if(appearEnemy == maxEnemy && enemyArr.size() == 0){gameState  = Constant.GAME_STATE_WIN;}repaint();break;case Constant.GAME_STATE_WIN:repaint();break;case Constant.GAME_STATE_OVER:repaint();break;}}public void gameOver() {//.clearRect(0, 0, Constant.SCREEN_WIDTH, Constant.SCREEN_HEIGHT);ctx2.drawImage(Constant.RESOURCE_IMAGE, overX+map.offsetX, overY+map.offsetY,overX+map.offsetX+64,overY+map.offsetY+32,Constant.POS.get("over").x, Constant.POS.get("over").y,Constant.POS.get("over").x+64, Constant.POS.get("over").y+32, null);overY-=2;if(overY<=map.mapHeight/2) {initObject();//if(menu.playNum==1) {//	player2.lives=0;//}gameState = Constant.GAME_STATE_MENU;}}public void action() {KeyAdapter l=new KeyAdapter() {@Overridepublic void keyPressed(KeyEvent e) {switch (gameState) {case Constant.GAME_STATE_MENU:if(e.getKeyCode()==KeyEvent.VK_ENTER){gameState = Constant.GAME_STATE_INIT;//只有一个玩家if(menu.playNum==1) {player2.lives=0;}}else {int n=0;if(e.getKeyCode()==KeyEvent.VK_DOWN) {n=1;}else if(e.getKeyCode()==KeyEvent.VK_UP) {n=-1;}menu.next(n);}break;case Constant.GAME_STATE_START:if(!keys.contains(e.getKeyCode())){keys.add(e.getKeyCode());}//射击if(e.getKeyCode()==KeyEvent.VK_SPACE && player1.lives > 0){player1.shoot(Constant.BULLET_TYPE_PLAYER, ctx2);}else if(e.getKeyCode()==KeyEvent.VK_ENTER && player2.lives > 0) {player2.shoot(Constant.BULLET_TYPE_PLAYER, ctx2);}else if(e.getKeyCode()==KeyEvent.VK_N) { //下一关nextLevel();}else if(e.getKeyCode() == KeyEvent.VK_P) {preLevel();}break;}}@Overridepublic void keyReleased(KeyEvent e) {// TODO Auto-generated method stub//super.keyReleased(e);if(keys != null && keys.size() > 0){Iterator<Integer> it=keys.iterator();while(it.hasNext()) {Integer key=it.next();if(key.intValue()==e.getKeyCode()) {it.remove();break;}}}}@Overridepublic void keyTyped(KeyEvent e) {//super.keyTyped(e);}};this.addKeyListener(l);this.setFocusable(true);Timer timer=new Timer();int interval=20;timer.schedule(new TimerTask() {@Overridepublic void run() {gameLoop();	}}, interval, interval);}public void keyEvent() {if(keys.contains(KeyEvent.VK_W)){player1.direct = Constant.UP;player1.hit = false;player1.move();}else if(keys.contains(KeyEvent.VK_S)){player1.direct = Constant.DOWN;player1.hit = false;player1.move();}else if(keys.contains(KeyEvent.VK_A)){player1.direct = Constant.LEFT;player1.hit = false;player1.move();}else if(keys.contains(KeyEvent.VK_D)){player1.direct = Constant.RIGHT;player1.hit = false;player1.move();}if(keys.contains(KeyEvent.VK_UP)){player2.direct = Constant.UP;player2.hit = false;player2.move();}else if(keys.contains(KeyEvent.VK_DOWN)){player2.direct = Constant.DOWN;player2.hit = false;player2.move();}else if(keys.contains(KeyEvent.VK_LEFT)){player2.direct = Constant.LEFT;player2.hit = false;player2.move();}else if(keys.contains(KeyEvent.VK_RIGHT)){player2.direct = Constant.RIGHT;player2.hit = false;player2.move();}}public void homeNoProtected(Graphics2D ctx2) {List<Integer[]> mapChangeIndexList=new ArrayList<Integer[]>();mapChangeIndexList.add(new Integer[] {23,11});mapChangeIndexList.add(new Integer[] {23,12});mapChangeIndexList.add(new Integer[] {23,13});mapChangeIndexList.add(new Integer[] {23,14});mapChangeIndexList.add(new Integer[] {24,11});mapChangeIndexList.add(new Integer[] {24,14});mapChangeIndexList.add(new Integer[] {25,11});mapChangeIndexList.add(new Integer[] {25,14});map.updateMap(mapChangeIndexList,Constant.WALL,ctx2);}public static void main(String[] args) {JFrame jf=new JFrame();jf.setTitle("坦克大战");jf.setSize(Constant.SCREEN_WIDTH, Constant.SCREEN_HEIGHT);GameMain gameMain=new GameMain();jf.add(gameMain);jf.setLocationRelativeTo(null);jf.setResizable(false);jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);	jf.setVisible(true);gameMain.initGame(gameMain);gameMain.initObject();gameMain.action();}
}

接下来就可运行了。

在这里插入图片描述
其中,切换到下一关,按键盘N,上一个按P,空格键射击。

有兴趣的可以试一试。
下载地址:
坦克大战小游戏完整源码

相关文章:

经典游戏,用java实现的坦克大战小游戏

今天给大家分享一个使用java编写的坦克大战小游戏&#xff0c;整体还是挺好玩的&#xff0c;通过对这款游戏的简单实现&#xff0c;加深对java基础的深刻理解。 一、设计思路 1.坦克大战小游戏通过java实现&#xff0c;其第一步需要先绘制每一关对应的地图&#xff0c;地图包括…...

linux开通端口命令

这块需要开通8088 8083 端口限制 查看已开放端口&#xff1a;sudo firewall-cmd --list-ports 开放8083端口&#xff1a;sudo firewall-cmd --add-port8088/tcp --permanent 开放8088端口&#xff1a;sudo firewall-cmd --add-port8083/tcp --permanent 移除端…...

5、并发锁机制之synchronized

并发锁机制之synchronized i/i--引起的线程安全问题分析原因分析i的JVM字节码指令i--的JVM 字节码指令结论 解决方案 synchronized的使用加锁方式使用synchronized解决之前的共享问题方式一方式二 synchronized底层实现原理分析查看synchronized的字节码指令序列重量级锁实现之…...

职场那些事:应对施暴者的智慧

在职场中&#xff0c;有些人用各种手段让你感到难受&#xff0c;让你屈服&#xff0c;甚至适应他们的变态心理。面对这种人&#xff0c;最重要的就是保持低调。&#x1f910; 很多同事选择倾诉&#xff0c;然而这其实是个大错特错。正如鲁迅所说&#xff0c;“同事间的悲欢并不…...

精细化管理和智慧化运营的智慧油站开源了。

AI视频监控平台简介 AI视频监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒&#xff0c;省去繁琐重复的适配流程&#xff0c;实现芯片、算法、应用的全流程组合&#xff0c;从而大大减少企业级应用约95%的开发成本。用…...

vue项目配置基础路由vue-router

1、运行以下命令安装vue-router yarn add vue-router 2、在src目录下的components中新建两个vue页面 3、在src目录下新建router文件夹&#xff0c;在router文件夹下面新建index.js文件 4、配置main.js文件 //引入Vue import Vue from "vue"; //引入App import App…...

2024年入职/转行网络安全,该如何规划?_网络安全职业规划

前言 前段时间&#xff0c;知名机构麦可思研究院发布了 《2022年中国本科生就业报告》&#xff0c;其中详细列出近五年的本科绿牌专业&#xff0c;其中&#xff0c;信息安全位列第一。 网络安全前景 对于网络安全的发展与就业前景&#xff0c;想必无需我多言&#xff0c;作为…...

【Python系列】执行 Shell 命令的六种方法

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

2024华为OD机试真题-部门人力分配Python-C卷D卷-200分

【华为OD机试】-(C卷+D卷)-2024最新真题目录 目录 题目描述 输入描述 输出描述 用例1 考点 解题思路 代码 题目描述 部门在进行需求开发时需要进行人力安排。 当前部门需要完成 N 个需求,需求用 requirements 表述,requirements[i] 表示第 i 个需求的工作量大小,单…...

【Leetcode 1436 】旅行终点站—— 哈希表

给你一份旅游线路图&#xff0c;该线路图中的旅行线路用数组 paths 表示&#xff0c;其中 paths[i] [cityAi, cityBi] 表示该线路将会从 cityAi 直接前往 cityBi 。请你找出这次旅行的终点站&#xff0c;即没有任何可以通往其他城市的线路的城市。 题目数据保证线路图会形成一…...

springboot自动配置原理-面试题

网络上看很多文章并没什么用&#xff0c;重点没说到&#xff0c;不知道从那里入手讲&#xff0c;刷到的直接按照下面这个&#xff0c;背出来就行了 1、当启动springboot应用程序的时候&#xff0c;会先创建SpringApplication的对象&#xff0c;在对象的构造方法中会进行某些参数…...

【C++题解】1140 - 亲密数对

欢迎关注本专栏《C从零基础到信奥赛入门级&#xff08;CSP-J&#xff09;》 问题&#xff1a;1140 - 亲密数对 类型&#xff1a;自定义函数 题目描述&#xff1a; 键盘输入 N &#xff0c;N 在 2 至 2000 之间&#xff0c;求 2 至 N 中的亲密数对&#xff0c;就是 A 的因子和…...

学习大数据DAY40 基于 hive 的数据处理

目录 Hive 复合数据定义方法 Hive 复合数据查询方法 hive 内置函数 上机练习 Hive 复合数据定义方法 Hive 复合数据查询方法 hive 内置函数 -- 查看系统自带的函数 show functions; -- 显示自带的函数的用法 desc function upper; -- 详细显示自带的函数的用法 desc …...

[数据集][目标检测]手钳检测数据集VOC+YOLO格式141张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;141 标注数量(xml文件个数)&#xff1a;141 标注数量(txt文件个数)&#xff1a;141 标注类别…...

SQL注入(head、报错、盲注)

目录 【学习目标、重难点知识】 【学习目标】 【重难点知识】 1. 报错注入 1.1 那么什么是报错注入呢&#xff1f; 1.2 报错注入原理 extractvalue函数 updatexml函数 1.3 靶场解析 靶场练习 2. HEAD注入 2.1 相关全局变量 2.2 靶场解析 burp暴力破解 靶场练习 3…...

30. 包含 min 函数的栈

comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/lcof/%E9%9D%A2%E8%AF%95%E9%A2%9830.%20%E5%8C%85%E5%90%ABmin%E5%87%BD%E6%95%B0%E7%9A%84%E6%A0%88/README.md 面试题 30. 包含 min 函数的栈 题目描述 定义栈的数据结构&#xff…...

五、OpenTK图形渲染基础

文章目录 一、顶点数据(一)顶点坐标、颜色、纹理坐标的定义(二)顶点数组的组织二、图元绘制(一)点列表、线列表、线带、三角形列表、三角形带的绘制(二)绘制模式(GL_POINTS、GL_LINES、GL_TRIANGLES 等)三、清除屏幕一、顶点数据 (一)顶点坐标、颜色、纹理坐标的定…...

桔子哥/基于云快充协议1.5版本的充电桩系统软件-充电桩系统 -新能源车充电平台源码

基于云快充协议1.5版本的充电桩系统软件 介绍 SpringBoot 框架&#xff0c;充电桩平台充电桩系统充电平台充电桩互联互通协议云快充协议1.5-1.6协议新能源汽车二轮车公交车二轮车充电-四轮车充电充电源代码充电平台源码Java源码 软件功能 小程序端&#xff1a;城市切换、附…...

零基础5分钟上手亚马逊云科技-高可用Web系统设计最佳实践

简介&#xff1a; 欢迎来到小李哥全新亚马逊云科技AWS云计算知识学习系列&#xff0c;适用于任何无云计算或者亚马逊云科技技术背景的开发者&#xff0c;通过这篇文章大家零基础5分钟就能完全学会亚马逊云科技一个经典的服务开发架构方案。 我会每天介绍一个基于亚马逊云科技…...

培训学校课程管理系统-计算机毕设Java|springboot实战项目

&#x1f34a;作者&#xff1a;计算机毕设匠心工作室 &#x1f34a;简介&#xff1a;毕业后就一直专业从事计算机软件程序开发&#xff0c;至今也有8年工作经验。擅长Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等。 擅长&#xff1a;按照需求定制化开发项目…...

macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用

文章目录 问题现象问题原因解决办法 问题现象 macOS启动台&#xff08;Launchpad&#xff09;多出来了&#xff1a;Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显&#xff0c;都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

Spring Boot面试题精选汇总

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现&#xff08;两者等价&#xff09;&#xff0c;用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例&#xff1a; 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

Java 二维码

Java 二维码 **技术&#xff1a;**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

免费PDF转图片工具

免费PDF转图片工具 一款简单易用的PDF转图片工具&#xff0c;可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件&#xff0c;也不需要在线上传文件&#xff0c;保护您的隐私。 工具截图 主要特点 &#x1f680; 快速转换&#xff1a;本地转换&#xff0c;无需等待上…...

08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险

C#入门系列【类的基本概念】&#xff1a;开启编程世界的奇妙冒险 嘿&#xff0c;各位编程小白探险家&#xff01;欢迎来到 C# 的奇幻大陆&#xff01;今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类&#xff01;别害怕&#xff0c;跟着我&#xff0c;保准让你轻松搞…...

MySQL 部分重点知识篇

一、数据库对象 1. 主键 定义 &#xff1a;主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 &#xff1a;确保数据的完整性&#xff0c;便于数据的查询和管理。 示例 &#xff1a;在学生信息表中&#xff0c;学号可以作为主键&#xff…...

Git常用命令完全指南:从入门到精通

Git常用命令完全指南&#xff1a;从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…...

【SpringBoot自动化部署】

SpringBoot自动化部署方法 使用Jenkins进行持续集成与部署 Jenkins是最常用的自动化部署工具之一&#xff0c;能够实现代码拉取、构建、测试和部署的全流程自动化。 配置Jenkins任务时&#xff0c;需要添加Git仓库地址和凭证&#xff0c;设置构建触发器&#xff08;如GitHub…...