关于这个坦克大战的项目是在学习Java基础的时候,拿来练习的最近看到这些代码,感觉很亲切,就把他们都复制下来,编辑成博客。回首看去,Java基础的学习确实应该建立在找项目练习上,这样才能将学到的基础知识用到实际当中,不然你知道什么是面向对象编程,什么是线程,什么是死锁,概念都了解了一大堆,等到实际应用的时候,还是力不从心。初学者千万不要灰心,真心是敲着敲着就有感觉了。下面还是循序渐进的介绍这个项目的几个版本,注释我写的很详细,新功能添加后部分代码有改动,如果感兴趣,可以看前几篇博客。

坦克大战(1.4版本)

1.MyTankGame类:

  1. /*
  2. * 删掉很多之前的注释
  3. * 功能:线程(坦克打子弹)进过分析:子弹是个类
  4. */
  5. package com.fanghua3;
  6.  
  7. import java.awt.*;
  8. import java.awt.event.KeyEvent;
  9. import java.util.Vector;
  10.  
  11. import javax.swing.*;
  12.  
  13. public class MyTankGame1_4 extends JFrame {
  14.  
  15. Mypanel1_2 mp = null;
  16.  
  17. public static void main(String[] args) {
  18. new MyTankGame1_4();
  19. }
  20.  
  21. // 构造函数
  22. public MyTankGame1_4() {
  23. mp = new Mypanel1_2();
  24.  
  25. // 启动mp线程
  26. Thread t = new Thread(mp);
  27. t.start();
  28.  
  29. this.add(mp);
  30. // 注册监听
  31. this.addKeyListener(mp);
  32.  
  33. this.setSize(400, 300);
  34. this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  35. this.setVisible(true);
  36.  
  37. }
  38. }
  39.  
  40. // 我的面板,拓宽思路:Panel本身就是一个刷新体
  41. class Mypanel1_2 extends JPanel implements java.awt.event.KeyListener, Runnable {
  42.  
  43. // 定义我的坦克
  44. Hero1_2 hero = null;
  45. // 定义敌人的坦克(不止一辆,线程安全,集合)
  46. Vector<EnemyTank> ets = new Vector<EnemyTank>();
  47. int enSize = 3;// 敌人坦克保持三个
  48.  
  49. // 构造函数
  50. public Mypanel1_2() {
  51. hero = new Hero1_2(10, 10);
  52. for (int i = 0; i < enSize; i++) {
  53.  
  54. // 创建一辆敌人的坦克
  55. EnemyTank et = new EnemyTank((i + 1) * 50, 0);
  56. et.setColor(0);
  57. // 坦克默认反向是0(向上),这里改一下
  58. et.setDirect(2);
  59. // 加入
  60. ets.add(et);
  61.  
  62. }
  63. }
  64.  
  65. // 重写paint函数
  66. public void paint(Graphics g) {
  67. // 一定要调用
  68. super.paint(g);
  69. g.fillRect(0, 0, 400, 300);
  70. // 画出自己的坦克(将方向填进去)
  71. this.drawTank(hero.getX(), hero.getY(), g, this.hero.direct, 1);
  72.  
  73. // 画出子弹(后添加 hero.s.isLive==true,节省资源)
  74. if (hero.s != null && hero.s.isLive == true) {
  75. g.draw3DRect(hero.s.x, hero.s.y, 1, 1, false);
  76. }
  77.  
  78. // 画出敌人的坦克
  79. for (int i = 0; i < enSize; i++) {
  80. this.drawTank(ets.get(i).getX(), ets.get(i).getY(), g, ets.get(i)
  81. .getDirect(), 0);
  82.  
  83. }
  84.  
  85. }
  86.  
  87. // 画出坦克的函数
  88. public void drawTank(int x, int y, Graphics g, int direct, int type) {
  89. // 坦克类型
  90. switch (type) {
  91. case 0:
  92. g.setColor(Color.green);
  93. break;
  94. case 1:
  95. g.setColor(Color.yellow);
  96. break;
  97. }
  98. // 方向设置
  99. switch (direct) {
  100. // 向上
  101. case 0:
  102. g.fill3DRect(x, y, 5, 30, false);
  103. g.fill3DRect(x + 15, y, 5, 30, false);
  104. g.fill3DRect(x + 5, y + 5, 10, 20, false);
  105. g.fillOval(x + 5, y + 10, 10, 10);
  106. g.drawLine(x + 10, y + 15, x + 10, y);
  107. break;
  108. // 向右
  109. case 1:
  110. g.fill3DRect(x, y, 30, 5, false);
  111. g.fill3DRect(x, y + 15, 30, 5, false);
  112. g.fill3DRect(x + 5, y + 5, 20, 10, false);
  113. g.fillOval(x + 10, y + 5, 10, 10);
  114. g.drawLine(x + 15, y + 10, x + 30, y + 10);
  115. break;
  116. // 向下
  117. case 2:
  118. g.fill3DRect(x, y, 5, 30, false);
  119. g.fill3DRect(x + 15, y, 5, 30, false);
  120. g.fill3DRect(x + 5, y + 5, 10, 20, false);
  121. g.fillOval(x + 5, y + 10, 10, 10);
  122. g.drawLine(x + 10, y + 15, x + 10, y + 30);
  123. break;
  124. // 向左
  125. case 3:
  126. g.fill3DRect(x, y, 30, 5, false);
  127. g.fill3DRect(x, y + 15, 30, 5, false);
  128. g.fill3DRect(x + 5, y + 5, 20, 10, false);
  129. g.fillOval(x + 10, y + 5, 10, 10);
  130. g.drawLine(x + 15, y + 10, x, y + 10);
  131. break;
  132. }
  133.  
  134. }
  135.  
  136. @Override
  137. public void keyTyped(KeyEvent e) {
  138. // TODO Auto-generated method stub
  139.  
  140. }
  141.  
  142. @Override
  143. public void keyPressed(KeyEvent e) {
  144. // TODO Auto-generated method stub
  145. // 已更正为顺时针
  146. if (e.getKeyCode() == KeyEvent.VK_UP
  147. || e.getKeyCode() == KeyEvent.VK_W) {
  148. this.hero.moveUp();
  149. this.hero.setDirect(0);
  150. } else if (e.getKeyCode() == KeyEvent.VK_RIGHT
  151. || e.getKeyCode() == KeyEvent.VK_D) {
  152. this.hero.setDirect(1);
  153. this.hero.moveRight();
  154. } else if (e.getKeyCode() == KeyEvent.VK_DOWN
  155. || e.getKeyCode() == KeyEvent.VK_S) {
  156. this.hero.moveDown();
  157. this.hero.setDirect(2);
  158. } else if (e.getKeyCode() == KeyEvent.VK_LEFT
  159. || e.getKeyCode() == KeyEvent.VK_A) {
  160. this.hero.moveLeft();
  161. this.hero.setDirect(3);
  162. } else if (e.getKeyCode() == KeyEvent.VK_J) {
  163. // 将J键设置为发出子弹
  164. this.hero.shotEnemy();
  165. this.repaint();
  166. }
  167.  
  168. }
  169.  
  170. @Override
  171. public void keyReleased(KeyEvent e) {
  172. // TODO Auto-generated method stub
  173.  
  174. }
  175.  
  176. @Override
  177. public void run() {
  178. // TODO Auto-generated method stub
  179. // 每隔100毫秒去重绘
  180. while (true) {
  181. try {
  182. Thread.sleep(100);
  183. } catch (InterruptedException e) {
  184. // TODO Auto-generated catch block
  185. e.printStackTrace();
  186. }
  187.  
  188. // 重绘
  189. this.repaint();
  190. }
  191. }
  192. }

