月度归档:2013年01月

随机迷宫生成算法

在线迷宫游戏地址: lbmaze@sae
项目地址: lbmaze@github
最近研究了下迷宫的生成算法,然后做了个简单的在线迷宫游戏。游戏地址和对应的开源项目地址可以通过上面的链接找到。开源项目中没有包含服务端的代码,因为服务端的代码实在太简单了。下面将简单的介绍下随机迷宫的生成算法。一旦理解后你会发现这个算法到底有多简单。

  • 将迷宫地图分成多个房间,每个房间都有四面墙。
  • 让“人”从地图任意一点A出发,开始在迷宫里游荡。从A房间的1/2/3/4个方向中的任选一个方向前进。在从A房间走到B房间的过程中,推倒A/B房间之间的墙。
  • 如果方向x对面的房间已经走过,则选择其他方向。如果所有方向的房间都已经走过,则退回上一个房间看是否还有可选道路。
  • 走到真正无路可走时,说明已经走过了所有房间,迷宫也生成好了。

下面是该算法的python实现(核心部分)

def gen_map(self, max_x=10, max_y=10):
    """ 生成迷宫 """
    self.max_x, self.max_y = max_x, max_y  # 设置地图大小
    self.mmap = [[None for j in range(self.max_y)] for i in range(self.max_x)]  # 生成原始地图
    self.solution = []  # 迷宫解法
    block_stack = [Block(self, 0, 0)]  # 从0,0开始生成迷宫(同时将这点作为起点),将起点放到栈里
    while block_stack:
        block = block_stack.pop()  #取出当前所在的房间
        next_block = block.get_next_block()  # 获取下一个要去的房间
        if next_block:  # 如果成功获取下一走发,将走过的房间放回到栈里
            block_stack.append(block)
            block_stack.append(next_block)
            if next_block.x == self.max_x - 1 and next_block.y == self.max_y - 1:  # 走到终点了,栈里的路径就是解法
                for o in block_stack:
                    self.solution.append((o.x, o.y))
def get_next_block_pos(self, direction):
   """ 获取指定方向的房间号 """
    x = self.x
    y = self.y
    if direction == 0:  # Top
        y -= 1
    elif direction == 1:  # Right
        x += 1
    if direction == 2:  # Bottom
        y += 1
    if direction == 3:  # Left
        x -= 1
    return x, y
def get_next_block(self):
    """ 获取下一要去的房间 """
    directions = list(range(4))
    random.shuffle(directions)  # 随机获取一个要去的方向
    for direction in directions:
        x, y = self.get_next_block_pos(direction)
        if x >= self.mmap.max_x or x < 0 or y >= self.mmap.max_y or y < 0:  # 房间号在许可范围内
            continue
        if self.mmap.mmap[x][y]:  # 如果已经走过
            continue
        self.walls[direction] = False
        return Block(self.mmap, x, y, direction)
    return None  # 没找到有可用的房间

注: 由于采用该方法生成的迷宫道路的分支数量并不是太多,coffeescript版在生成迷宫的过程中增加了随机处理,对应算法也稍微复杂一点点。

Mac初体验

经不住身边苹果迷们的忽悠,入手了个Mac mini。此前一直混用windows、ubuntu,初次使用Mac下倒也没感到什么太多的不适应。如果说真有什么不适应,主要还是一些windows下的软件没有Mac版,或是Mac版的功能要比windows版的简陋很多。
下面推荐些Mac下的软件

  • TotalTerminal
    命令行增强工具。增加多Tab功能,多个配色方案可选。
  • 启用命令行颜色显示
    在linux下不同类型的文件会以不同颜色显示,Mac下没有默认开启该功能。
# 在~/.bash_profile 中增加
export CLICOLOR=1
  • 安装 brew 为Mac增加类似apt-get的功能
  • 下面这个脚本,大家应当都懂的
#!/usr/bin/env bash
while true
do
    ssh -D 7070 -C xx@haoluobo.com
done

to myself

今日之日不可留,奈何多烦忧。只是作为凡人,难免会有些凡人的烦恼。
写下一些NOTE,提醒自己不要迷失。

  • 乐观
    负面的情绪从来都不会起到什么积极的作用。
  • 耐心&宽容
    对自己宽容,对他人宽容。在很多事面前,你是无力的。改变自己所能改变,然后给自己多些宽容,别让自己陷入负面情绪的包围中。
  • 目标
    纷繁的世界太容易让自己迷失,在纷繁的事情面前被其所吸引,被其所恼,渐渐忘了自己是为了什么。在遇到问题时先想想自己的目标是什么,如果无关大局就先放下,不必再被其所恼。
  • 原则
    没有原则也就没有底线,在底线一步步沦落的过程中也将迷失自己。给自己制定一些最基本的原则,在原则范围了行事。

让你的python程序同时兼容python2和python3

