aiqier的水果蛇(二)
上一篇博客写到关于类的设计,这里我还想在举一个列子,
这是oop中常见的一个问题,
比如现在我已经写好了Wallpaper类(画板)和Snake类,那么之间要如何建立关系呢?
第一种:
wallpaper.drawSnake(Snake)
第二种:
snake.draw(Wallpaper)
第三种:
for i in snake.getnodes():
wall.paper.setcolor(i,snake.getcolor())
对于前两种,就是能够把算法封装在类里,这样在调用的时候,看着轻巧,但是会破坏一定的可重用性,如果让我选,我选择第二个,因为,毕竟Wallpaper被重用的概率会更大一些。
第三种带来的好处自然是重用性,snake和wallpaper都可以被重用,但是有的时候真的需要这种重用性吗?一个类什么时候的重用性最高?就是只有get和set方法的时候,但是,这个重用性高的原因是它什么都不会,
就拿磁带和录音机的列子来说把,两者都可以重用,但是如果成本足够,制造出可以自己播放的磁带也是可以的。
如果程序要画许多东西,那么常见的做法是那些东西都要实现一个接口(比如draw()),之后他们被传入wallpaper类,wallpaper仅仅是迭代每一个对象,然后调用它们的draw接口,在java中你就不得不写一个接口去让类来“继承”,python的鸭子类型,连接口都不用继承了。
下面是我对写这个程序的两个看法,
关于python
python语言的动态性和高级性,让你可以方便的实现自己想要的功能,让你把注意力集中于问题的解决,而不是其他一些琐碎的事。就拿我之前写过的一篇关于快速排序算法的博客来说吧。
如果你是第一次看c版本的快速排序算法代码,如果让你亲自写一个,你会觉得有点不好下手,就算能下手,也会觉得很麻烦,因为快速排序的原理是找一个标准,然后将其分为大于标准的,和小于等于标准的的两组,再分别递归,整个算法都要在那么一个大的数组上进行,除了算法本身,你还要考虑,将"标准"放在开头,之后再交换回来,如果粗心,for循环的多一少一。。。。。(关于for循环的使用心得,我推荐你我的另一篇blog)
而用python的高级内建数组结构,让你可以方便的表达自己的思想,就像自己说话一样,把算法描述出来。
比如这个贪吃蛇的代码吧,对于snake的move函数,我做的,仅仅是在列表头插入一个元素,在pop列表的最后一个元素。
不用声明变亮,代码写起来,信手拈来,但是不要以为代码会变乱,因为python的作用域缩进会让代码看上去很清晰,而且,随着水平的提高,你的代码会越写越漂亮,比如一开始你写出的python代码就像是c语言(把列表当数组用),后来,你慢慢会学会更多更聪明的,更高级的东西,轻量级循环,lamp表达式,函数闭包。和一些超好用的标准库。。
之后,你可以去尝试把自己的代码改的越来越短,越来越漂亮。
我觉得有两种练习编程的方式,一种是把程序写大,一种是写小。
关于调试
这又不是什么高深的c语言的系统级程序,要你看内存,就一个‘玩具程序’,但是调试都够你玩的了。
比如一开始的我,没学过什么单步调试。
有一次写了一个C语言程序,发现算法不对,是关于数组的,我就在每次对数组的操作代码后面,加入一行for printf。以打印数组的每一个值,来看看是什么时候出了问题,(像不像自己打印内存?)
再比如一次,是一个绘制长方体的程序,有一根线不对了,但我不知道是哪根不对,就用12种不同的颜色来表示不同的线,来看看是哪里出了问题。
你可能会说,唉,你这个方法不行,要是1000根线是不是要1000种颜色呀?
我之前的做法是对比较少的线的做法,如果是1000根,那我就用2种颜色来表示,这样调试一次就能把一半的线排除,之后再一半,是不是有折半查找的思想?其实这就是“分”的思想,像CDE盘,硬盘分区也是这种思想,这样找东西的时候直接从一个盘入口进,而且如果一个盘坏了,那么其他盘也是可以用的,说到这,你是不是觉得微软的那个称乒乓球面试题就是在调试程序呢?
之所以这样说,是因为工具是死的,人是活的,如果因为自己许多东西没学不敢去做,或者干脆不去学习,那么始终很难进步,编程的乐趣在于能够用代码表达自己的思想,如果你大胆的亲手尝试了,那么多年之后,你在书上读到TDD,读到设计模式,读到《Unix编程艺术》的时候,就不会惊讶,而是共鸣。
下一篇blog谈谈自己设计并实现的一个贪吃蛇类游戏,--水果蛇。
作者:aiqier
博客:http://blog.csdn.net/aiqier627