2.Menbers类:

  1. package com.fanghua3;
  2. //子弹类
  3. class Shot implements Runnable{
  4. int x;
  5. int y;
  6. int direct;
  7. //设置子弹的消亡(默认活着的)
  8. boolean isLive=true;
  9. //speed要给个初始值1,之前给0,按J键,子弹没有动
  10. int speed=1;
  11. public Shot(int x, int y,int direct) {
  12. super();
  13. this.x = x;
  14. this.y= y;
  15. this.direct=direct;
  16.  
  17. }
  18. @Override
  19. public void run() {
  20. // TODO Auto-generated method stub
  21.  
  22. while(true){
  23. //设置子弹休息50毫秒
  24.  
  25. try {
  26. Thread.sleep(50);
  27. } catch (InterruptedException e) {
  28. // TODO Auto-generated catch block
  29. e.printStackTrace();
  30. }
  31.  
  32. switch(direct){
  33. case 0:
  34. y-=speed;
  35. break;
  36. case 1:
  37. x+=speed;
  38. break;
  39. case 2:
  40. y+=speed;
  41. break;
  42. case 3:
  43. x-=speed;
  44. break;
  45. }
  46. System.out.println("子弹坐标x="+x+"y="+y);
  47. //子弹什么时候死亡
  48. //判断该子弹是否碰到边缘
  49. if(x<0||x>400||y<0||y>300){
  50. this.isLive=false;
  51. break;
  52. }
  53. }
  54. }
  55. }
  56.  
  57. //坦克类
  58. class Tank1_2 {
  59.  
  60. int x = 0;
  61. int y = 0;
  62.  
  63. // 坦克方向:0表示上,1表示右,2表示下,3表示左
  64. int direct = 0;
  65. int speed = 1;
  66. //坦克的颜色
  67. int color;
  68.  
  69. public int getColor() {
  70. return color;
  71. }
  72.  
  73. public void setColor(int color) {
  74. this.color = color;
  75. }
  76.  
  77. public int getSpeed() {
  78. return speed;
  79. }
  80.  
  81. public void setSpeed(int speed) {
  82. this.speed = speed;
  83. }
  84.  
  85. public int getDirect() {
  86. return direct;
  87. }
  88.  
  89. public void setDirect(int direct) {
  90. this.direct = direct;
  91. }
  92.  
  93. public int getX() {
  94. return x;
  95. }
  96.  
  97. public void setX(int x) {
  98. this.x = x;
  99. }
  100.  
  101. public int getY() {
  102. return y;
  103. }
  104.  
  105. public void setY(int y) {
  106. this.y = y;
  107. }
  108.  
  109. // 构造函数
  110. public Tank1_2(int x, int y) {
  111. this.x = x;
  112. this.y = y;
  113.  
  114. }
  115.  
  116. }
  117. //敌人的坦克
  118. class EnemyTank extends Tank1_2{
  119.  
  120. public EnemyTank(int x, int y) {
  121. super(x, y);
  122. // TODO Auto-generated constructor stub
  123. }
  124. }
  125.  
  126. //我的坦克
  127. class Hero1_2 extends Tank1_2 {
  128. //子弹
  129. Shot s=null;
  130. public Hero1_2(int x, int y) {
  131. super(x, y);
  132. }
  133. //坦克开火
  134. public void shotEnemy(){
  135.  
  136. switch(this.direct){
  137. case 0:
  138. s=new Shot(x+10,y,0);
  139.  
  140. break;
  141.  
  142. case 1:
  143. s=new Shot(x+30,y+10,1);
  144. break;
  145.  
  146. case 2:
  147. s=new Shot(x+10,y+30,2);
  148. break;
  149.  
  150. case 3:
  151. s=new Shot(x,y+10,3);
  152. break;
  153. }
  154. //启动子弹线程
  155. Thread t=new Thread(s);
  156. t.start();
  157. }
  158.  
  159. public void moveUp() {
  160. y -= speed;
  161. }
  162. public void moveRight() {
  163. x += speed;
  164. }
  165. public void moveDown() {
  166. y += speed;
  167. }
  168. public void moveLeft() {
  169. x -= speed;
  170. }
  171. }

坦克大战(1.5版本)