python邮件列表里有人发表言论说“python3在10内都无法普及”。在我看来这样的观点有些过于悲观,python3和python2虽然不兼容,但他们之间差别并没很多人想像的那么大。你只需要对自己的代码稍微做些修改就可以很好的同时支持python2和python3的。下面我将简要的介绍一下如何让自己的python代码如何同时支持python2和python3。

  • 放弃python 2.6之前的python版本
    python 2.6之前的python版本缺少一些新特性,会给你的迁移工作带来不少麻烦。如果不是迫不得已还是放弃对之前版本的支持吧。
  • 使用 2to3 工具对代码检查
    2to3是python自带的一个代码转换工具,可以将python2的代码自动转换为python3的代码。当然,不幸的是转换出的代码并没有对python2的兼容做任何的处理。所以我们并不真正使用2to3转换出的代码。执行 2to3 t.py 查看输出信息,并修正相关问题。
  • 使用python -3执行python程序
    2to3 可以检查出很多python2&3的兼容性问题,但也有很多问题是2to3发现不了的。在加上 -3 参数后,程序在运行时会在控制台上将python2和python3不一致,同时2to3无法处理的问题提示出来。比如python3和python2中对除法的处理规则做过改变。使用-3参数执行4/2将提示 DeprecationWarning: classic int division 。
  • from __future__ import
    from __future__ import”后即可使使用python的未来特性了。python的完整future特性可见 __future__ 。python3中所有字符都变成了unicode。在python2中unicode字符在定义时需要在字符前面加 u,但在3中则不需要家u,而且在加u后程序会无法编译通过。为了解决该问题可以 “from future import unicode_literals” ,这样python2中字符的行为将和python3中保持一致,python2中定义普通字符将自动识别为unicode。
  • import问题
    python3中“少”了很多python2的包,在大多情况下这些包之是改了个名字而已。我们可以在import的时候对这些问题进行处理。
try:#python2
    from UserDict import UserDict
    #建议按照python3的名字进行import
    from UserDict import DictMixin as MutableMapping
except ImportError:#python3
    from collections import UserDict
    from collections import MutableMapping
  • 使用python3的方式写程序
    python2中print是关键字,到了python3中print变成了函数。事实上在python2.6中已经带了print函数,所以对print你直接按照2to3中给出的提示改为新写法即可。在python3中对异常的处理做了些变化,这个和print类似,直接按照2to3中的提示修改即可。
  • 检查当前运行的python版本
    有时候你或许必须为python2和python3写不同的代码,你可以用下面的代码检查当前系统的python版本。
import sys
if sys.version > '3':
    PY3 = True
else:
    PY3 = False
  • six
    six 提供了一些简单的工具用来封装 Python 2 和 Python 3 之间的差异性。我并不太推荐使用six。如果不需要支持python2.6之前的python版本,即使不用six也是比较容易处理兼容性问题的。使用six会让你的代码更像python2而不是python3。

python3的普及需要每位pythoner的推动,或许你还无法立即升级到python3,但请现在就开始写兼容python3的代码,并在条件成熟时升级到python3。
注:

将VIM的配置文件切换到janus

janus是一个非常流行的VIM配置脚本,其中集合了很多优秀的VIM插件。
此前我一直都是用自己收集的VIM配置以及插件,到现在之前的某些插件已经出现了更优秀的替代品。索性将janus fork了一份(vicalloy’s janus),针对自己的使用习惯做了少许的定制。
janus具体加载了哪些插件,做了哪些默认配置,大家还是直接去看官方的README吧。
我主要做了下面一些改动:

  • 取消了Tab、空格等不可见字符的提示功能。
  • 取消行号显示。在vim中直接 :num 即可跳转到对应的行,所以我一直感觉行号显示并不是太有用。
  • 关闭supertab插件。这个插件似乎和某些插件有冲突。
  • 增加部分插件
    • FencView 国人写的自动识别文件编码的插件。
    • ZenCoding Zen Coding简单的说就是用css来写html,至于具体怎么用还是去找些Zen Coding的文章来看吧。
    • eclim 将Eclipse的功能集成到vim的插件。其中有很多很好用的vim scripts,比如htmldjango的语法高亮以及缩进处理等。将其中的部分脚本打包到了我的vim配置中。
    • jedi vim的代码补全能力非常的弱。jedi相比来说要强大很多,不过对动态语言来说补全想做到非常智能并不容易。
    • vim-powerline 状态栏定制插件

注:

  • janus并不支持windows系统,如果你需要在windows下使用janus需要自己做些小改动。
  • 加了一堆的插件后VIM的启动速度明显变慢,此前都是秒开,现在要个2~3秒的启动时间。

hello,2013

2012的自己依旧没有做到让自己满意。有人说在30岁之后人会变的越来越自信。希望有一天能做到让自己满意。