这是我的坦克游戏大战的最后一版,里面添加很多新的功能。这个坦克大战的有很多不足之处,但是对于初学者来说依然是一个很好的练习项目,从中我们可以学习Java基础知识,将知识与项目结合,学习面向对象编程思想,最主要的是编程的逻辑练习,代码往往不像是写文章从上到下一气呵成完成,中间很可能为增加一个功能来添加一个类一个方法等,中间有很多细节需要我们考虑。文章最后会附加该坦克大战涉及的相关素材。

功能:

1.防止坦克重叠

2.可以分关(闪烁效果)

3.记录成绩(小型游戏都是写在文件中)

4.存盘退出,可以记录但是敌人坦克的坐标

5.可以恢复上局,继续玩

6.坦克的声音

坦克大战最终版本(2.1)

MyTanKGame类:

  1. /*
  2. * 功能:
  3. * 1.防止坦克重叠
  4. * 2.可以分关(闪烁效果)
  5. * 3.记录成绩(小型游戏都是写在文件中)
  6. * 4.存盘退出,可以记录但是敌人坦克的坐标
  7. * 5.可以恢复上局,继续玩
  8. * 6.坦克的声音
  9. */
  10. package com.fanghua6;
  11.  
  12. import java.awt.*;
  13. import java.awt.event.ActionEvent;
  14. import java.awt.event.ActionListener;
  15. import java.awt.event.KeyEvent;
  16. import java.util.Vector;
  17. import javax.swing.*;
  18.  
  19. public class MyTankGame1_7 extends JFrame implements ActionListener {
  20.  
  21. Mypanel1_2 mp = null;
  22.  
  23. // 定义开始面板
  24. MyStartPanel msp = null;
  25. // 做出菜单
  26. JMenuBar jmb = null;
  27. // 开始游戏
  28. JMenu jm1 = null;
  29. JMenuItem jmi1 = null;
  30. // 退出游戏
  31. JMenuItem jmi2 = null;
  32. // 存盘退出
  33. JMenuItem jmi3 = null;
  34. JMenuItem jmi4 = null;
  35.  
  36. public static void main(String[] args) {
  37. new MyTankGame1_7();
  38. }
  39.  
  40. // 构造函数
  41. public MyTankGame1_7() {
  42. // mp = new Mypanel1_2();
  43.  
  44. // 启动mp线程
  45. // Thread t = new Thread(mp);
  46. // t.start();
  47.  
  48. // this.add(mp);
  49. // 注册监听
  50. // this.addKeyListener(mp);
  51. // 创建菜单及菜单选项
  52. jmb = new JMenuBar();
  53. jm1 = new JMenu("游戏(G)");
  54. jm1.setMnemonic('G');
  55. jmi1 = new JMenuItem("开始新游戏(N)");
  56. jmi1.setMnemonic('N');
  57.  
  58. jmi2 = new JMenuItem("退出游戏(E)");
  59. jmi2.setMnemonic('E');
  60.  
  61. jmi3 = new JMenuItem("存盘退出(C)");
  62. jmi3.setMnemonic('C');
  63.  
  64. jmi4 = new JMenuItem("继续上局(S)");
  65. jmi4.setMnemonic('S');
  66.  
  67. // jmi1相应
  68. jmi1.addActionListener(this);
  69. jmi1.setActionCommand("newgame");
  70. jmi2.addActionListener(this);
  71. jmi2.setActionCommand("exit");
  72. jmi3.addActionListener(this);
  73. jmi3.setActionCommand("saveExit");
  74. jmi4.addActionListener(this);
  75. jmi4.setActionCommand("conGame");
  76.  
  77. jm1.add(jmi1);
  78. jm1.add(jmi2);
  79. jm1.add(jmi3);
  80. jm1.add(jmi4);
  81.  
  82. jmb.add(jm1);
  83.  
  84. // 加了开始面板(上面的全注释掉)
  85. msp = new MyStartPanel();
  86. this.add(msp);
  87. // 启动msp面板
  88. Thread t = new Thread(msp);
  89. t.start();
  90.  
  91. this.setJMenuBar(jmb);
  92.  
  93. this.setSize(600, 500);
  94. this.setTitle("我的坦克大战");
  95. ImageIcon icon = new ImageIcon("images\\tanke.png");
  96. this.setIconImage(icon.getImage());
  97. this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  98. this.setVisible(true);
  99.  
  100. }
  101.  
  102. @Override
  103. public void actionPerformed(ActionEvent e) {
  104. // TODO Auto-generated method stub
  105. // 对用户不同的点击做出不同的处理
  106. if (e.getActionCommand().equals("newgame")) {
  107.  
  108. // 创建战场面板
  109. mp = new Mypanel1_2("newGame");
  110. // 启动mp线程
  111. Thread t = new Thread(mp);
  112. t.start();
  113. // 先把msp删掉,再加mp
  114. this.remove(msp);
  115. this.add(mp);
  116. // 注册监听
  117. this.addKeyListener(mp);
  118. // 显示,刷新JFrame(这个很重要)
  119. this.setVisible(true);
  120. } else if (e.getActionCommand().equals("exit")) {
  121.  
  122. // 用户退出系统的菜单(保存击毁敌人数量)
  123. Recorder.keepRecording();
  124.  
  125. System.exit(0);
  126. }// 对存盘退出的处理
  127. else if (e.getActionCommand().equals("saveExit")) {
  128.  
  129. /*
  130. * 当时这里这样处理的,大错特错。new两次 工作 new Recorder().setEts(mp.ets);new
  131. * 保存击毁敌人的数量和敌人的坐标 Recorder().keepRecAndEnemyTank();
  132. */
  133.  
  134. // 工作
  135. Recorder rd = new Recorder();
  136. rd.setEts(mp.ets);
  137. // 保存击毁敌人的数量和敌人的坐标
  138. rd.keepRecAndEnemyTank();
  139.  
  140. // 退出
  141. System.exit(0);
  142. } else if (e.getActionCommand().equals("conGame")) {
  143. // 继续游戏
  144. // 创建战场面板
  145. mp = new Mypanel1_2("con");
  146.  
  147. // 不在这:mp.nodes = new Recorder().getNodesAndEnNums();
  148. // 启动mp线程
  149. Thread t = new Thread(mp);
  150. t.start();
  151. // 先把msp删掉,再加mp
  152. this.remove(msp);
  153. this.add(mp);
  154. // 注册监听
  155. this.addKeyListener(mp);
  156. // 显示,刷新JFrame(这个很重要)
  157. this.setVisible(true);
  158.  
  159. }
  160. }
  161. }
  162.  
  163. // 提示面板(用线程来实现闪烁效果)
  164. class MyStartPanel extends JPanel implements Runnable {
  165. // 做一个开关
  166. int times = 0;
  167.  
  168. public void paint(Graphics g) {
  169. super.paint(g);
  170. g.fillRect(0, 0, 400, 300);
  171. // 提示信息
  172. if (times % 2 == 0) {
  173. g.setColor(Color.yellow);
  174. // 开关信息的字体
  175. Font myFont = new Font("华文新魏", Font.BOLD, 30);
  176. g.setFont(myFont);// 别忘了
  177. g.drawString("stage: 1", 140, 200);
  178. }
  179. }
  180.  
  181. @Override
  182. public void run() {
  183. // TODO Auto-generated method stub
  184. while (true) {
  185. // 休眠
  186. try {
  187. Thread.sleep(500);
  188. } catch (Exception e) {
  189. // TODO Auto-generated catch block
  190. e.printStackTrace();
  191. }
  192. times++;
  193. // 重画
  194. this.repaint();
  195. }
  196. }
  197.  
  198. }
  199.  
  200. // 我的面板,拓宽思路:Panel本身就是一个刷新体
  201. class Mypanel1_2 extends JPanel implements java.awt.event.KeyListener, Runnable {
  202.  
  203. // 定义我的坦克
  204. Hero1_2 hero = null;
  205.  
  206. // 判断是续上局,还是新游戏
  207.  
  208. // 定义敌人的坦克(不止一辆,线程安全,集合)
  209. Vector<EnemyTank> ets = new Vector<EnemyTank>();
  210. Vector<Node> nodes = new Vector<Node>();
  211.  
  212. // 定义炸弹集合
  213. Vector<Bomb> bombs = new Vector<Bomb>();
  214.  
  215. int enSize = 4;// 敌人坦克保持4个
  216.  
  217. // 定义三张图片(三张图片才能组成一颗炸弹)
  218. Image image1 = null;
  219. Image image2 = null;
  220. Image image3 = null;
  221.  
  222. // 构造函数(续局,变成含参的构造函数)
  223. public Mypanel1_2(String flag) {
  224.  
  225. // 恢复记录(写在这里)
  226. Recorder.getRecoring();
  227.  
  228. hero = new Hero1_2(70, 100);
  229.  
  230. if (flag.equals("newGame")) {
  231. // 初始化敌人的坦克
  232. for (int i = 0; i < enSize; i++) {
  233. // 创建一辆敌人的坦克
  234. EnemyTank et = new EnemyTank((i + 1) * 50, 0);
  235. et.setColor(0);
  236. // 坦克默认反向是0(向上),这里改一下
  237. et.setDirect(2);
  238.  
  239. // 将MyPanel的敌人坦克向量交给该敌人坦克
  240. et.setEts(ets);
  241.  
  242. // 启动敌人的坦克
  243. Thread t = new Thread(et);
  244. t.start();
  245. // 给敌人坦克添加一颗子弹
  246. Shot s = new Shot(et.x + 10, et.y + 30, 2);
  247. // 加入给敌人的坦克
  248. et.ss.add(s);
  249.  
  250. Thread t2 = new Thread(s);
  251. t2.start();
  252. ets.add(et);
  253. }
  254. } else {
  255.  
  256. nodes = new Recorder().getNodesAndEnNums();
  257.  
  258. for (int i = 0; i < nodes.size(); i++) {
  259.  
  260. Node node = nodes.get(i);
  261. // 创建一辆敌人的坦克
  262. EnemyTank et = new EnemyTank(node.x, node.y);
  263. et.setColor(0);
  264. et.setDirect(node.direct);
  265.  
  266. // 将MyPanel的敌人坦克向量交给该敌人坦克
  267. et.setEts(ets);
  268.  
  269. // 启动敌人的坦克
  270. Thread t = new Thread(et);
  271. t.start();
  272. // 给敌人坦克添加一颗子弹
  273. Shot s = new Shot(et.x + 10, et.y + 30, 2);
  274. // 加入给敌人的坦克
  275. et.ss.add(s);
  276.  
  277. Thread t2 = new Thread(s);
  278. t2.start();
  279. ets.add(et);
  280. }
  281. }
  282. // 初始话图片,这样做击中第一个坦克,爆炸的效果不明显。下面优化
  283. image1 = Toolkit.getDefaultToolkit().getImage(
  284. Panel.class.getResource("/bomb_1.gif"));
  285. image2 = Toolkit.getDefaultToolkit().getImage(
  286. Panel.class.getResource("/bomb_2.gif"));
  287. image3 = Toolkit.getDefaultToolkit().getImage(
  288. Panel.class.getResource("/bomb_3.gif"));
  289.  
  290. // 引包:import javax.imageio.ImagesssIO;
  291. // try {
  292. // image1=ImageIO.read(new File("/bomsb_1.gif"));
  293. // image2=ImageIO.read(new File("/bomb_2.gif"));
  294. // image3=ImageIO.read(new File("/bomb_3.gif"));
  295. // } catch (IOException e) {
  296. // // TODO Auto-generated catch block
  297. // e.printStackTrace();
  298. // }
  299.  
  300. // 在Mypanel1_2初始化里,放置开战音效,加载即播放
  301. // 以后再添加爆炸效果的声音也是这样做的思路
  302. AePlayWave apw = new AePlayWave("E:\\111.wav");
  303. apw.start();
  304.  
  305. }
  306.  
  307. // 提示信息(只需要画笔即可)
  308. public void showInfo(Graphics g) {
  309. // 画出提示信息坦克
  310. this.drawTank(70, 310, g, 0, 0);
  311. g.setColor(Color.black);
  312. g.drawString(Recorder.getEnNum() + "", 100, 330);
  313.  
  314. this.drawTank(70, 360, g, 0, 1);
  315. g.setColor(Color.black);
  316. g.drawString(Recorder.getMyLife() + "", 100, 380);
  317.  
  318. // 画出玩家的总成绩
  319. g.setColor(Color.black);
  320. Font f = new Font("宋体", Font.BOLD, 20);
  321. g.setFont(f);
  322. g.drawString("你的总成绩", 410, 30);
  323. this.drawTank(410, 60, g, 0, 0);
  324.  
  325. g.setColor(Color.black);
  326. g.drawString(Recorder.getAllEnNum() + "", 440, 80);
  327. }
  328.  
  329. // 重写paint函数
  330. public void paint(Graphics g) {
  331. // 一定要调用
  332. super.paint(g);
  333. g.fillRect(0, 0, 400, 300);
  334. // 画出提示信息
  335. this.showInfo(g);
  336.  
  337. // 画出自己的坦克(将方向填进去)
  338. if (hero.isLive == true) {
  339. this.drawTank(hero.getX(), hero.getY(), g, this.hero.direct, 1);
  340. }
  341. // 从ss中取出每一颗子弹,并画出
  342. for (int i = 0; i < hero.ss.size(); i++) {
  343.  
  344. Shot myShot = hero.ss.get(i);
  345. if (myShot != null && myShot.isLive == true) {
  346. g.draw3DRect(myShot.x, myShot.y, 1, 1, false);
  347.  
  348. /*
  349. * 画出一颗子弹(后添加 hero.s.isLive==true,节省资源) if (hero.s != null
  350. * &&hero.s.isLive == true) { g.draw3DRect(hero.s.x, hero.s.y,
  351. * 1, 1,false); }
  352. */
  353. }
  354. if (myShot.isLive == false) {
  355. // 从ss(向量)中删除该子弹
  356. // hero.ss.remove(i);会报异常。
  357. hero.ss.remove(myShot);
  358. }
  359. }
  360.  
  361. // 画出炸弹
  362. for (int i = 0; i < bombs.size(); i++) {
  363. // 取出炸弹
  364. Bomb b = bombs.get(i);
  365. if (b.life > 6) {
  366. g.drawImage(image1, b.x, b.y, 30, 30, this);
  367. } else if (b.life > 4) {
  368. g.drawImage(image2, b.x, b.y, 30, 30, this);
  369. } else {
  370. g.drawImage(image3, b.x, b.y, 30, 30, this);
  371. }
  372. // 让b的生命值减小
  373. b.lifeDown();
  374. // 如果炸弹生命值为零,就把该炸弹从bombs向量中去掉
  375. if (b.life == 0) {
  376. bombs.remove(b);
  377. }
  378.  
  379. }
  380.  
  381. // 画出敌人的坦克
  382. for (int i = 0; i < ets.size(); i++) {
  383. EnemyTank et = ets.get(i);
  384. if (et.isLive) {
  385. this.drawTank(et.getX(), et.getY(), g, et.getDirect(), 0);
  386.  
  387. // 画出敌人的子弹
  388. for (int j = 0; j < et.ss.size(); j++) {
  389. // 取出子弹
  390. Shot enemyShot = et.ss.get(j);
  391. if (enemyShot != null && enemyShot.isLive == true) {
  392. g.draw3DRect(enemyShot.x, enemyShot.y, 1, 1, false);
  393. }
  394. if (enemyShot.isLive == false) {
  395. // 如果敌人的坦克死亡了,就从Vector中删除
  396. et.ss.remove(enemyShot);
  397. }
  398. }
  399. }
  400. }
  401. }
  402.  
  403. // 敌人的坦克是否击中我
  404. public void hitMe() {
  405. // 取出每一个敌人的坦克
  406. for (int i = 0; i < this.ets.size(); i++) {
  407. // 取出坦克
  408. EnemyTank et = ets.get(i);
  409.  
  410. // 取出每一颗子弹
  411. for (int j = 0; j < et.ss.size(); j++) {
  412. // 取出子弹
  413. Shot enemyShot = et.ss.get(j);
  414. if (hero.isLive) {
  415. if (this.hitTank(enemyShot, hero)) {
  416.  
  417. }
  418. }
  419. }
  420. }
  421. }
  422.  
  423. // 判断我的子弹是否击中敌人的坦克
  424. public void hitEnemyTank() {
  425. // 判断是否击中敌人的坦克
  426. for (int i = 0; i < hero.ss.size(); i++) {
  427. // 取出子弹
  428. Shot myShot = hero.ss.get(i);
  429. // 判断子弹是否有效
  430. if (myShot.isLive) {
  431. // 取出每个坦克,与它判断
  432. for (int j = 0; j < ets.size(); j++) {
  433. // 取出坦克
  434. EnemyTank et = ets.get(j);
  435.  
  436. if (et.isLive) {
  437. if (this.hitTank(myShot, et)) {
  438.  
  439. // 减少敌人数量
  440. Recorder.reduceEnNum();
  441. // 增加我的记录
  442. Recorder.addEnNumRec();
  443. }
  444. }
  445.  
  446. }
  447. }
  448. }
  449. }
  450.  
  451. // 写一个函数 专门判断是否击中敌人坦克(原来第二参数: EnemyTank et)
  452. // void改成boolean 判断击中的目标是谁
  453.  
  454. public boolean hitTank(Shot s, Tank1_2 et) {
  455. boolean b2 = false;
  456.  
  457. // 判断该坦克的方向
  458. switch (et.direct) {
  459. // 如果敌人坦克的方向是上或者是下
  460. case 0:
  461. case 2:
  462. if (s.x > et.x && s.x < et.x + 20 && s.y > et.y && s.y < et.y + 30) {
  463. // 击中
  464. // 子弹死亡
  465. s.isLive = false;
  466. // 敌人坦克死亡
  467. et.isLive = false;
  468. b2 = true;
  469. // 创建一颗炸弹,放入Vector
  470. Bomb b = new Bomb(et.x, et.y);
  471. // 放入Vector
  472. bombs.add(b);
  473.  
  474. }
  475.  
  476. break;
  477. case 1:
  478. case 3:
  479. if (s.x > et.x && s.x < et.x + 30 && s.y > et.y && s.y < et.y + 20) {
  480. // 击中
  481. // 子弹死亡
  482. s.isLive = false;
  483. // 敌人坦克死亡
  484. et.isLive = false;
  485. b2 = true;
  486. // 创建一颗炸弹,放入Vector
  487. Bomb b = new Bomb(et.x, et.y);
  488. // 放入Vector
  489. bombs.add(b);
  490.  
  491. }
  492. break;
  493. }
  494.  
  495. return b2;
  496.  
  497. }
  498.  
  499. // 画出坦克的函数
  500. public void drawTank(int x, int y, Graphics g, int direct, int type) {
  501. // 坦克类型
  502. switch (type) {
  503. case 0:
  504. g.setColor(Color.green);
  505. break;
  506. case 1:
  507. g.setColor(Color.yellow);
  508. break;
  509. }
  510. // 方向设置
  511. switch (direct) {
  512. // 向上
  513. case 0:
  514. g.fill3DRect(x, y, 5, 30, false);
  515. g.fill3DRect(x + 15, y, 5, 30, false);
  516. g.fill3DRect(x + 5, y + 5, 10, 20, false);
  517. g.fillOval(x + 5, y + 10, 10, 10);
  518. g.drawLine(x + 10, y + 15, x + 10, y);
  519. break;
  520. // 向右
  521. case 1:
  522. g.fill3DRect(x, y, 30, 5, false);
  523. g.fill3DRect(x, y + 15, 30, 5, false);
  524. g.fill3DRect(x + 5, y + 5, 20, 10, false);
  525. g.fillOval(x + 10, y + 5, 10, 10);
  526. g.drawLine(x + 15, y + 10, x + 30, y + 10);
  527. break;
  528. // 向下
  529. case 2:
  530. g.fill3DRect(x, y, 5, 30, false);
  531. g.fill3DRect(x + 15, y, 5, 30, false);
  532. g.fill3DRect(x + 5, y + 5, 10, 20, false);
  533. g.fillOval(x + 5, y + 10, 10, 10);
  534. g.drawLine(x + 10, y + 15, x + 10, y + 30);
  535. break;
  536. // 向左
  537. case 3:
  538. g.fill3DRect(x, y, 30, 5, false);
  539. g.fill3DRect(x, y + 15, 30, 5, false);
  540. g.fill3DRect(x + 5, y + 5, 20, 10, false);
  541. g.fillOval(x + 10, y + 5, 10, 10);
  542. g.drawLine(x + 15, y + 10, x, y + 10);
  543. break;
  544. }
  545.  
  546. }
  547.  
  548. @Override
  549. public void keyPressed(KeyEvent e) {
  550. // TODO Auto-generated method stub
  551. // 已更正为顺时针
  552. if (e.getKeyCode() == KeyEvent.VK_UP || e.getKeyCode() == KeyEvent.VK_W) {
  553. this.hero.moveUp();
  554. this.hero.setDirect(0);
  555. } else if (e.getKeyCode() == KeyEvent.VK_RIGHT
  556. || e.getKeyCode() == KeyEvent.VK_D) {
  557. this.hero.setDirect(1);
  558. this.hero.moveRight();
  559. } else if (e.getKeyCode() == KeyEvent.VK_DOWN
  560. || e.getKeyCode() == KeyEvent.VK_S) {
  561. this.hero.moveDown();
  562. this.hero.setDirect(2);
  563. } else if (e.getKeyCode() == KeyEvent.VK_LEFT
  564. || e.getKeyCode() == KeyEvent.VK_A) {
  565. this.hero.moveLeft();
  566. this.hero.setDirect(3);
  567. } else if (e.getKeyCode() == KeyEvent.VK_J) {
  568. // 将J键设置为发出子弹
  569. // 子弹连发,J被按几下,发几颗:this.hero.shotEnemy();
  570. // this.repaint();在run函数里,不应该设计在这里
  571. if (this.hero.ss.size() <= 4) {
  572. this.hero.shotEnemy();
  573. }
  574. }
  575. // 必须重新绘制Panel
  576. this.repaint();
  577. }
  578.  
  579. @Override
  580. public void keyReleased(KeyEvent e) {
  581. // TODO Auto-generated method stub
  582.  
  583. }
  584.  
  585. @Override
  586. public void keyTyped(KeyEvent e) {
  587. // TODO Auto-generated method stub
  588.  
  589. }
  590.  
  591. @Override
  592. public void run() {
  593. // TODO Auto-generated method stub
  594. // 每隔100毫秒去重绘
  595. while (true) {
  596. try {
  597. Thread.sleep(100);
  598. } catch (InterruptedException e) {
  599. // TODO Auto-generated catch block
  600. e.printStackTrace();
  601. }
  602.  
  603. // 谨记这里:由于这里多写了这些,线程每次都被重新调用
  604. // showInfo的信息不会动态改变 调了好久好久。苦笑脸
  605. // 判断是否击中(写在这里,虽然在每次重绘的时候都要调用,但是没办法)
  606. // 每一颗子弹都要和每个坦克进行匹配
  607. // for (int i = 0; i < hero.ss.size(); i++) {
  608. // // 取出子弹
  609. // Shot myShot = hero.ss.get(i);
  610. // // 判断子弹是否有效
  611. // if (myShot.isLive) {
  612. // // 取出每个坦克,与它判断
  613. // for (int j = 0; j < ets.size(); j++) {
  614. // // 取出坦克
  615. // EnemyTank et = ets.get(j);
  616. //
  617. // if (et.isLive) {
  618. // this.hitTank(myShot, et);
  619. // }
  620. // }
  621. // }
  622. // }
  623. this.hitEnemyTank();
  624.  
  625. this.hitMe();
  626.  
  627. // 重绘
  628. this.repaint();
  629. }
  630. }
  631. }

