4子棋程序
规则简单,没有斜线。棋力低还慢,但程序完整、短。Search(博弈树 α-β剪枝 评价函数/局面分)
1 # -*- coding: gbk -*- 2 from functools import reduce 3 from copy import deepcopy 4 5 def get_list(n, v): return list(map(lambda _:deepcopy(v), range(n))) 6 7 B = 'B'; W = 'W'; E = '.' # black, white, empty 8 ltm = [9, 9] # left-top-most 9 10 def init_brd(): 11 global b 12 b = get_list(11, 11 * [E]) 13 b[0] = b[10] = [' '] + list(map(lambda _:str(_), range(1, 10))) + [' '] 14 for i in range(1, 10): b[i][0] = b[i][10] = str(i) 15 16 def print_brd(): # Don't nest reduce it's like n += i 17 for i in range(11): print(reduce(lambda x,y:x+' '+y, b[i], '')) 18 19 class Won(Exception): 20 def __init__(m, n) : m.n = n 21 22 def update_ltm(x, y): # update 23 global ltm 24 x -= 1; y -= 1 25 if x < 1: x = 1 26 if y < 1: y = 1 27 if x < ltm[0]: ltm[0] = x 28 if y < ltm[1]: ltm[1] = y 29 30 def get_longest_run(x, y, dx, dy): # 搜索水平或竖直最长连续串 31 m = [0, 0]; nb = nw = 0; pp = '' # max, n_black, n_white, previous_piece 32 def um(): # update max 33 if nb == 4: raise Won(9) 34 if nw == 4: raise Won(-9) 35 if nb > m[0]: m[0] = nb 36 if nw > m[1]: m[1] = nw 37 def cont(): return pp == '' or pp == p # continuous 38 while True: 39 p = b[y][x] 40 if p == W: 41 if cont(): nw += 1 42 else: um(); nb = 0; nw = 1 43 elif p == B: 44 if cont(): nb += 1 45 else: um(); nb = 1; nw = 0 46 elif p == E: um(); nb = nw = 0 47 else: break 48 x += dx; y += dy; pp = p 49 return m 50 51 def get_score(): # 搜索全盘,不支持对角线 52 try: 53 m = [0, 0] 54 def um(t): 55 if t[0] > m[0]: m[0] = t[0] 56 if t[1] > m[1]: m[1] = t[1] 57 for x in range(1, 10): um(get_longest_run(x, 1, 0, 1)) 58 for y in range(1, 10): um(get_longest_run(1, y, 1, 0)) 59 return m[0] - m[1] # 黑方最长串长度 - 白方 60 except Won as w: return w.n # raised by get_longest_run 61 62 def get_winner(): 63 s = get_score() 64 return '' if s == -9 or s == 9 else None 65 66 def search(ll): # level 67 global best 68 s = []; c = [] # scores, coordinates 69 for y in range(ltm[0], 10): 70 for x in range(ltm[1], 10): 71 if b[y][x] != E: continue 72 b[y][x] = W if ll & 1 else B # 双方交替落子 73 s.append(get_score() if ll > 0 else search(ll + 1)) 74 if ll == 0: c.append((x, y)) 75 b[y][x] = E 76 if ll & 1: return min(s) # 对手走时按最坏情况考虑 77 else: 78 m = max(s) # 自己走时选最好一步 79 if ll != 0: return m 80 for i in range(len(s)): 81 if s[i] != m: continue 82 best = c[i] 83 return 84 raise Won(0) 85 86 def put_piece(x, y, p): b[y][x] = p; update_ltm(x, y) 87 88 def machine_move(): 89 try: 90 search(0) 91 put_piece(best[0], best[1], B) 92 except Exception: quit() 93 94 def human_move(): 95 while 1: 96 try: 97 (x, y) = map(lambda _:int(_), input('Your move (x <no-space> y, 00 to quit) ? ')) 98 if (x, y) == (0, 0): quit() 99 if x < 1 or x > 9 or y < 1 or y > 9 or b[y][x] != E: continue 100 put_piece(x, y, W); break 101 except Exception: pass 102 103 init_brd(); b[5][5] = B 104 while 1: 105 print_brd() 106 if get_winner() != None: break 107 human_move() 108 machine_move()