Ruby Ruby 练习题:打战舰

knwang · 2015年12月27日 · 最后由 msg7086 回复于 2016年01月06日 · 5041 次阅读

我们 的假期 Ruby 练习题:

论坛好像不能直接上 video, 就把连接贴过来,需要下载下视频 (英文, 但应该跟着看比较好理解):

https://d1b1wr57ag5rdp.cloudfront.net/videos/output/battleship_game_f38fa9_s349/battleship_game_f38fa9_s349.mp4

欢迎大家尝试。 我过两天会给提示,在新年后会给详细解答。

感觉课程很好,可是英语跟不上

网站貌似挂了,进不去

@knwang 进入了 launchschool 不过没找到打战舰的链接

#3 楼 @duobei 视频就在上面的链接里面。 讨论直接在这里就可以了 - 我会在这里给予反馈和点评。

如果想在 Launch School 里面参加讨论, 可以到这个链接 (需要注册)

https://launchschool.com/posts/974de05b

最开始我还以为是写算法来实现如何攻击才能最大概率击败对手呢。

@knwang 先祝贺 launchschool.com 隆重登场~! +1

诶?Open fire 是什么意思。

#5 楼 @w7938940 可以啊, 欢迎借题发挥

5x5 矩阵有讲究啊,如果是 4x4 会有点麻烦

-------------12.31. 更新分割线----------- 试了一下,累计时间已经超过两个小时了,目前还有 bug,好泄气

新站好赞!!!

一些解题帮助:

这个练习题有满多的复杂性,主要呈现在两个方面: 1. 如何记载和跟踪游戏状态,以及带来的怎么样的面向对象的数据封装比较合适?2. 如何把一个大的题目化整为零,来计划一步步的实现过程? 其他在具体的算法和编程方面并不是很难。

在第一个方面,可以首先在全局上检查可能需要追踪的游戏状态:

- 两个玩家(电脑/人) -两个棋盘及其方格 - 游戏状态:现在该哪个玩家打;是否有人胜出 - 所有方格的状态(被打击但无船;被打击打到船;未被打击) - 所有舰船的方位和朝向 - 舰船的状态(未被击沉/被击沉) -朝每个棋盘发射过的所有炮弹

在面向对象编程的框世里,一般来讲是把名词抽出来作为对象的,比如说这里面的 玩家,舰船,炮弹,棋盘,方格,游戏。但如果从这个角度入手,往往在一开始的时候就面对着如何设计对象层级及对象间交互的方式,是比较困难的。有些同学会不太多考虑的选择几个概念来封装成类,代码写起来再说,但其实不理想的封装会带来后面程序复杂度的大幅度提高。

可以考虑这样一个角度:如果检查所有的状态,会发现这些游戏状态并不是互相独立的 - 而有些状态是可以从其他的状态计算出来的 - 比如说所有方格的状态可以由舰船位置和所有炮弹的位置计算出来。在选择类/对象的时候,尽量选择基本的,相互独立的状态,把它们封装,由他们再计算出其他的状态。

还有一个角度,是优先考虑再问题描述中高频出现的概念。在这个问题描述中,“船” 的概念非常频繁的出现,这说明在这个题目里,有很多的算法(步骤)和逻辑对 ” 船 “ 这个概念是有依赖的。 所以把 ” 船 “ 抽象出来作为一个基本砌块是有优势的。而如果不固化这个概念,势必在代码中到处计算和反推这个概念,增加不必要的复杂度。

在选择出基本的几个状态及类封装后,可以回头把需求中的所有逻辑和其他状态 向选择的基本状态沉积。这样程序的大体框架就有了。

下次讲 化整为零 解决问题的方法。

#11 楼 @fsword 别太在意时间 :) 欢迎分享心得!

祝贺 tealeaf academy 升级为 launch school.

想了一下,不应该怕丢人,代码在 https://github.com/fsword/ship-game

总结一下试验的收获:

  • 对 player、ship、screen、matrix 的建模比较重要
  • 虽然以前没写过类似的程序,但是在其它方面得到的一些经验有助于简化工作,比如 repaint
  • 分离关注点的价值,以及对 listener 的理解
  • 最后处理 Array.new 导致的那个 bug 花了很久时间,说明 API 掌握不熟练会导致很高的成本

#16 楼 @fsword

在游戏流程控制上, 感觉是你是在用类似即时战略游戏的思想来实现回合制的游戏 :) 事件驱动和绑定玩的蛮高端, 对这个题目是牛刀了,因为本身游戏的流程可以都放在 game loop 里面的, 而且总是 玩家 -> 电脑 -> 重新画屏。你的实现方法如果是很多玩家同时乱打倒是很合适的。

在跟踪状态和建模上面, 用每个 shot 引起从 TeamController 到 Team 到 Matrix 到 Ship 的状态改变,以及 MatrixDelegator 对 Matrix 本身的加强,感觉对象间太多依赖,交互太多; 从另一个角度看, 这些对象除了 Ship 外都比较浅,执行形式以 delegation / pass through 为主 (尤其是 shot_at 的 delegations ), 可以考虑把一些对象变化成类似 transformation 的函数。在代码从面上,你大多数的方法是以 command / delegation 为主,如果多考虑用 数据进 /数据出的函数,会逼迫你简化对状态的代表方式,从而减少总体复杂度。

#17 楼 @knwang 非常感谢,我写完以后就觉得可以合并 team/team controller,以及 matrix/matrix delegator,有空再重构一下,这种练习很有意思。

over design 的问题有原因,我本来是想做玩家对决,后来发现还是想多了 :-P

另外有个困难,就是 ship 里面那段代码,主要是为了避免碰撞,感觉很啰嗦,而且降低了可测性

跑题: #7 楼 @msg7086 你想说那个是中国式英语吗,很遗憾还真不是 说不定中文的是从英文直译过来的?

#20 楼 @krrr 不,我只是从来没见过这种用法,比较好奇。多谢解答。

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册