经典游戏,用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编写的坦克大战小游戏,整体还是挺好玩的,通过对这款游戏的简单实现,加深对java基础的深刻理解。 一、设计思路 1.坦克大战小游戏通过java实现,其第一步需要先绘制每一关对应的地图,地图包括…...
linux开通端口命令
这块需要开通8088 8083 端口限制 查看已开放端口:sudo firewall-cmd --list-ports 开放8083端口:sudo firewall-cmd --add-port8088/tcp --permanent 开放8088端口:sudo firewall-cmd --add-port8083/tcp --permanent 移除端…...
5、并发锁机制之synchronized
并发锁机制之synchronized i/i--引起的线程安全问题分析原因分析i的JVM字节码指令i--的JVM 字节码指令结论 解决方案 synchronized的使用加锁方式使用synchronized解决之前的共享问题方式一方式二 synchronized底层实现原理分析查看synchronized的字节码指令序列重量级锁实现之…...
职场那些事:应对施暴者的智慧
在职场中,有些人用各种手段让你感到难受,让你屈服,甚至适应他们的变态心理。面对这种人,最重要的就是保持低调。🤐 很多同事选择倾诉,然而这其实是个大错特错。正如鲁迅所说,“同事间的悲欢并不…...
精细化管理和智慧化运营的智慧油站开源了。
AI视频监控平台简介 AI视频监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒,省去繁琐重复的适配流程,实现芯片、算法、应用的全流程组合,从而大大减少企业级应用约95%的开发成本。用…...
vue项目配置基础路由vue-router
1、运行以下命令安装vue-router yarn add vue-router 2、在src目录下的components中新建两个vue页面 3、在src目录下新建router文件夹,在router文件夹下面新建index.js文件 4、配置main.js文件 //引入Vue import Vue from "vue"; //引入App import App…...
2024年入职/转行网络安全,该如何规划?_网络安全职业规划
前言 前段时间,知名机构麦可思研究院发布了 《2022年中国本科生就业报告》,其中详细列出近五年的本科绿牌专业,其中,信息安全位列第一。 网络安全前景 对于网络安全的发展与就业前景,想必无需我多言,作为…...
【Python系列】执行 Shell 命令的六种方法
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...
2024华为OD机试真题-部门人力分配Python-C卷D卷-200分
【华为OD机试】-(C卷+D卷)-2024最新真题目录 目录 题目描述 输入描述 输出描述 用例1 考点 解题思路 代码 题目描述 部门在进行需求开发时需要进行人力安排。 当前部门需要完成 N 个需求,需求用 requirements 表述,requirements[i] 表示第 i 个需求的工作量大小,单…...
【Leetcode 1436 】旅行终点站—— 哈希表
给你一份旅游线路图,该线路图中的旅行线路用数组 paths 表示,其中 paths[i] [cityAi, cityBi] 表示该线路将会从 cityAi 直接前往 cityBi 。请你找出这次旅行的终点站,即没有任何可以通往其他城市的线路的城市。 题目数据保证线路图会形成一…...
springboot自动配置原理-面试题
网络上看很多文章并没什么用,重点没说到,不知道从那里入手讲,刷到的直接按照下面这个,背出来就行了 1、当启动springboot应用程序的时候,会先创建SpringApplication的对象,在对象的构造方法中会进行某些参数…...
【C++题解】1140 - 亲密数对
欢迎关注本专栏《C从零基础到信奥赛入门级(CSP-J)》 问题:1140 - 亲密数对 类型:自定义函数 题目描述: 键盘输入 N ,N 在 2 至 2000 之间,求 2 至 N 中的亲密数对,就是 A 的因子和…...
学习大数据DAY40 基于 hive 的数据处理
目录 Hive 复合数据定义方法 Hive 复合数据查询方法 hive 内置函数 上机练习 Hive 复合数据定义方法 Hive 复合数据查询方法 hive 内置函数 -- 查看系统自带的函数 show functions; -- 显示自带的函数的用法 desc function upper; -- 详细显示自带的函数的用法 desc …...
[数据集][目标检测]手钳检测数据集VOC+YOLO格式141张1类别
数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):141 标注数量(xml文件个数):141 标注数量(txt文件个数):141 标注类别…...
SQL注入(head、报错、盲注)
目录 【学习目标、重难点知识】 【学习目标】 【重难点知识】 1. 报错注入 1.1 那么什么是报错注入呢? 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 函数的栈 题目描述 定义栈的数据结构ÿ…...
五、OpenTK图形渲染基础
文章目录 一、顶点数据(一)顶点坐标、颜色、纹理坐标的定义(二)顶点数组的组织二、图元绘制(一)点列表、线列表、线带、三角形列表、三角形带的绘制(二)绘制模式(GL_POINTS、GL_LINES、GL_TRIANGLES 等)三、清除屏幕一、顶点数据 (一)顶点坐标、颜色、纹理坐标的定…...
桔子哥/基于云快充协议1.5版本的充电桩系统软件-充电桩系统 -新能源车充电平台源码
基于云快充协议1.5版本的充电桩系统软件 介绍 SpringBoot 框架,充电桩平台充电桩系统充电平台充电桩互联互通协议云快充协议1.5-1.6协议新能源汽车二轮车公交车二轮车充电-四轮车充电充电源代码充电平台源码Java源码 软件功能 小程序端:城市切换、附…...
零基础5分钟上手亚马逊云科技-高可用Web系统设计最佳实践
简介: 欢迎来到小李哥全新亚马逊云科技AWS云计算知识学习系列,适用于任何无云计算或者亚马逊云科技技术背景的开发者,通过这篇文章大家零基础5分钟就能完全学会亚马逊云科技一个经典的服务开发架构方案。 我会每天介绍一个基于亚马逊云科技…...
培训学校课程管理系统-计算机毕设Java|springboot实战项目
🍊作者:计算机毕设匠心工作室 🍊简介:毕业后就一直专业从事计算机软件程序开发,至今也有8年工作经验。擅长Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等。 擅长:按照需求定制化开发项目…...
docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...
浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...
django blank 与 null的区别
1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是,要注意以下几点: Django的表单验证与null无关:null参数控制的是数据库层面字段是否可以为NULL,而blank参数控制的是Django表单验证时字…...
elementUI点击浏览table所选行数据查看文档
项目场景: table按照要求特定的数据变成按钮可以点击 解决方案: <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...
针对药品仓库的效期管理问题,如何利用WMS系统“破局”
案例: 某医药分销企业,主要经营各类药品的批发与零售。由于药品的特殊性,效期管理至关重要,但该企业一直面临效期问题的困扰。在未使用WMS系统之前,其药品入库、存储、出库等环节的效期管理主要依赖人工记录与检查。库…...
解析“道作为序位生成器”的核心原理
解析“道作为序位生成器”的核心原理 以下完整展开道函数的零点调控机制,重点解析"道作为序位生成器"的核心原理与实现框架: 一、道函数的零点调控机制 1. 道作为序位生成器 道在认知坐标系$(x_{\text{物}}, y_{\text{意}}, z_{\text{文}}…...
【51单片机】4. 模块化编程与LCD1602Debug
1. 什么是模块化编程 传统编程会将所有函数放在main.c中,如果使用的模块多,一个文件内会有很多代码,不利于组织和管理 模块化编程则是将各个模块的代码放在不同的.c文件里,在.h文件里提供外部可调用函数声明,其他.c文…...
