实现华容道

第一次改代码

看到文章  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) = 124
found solution with 116 steps

real	0m0.026s
user	0m0.024s
sys	0m0.000s


我写的
 time ./BFS_huarongdao >/dev/null 2>&1

real	13m30.522s
user	12m59.717s
sys	0m30.474s


终于能跑出正确结果了。

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

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

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

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

real	0m3.116s
user	0m2.220s
sys	0m0.884s

优化性能, 工具gprof

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

4) 用vector 代替 deque后放chess后
real	0m0.216s
user	0m0.212s
sys	0m0.000s

5) 修改用 uint8_t 表示 chess_id, point 后, 
$ time ./BFS_huarongdao 

real	0m0.035s
user	0m0.032s
sys	0m0.004s



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值