Menbers类:

  1. package com.fanghua6;
  2.  
  3. import java.io.BufferedReader;
  4. import java.io.BufferedWriter;
  5. import java.io.File;
  6. import java.io.FileReader;
  7. import java.io.FileWriter;
  8. import java.io.IOException;
  9. import java.util.Vector;
  10. import javax.sound.sampled.AudioFormat;
  11. import javax.sound.sampled.AudioInputStream;
  12. import javax.sound.sampled.AudioSystem;
  13. import javax.sound.sampled.DataLine;
  14. import javax.sound.sampled.SourceDataLine;
  15.  
  16. //播放声音的类
  17. class AePlayWave extends Thread {
  18.  
  19. private String filename;
  20.  
  21. public AePlayWave(String wavfile) {
  22. filename = wavfile;
  23.  
  24. }
  25.  
  26. public void run() {
  27.  
  28. File soundFile = new File(filename);
  29.  
  30. AudioInputStream audioInputStream = null;
  31. try {
  32. audioInputStream = AudioSystem.getAudioInputStream(soundFile);
  33. } catch (Exception e1) {
  34. e1.printStackTrace();
  35. return;
  36. }
  37.  
  38. AudioFormat format = audioInputStream.getFormat();
  39. SourceDataLine auline = null;
  40. DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
  41.  
  42. try {
  43. auline = (SourceDataLine) AudioSystem.getLine(info);
  44. auline.open(format);
  45. } catch (Exception e) {
  46. e.printStackTrace();
  47. return;
  48. }
  49.  
  50. auline.start();
  51. int nBytesRead = 0;
  52. // 这是缓冲
  53. byte[] abData = new byte[512];
  54.  
  55. try {
  56. while (nBytesRead != -1) {
  57. nBytesRead = audioInputStream.read(abData, 0, abData.length);
  58. if (nBytesRead >= 0)
  59. auline.write(abData, 0, nBytesRead);
  60. }
  61. } catch (IOException e) {
  62. e.printStackTrace();
  63. return;
  64. } finally {
  65. auline.drain();
  66. auline.close();
  67. }
  68. }
  69. }
  70.  
  71. // 继续上一局的记记录点的类
  72. class Node {
  73. int x;
  74. int y;
  75. int direct;
  76.  
  77. public Node(int x, int y, int direct) {
  78. this.x = x;
  79. this.y = y;
  80. this.direct = direct;
  81. }
  82. }
  83.  
  84. // 记录类,同时也可以保存玩家的设置(一般都是事先写在缓存里面的)
  85. class Recorder {
  86. // 记录每关有多少敌人
  87. private static int enNum = 20;
  88. // 设置我有多少可以用的坦克
  89. private static int myLife = 3;
  90. // 记录一共消灭多少敌人
  91. private static int allEnNum = 0;
  92.  
  93. // 从文件中恢复记录点
  94. static Vector<Node> nodes = new Vector<Node>();
  95.  
  96. private static FileWriter fw = null;
  97. private static BufferedWriter bw = null;
  98. private static FileReader fr = null;
  99. private static BufferedReader br = null;
  100.  
  101. private Vector<EnemyTank> ets = new Vector<EnemyTank>();
  102.  
  103. // 完成读取的函数(记录点和敌人的数量)
  104. public Vector<Node> getNodesAndEnNums() {
  105. try {
  106. fr = new FileReader("E:/Tanke.txt");
  107. br = new BufferedReader(fr);
  108. String n = "";
  109. n = br.readLine();// 设置先读第一行
  110. allEnNum = Integer.parseInt(n);
  111. // 接着读
  112. while ((n = br.readLine()) != null) {
  113. String[] xyz = n.split(" ");
  114. // 在知道只有三条数据的情况下,用了这个方法。否则要用for循环
  115. Node node = new Node(Integer.parseInt(xyz[0]),
  116. Integer.parseInt(xyz[1]), Integer.parseInt(xyz[2]));
  117. nodes.add(node);
  118. }
  119.  
  120. } catch (Exception e) {
  121. // TODO Auto-generated catch block
  122. e.printStackTrace();
  123. } finally {
  124. try {
  125. br.close();
  126. fr.close();
  127. } catch (Exception e) {
  128. // TODO Auto-generated catch block
  129. e.printStackTrace();
  130. }
  131. }
  132. return nodes;
  133. }
  134.  
  135. public Vector<EnemyTank> getEts() {
  136. return ets;
  137. }
  138.  
  139. public void setEts(Vector<EnemyTank> ets) {
  140. this.ets = ets;
  141. }
  142.  
  143. // 保存击毁敌人的数量和击毁敌人坦克的坐标、方向
  144. public void keepRecAndEnemyTank() {
  145. try {
  146. fw = new FileWriter("E:/Tanke.txt");
  147. bw = new BufferedWriter(fw);
  148.  
  149. bw.write(allEnNum + "\r\n");
  150.  
  151. // 保存当前的敌人坦克的坐标和方向
  152. for (int i = 0; i < ets.size(); i++) {
  153. // 取出第一个坦克
  154. EnemyTank et = ets.get(i);
  155. if (et.isLive) {
  156. // 活的就保存
  157. String recode = et.x + " " + et.y + " " + et.direct;
  158. // 写入
  159. bw.write(recode + "\r\n");
  160.  
  161. }
  162. }
  163. } catch (IOException e) {
  164. // TODO Auto-generated catch block
  165. e.printStackTrace();
  166. } finally {
  167. try {
  168. bw.close();
  169. } catch (IOException e) {
  170. // TODO Auto-generated catch block
  171. e.printStackTrace();
  172. }
  173. try {
  174. fw.close();
  175. } catch (IOException e) {
  176. // TODO Auto-generated catch block
  177. e.printStackTrace();
  178. }
  179. }
  180. }
  181.  
  182. // 从文件中读取,记录
  183. public static void getRecoring() {
  184. try {
  185. fr = new FileReader("E:/Tanke.txt");
  186. br = new BufferedReader(fr);
  187. String n = br.readLine();
  188. allEnNum = Integer.parseInt(n);
  189. } catch (Exception e) {
  190. // TODO Auto-generated catch block
  191. e.printStackTrace();
  192. } finally {
  193. try {
  194. br.close();
  195. fr.close();
  196. } catch (Exception e) {
  197. // TODO Auto-generated catch block
  198. e.printStackTrace();
  199. }
  200. }
  201.  
  202. }
  203.  
  204. // 把玩家击毁敌人坦克数量保存到文件中
  205. public static void keepRecording() {
  206. try {
  207. fw = new FileWriter("E:/Tanke.txt");
  208. bw = new BufferedWriter(fw);
  209.  
  210. bw.write(allEnNum + "\r\n");
  211. } catch (IOException e) {
  212. // TODO Auto-generated catch block
  213. e.printStackTrace();
  214. } finally {
  215. try {
  216. bw.close();
  217. } catch (IOException e) {
  218. // TODO Auto-generated catch block
  219. e.printStackTrace();
  220. }
  221. try {
  222. fw.close();
  223. } catch (IOException e) {
  224. // TODO Auto-generated catch block
  225. e.printStackTrace();
  226. }
  227.  
  228. }
  229.  
  230. }
  231.  
  232. public static int getAllEnNum() {
  233. return allEnNum;
  234. }
  235.  
  236. public static void setAllEnNum(int allEnNum) {
  237. Recorder.allEnNum = allEnNum;
  238. }
  239.  
  240. public static int getEnNum() {
  241. return enNum;
  242. }
  243.  
  244. public static void setEnNum(int enNum) {
  245. Recorder.enNum = enNum;
  246. }
  247.  
  248. public static int getMyLife() {
  249. return myLife;
  250. }
  251.  
  252. public void setMyLife(int myLife) {
  253. Recorder.myLife = myLife;
  254. }
  255.  
  256. // 减少敌人数
  257. public static void reduceEnNum() {
  258. enNum--;
  259. }
  260.  
  261. // 消灭敌人
  262. public static void addEnNumRec() {
  263. allEnNum++;
  264. }
  265.  
  266. }
  267.  
  268. // 炸弹类(没必要定义为线程,因为它不会移动,没有坐标改变)
  269. class Bomb {
  270. // 定义炸弹的坐标
  271. int x, y;
  272. int life = 9;// 炸弹的生命(三张图片)
  273. // 可以看出isLive很有用,它可以决定类(或者对象)要不要展现在面板上
  274. boolean isLive = true;
  275.  
  276. public Bomb(int x, int y) {
  277. this.x = x;
  278. this.y = y;
  279. }
  280.  
  281. // 炸弹减少生命值
  282. public void lifeDown() {
  283. if (life > 0) {
  284. life--;
  285. } else {
  286. this.isLive = false;
  287. }
  288. }
  289.  
  290. }
  291.  
  292. // 子弹类
  293. class Shot implements Runnable {
  294. int x;
  295. int y;
  296. int direct;
  297. // 设置子弹的消亡(默认活着的)
  298. boolean isLive = true;
  299. // speed要给个初始值1,之前给0,按J键,子弹没有动
  300. int speed = 1;
  301.  
  302. public Shot(int x, int y, int direct) {
  303. super();
  304. this.x = x;
  305. this.y = y;
  306. this.direct = direct;
  307.  
  308. }
  309.  
  310. @Override
  311. public void run() {
  312. // TODO Auto-generated method stub
  313.  
  314. while (true) {
  315. // 设置子弹休息50毫秒
  316.  
  317. try {
  318. Thread.sleep(50);
  319. } catch (InterruptedException e) {
  320. // TODO Auto-generated catch block
  321. e.printStackTrace();
  322. }
  323.  
  324. switch (direct) {
  325. case 0:
  326. y -= speed;
  327. break;
  328. case 1:
  329. x += speed;
  330. break;
  331. case 2:
  332. y += speed;
  333. break;
  334. case 3:
  335. x -= speed;
  336. break;
  337. }
  338. // 测试用:System.out.println("子弹坐标x=" + x + "y=" + y);
  339. // 子弹什么时候死亡
  340. // 判断该子弹是否碰到边缘
  341. if (x < 0 || x > 400 || y < 0 || y > 300) {
  342. this.isLive = false;
  343. break;
  344. }
  345. }
  346. }
  347. }
  348.  
  349. // 坦克类
  350. class Tank1_2 {
  351.  
  352. int x = 0;
  353. int y = 0;
  354. boolean isLive = true;
  355.  
  356. // 坦克方向:0表示上,1表示右,2表示下,3表示左
  357. int direct = 0;
  358. int speed = 1;
  359. // 坦克的颜色
  360. int color;
  361.  
  362. public int getColor() {
  363. return color;
  364. }
  365.  
  366. public void setColor(int color) {
  367. this.color = color;
  368. }
  369.  
  370. public int getSpeed() {
  371. return speed;
  372. }
  373.  
  374. public void setSpeed(int speed) {
  375. this.speed = speed;
  376. }
  377.  
  378. public int getDirect() {
  379. return direct;
  380. }
  381.  
  382. public void setDirect(int direct) {
  383. this.direct = direct;
  384. }
  385.  
  386. public int getX() {
  387. return x;
  388. }
  389.  
  390. public void setX(int x) {
  391. this.x = x;
  392. }
  393.  
  394. public int getY() {
  395. return y;
  396. }
  397.  
  398. public void setY(int y) {
  399. this.y = y;
  400. }
  401.  
  402. // 构造函数
  403. public Tank1_2(int x, int y) {
  404. this.x = x;
  405. this.y = y;
  406.  
  407. }
  408.  
  409. }
  410.  
  411. // 敌人的坦克(做成线程,会移动)
  412. class EnemyTank extends Tank1_2 implements Runnable {
  413.  
  414. int times = 0;
  415. // 定义一个向量,可以访问MyPanel上所有敌人的坦克
  416. Vector<EnemyTank> ets = new Vector<EnemyTank>();
  417. // 定义向量,可以存放敌人的子弹
  418. Vector<Shot> ss = new Vector<Shot>();
  419.  
  420. // 敌人添加子弹,应该刚刚创建坦克和敌人子弹死亡后
  421.  
  422. public EnemyTank(int x, int y) {
  423. super(x, y);
  424. }
  425.  
  426. // 得到MyPaneld的敌人坦克向量
  427. public void setEts(Vector<EnemyTank> vv) {
  428. // 此时拥有一种能力,可以拿到yPan el上所有敌人的坦克
  429. this.ets = vv;
  430. }
  431.  
  432. // 判断是否碰到别的敌人的坦克
  433. public boolean isTouchOtherEnemy() {
  434. boolean b = false;
  435.  
  436. switch (this.direct) {
  437. case 0:
  438. // 我的坦克向上
  439. for (int i = 0; i < ets.size(); i++) {
  440. // 取出第一个坦克(很有可能是自己哦)
  441. EnemyTank et = ets.get(i);
  442. // 如果不是自己
  443. if (et != this) {
  444. // 如果敌人的方向是向下或者向下
  445. if (et.direct == 0 || et.direct == 2) {
  446. if (this.x >= et.x && this.x <= et.x + 20
  447. && this.y >= et.y && this.y <= et.y + 30) {
  448. return true;
  449. }
  450. if (this.x + 20 >= et.x && this.x + 20 <= et.x + 20
  451. && this.y >= et.y && this.y <= et.y + 30) {
  452. return true;
  453. }
  454. }
  455. if (et.direct == 1 || et.direct == 3) {
  456. if (this.x >= et.x && this.x <= et.x + 30
  457. && this.y >= et.y && this.y <= et.y + 20) {
  458. return true;
  459. }
  460. if (this.x + 20 >= et.x && this.x + 20 <= et.x + 30
  461. && this.y >= et.y && this.y <= et.y + 20) {
  462. return true;
  463. }
  464. }
  465. }
  466. }
  467. break;
  468. case 1:
  469. for (int i = 0; i < ets.size(); i++) {
  470. EnemyTank et = ets.get(i);
  471. if (et != this) {
  472. if (et.direct == 0 || et.direct == 2) {
  473. if (this.x + 30 >= et.x && this.x + 30 <= et.x + 20
  474. && this.y >= et.y && this.y <= et.y + 30) {
  475. return true;
  476. }
  477. if (this.x + 30 >= et.x && this.x + 30 <= et.x + 20
  478. && this.y + 20 >= et.y
  479. && this.y + 20 <= et.y + 30) {
  480. return true;
  481. }
  482. }
  483. if (et.direct == 1 || et.direct == 3) {
  484. if (this.x + 30 >= et.x && this.x + 30 <= et.x + 30
  485. && this.y >= et.y && this.y <= et.y + 20) {
  486. return true;
  487. }
  488. if (this.x + 30 >= et.x && this.x + 30 <= et.x + 30
  489. && this.y + 20 >= et.y
  490. && this.y + 20 <= et.y + 20) {
  491. return true;
  492. }
  493. }
  494. }
  495. }
  496. break;
  497. case 2:
  498. for (int i = 0; i < ets.size(); i++) {
  499. EnemyTank et = ets.get(i);
  500. if (et != this) {
  501. if (et.direct == 0 || et.direct == 2) {
  502. if (this.x >= et.x && this.x <= et.x + 20
  503. && this.y + 30 >= et.y
  504. && this.y + 30 <= et.y + 30) {
  505. return true;
  506. }
  507. if (this.x + 20 >= et.x && this.x + 20 <= et.x + 20
  508. && this.y + 30 >= et.y
  509. && this.y + 30 <= et.y + 30) {
  510. return true;
  511. }
  512. }
  513. if (et.direct == 1 || et.direct == 3) {
  514. if (this.x >= et.x && this.x <= et.x + 30
  515. && this.y + 30 >= et.y
  516. && this.y + 30 <= et.y + 20) {
  517. return true;
  518. }
  519. if (this.x + 20 >= et.x && this.x + 20 <= et.x + 30
  520. && this.y + 30 >= et.y
  521. && this.y + 30 <= et.y + 20) {
  522. return true;
  523. }
  524. }
  525. }
  526. }
  527. break;
  528. case 3:
  529. for (int i = 0; i < ets.size(); i++) {
  530. EnemyTank et = ets.get(i);
  531. if (et != this) {
  532. if (et.direct == 0 || et.direct == 2) {
  533. if (this.x >= et.x && this.x <= et.x + 20
  534. && this.y >= et.y && this.y <= et.y + 30) {
  535. return true;
  536. }
  537. if (this.x >= et.x && this.x <= et.x + 20
  538. && this.y + 20 >= et.y
  539. && this.y + 20 <= et.y + 30) {
  540. return true;
  541. }
  542. }
  543. if (et.direct == 1 || et.direct == 3) {
  544. if (this.x >= et.x && this.x <= et.x + 30
  545. && this.y >= et.y && this.y <= et.y + 20) {
  546. return true;
  547. }
  548. if (this.x >= et.x && this.x <= et.x + 30
  549. && this.y + 20 >= et.y
  550. && this.y + 20 <= et.y + 20) {
  551. return true;
  552. }
  553. }
  554. }
  555. }
  556. break;
  557. }
  558. return b;
  559. }
  560.  
  561. @Override
  562. public void run() {
  563. // TODO Auto-generated method stub
  564. while (true) {
  565. try {
  566. // 设置坦克休息一会
  567. Thread.sleep(50);
  568. } catch (InterruptedException e) {
  569. // TODO Auto-generated catch block
  570. e.printStackTrace();
  571. }
  572. switch (this.direct) {
  573. case 0:
  574. // 说明坦克正在向上运动(继续往上走,符合实际)
  575. // y -= speed;设置坦克平滑移动的效果
  576. for (int i = 0; i < 30; i++) {
  577. if (y > 0 && !this.isTouchOtherEnemy()) {
  578. y -= speed;
  579. }
  580. try {
  581. Thread.sleep(50);
  582. } catch (InterruptedException e) {
  583. // TODO Auto-generated catch block
  584. e.printStackTrace();
  585. }
  586. }
  587. break;
  588. case 1:
  589. for (int i = 0; i < 30; i++) {
  590. // 这里注意坐标起点问题不是(400x300)
  591. if (x < 400 && !this.isTouchOtherEnemy()) {
  592. x += speed;
  593. }
  594. try {
  595. Thread.sleep(50);
  596. } catch (InterruptedException e) {
  597. // TODO Auto-generated catch block
  598. e.printStackTrace();
  599. }
  600. }
  601. break;
  602. case 2:
  603. for (int i = 0; i < 30; i++) {
  604. if (y < 300 && !this.isTouchOtherEnemy()) {
  605. y += speed;
  606. }
  607. try {
  608. Thread.sleep(50);
  609. } catch (InterruptedException e) {
  610. // TODO Auto-generated catch block
  611. e.printStackTrace();
  612. }
  613. }
  614. break;
  615. case 3:
  616. for (int i = 0; i < 30; i++) {
  617. if (x > 0 && !this.isTouchOtherEnemy()) {
  618. x -= speed;
  619. }
  620. try {
  621. Thread.sleep(50);
  622. } catch (InterruptedException e) {
  623. // TODO Auto-generated catch block
  624. e.printStackTrace();
  625. }
  626. }
  627. break;
  628. }
  629. this.times++;
  630. // 设置3秒发一颗子弹
  631. if (times % 2 == 0) {
  632. if (isLive) {
  633. if (ss.size() < 5) {
  634. Shot s = null;
  635. // 没有子弹,添加
  636. switch (direct) {
  637. case 0:
  638. s = new Shot(x + 10, y, 0);
  639. ss.add(s);
  640. break;
  641. case 1:
  642. s = new Shot(x + 30, y + 10, 1);
  643. ss.add(s);
  644. break;
  645. case 2:
  646. s = new Shot(x + 10, y + 30, 2);
  647. ss.add(s);
  648. break;
  649. case 3:
  650. s = new Shot(x, y + 10, 3);
  651. ss.add(s);
  652. break;
  653. }
  654. // 启动子弹线程
  655. Thread t = new Thread(s);
  656. t.start();
  657. }
  658. }
  659. }
  660. // 让坦克随机产生一个新的方向
  661. this.direct = (int) (Math.random() * 4);
  662. // 判断敌人坦克是否死亡了(双等号)
  663. if (this.isLive == false) {
  664. // 让坦克死亡,后退出线程
  665. return;
  666. }
  667.  
  668. }
  669. }
  670. }
  671.  
  672. // 我的坦克
  673. class Hero1_2 extends Tank1_2 {
  674. // 多个子弹,用向量创建
  675. Vector<Shot> ss = new Vector<Shot>();
  676. // 子弹
  677. Shot s = null;
  678.  
  679. public Hero1_2(int x, int y) {
  680. super(x, y);
  681. }
  682.  
  683. // 坦克开火
  684. public void shotEnemy() {
  685.  
  686. switch (this.direct) {
  687. case 0:
  688. s = new Shot(x + 10, y, 0);
  689. // 把子弹加入向量
  690. ss.add(s);
  691. break;
  692.  
  693. case 1:
  694. s = new Shot(x + 30, y + 10, 1);
  695. // 把子弹加入向量
  696. ss.add(s);
  697. break;
  698.  
  699. case 2:
  700. s = new Shot(x + 10, y + 30, 2);
  701. // 把子弹加入向量
  702. ss.add(s);
  703. break;
  704.  
  705. case 3:
  706. s = new Shot(x, y + 10, 3);
  707. // 把子弹加入向量
  708. ss.add(s);
  709. break;
  710. }
  711. // 启动子弹线程(创建线程,赶紧传参,我在这里吃了大亏!)
  712. Thread t = new Thread(s);
  713. t.start();
  714. }
  715.  
  716. public void moveUp() {
  717. y -= speed;
  718. }
  719.  
  720. public void moveRight() {
  721. x += speed;
  722. }
  723.  
  724. public void moveDown() {
  725. y += speed;
  726. }
  727.  
  728. public void moveLeft() {
  729. x -= speed;
  730. }
  731. }