1.MyTankGame类:

  1. /*
  2. * 删掉很多之前的注释
  3. * 功能:子弹连发,(线程)最多5颗子弹
  4. * 敌人坦克消失
  5. */
  6. package com.fanghua4;
  7.  
  8. import java.awt.*;
  9. import java.awt.event.KeyEvent;
  10. import java.util.Vector;
  11.  
  12. import javax.swing.*;
  13.  
  14. public class MyTankGame1_5 extends JFrame {
  15.  
  16. Mypanel1_2 mp = null;
  17.  
  18. public static void main(String[] args) {
  19. new MyTankGame1_5();
  20. }
  21.  
  22. // 构造函数
  23. public MyTankGame1_5() {
  24. mp = new Mypanel1_2();
  25.  
  26. // 启动mp线程
  27. Thread t = new Thread(mp);
  28. t.start();
  29.  
  30. this.add(mp);
  31. // 注册监听
  32. this.addKeyListener(mp);
  33.  
  34. this.setSize(400, 300);
  35. this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  36. this.setVisible(true);
  37.  
  38. }
  39. }
  40.  
  41. // 我的面板,拓宽思路:Panel本身就是一个刷新体
  42. class Mypanel1_2 extends JPanel implements java.awt.event.KeyListener, Runnable {
  43.  
  44. // 定义我的坦克
  45. Hero1_2 hero = null;
  46. // 定义敌人的坦克(不止一辆,线程安全,集合)
  47. Vector<EnemyTank> ets = new Vector<EnemyTank>();
  48. int enSize = 3;// 敌人坦克保持三个
  49.  
  50. // 构造函数
  51. public Mypanel1_2() {
  52. hero = new Hero1_2(10, 10);
  53. for (int i = 0; i < enSize; i++) {
  54.  
  55. // 创建一辆敌人的坦克
  56. EnemyTank et = new EnemyTank((i + 1) * 50, 0);
  57. et.setColor(0);
  58. // 坦克默认反向是0(向上),这里改一下
  59. et.setDirect(2);
  60. // 加入
  61. ets.add(et);
  62.  
  63. }
  64. }
  65.  
  66. // 重写paint函数
  67. public void paint(Graphics g) {
  68. // 一定要调用
  69. super.paint(g);
  70. g.fillRect(0, 0, 400, 300);
  71. // 画出自己的坦克(将方向填进去)
  72. this.drawTank(hero.getX(), hero.getY(), g, this.hero.direct, 1);
  73.  
  74. // 从ss中取出每一颗子弹,并画出
  75. for (int i = 0; i < hero.ss.size(); i++) {
  76.  
  77. Shot myShot = hero.ss.get(i);
  78. if (myShot != null && myShot.isLive == true) {
  79. g.draw3DRect(myShot.x, myShot.y, 1, 1, false);
  80.  
  81. /*
  82. * 画出一颗子弹(后添加 hero.s.isLive==true,节省资源) if (hero.s != null
  83. * &&hero.s.isLive == true) { g.draw3DRect(hero.s.x, hero.s.y,
  84. * 1, 1,false); }
  85. */
  86. }
  87. if (myShot.isLive == false) {
  88. // 从ss(向量)中删除该子弹
  89. // hero.ss.remove(i);会报异常。
  90. hero.ss.remove(myShot);
  91. }
  92. }
  93.  
  94. // 画出敌人的坦克
  95. for (int i = 0; i < enSize; i++) {
  96. EnemyTank et = ets.get(i);
  97. if (et.isLive) {
  98. this.drawTank(et.getX(), et.getY(), g, et.getDirect(), 0);
  99. }
  100. }
  101. }
  102.  
  103. // 写一个函数 专门判断是否击中敌人坦克
  104. public void hitTank(Shot s, EnemyTank et) {
  105. // 判断该坦克的方向
  106. switch (et.direct) {
  107. // 敌人坦克的方向是0或2,一致
  108. case 0:
  109. case 2:
  110. if (s.x > et.x && s.x < et.x + 20 && s.y > et.y && s.y < et.y + 30) {
  111. // 击中(子弹死亡,敌人四万)
  112. s.isLive = false;
  113. et.isLive = false;
  114. }
    break;
  115. case 1:
  116. case 3:
  117. if (s.x > et.x && s.x < et.x + 30 && s.y > et.y && s.y < et.y + 20) {
  118. // 击中(子弹死亡,敌人四万)
  119. s.isLive = false;
  120. et.isLive = false;
  121. }
    break;
  122. }
  123. }
  124.  
  125. // 画出坦克的函数
  126. public void drawTank(int x, int y, Graphics g, int direct, int type) {
  127. // 坦克类型
  128. switch (type) {
  129. case 0:
  130. g.setColor(Color.green);
  131. break;
  132. case 1:
  133. g.setColor(Color.yellow);
  134. break;
  135. }
  136. // 方向设置
  137. switch (direct) {
  138. // 向上
  139. case 0:
  140. g.fill3DRect(x, y, 5, 30, false);
  141. g.fill3DRect(x + 15, y, 5, 30, false);
  142. g.fill3DRect(x + 5, y + 5, 10, 20, false);
  143. g.fillOval(x + 5, y + 10, 10, 10);
  144. g.drawLine(x + 10, y + 15, x + 10, y);
  145. break;
  146. // 向右
  147. case 1:
  148. g.fill3DRect(x, y, 30, 5, false);
  149. g.fill3DRect(x, y + 15, 30, 5, false);
  150. g.fill3DRect(x + 5, y + 5, 20, 10, false);
  151. g.fillOval(x + 10, y + 5, 10, 10);
  152. g.drawLine(x + 15, y + 10, x + 30, y + 10);
  153. break;
  154. // 向下
  155. case 2:
  156. g.fill3DRect(x, y, 5, 30, false);
  157. g.fill3DRect(x + 15, y, 5, 30, false);
  158. g.fill3DRect(x + 5, y + 5, 10, 20, false);
  159. g.fillOval(x + 5, y + 10, 10, 10);
  160. g.drawLine(x + 10, y + 15, x + 10, y + 30);
  161. break;
  162. // 向左
  163. case 3:
  164. g.fill3DRect(x, y, 30, 5, false);
  165. g.fill3DRect(x, y + 15, 30, 5, false);
  166. g.fill3DRect(x + 5, y + 5, 20, 10, false);
  167. g.fillOval(x + 10, y + 5, 10, 10);
  168. g.drawLine(x + 15, y + 10, x, y + 10);
  169. break;
  170. }
  171.  
  172. }
  173.  
  174. @Override
  175. public void keyTyped(KeyEvent e) {
  176. // TODO Auto-generated method stub
  177.  
  178. }
  179.  
  180. @Override
  181. public void keyPressed(KeyEvent e) {
  182. // TODO Auto-generated method stub
  183. // 已更正为顺时针
  184. if (e.getKeyCode() == KeyEvent.VK_UP || e.getKeyCode() == KeyEvent.VK_W) {
  185. this.hero.moveUp();
  186. this.hero.setDirect(0);
  187. } else if (e.getKeyCode() == KeyEvent.VK_RIGHT
  188. || e.getKeyCode() == KeyEvent.VK_D) {
  189. this.hero.setDirect(1);
  190. this.hero.moveRight();
  191. } else if (e.getKeyCode() == KeyEvent.VK_DOWN
  192. || e.getKeyCode() == KeyEvent.VK_S) {
  193. this.hero.moveDown();
  194. this.hero.setDirect(2);
  195. } else if (e.getKeyCode() == KeyEvent.VK_LEFT
  196. || e.getKeyCode() == KeyEvent.VK_A) {
  197. this.hero.moveLeft();
  198. this.hero.setDirect(3);
  199. } else if (e.getKeyCode() == KeyEvent.VK_J) {
  200. // 将J键设置为发出子弹
  201. // 子弹连发,J被按几下,发几颗:this.hero.shotEnemy();
  202. // this.repaint();在run函数里,不应该设计在这里
  203. if (this.hero.ss.size() <= 4) {
  204. this.hero.shotEnemy();
  205. }
  206.  
  207. }
  208.  
  209. }
  210.  
  211. @Override
  212. public void run() {
  213. // TODO Auto-generated method stub
  214. // 每隔100毫秒去重绘
  215. while (true) {
  216. try {
  217. Thread.sleep(100);
  218. } catch (InterruptedException e) {
  219. // TODO Auto-generated catch block
  220. e.printStackTrace();
  221. }
  222. // 判断是否击中(写在这里,虽然在每次重绘的时候都要调用,但是没办法)
  223. // 每一颗子弹都要和每个坦克进行匹配
  224. for (int i = 0; i < hero.ss.size(); i++) {
  225. // 取出子弹
  226. Shot myShot = hero.ss.get(i);
  227. // 判断子弹是否有效
  228. if (myShot.isLive) {
  229. // 取出每个坦克,与它判断
  230. for (int j = 0; j < ets.size(); j++) {
  231. // 取出坦克
  232. EnemyTank et = ets.get(j);
  233.  
  234. if (et.isLive) {
  235. this.hitTank(myShot, et);
  236. }
  237. }
  238. }
  239. }
  240.  
  241. // 重绘
  242. this.repaint();
  243. }
  244. }
  245.  
  246. @Override
  247. public void keyReleased(KeyEvent e) {
  248. // TODO Auto-generated method stub
  249.  
  250. }
  251.  
  252. }

