实现华容道

来源:互联网 发布:手机网络提速方法 编辑:程序博客网 时间:2024/04/27 14:45

第一次改代码

看到文章  http://coolshell.cn/articles/10476.html

文章对应代码在: https://github.com/chenshuo/recipes/blob/master/puzzle/huarong.cc


学习C++, 也自己实现一个华容道。 脑袋一拍就出来下面的代码

class chessboard;class chess;class chess {public:  virtual void to_right (chessboard &board) = 0;  virtual void to_left (chessboard &board) = 0;  virtual void to_up (chessboard &board) = 0;  virtual void to_down (chessboard &board) = 0;protected:  int x_;  int y_;  int width_;  int height_;};enum direction {  up, down, right, left};class chessboard {public:  virtual void move (chess &c, const direction &d) = 0;};


第二次改代码

接口不好用, 尤其是main 函数中, 根本不能用。 考虑不够周全, 只考虑了对象(棋子和棋盘)的交互。 没有关注 棋子的集合, 棋盘的集合等等。

在写main 函数的时候, 不停的改接口, 直到面目全非。 

回过头来,看main 函数发现只需要知道

1)初始化棋盘: 把每个棋子放到棋盘的某个位子

2)棋盘的状态(棋盘上棋子的分布位子), 并把这些状态放到std容器中 (实现需要)

3) 当前状态走一步后所有的有效状态

4)如何有效的区分这个状态是否已经出现过。

5) 不喜欢enum 里有 Shape:kInvalid 这个。 能了个类型的继承来, 不知道是否有效? 

6) unordered_set 一直编译不过, 看下文档说需要 定义对应类型的 std::hash, std:equal_to

而上下左右的移动, 和怎么表示棋子在棋盘上(主要用与移动是否有效), main 函数是不需要知道的。 对应的代码是

enum direction {  up, down, right, left};struct board_map {  int board_[max_row][max_col];};

另外: 代码还不能正常工作, 需要增加 chessboard.is_solved (曹操是否已经跑了)& can_move_steps (去所有有效的下一步) 函数


第三次修改

实现了部分功能。
由于chess 的继承,以及需要shared_ptr 中申请新的chess 初始化新的棋盘, 太麻烦了, 决定不要了。
  加了chess_id 放棋子的信息, 方便多了。
 实现棋子移动, 很多代码, 实现也很容易出错。 



第四次修改


经过调试, 用string 代替 board_mask 类型终于跑出结果。 想想很容易的事情, 自己写也很累。 
运行的很慢。 和参考文档中“耗时约几十毫秒”, 不是一个数量级的。 
文档中的代码运行time ./a.out sizeof(Mask) = 20, sizeof(State) = 124found solution with 116 stepsreal0m0.026suser0m0.024ssys0m0.000s我写的 time ./BFS_huarongdao >/dev/null 2>&1real13m30.522suser12m59.717ssys0m30.474s


终于能跑出正确结果了。


正确跑后 第1次修改 目标跑的快的, 在1分钟内吧, 不然没耐心了。 

统计下尝试移动的步骤: 我的程序有 10804822次。 参考程序需要 24027 次。 先从这里入手。 可能原因: seen 判断是否重复有问题。 

查到问题所在, 用宽高位置表示没有问题, 棋子的顺序,影响棋盘的mask, 程序会认为当前局面没 有出现过。 

排序棋子后, 24050次完成查找。 用时也在3秒多
$ time ./BFS_huarongdao >b 2>&1real0m3.116suser0m2.220ssys0m0.884s

优化性能, 工具gprof

1) 用unordered_set 代替 set。 效果不明显。 可能在数据量小 , 24K数据。
2) 用gprof 测试性能。 从结果上看, 我包的结构体和类有搜索结果外太多的信息
3) 简化数据结构后, 能在1秒内完成
real0m0.961suser0m0.952ssys0m0.008s

4) 用vector 代替 deque后放chess后
real0m0.216suser0m0.212ssys0m0.000s

5) 修改用 uint8_t 表示 chess_id, point 后, 
$ time ./BFS_huarongdao real0m0.035suser0m0.032ssys0m0.004s



代码  https://github.com/linjing/some-real-codes/tree/master/HuaRongDao/src
原创粉丝点击