实现图片:

相关素材:

1.爆炸效果的图片(3张)

2.游戏声音素材

这个自己下载一个好啦(我的是上面命名为111.wav的文件,这里不支持上传)

Java坦克大战(四)的更多相关文章

  1. Java坦克大战 (四) 之子弹的产生

    本文来自:小易博客专栏.转载请注明出处:http://blog.csdn.net/oldinaction 在此小易将坦克大战这个项目分为几个版本,以此对J2SE的知识进行回顾和总结,希望这样也能给刚学 ...

  2. Java坦克大战(三)

    关于这个坦克大战的项目是在学习Java基础的时候,拿来练习的最近看到这些代码,感觉很亲切,就把他们都复制下来,编辑成博客.回首看去,Java基础的学习确实应该建立在找项目练习上,这样才能将学到的基础知 ...

  3. Java坦克大战(二)

    本文紧接上一篇讲解坦克大战这个项目,因为当初在学习的时候,是以这个案例逐步学习Java基础的,过程是先讲知识点,再将知识点逐步的融入到项目中,即给坦克添加新的功能.之前的Demo练习,想都记录下来.这 ...

  4. Java坦克大战(一)

    接下来的几篇博客,想记录一下通过学习坦克大战项目来循序渐进的学习Java基础.主要是为了巩固基础知识,当然学习编程重要的还是多敲,问题通常是在敲代码的过程中发现的,积累也是在敲代码中寻求的经验.这个坦 ...

  5. Java坦克大战 (七) 之图片版

    本文来自:小易博客专栏.转载请注明出处:http://blog.csdn.net/oldinaction 在此小易将坦克大战这个项目分为几个版本,以此对J2SE的知识进行回顾和总结,希望这样也能给刚学 ...

  6. Java坦克大战 (六) 之增加可玩性

    本文来自:小易博客专栏.转载请注明出处:http://blog.csdn.net/oldinaction 在此小易将坦克大战这个项目分为几个版本,以此对J2SE的知识进行回顾和总结,希望这样也能给刚学 ...

  7. Java坦克大战 (五) 之产生敌方坦克和爆炸效果

    本文来自:小易博客专栏.转载请注明出处:http://blog.csdn.net/oldinaction 在此小易将坦克大战这个项目分为几个版本,以此对J2SE的知识进行回顾和总结,希望这样也能给刚学 ...

  8. Java坦克大战 (三) 之可完全控制坦克朝八个方向运动

    本文来自:小易博客专栏.转载请注明出处:http://blog.csdn.net/oldinaction 在此小易将坦克大战这个项目分为几个版本,以此对J2SE的知识进行回顾和总结,希望这样也能给刚学 ...

  9. Java坦克大战 (二) 之画一个能动的圆圈代表坦克

    本文来自:小易博客专栏.转载请注明出处:http://blog.csdn.net/oldinaction 在此小易将坦克大战这个项目分为几个版本,以此对J2SE的知识进行回顾和总结,希望这样也能给刚学 ...

