Skip to content

Latest commit

 

History

History
139 lines (110 loc) · 4.19 KB

emacs-chess-cn.org

File metadata and controls

139 lines (110 loc) · 4.19 KB

请输入文章标题

设计

展示层

功能

  • 绘制/更新字符界面
  • 棋盘坐标与buffer坐标互相转换

棋局字符总数 1395 共28行,每行理应50个字符,总共32个棋子,每个棋子由于一个汉字占两个字符位置引起少一个字符,然后有27个换行(最后无换行),所以总数 28x50-32+27=1395 每一行字符数,共28行 (41 50 50 50 50 50 48 50 50 45 50 50 50 50 50 50 50 50 45 50 50 48 50 50 50 50 50 41) (1-41, 42换行) 车马相士帅士相马车 (43-92, 93 换行) (94-143, 144 换行) (145-194, 195 换行) 九宫格腰线 (196-245, 246 换行) (247-296, 297 换行) (298-345, 346 换行) 双炮,九宫格顶横线 (347-396, 397换行) (398-447, 448 换行) (449-493, 494 换行) 五卒 (495-544, 545 换行) (546-595, 596 换行) (597-646, 647 换行) 界线 (648-697, 698 换行) 楚河 (699-748, 749 换行) 汉界 (750-799, 800 换行) 界线 (801-850, 851 换行) (852-901, 902 换行) (903-947, 948 换行) 五兵 (949-998, 999 换行) (1000-1049, 1050 换行) (1051-1098, 1099 换行) 双炮 (1100-1149, 1150 换行) (1151-1200, 1201 换行) (1202-1251, 1252 换行) 九宫格腰线 (1253-1302, 1303 换行) (1304-1353, 1354 换行) (1355-1395, 无换行)

(read-only-mode 1) 启用只读模式 (read-only-mode -1) 禁用只读模式

buffer 坐标与棋盘坐标转换,buffer 索引从1开始,棋盘起止位置使用 marker 进行标记.

(defun get-board-pos (pos situation)
  (0 . 0))
  
(defun get-buffer-pos (board-pos situation)
  1)

内核层

走子/吃子规则

每个兵种有其基本走法,即棋子本身的走法,无关棋局

(defun move-rule-base (oldpos dstops)
 t/nil)   

棋局走法即与棋局有关的走法限制,包括最基本的不能走到棋盘外,此外最重要的走法限制,如马绊腿、象填心、卒不能后退且过河后可以横走、车炮直线被挡不能跳跃移动之类,士象不能过河,士和将帅不能离开九宫格,将帅不可见面.

(defun move-rule (oldpos dstops curt-situation)
  (unless (move-rule-base oldpos dstops)
    nil)
 t/nil)

除炮外的所有兵种,其吃子规则与走子规则相同,移动目标位置上有对方棋子即可以吃子,只有炮例外. 只能吃掉对方的棋子,不可吃掉己方棋子. 每次吃子后要判断胜负是否已分,通过被吃棋子是否为将帅进行判断.

(defun eat-rule (oldpos dstpos curt-situation)
 t/nil)

通过移动时的目标位置上是否有对方棋子来判断是走子还是吃子. 吃子时,除炮外,先判断移动规则是否满足,炮单独判定,如果是走子,则判断移动规则.

胜负判断,吃掉对方将帅判赢.

兵种(chess-piece-type)

((name . (蓝方名称 红方名称)) (走子规则 . 规则函数) (吃子规则 . 规则函数) (是否统帅 . t/nil))

棋子(chess-piece)

((兵种 . xx) (阵营 . xx) (棋盘坐标 . (x . y))) 其它状态包括

棋局(chess-situation)

棋子的二维10x9矩阵 ( (棋子1 棋子2 … 棋子9) …)

操作方法

全局数据

  • 走子方列表,先手两方均可,因此初始化为 (side-blue side-red),以后只能有一个.
  • 被选择子,移动/吃子时使用,存储当前操作的棋子坐标.

操作: 光标移到棋盘上任意位置,按下 Enter 键,此时逻辑:

初始允许走子方为双方 if (当前已选择棋子非空) { if (光标处有棋子) { if (光标处为允许走子方) { // 重新选子 } else { // 吃子,重置已选择子, 更新允许走子方为另一方 } } else { // 移动走子,重置已选择棋子,并更新允许走子方为另一方 } } else { if (光标处有棋子) { if (光标处棋子为允许走子方) { // 选子,更新允许走子方为光标处棋子所属方(应付第一步棋) } else { // 无效走子 } } else { // 无效走子 } }