2.Menbers类:

  1. package com.fanghua4;
  2.  
  3. import java.util.Vector;
  4.  
  5. //子弹类
  6. class Shot implements Runnable {
  7. int x;
  8. int y;
  9. int direct;
  10. // 设置子弹的消亡(默认活着的)
  11. boolean isLive = true;
  12. // speed要给个初始值1,之前给0,按J键,子弹没有动
  13. int speed = 1;
  14.  
  15. public Shot(int x, int y, int direct) {
  16. super();
  17. this.x = x;
  18. this.y = y;
  19. this.direct = direct;
  20.  
  21. }
  22.  
  23. @Override
  24. public void run() {
  25. // TODO Auto-generated method stub
  26.  
  27. while (true) {
  28. // 设置子弹休息50毫秒
  29.  
  30. try {
  31. Thread.sleep(50);
  32. } catch (InterruptedException e) {
  33. // TODO Auto-generated catch block
  34. e.printStackTrace();
  35. }
  36.  
  37. switch (direct) {
  38. case 0:
  39. y -= speed;
  40. break;
  41. case 1:
  42. x += speed;
  43. break;
  44. case 2:
  45. y += speed;
  46. break;
  47. case 3:
  48. x -= speed;
  49. break;
  50. }
  51. System.out.println("子弹坐标x=" + x + "y=" + y);
  52. // 子弹什么时候死亡
  53. // 判断该子弹是否碰到边缘
  54. if (x < 0 || x > 400 || y < 0 || y > 300) {
  55. this.isLive = false;
  56. break;
  57. }
  58. }
  59. }
  60. }
  61.  
  62. // 坦克类
  63. class Tank1_2 {
  64.  
  65. int x = 0;
  66. int y = 0;
  67.  
  68. // 坦克方向:0表示上,1表示右,2表示下,3表示左
  69. int direct = 0;
  70. int speed = 1;
  71. // 坦克的颜色
  72. int color;
  73.  
  74. public int getColor() {
  75. return color;
  76. }
  77.  
  78. public void setColor(int color) {
  79. this.color = color;
  80. }
  81.  
  82. public int getSpeed() {
  83. return speed;
  84. }
  85.  
  86. public void setSpeed(int speed) {
  87. this.speed = speed;
  88. }
  89.  
  90. public int getDirect() {
  91. return direct;
  92. }
  93.  
  94. public void setDirect(int direct) {
  95. this.direct = direct;
  96. }
  97.  
  98. public int getX() {
  99. return x;
  100. }
  101.  
  102. public void setX(int x) {
  103. this.x = x;
  104. }
  105.  
  106. public int getY() {
  107. return y;
  108. }
  109.  
  110. public void setY(int y) {
  111. this.y = y;
  112. }
  113.  
  114. // 构造函数
  115. public Tank1_2(int x, int y) {
  116. this.x = x;
  117. this.y = y;
  118.  
  119. }
  120.  
  121. }
  122.  
  123. // 敌人的坦克
  124. class EnemyTank extends Tank1_2 {
  125.  
  126. boolean isLive = true;
  127.  
  128. public EnemyTank(int x, int y) {
  129. super(x, y);
  130. // TODO Auto-generated constructor stub
  131. }
  132. }
  133.  
  134. // 我的坦克
  135. class Hero1_2 extends Tank1_2 {
  136. // 多个子弹,用向量创建
  137. Vector<Shot> ss = new Vector<Shot>();
  138. // 子弹
  139. Shot s = null;
  140.  
  141. public Hero1_2(int x, int y) {
  142. super(x, y);
  143. }
  144.  
  145. // 坦克开火
  146. public void shotEnemy() {
  147.  
  148. switch (this.direct) {
  149. case 0:
  150. s = new Shot(x + 10, y, 0);
  151. // 把子弹加入向量
  152. ss.add(s);
  153. break;
  154.  
  155. case 1:
  156. s = new Shot(x + 30, y + 10, 1);
  157. // 把子弹加入向量
  158. ss.add(s);
  159. break;
  160.  
  161. case 2:
  162. s = new Shot(x + 10, y + 30, 2);
  163. // 把子弹加入向量
  164. ss.add(s);
  165. break;
  166.  
  167. case 3:
  168. s = new Shot(x, y + 10, 3);
  169. // 把子弹加入向量
  170. ss.add(s);
  171. break;
  172. }
  173. // 启动子弹线程
  174. Thread t = new Thread(s);
  175. t.start();
  176. }
  177.  
  178. public void moveUp() {
  179. y -= speed;
  180. }
  181.  
  182. public void moveRight() {
  183. x += speed;
  184. }
  185.  
  186. public void moveDown() {
  187. y += speed;
  188. }
  189.  
  190. public void moveLeft() {
  191. x -= speed;
  192. }
  193. }

坦克大战(1.6版本)