随机推荐

  1. javascript 取整,取余数 math方法

    1.丢弃小数部分,保留整数部分 parseInt() 函数可解析一个字符串,并返回一个整数. parseInt(string, radix) 参数 描述 string 必需.要被解析的字符串. rad ...

  2. python3 与 Django 连接数据库报错:ImportError: No module named 'MySQLdb'

    在 python2 中,使用 pip install mysql-python 进行安装连接MySQL的库,使用时 import MySQLdb 进行使用 在 python3 中,改变了连接库,改为了 ...

  3. 宽字符————_T、_TEXT、L、TEXT之间的区别

    _T._TEXT.L.TEXT之间的区别 在分析前先对三者做一个简单的分类 _T._TEXT.TEXT三者都是根据编译器的环境进行ANSI/UNICODE变换的,_T和_TEXT是根据_UNICODE ...

  4. 关于javac和java

    1.为什么安装完jdk后不配置环境变量就能直接运行java,而不能运行javac 在安装jdk的时候jdk会自带一个jre(java运行环境),还会单独安装一个jre,默认路径是和jdk在同级目录,而 ...

  5. SQL-1--语句分类

  6. linux常用的BootLoader U-boot的前世今生

    U-Boot,全称 Universal Boot Loader,是遵循GPL条款的开放源码项目.U-Boot的作用是系统引导. U-Boot从FADSROM.8xxROM.PPCBOOT逐步发展演化而 ...

  7. 机器学习技法笔记:05 Kernel Logistic Regression

    Roadmap Soft-Margin SVM as Regularized Model SVM versus Logistic Regression SVM for Soft Binary Clas ...

  8. Spring Boot读取配置的 5 种方式

    读取application文件 在application.yml或者properties文件中添加: info.address=USA info.company=Spring info.degree= ...

  9. 3-5 Vue中的样式绑定

    Vue中的样式绑定: 本案例,简单设计一个<div>的点击绑定事件来改变div的样式效果 方法一:[class] ①(class和对象的绑定) //如上,运用class和一个对象的形式来解 ...

  10. JavaEmail-邮箱

    package service; import com.sun.mail.util.MailSSLSocketFactory;import javax.mail.Message;import java ...