1、一、 eclipse 的使用 调用方法:类名(右键) Source 显示窗口: WindowShow View 调整代码格式:右键 Source Format 鼠标划词显示设置:右键窗口 Java Editor Hovers Combined Hover Debug 的运用 一步一步跟踪代码 为 代码设置 断点 ( break point) Step into 和 step over 的概念 在运行过程中观测变量的值 右键 Open Call Hierarchy 查看方法被谁调用了 二、 J2SE 练习项目 聊天系统 开发思路: Start main 方法 调用 launchFrame()方法
2、 connect()方法 Socket 连接到服务器端 把对外的输出流保存好 actionPerformed 中 往外写字符串时直接用即可 disConnect 方法(清理资源) 从服务器端断开 在窗口关闭时调用 此时写两下,读一下,有问题 ; 定义控制 accept()方法和是否 绑定 上 服务器端 的 boolean 类型变量 客户端可写多个语句并被 server 端接收。 多个 client 端连接 server 端 Server 端将各个客户端发送的内容转发给其他客户端。 结束 总结 与真正聊天系统的差距 1) 管理 clients 的办法 此: List 把 Socket 去掉,用的
3、是 catch Exception 的方法。 实 : 设置一个 boolean 的量,代表是否退出。 起一个单独的监视线程,监听客户端什么时候退出或死掉。 2) 聊天账户名 3)选择聊天对象 4) 写程序步骤: 1. 写界面窗口 2. 窗口、组件事件监听 3. 连接 server 端 4. client 端与 server 端通信 问题 1: server 已在一个端口上监听, 重复启动 server .BindException: Address already in use: JVM_Bind 解决 : 先把第一个 server 停掉。 问题 2: 服务器端 end of file jav
4、a.io.EOFException 解决: readUTF()是阻塞式的, 写 try/catch,将 ServerSocket 异常抛出,catch到任何 Exception后将 dis/socket关掉。 问题 3: 多个 client 端连接 server 端 .SocketException: Connection reset 解决 : readUTF()是阻塞式方法, accept 第一个连接后进入死循环 ,第二个客户端就连接不上来了。 异步解决办法 newIO,异步模式 使用单独线程(传统解决办法) : 一个线程控制一个客户端; 1)建立一个线程类( 按需写成 内部类) ,类名:
5、client 2)重写 run方法,要求每接收到一个 Socket都交给一个线程去处理。 在拿到相关东西进行处理。 3)接收到一个 Socket连接后,启动一个线程,把 socket连接传递给线程,用构造方法传递属性 。 5. client 端与 client 端通信 Server 端: 1)用集合类将 client 端存储起来 2)每接收到一个客户端连接,起一个线程,挨排写给每一个客户端对象 。 Client 端 : 1) 起一个线程,显示内容 问题: 1)两个客户端正在通信,突然关掉一个客户端 , send(),run()出问题 解决:将 Client 定义在外面 一层 , 再 移除 cl
6、ient。 错误 .SocketException: Software caused connection abort: socket write error 软件导致连接终止 :套接字写错误 定义控制 accept()方法和是否连接上服务器端的 boolean 类型变量判断。 java.io.EOFException EOF end of file 内部类 BlockDataInputStream.的方法 peekByte 抛出的异常,意思就是到达了文件的末尾,程序却没有正常结束读取文件内容,你可以单步调试一下看看到达文件末尾之后程序为什么没有停下来 静态方法中 new 不出内部类对象 ,在
7、外部类中包装一个方法,不要直接 new。 调试程序: 打印 相关信息 使用 debug 坦克大战 项目需求 1. 能够四处移动 2. 能够打击敌人 3. 敌人能够移动 4. 能够模拟爆炸 5. 能够产生障碍 6. 能够增长生命 开发步骤 : 1. 版本 0.1 功能: 产生一个窗口 800*600 - - 2. 版本 0.2 功能 : 1)添加关闭窗口的事件处理 2)不允许窗口的大小改动 Api 文档中 Frame 类或其父类方法。 掌握 1)匿名类的用法 类短小、不涉及将来的扩展、不涉及重要的业务逻辑。 2)通过 Eclipse 重写父类的方法 - - 3. 版本 0.3 功能: 画出代表坦
8、克的实心圆。 掌握: 如何重写 paint 方法。 注意: 不要改变原来的前景色 回顾: 1) paint(Graphics g)方法,窗口重画时自动调用 2) X 轴、 Y 轴的方向 - 4. 版本 0.4 功能: 1)让坦克动起来 2)步骤: a. 将位置改变为变量 paint(x,y,w,h),改变 x,y 值。 b. 启动线程不断重画 为什么使用线程重画,而不是每按下一个键进行一次重画? - 线程重画更均匀,能控制重画的速度; - 按键重画不能解决子弹自动飞行的问题。 c. 每次重画改变 Tank 位置 问题:屏幕闪烁现象 解决:双缓冲 掌握: 内部类的使用: a. 好处:可以方便的方
9、位包装类的方法。 b. 使用时机:不方便公开的,职位包装类服务的类应当定义为内部类。 注意: X,y 值的含义,指的是小方块的左上角点。 - - 4_1. 版本 0.41 功能 使用双缓冲消除闪烁现象。 原因 1)刷新重画频率太快, paint 方法还没有完成 2)逐条显示 解决办法 将所有东西画在虚拟图片上,一次性显示出来 1)模拟一张虚拟图片 2)重写 update 方法 创建虚拟图片 ( 800*600) 将所有的东西画到图片上 图片的 画笔 paint() 前面的画笔drawImage() 重置背景颜色 思考: 把游戏窗口的大小改变为 640 *480? 解决:定义常量以应付将来的改动
10、 - - 5. 版本 0.5 功能: 代码重构 a. 讲以后可能需要多处改变的量定义为常量 Frame 的宽度和高度 常量名一般大写 。 注意: 常量一般是 public static final 的。 - 6. 版本 0.6 功能: 让坦克听从指挥: 1) 加入键盘事件监听 (方向键) ,即添加键盘监听器类 KeyMonitor; 2) TankClient 添加键盘监听器 ; 3)针对不同的键改变坦克的位置,与重画线程结合产生不同方向运动。 注意: switch case 语句中 break 语句的运用 思考 增加 100 辆坦克到游戏中 - - 7. 版本 0.7 思路:存放 100 个
11、坦克? 1) 采用面向对象的思维 2) 把坦克包装成一个类 Tank构造方法 draw 坦克 3) 在 TankClient 的 paint()方法中直接调用 draw 方法; 4)在 Tank 类中定义 keyEvent 功能: 1)将坦克单独包装成类 2)步骤: a. 建立 Tank 类 b. 为 Tank 类添加成员变量 x,y c. 添加 draw 方法,使 Tank 类独立控制自己的画法 d. 添加 Tank 类处理按键的方法 e. 根据 Tank 类修改 TankClient 类 掌握 : 面向对象的思考方法: 1)细节隐藏、构建单独的类、首先考虑系统中有哪些类 2)合适的方法应该
12、出现在合适的类中 思考 如何让坦克向 8 个方向行走? - - 8. 版本 0.8 思路: 定义 boolean 类型成员变量控制 方向 键是否被按。 枚举 Driection(八个方向 ) Move 方法 locateDriection 方法 定位方向键。 功能: 1)让主坦克向 8 个方向行走( 1) 2)步骤: a. 添加记录按键状态的布尔量 b. 添加代表方向的量(使用枚举) c. 根据按键状态确定 Tank 方向 d. 根据方向进行下一步的移动( move) - - 9. 版本 0.9 功能: 1)让主坦克向 8 个方向行走( 2) 2)步骤: a. 处理键抬起的消息 b. 修改 T
13、ankClient 相关代码 - 10. 版本 1.0 功能 1)添加子弹类 2)步骤: a. 添加 Missile 类 b. 添加 x,y,dir 等属性以及常量 b.1. 添加构造方法, draw 方法等必要方法 b.2. 根据不同方向,进行不同的运动 b.3. 在 TankClient 中模拟一颗子弹 - new 一颗子弹出来 - 画出来 注意 将步骤分解开来注意进行调试。 - - 11. 版本 1.1 功能: 1)根据主战坦克的方向和位置,打出子弹 2)步骤 a. 增加对 Ctrl 按键处理 b. 根据“坦克打出一发子弹”这句话,来确定 Tank 中的方法 fire,其返回值为 Mis
14、sile c. 根据 Tank 方向和位置设定子弹的方向和位置并计算出来,然后返回( fire方法的实现) 注意: 掌握面向对象的思维方式来确定类应该具有的方法。 思考: 坦克不动时,打出的炮弹也是不动的。怎么解决? - - 12. 版本 1.2 思路: 定义炮筒方向 功能: 1)为了解决坦克停下也能打出炮弹的问题 画出炮筒 2)步骤: a. Tank 类增加新的属性 炮筒方向 ( ptDri) b. 每次 move 后根据 Tank 新的方向确定炮筒的方向 c. 将炮筒用直线的形式表现出来 - - 13. 版本 1.3 功能: 1)打出多发炮弹 2)步骤: a. 使用容器装炮弹 b. 每当抬
15、起 Ctrl 键就往容器中加入新的炮弹 c. 逐一画出每一发炮弹 注意: 1) 泛型的使用 2) 将 TankClient 的实例传递到 Tank 中 3) this 的运用,类的初始化过程 - - 14. 版本 1.4 功能: 1)解决炮弹不消亡的问题 2)解决坦克出界的问题 3)步骤: a. 加入控制炮弹生死的量 bLive(Missile) b. 当炮弹已经死去就不需要对其重画 c. 当炮弹飞出边界就死亡 d.当炮弹死亡就从容器中去除 debug - - 15. 版本 1.5 功能: 1)画一辆敌人的坦克 2)步骤: 加入区别敌我的量 bGood 根据敌我的不同设置不同的颜色 更新 Ta
16、nk 的构造函数,加入 good TankClient 中 new 出敌人的坦克并画出 - - 16. 版本 1.6 功能: 1)将敌人坦克击毙 2)分析:一颗子弹击中敌人坦克 3)步骤: Missile 中加入 hitTank( Tank)方法,返回布尔类型 碰撞检测的辅助类 Rectangle 为 Tank 和 Missile 都加入 getRect 方法 当击中敌人坦克时,坦克被打死,子弹也死去 增加控制 Tank 生死的量 live 如果死去就不画了 WinMerge 比较前后目录内容的工具 - - 17. 版本 1.7 功能: 1)加入爆炸 2)步骤: a. 添加爆炸类 用不同直径的
17、圆模拟爆炸 加入 live 加入位置属性 加入 draw 方法 b. 爆炸应该存在于集合类中 TankClient 加入集合 将集合中的爆炸逐一画出(如果死去就去除) c. 击毙一辆坦克后应产生爆炸 hitTank 时应产生爆炸 不能直接访问爆炸集合 加入 TankClient 引用( Missile 类) 当 new Missile 时应制定在哪里画出(哪个 TankClient) 修改 Tank 类 fire 方法,当 new Missile 时将保存好的 TankClient 变量传递给 Missile。 - - 18. 版本 1.8 功能: 1)添加多辆坦克 2)步骤: a. 用容器来
18、装敌人的 Tank b. 向容器中装入多辆敌人 Tank c. 画出来 d. 运行,不能打掉 添加 hitTanks 方 法,打一系列 Tank TankClient 里面每发子弹都打 tanks - - 19. 版本 1.9 思路: 让敌方的坦克动起来 。 随机数控制方向。 功能 : 1) 让敌军坦克更加智能 2) 步骤: a. 让敌军坦克动起来 b. 让敌军坦克向随机方向移动 c. 让敌军坦克向随机方向移动随机的步骤 d. 让敌军坦克发射炮弹 e. 敌军炮火不能太猛烈 - - 20. 版本 2.0 功能: 1)添加两堵墙 2)步骤: a. 建 Wall 类、建立 Wall 对象、画出来 b. 让每一颗子弹打击每一堵墙 hitWall()方法 注意:子弹速度不能太快,否则很容易穿过墙 c. 让坦克不能穿过墙 记录上一次的位置 oldX, oldY 修改构造函数 每次 move 之前记录上一次位置 添加 stay 方法 记录移动前的位置 当撞到时回到移动前的位置 当碰到墙的时候 stay - - 21. 版本 2.1 功能: 1)坦克不能互相穿越 2)步骤:当坦克撞到 Tank 时 stay; - 22. 版本 2.2 功能: 1)超级炮弹 2)步骤:处理按键 A - - 23. 版本 2.3