1.MyTankGame类

  1. /*
  2. * 功能:
  3. * 1.实现爆炸效果
  4. * 2.敌人坦克可移动,可以连发子弹
  5. * 3.敌人击中我的坦克,我爆炸
  6. * 4.击中第一个坦克爆炸的效果不明显
  7. */
  8. package com.fanghua5;
  9.  
  10. import java.awt.*;
  11. import java.awt.event.KeyEvent;
  12. import java.util.Vector;
  13. import javax.swing.*;
  14.  
  15. public class MyTankGame1_6 extends JFrame {
  16.  
  17. Mypanel1_2 mp = null;
  18.  
  19. public static void main(String[] args) {
  20. new MyTankGame1_6();
  21. }
  22.  
  23. // 构造函数
  24. public MyTankGame1_6() {
  25. mp = new Mypanel1_2();
  26.  
  27. // 启动mp线程
  28. Thread t = new Thread(mp);
  29. t.start();
  30.  
  31. this.add(mp);
  32. // 注册监听
  33. this.addKeyListener(mp);
  34.  
  35. this.setSize(400, 300);
  36. this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  37. this.setVisible(true);
  38.  
  39. }
  40. }
  41.  
  42. // 我的面板,拓宽思路:Panel本身就是一个刷新体
  43. class Mypanel1_2 extends JPanel implements java.awt.event.KeyListener, Runnable {
  44.  
  45. // 定义我的坦克
  46. Hero1_2 hero = null;
  47. // 定义敌人的坦克(不止一辆,线程安全,集合)
  48. Vector<EnemyTank> ets = new Vector<EnemyTank>();
  49.  
  50. // 定义炸弹集合
  51. Vector<Bomb> bombs = new Vector<Bomb>();
  52.  
  53. int enSize = 4;// 敌人坦克保持四个
  54.  
  55. // 定义三张图片(三张图片才能组成一颗炸弹)
  56. Image image1 = null;
  57. Image image2 = null;
  58. Image image3 = null;
  59.  
  60. // 构造函数
  61. public Mypanel1_2() {
  62. hero = new Hero1_2(10, 10);
  63. for (int i = 0; i < enSize; i++) {
  64.  
  65. // 创建一辆敌人的坦克
  66. EnemyTank et = new EnemyTank((i + 1) * 50, 0);
  67. et.setColor(0);
  68. // 坦克默认反向是0(向上),这里改一下
  69. et.setDirect(2);
  70. // 加入
  71. ets.add(et);
  72.  
  73. // 启动敌人的坦克
  74. Thread t = new Thread(et);
  75. t.start();
  76. // 给敌人坦克添加一颗子弹
  77. Shot s = new Shot(et.x + 10, et.y + 30, 2);
  78. // 加入给敌人的坦克
  79. et.ss.add(s);
  80.  
  81. Thread t2 = new Thread(s);
  82. t2.start();
  83. ets.add(et);
  84.  
  85. }
  86. // 初始话图片,这样做击中第一个坦克,爆炸的效果不明显。下面优化
  87. image1 = Toolkit.getDefaultToolkit().getImage(
  88. Panel.class.getResource("/bomb_1.gif"));
  89. image2 = Toolkit.getDefaultToolkit().getImage(
  90. Panel.class.getResource("/bomb_2.gif"));
  91. image3 = Toolkit.getDefaultToolkit().getImage(
  92. Panel.class.getResource("/bomb_3.gif"));
  93.  
  94. // 引包:import javax.imageio.ImagesssIO;
  95. // try {
  96. // image1=ImageIO.read(new File("/bomsb_1.gif"));
  97. // image2=ImageIO.read(new File("/bomb_2.gif"));
  98. // image3=ImageIO.read(new File("/bomb_3.gif"));
  99. // } catch (IOException e) {
  100. // // TODO Auto-generated catch block
  101. // e.printStackTrace();
  102. // }
  103. }
  104.  
  105. // 重写paint函数
  106. public void paint(Graphics g) {
  107. // 一定要调用
  108. super.paint(g);
  109. g.fillRect(0, 0, 400, 350);
  110. // 画出自己的坦克(将方向填进去)
  111. if (hero.isLive == true) {
  112. this.drawTank(hero.getX(), hero.getY(), g, this.hero.direct, 1);
  113. }
  114. // 从ss中取出每一颗子弹,并画出
  115. for (int i = 0; i < hero.ss.size(); i++) {
  116.  
  117. Shot myShot = hero.ss.get(i);
  118. if (myShot != null && myShot.isLive == true) {
  119. g.draw3DRect(myShot.x, myShot.y, 1, 1, false);
  120.  
  121. /*
  122. * 画出一颗子弹(后添加 hero.s.isLive==true,节省资源) if (hero.s != null
  123. * &&hero.s.isLive == true) { g.draw3DRect(hero.s.x, hero.s.y,
  124. * 1, 1,false); }
  125. */
  126. }
  127. if (myShot.isLive == false) {
  128. // 从ss(向量)中删除该子弹
  129. // hero.ss.remove(i);会报异常。
  130. hero.ss.remove(myShot);
  131. }
  132. }
  133.  
  134. // 画出炸弹
  135. for (int i = 0; i < bombs.size(); i++) {
  136. // 取出炸弹
  137. Bomb b = bombs.get(i);
  138. if (b.life > 6) {
  139. g.drawImage(image1, b.x, b.y, 30, 30, this);
  140. } else if (b.life > 4) {
  141. g.drawImage(image2, b.x, b.y, 30, 30, this);
  142. } else {
  143. g.drawImage(image3, b.x, b.y, 30, 30, this);
  144. }
  145. // 让b的生命值减小
  146. b.lifeDown();
  147. // 如果炸弹生命值为零,就把该炸弹从bombs向量中去掉
  148. if (b.life == 0) {
  149. bombs.remove(b);
  150. }
  151.  
  152. }
  153.  
  154. // 画出敌人的坦克
  155. for (int i = 0; i < ets.size(); i++) {
  156. EnemyTank et = ets.get(i);
  157. if (et.isLive) {
  158. this.drawTank(et.getX(), et.getY(), g, et.getDirect(), 0);
  159.  
  160. // 画出敌人的子弹
  161. for (int j = 0; j < et.ss.size(); j++) {
  162. // 取出子弹
  163. Shot enemyShot = et.ss.get(j);
  164. if (enemyShot != null && enemyShot.isLive == true) {
  165. g.draw3DRect(enemyShot.x, enemyShot.y, 1, 1, false);
  166. }
  167. if (enemyShot.isLive == false) {
  168. // 如果敌人的坦克死亡了,就从Vector中删除
  169. et.ss.remove(enemyShot);
  170. }
  171. }
  172. }
  173. }
  174. }
  175.  
  176. // 判断敌人的子弹是否击中我
  177. public void hitMe() {
  178. // 取出每一个敌人的坦克
  179. for (int i = 0; i < this.ets.size(); i++) {
  180. // 取出坦克
  181. EnemyTank et = ets.get(i);
  182. // 取出每一颗子弹
  183. for (int j = 0; j < et.ss.size(); j++) {
  184. // 取出子弹
  185. Shot enemyShot = et.ss.get(j);
  186.  
  187. this.hitTank(enemyShot, hero);
  188. }
  189.  
  190. }
  191. }
  192.  
  193. // 判断我是否击中敌人的坦克
  194. public void hitEnemyTank() {
  195. // 判断是否被击中敌人的坦克
  196. for (int i = 0; i < hero.ss.size(); i++) {
  197. // 取出我的子弹与敌人坦克匹配
  198. Shot myShot = hero.ss.get(i);
  199. // 判断子弹是否有效
  200. if (myShot.isLive) {
  201. // 取出每个坦克,与它判断
  202. for (int j = 0; j < ets.size(); j++) {
  203. // 取出坦克
  204. EnemyTank et = ets.get(j);
  205. if (et.isLive) {
  206. this.hitTank(myShot, et);
  207. }
  208. }
  209. }
  210. }
  211. }
  212.  
  213. // 写一个函数 专门判断是否击中敌人坦克(原来第二参数: EnemyTank et)
  214. public void hitTank(Shot s, Tank1_2 et) {
  215. // 判断该坦克的方向
  216. switch (et.direct) {
  217. // 敌人坦克的方向是0或2,一致
  218. case 0:
  219. case 2:
  220. if (s.x >= et.x && s.x <= et.x + 20 && s.y >= et.y
  221. && s.y <= et.y + 30) {
  222. // 击中(子弹死亡,敌人死亡)
  223. s.isLive = false;
  224. et.isLive = false;
  225.  
  226. // 创建一颗炸弹,放入Vector中
  227. Bomb b = new Bomb(et.x, et.y);
  228. // 放入
  229. bombs.add(b);
  230. }
    break;
  231. case 1:
  232. case 3:
  233. if (s.x >= et.x && s.x <= et.x + 30 && s.y >= et.y
  234. && s.y <= et.y + 20) {
  235. // 击中(子弹死亡,敌人死亡)
  236. s.isLive = false;
  237. et.isLive = false;
  238. // 创建一颗炸弹,放入Vector中
  239. Bomb b = new Bomb(et.x, et.y);
  240. // 放入
  241. bombs.add(b);
  242. }
    break;
  243. }
  244. }
  245.  
  246. // 画出坦克的函数
  247. public void drawTank(int x, int y, Graphics g, int direct, int type) {
  248. // 坦克类型
  249. switch (type) {
  250. case 0:
  251. g.setColor(Color.green);
  252. break;
  253. case 1:
  254. g.setColor(Color.yellow);
  255. break;
  256. }
  257. // 方向设置
  258. switch (direct) {
  259. // 向上
  260. case 0:
  261. g.fill3DRect(x, y, 5, 30, false);
  262. g.fill3DRect(x + 15, y, 5, 30, false);
  263. g.fill3DRect(x + 5, y + 5, 10, 20, false);
  264. g.fillOval(x + 5, y + 10, 10, 10);
  265. g.drawLine(x + 10, y + 15, x + 10, y);
  266. break;
  267. // 向右
  268. case 1:
  269. g.fill3DRect(x, y, 30, 5, false);
  270. g.fill3DRect(x, y + 15, 30, 5, false);
  271. g.fill3DRect(x + 5, y + 5, 20, 10, false);
  272. g.fillOval(x + 10, y + 5, 10, 10);
  273. g.drawLine(x + 15, y + 10, x + 30, y + 10);
  274. break;
  275. // 向下
  276. case 2:
  277. g.fill3DRect(x, y, 5, 30, false);
  278. g.fill3DRect(x + 15, y, 5, 30, false);
  279. g.fill3DRect(x + 5, y + 5, 10, 20, false);
  280. g.fillOval(x + 5, y + 10, 10, 10);
  281. g.drawLine(x + 10, y + 15, x + 10, y + 30);
  282. break;
  283. // 向左
  284. case 3:
  285. g.fill3DRect(x, y, 30, 5, false);
  286. g.fill3DRect(x, y + 15, 30, 5, false);
  287. g.fill3DRect(x + 5, y + 5, 20, 10, false);
  288. g.fillOval(x + 10, y + 5, 10, 10);
  289. g.drawLine(x + 15, y + 10, x, y + 10);
  290. break;
  291. }
  292.  
  293. }
  294.  
  295. @Override
  296. public void keyTyped(KeyEvent e) {
  297. // TODO Auto-generated method stub
  298.  
  299. }
  300.  
  301. @Override
  302. public void keyPressed(KeyEvent e) {
  303. // TODO Auto-generated method stub
  304. // 已更正为顺时针
  305. if (e.getKeyCode() == KeyEvent.VK_UP || e.getKeyCode() == KeyEvent.VK_W) {
  306. this.hero.moveUp();
  307. this.hero.setDirect(0);
  308. } else if (e.getKeyCode() == KeyEvent.VK_RIGHT
  309. || e.getKeyCode() == KeyEvent.VK_D) {
  310. this.hero.setDirect(1);
  311. this.hero.moveRight();
  312. } else if (e.getKeyCode() == KeyEvent.VK_DOWN
  313. || e.getKeyCode() == KeyEvent.VK_S) {
  314. this.hero.moveDown();
  315. this.hero.setDirect(2);
  316. } else if (e.getKeyCode() == KeyEvent.VK_LEFT
  317. || e.getKeyCode() == KeyEvent.VK_A) {
  318. this.hero.moveLeft();
  319. this.hero.setDirect(3);
  320. } else if (e.getKeyCode() == KeyEvent.VK_J) {
  321. // 将J键设置为发出子弹
  322. // 子弹连发,J被按几下,发几颗:this.hero.shotEnemy();
  323. // this.repaint();在run函数里,不应该设计在这里
  324. if (this.hero.ss.size() <= 4) {
  325. this.hero.shotEnemy();
  326. }
  327.  
  328. }
  329.  
  330. }
  331.  
  332. @Override
  333. public void keyReleased(KeyEvent e) {
  334. // TODO Auto-generated method stub
  335.  
  336. }
  337.  
  338. @Override
  339. public void run() {
  340. // TODO Auto-generated method stub
  341. // 每隔100毫秒去重绘
  342. while (true) {
  343. try {
  344. Thread.sleep(100);
  345. } catch (InterruptedException e) {
  346. // TODO Auto-generated catch block
  347. e.printStackTrace();
  348. }
  349. // 判断是否击中(写在这里,虽然在每次重绘的时候都要调用,但是没办法)
  350. // 每一颗子弹都要和每个坦克进行匹配
  351. for (int i = 0; i < hero.ss.size(); i++) {
  352. // 取出子弹
  353. Shot myShot = hero.ss.get(i);
  354. // 判断子弹是否有效
  355. if (myShot.isLive) {
  356. // 取出每个坦克,与它判断
  357. for (int j = 0; j < ets.size(); j++) {
  358. // 取出坦克
  359. EnemyTank et = ets.get(j);
  360.  
  361. if (et.isLive) {
  362. this.hitTank(myShot, et);
  363. }
  364. }
  365. }
  366. }
  367. this.hitEnemyTank();
  368.  
  369. this.hitMe();
  370.  
  371. // 重绘
  372. this.repaint();
  373. }
  374. }
  375. }

