1.坦克大战 0.3

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

编写Shot类

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;}@Overridepublic 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://表示方向向zuox -= speed;break;}//测试下,输出x,y的坐标System.out.println("子弹 x=" + x + " y=" + y);//子弹出边界了if (!(x>= 0 && x <=1000 && y>=0 && y<=750)){isLive = false;break;}}}
}

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

//射击
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();

绘制射击的子弹

将面板设置成线程

启动线程

2.坦克大战 0.4 版

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

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

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

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

编写炸弹类

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

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

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

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

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

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

启动线程

3.坦克大战0.5

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

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

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

我方坦克发射多颗子弹

控制只能发射5颗子弹

多颗子弹打多个坦克

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

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

4.项目目录

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保存多个ShotVector<Shot> shots = new Vector<>();boolean isLive = true;public EnemyTank(int x, int y) {super(x, y);}@Overridepublic 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对象到bombsVector<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"));//}@Overridepublic 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);}//画出敌人的坦克,遍历Vectorfor (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;}}@Overridepublic void keyTyped(KeyEvent e) {}//处理w s a d 键的按下情况@Overridepublic 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();}@Overridepublic void keyReleased(KeyEvent e) {}@Overridepublic 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;}@Overridepublic 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://表示方向向zuox -= 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 {//定义MyPanelMyPanel 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);}}

坦克大战2.0,3.0,4.0版本相关推荐

  1. 坦克大战-C语言-详注版

    代码地址如下: http://www.demodashi.com/demo/14259.html 坦克大战-C语言-详注版 概述 本文详述了C语言版坦克大战游戏的原理以及实现方法,对游戏代码进行了详细 ...

  2. JavaStudy7(18章-坦克大战2)—B站韩顺平

    JavaStudy7(18章-坦克大战2)-B站韩顺平 1.坦克大战 1.1线程-应用到坦克大战 1.1.1 坦克大战 0.3 代码演示: //为了监听 键盘事件, 实现 KeyListener pu ...

  3. JavaStudy5(坦克大战)—B站韩顺平

    JavaStudy5(坦克大战01)-B站韩顺平 跳转坦克大战02: 跳转坦克大战03: 1. 坦克大战 1.1坦克大战游戏演示 1.1.1游戏演示 1.1.2 为什么写这个项目 1.1.3 写项目前 ...

  4. 坦克大战项目需求文档

    01_坦克大战案例演示  * 略     1. 创建游戏窗体     2. 绘制地图(阻碍物,坦克)     3. 坦克可以移动,也可以发射子弹     4. 碰撞(坦克和阻碍物的碰撞,子弹和阻碍物的 ...

  5. python 中的坦克大战0.1版本

    这个只是初步的坦克大战,只有一个坦克,进行刷新的动作.线程类的操作不是太懂.唯一知道的就是不能再主线程里面使用sleep ,这样子的话,主线程就进入休眠的状态,不能进行时间的监听. import py ...

  6. java坦克大战(1.0)

    坦克大战 后面开始学习怎么使用java制造一个坦克大战游戏 但是不是直接开始做,而是随着这个游戏程序的制造,一边学习新知识融入到游戏中.包括多线程,反射,IO流- Java坐标体系 在几乎所有的坐标中 ...

  7. 韩老师坦克大战2.0版本

    本博文源于对b站视频韩老师(韩顺平)的java学习,本章学习坦克大战2.0版本,用多线程实现,本章内容还是比较多的,先看内容效果 内容效果 开局 被打死(黄色是hero) 打死别人 源码 Bomb.j ...

  8. java坦克大战(2.0)

    坦克大战(2.0) 在前面的坦克大战1.0已经完成了移动 绘制我方/敌方坦克. 接下来会运用到前面学习的多线程的基础,来实现发射子弹的效果 发射子弹 想要坦克发射子弹,可以用以下思路 按J发射子弹 将 ...

  9. [ java ] 坦克大战 5.0 ~ 最终完整版

    坦克大战5.0 新增功能内容:(加入IO流内容) 防止敌坦克间重叠 击杀数显示 保存上局游戏进度–>两种开局方式 加入开局音乐 修复记录文件丢失后的异常 5.0版本为最终版 提示:爆炸图片需自行 ...

最新文章

  1. LLVM 编译器和工具链技术
  2. VCSA 6.5 HA配置 之三 :准备工作
  3. XamarinAndroid组件教程RecylerView动画组件使用动画(2)
  4. Kaggle知识点:对比学习基础
  5. Retina时代的前端视觉优化
  6. java常用代码解析_Java设计模式常用原则代码解析
  7. Mysql 在DOS窗口下的操作
  8. 技术实践丨列存表并发更新时的锁等待问题原理
  9. 数组常见异常 学习笔记
  10. 南非世界杯火热角逐 金山网盾开启搜索保护
  11. 【淘坏菌】Markdown 积累
  12. jQuery缓存操作-cache数据
  13. linux中fish脚本,FISH:Linux 下的一个智能易用的 Shell
  14. 2022年最新最全软件测试面试题大全
  15. 数据库中了勒索病毒,怎么办?
  16. 计算机专业大专考研考什么科目,计算机专业考研都考什么科目?
  17. Visual C++ 2010如何解决程序运行闪退问题
  18. 蝴蝶键盘 Linux,Macbook蝴蝶键盘与普通键盘有什么不一样? 蝶式结构键盘解析
  19. 浙江环宇集团“营改增”项目启动会成功举办
  20. 读书笔记 | 《推荐系统》

热门文章

  1. QTextStream 类(文本流)和 QDataStream 类(数据流)
  2. MySQL-查看数据库
  3. eclipse git 取远程代码_【JAVA】Eclipse中使用git进行pull远程代码
  4. 九世轮回篇电子计算机乐谱,mc九局九世轮回篇的歌词
  5. 21岁日本女星惨遭猥亵,只因自拍瞳孔倒影暴露住址? 一张照片是怎么出卖你的?
  6. 薇娅,李佳琦都点赞的淘宝双11直播系统,是如何打造的?
  7. jsp mysql电影网站_JSP+Servlet+C3P0+Mysql实现的YCU movies电影网站
  8. docker运行yyets_docker 使用教程1
  9. C++中如何使输出对齐
  10. 论文阅读笔记----《Explaining Answers with Entailment Trees》