2.Menbers类:

  1. package com.fanghua5;
  2.  
  3. import java.util.Vector;
  4.  
  5. //炸弹类(没必要定义为线程,因为它不会移动,没有坐标改变)
  6. class Bomb {
  7. // 定义炸弹的坐标
  8. int x, y;
  9. int life = 9;// 炸弹的生命(三张图片)
  10. // 可以看出isLive很有用,它可以决定类(或者对象)要不要展现在面板上
  11. boolean isLive = true;
  12.  
  13. public Bomb(int x, int y) {
  14. this.x = x;
  15. this.y = y;
  16. }
  17.  
  18. // 炸弹减少生命值
  19. public void lifeDown() {
  20. if (life > 0) {
  21. life--;
  22. } else {
  23. this.isLive = false;
  24. }
  25. }
  26.  
  27. }
  28.  
  29. // 子弹类
  30. class Shot implements Runnable {
  31. int x;
  32. int y;
  33. int direct;
  34. // 设置子弹的消亡(默认活着的)
  35. boolean isLive = true;
  36. // speed要给个初始值1,之前给0,按J键,子弹没有动
  37. int speed = 1;
  38.  
  39. public Shot(int x, int y, int direct) {
  40. super();
  41. this.x = x;
  42. this.y = y;
  43. this.direct = direct;
  44.  
  45. }
  46.  
  47. @Override
  48. public void run() {
  49. // TODO Auto-generated method stub
  50.  
  51. while (true) {
  52. // 设置子弹休息50毫秒
  53.  
  54. try {
  55. Thread.sleep(50);
  56. } catch (InterruptedException e) {
  57. // TODO Auto-generated catch block
  58. e.printStackTrace();
  59. }
  60.  
  61. switch (direct) {
  62. case 0:
  63. y -= speed;
  64. break;
  65. case 1:
  66. x += speed;
  67. break;
  68. case 2:
  69. y += speed;
  70. break;
  71. case 3:
  72. x -= speed;
  73. break;
  74. }
  75. // 测试用:System.out.println("子弹坐标x=" + x + "y=" + y);
  76. // 子弹什么时候死亡
  77. // 判断该子弹是否碰到边缘
  78. if (x < 0 || x > 400 || y < 0 || y > 300) {
  79. this.isLive = false;
  80. break;
  81. }
  82. }
  83. }
  84. }
  85.  
  86. // 坦克类
  87. class Tank1_2 {
  88.  
  89. int x = 0;
  90. int y = 0;
  91. boolean isLive=true;
  92.  
  93. // 坦克方向:0表示上,1表示右,2表示下,3表示左
  94. int direct = 0;
  95. int speed = 1;
  96. // 坦克的颜色
  97. int color;
  98.  
  99. public int getColor() {
  100. return color;
  101. }
  102.  
  103. public void setColor(int color) {
  104. this.color = color;
  105. }
  106.  
  107. public int getSpeed() {
  108. return speed;
  109. }
  110.  
  111. public void setSpeed(int speed) {
  112. this.speed = speed;
  113. }
  114.  
  115. public int getDirect() {
  116. return direct;
  117. }
  118.  
  119. public void setDirect(int direct) {
  120. this.direct = direct;
  121. }
  122.  
  123. public int getX() {
  124. return x;
  125. }
  126.  
  127. public void setX(int x) {
  128. this.x = x;
  129. }
  130.  
  131. public int getY() {
  132. return y;
  133. }
  134.  
  135. public void setY(int y) {
  136. this.y = y;
  137. }
  138.  
  139. // 构造函数
  140. public Tank1_2(int x, int y) {
  141. this.x = x;
  142. this.y = y;
  143.  
  144. }
  145.  
  146. }
  147.  
  148. // 敌人的坦克(做成线程,会移动)
  149. class EnemyTank extends Tank1_2 implements Runnable {
  150.  
  151. //从父类继承了,去掉:boolean isLive = true;
  152. int times = 0;// 让time累积
  153. // 定义向量,可以存放敌人的子弹
  154. Vector<Shot> ss = new Vector<Shot>();
  155.  
  156. // 敌人添加子弹,应该刚刚创建坦克和敌人子弹死亡后
  157.  
  158. public EnemyTank(int x, int y) {
  159. super(x, y);
  160. }
  161.  
  162. @Override
  163. public void run() {
  164. // TODO Auto-generated method stub
  165. while (true) {
  166. try {
  167. // 设置坦克休息一会
  168. Thread.sleep(50);
  169. } catch (InterruptedException e) {
  170. // TODO Auto-generated catch block
  171. e.printStackTrace();
  172. }
  173. switch (this.direct) {
  174. case 0:
  175. // 说明坦克正在向上运动(继续往上走,符合实际)
  176. // y -= speed;设置坦克平滑移动的效果
  177. for (int i = 0; i < 30; i++) {
  178. if (y > 0) {
  179. y -= speed;
  180. }
  181. try {
  182. Thread.sleep(50);
  183. } catch (InterruptedException e) {
  184. // TODO Auto-generated catch block
  185. e.printStackTrace();
  186. }
  187. }
  188. break;
  189. case 1:
  190. for (int i = 0; i < 30; i++) {
  191. // 这里注意坐标起点问题不是(400x300)
  192. if (x < 350) {
  193. x += speed;
  194. }
  195. try {
  196. Thread.sleep(50);
  197. } catch (InterruptedException e) {
  198. // TODO Auto-generated catch block
  199. e.printStackTrace();
  200. }
  201. }
  202. break;
  203. case 2:
  204. for (int i = 0; i < 30; i++) {
  205. if (y < 250) {
  206. y += speed;
  207. }
  208. try {
  209. Thread.sleep(50);
  210. } catch (InterruptedException e) {
  211. // TODO Auto-generated catch block
  212. e.printStackTrace();
  213. }
  214. }
  215. break;
  216. case 3:
  217. for (int i = 0; i < 30; i++) {
  218. if (x > 0) {
  219. x -= speed;
  220. }
  221. try {
  222. Thread.sleep(50);
  223. } catch (InterruptedException e) {
  224. // TODO Auto-generated catch block
  225. e.printStackTrace();
  226. }
  227. }
  228. break;
  229. }
  230. this.times++;
  231. // 设置3秒发一颗子弹
  232. if (times % 2 == 0) {
  233. if (isLive) {
  234. if (ss.size() < 5) {
  235. Shot s = null;
  236. // 没有子弹,添加
  237. switch (direct) {
  238. case 0:
  239. s = new Shot(x + 10, y, 0);
  240. ss.add(s);
  241. break;
  242. case 1:
  243. s = new Shot(x + 30, y + 10, 1);
  244. ss.add(s);
  245. break;
  246. case 2:
  247. s = new Shot(x + 10, y + 30, 2);
  248. ss.add(s);
  249. break;
  250. case 3:
  251. s = new Shot(x, y + 10, 3);
  252. ss.add(s);
  253. break;
  254. }
  255. // 启动子弹线程
  256. Thread t = new Thread(s);
  257. t.start();
  258. }
  259. }
  260. }
  261. // 让坦克随机产生一个新的方向
  262. this.direct = (int) (Math.random() * 4);
  263. // 判断敌人坦克是否死亡了(双等号)
  264. if (this.isLive == false) {
  265. // 让坦克死亡,后退出线程
  266. return;
  267. }
  268.  
  269. }
  270. }
  271. }
  272.  
  273. // 我的坦克
  274. class Hero1_2 extends Tank1_2 {
  275. // 多个子弹,用向量创建
  276. Vector<Shot> ss = new Vector<Shot>();
  277. // 子弹
  278. Shot s = null;
  279.  
  280. public Hero1_2(int x, int y) {
  281. super(x, y);
  282. }
  283.  
  284. // 坦克开火
  285. public void shotEnemy() {
  286.  
  287. switch (this.direct) {
  288. case 0:
  289. s = new Shot(x + 10, y, 0);
  290. // 把子弹加入向量
  291. ss.add(s);
  292. break;
  293.  
  294. case 1:
  295. s = new Shot(x + 30, y + 10, 1);
  296. // 把子弹加入向量
  297. ss.add(s);
  298. break;
  299.  
  300. case 2:
  301. s = new Shot(x + 10, y + 30, 2);
  302. // 把子弹加入向量
  303. ss.add(s);
  304. break;
  305.  
  306. case 3:
  307. s = new Shot(x, y + 10, 3);
  308. // 把子弹加入向量
  309. ss.add(s);
  310. break;
  311. }
  312. // 启动子弹线程(创建线程,赶紧传参,我在这里吃了大亏!)
  313. Thread t = new Thread(s);
  314. t.start();
  315. }
  316.  
  317. public void moveUp() {
  318. y -= speed;
  319. }
  320.  
  321. public void moveRight() {
  322. x += speed;
  323. }
  324.  
  325. public void moveDown() {
  326. y += speed;
  327. }
  328.  
  329. public void moveLeft() {
  330. x -= speed;
  331. }
  332. }

1.6版本(图:基本功能都已经实现)

之后,我还会继续写一篇博客,来记录该坦克大战的最终版本(2.0),这个坦克大战的项目利用Java图形界面来实现坦克的绘制,画质比较粗糙,部分的坐标没有那么精确。

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

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

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

  2. 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. Java 线程使用注意事项

    事件处理线程说明 如果事件处理的逻辑能迅速完成,并且不会发起新的IO请求,比如只是在内存中记个标识,则直接在IO线程上处理更快,因为减少了线程池调度. 但如果事件处理逻辑较慢,或者需要发起新的IO请求 ...

  2. 图像质量评价方法PSNR+SSIM&&评估指标SROCC,PLCC

    update:2018-04-07 今天发现ssim的计算里面有高斯模糊,为了快速计算,先对每个小块进行计算,然后计算所有块的平均值.可以参考源代码实现,而且代码实现有近似的在里面!matlab中中图 ...

  3. 构建一个Gods Eye Android应用程序:第1部分 – 收集已安装的Android应用程序

    首先问候一下我的黑客伙伴们,在之前的Introduction to Amunet 教程中,我们了解到Amunet可能是一个间谍Android应用程序. 我不浪费太多时间因而直入主题. 在本教程中,我们 ...

  4. 走你!Github 开源整合

    加入知识星球,最好的分享交流平台哦~ <我的知识星球,最好的分享交流平台>,一年的服务平台,对于一个成年人来说,就是小费了(更多详情,请点击文章了解)~ 走你!Github 开源整合 1. ...

  5. 读取.Properties文件以及Spring注解读取文件内容

    public class Main { public static void main(String[] args) throws IOException { //创建Properties对象 Pro ...

  6. Java中的引用传递和值传递

    Java中的引用传递和值传递 关于Java的引用传递和值传递,在听了老师讲解后,还是没有弄清楚是怎么一回事,于是查了资料,所以在这里与大家分享,有不对的地方,欢迎大家留言. java中是没有指针的,j ...

  7. linux中环境变量PATH设置错误,导致ls cd 等命令不能使用,提示:没有那个文件或目录

    在CentOS7中执行了 PATH=/opt/:$PATH 然后执行ls时,出现 ls-bash: ls: 没有那个文件或目录 试了试其他命令也一样无法使用 后来执行 : export PATH=/u ...

  8. Python Web Service

    搞移动端有段时间了,一直使用别人的API,自己也只写过ASP.NET网站作为网络服务,相对来讲是很大的短板.虽然ASP.NET可以提供想要的web服务,但是其体量臃肿,响应速度非常慢,这点我非常不喜欢 ...

  9. MySql安装与使用(linux)

    安装 MySQL 注意:此处安装是yum安装为例: MySQL安装 #yum install mysql-server 完后显示如下: MySQL初始化 #service mysqld start 查 ...

  10. C语言最最最基础部分(a+b为例)

      此篇为C语言最基础的部分知识简单概括,对C语言有一定了解的同学建议绕道哦~另外,文底附有此文知识点详细了解的链接. 下面我们以“a+b”为例,分析这个程序的组成. #include<stdi ...