一行流
实验一 Python 运算符、内置函数
#1、编写程序,输入任意大的自然数,输出各位数字之和。 print(sum(map(int, input('请输入一个自然数:')))) #2、编写程序,输入两个集合 setA 和 setB,分别输出它们的交集、并集和差集 setA-setB。 (lambda op, x: [print(s, __import__('functools').reduce(f, x)) for s, f in [('交集', op.and_), ('并集', op.or_), ('差集', op.sub)]])(__import__('operator'), [set(input('请输入第{}个集合:'.format(i)).split()) for i in range(2)]) #3、编写程序,输入一个自然数,输出它的二进制、八进制、十六进制表示形式。 [print(s, f(x)) for (s, f), x in zip([('二进制', bin), ('八进制', oct), ('十六进制', hex)], [int(input('请输入一个自然数:'))] * 3)]
实验二 Python程序设计的结构
#1.编写一个程序,其功能为:求1-100之间的奇数之和。 sum(range(1, 101)[::2]) #2、编写一个程序,其功能为:计算并输出一年12个月的总降雨量和平均降雨量。 (lambda x: [print(s, f(x)) for s, f in [('总降雨量', sum), ('平均降雨量', __import__('statistics').mean)]])([float(input('{}月降水量:'.format(i))) for i in range(1, 13)]) #3、编写一个程序,求1+2!+3!+…+20!的和。 sum(map(__import__('math').factorial, range(1, 21)))
实验三 爬楼梯
#假设一段楼梯共 15 个台阶,小明一步最多能上 3 个台阶。编写程序计算小明上这段楼梯一共有多少种方法。要求给出递推法和递归法两种代码。 #递推法 __import__('functools').reduce(lambda s, _: s[1:] + [sum(s)], range(16), [0, 1, 1])[0] #递归法 (lambda f: (lambda x: x(x))(lambda y: f(lambda a: y(y)(a))))(lambda f: lambda n: max(0, n) if n < 2 else sum(map(f, range(n - 3, n))))(16)
实验四 抓狐狸游戏
#编写程序,模拟抓狐狸小游戏。假设一共有一排 5 个洞口,小狐狸最开始的时候在其中一个洞口,然后玩家随机打开一个洞口,如果里面有狐狸就抓到了。如果洞口里没有狐狸就第二天再来抓,但是第二天狐狸会在玩家来抓之前跳到隔壁洞口里。 (lambda rd: (lambda f: (lambda x: x(x))(lambda y: f(lambda *a: y(y)(*a))))(lambda f: lambda pos, select, valid: f(pos, input("invalid value, retry:"), valid) if select not in valid else print("found!") if int(select) - 1 == pos else f((5 + pos + -1 ** rd(1, 2)) % 5, input("not found, retry:"), valid))(rd(0, 4), input("where is fox(1-5):"), list(map(str, range(1, 6)))))(__import__('random').SystemRandom().randint)
实验五 猜数字游戏开发
#使用tkinter开发猜数字游戏,运行效果如下图所示。 #程序运行时,系统生成一个1024以内的随机数,然后提示用户进行猜测并根据用户输入进行必要的提示(猜对了、太大了、太小了),如果猜对则提前结束程序。程序要统计玩家猜的次数,如果次数用完仍没有猜对,提示游戏结束并给出正确答案。 (tk := __import__('tkinter'), done := False, times := [1], target := __import__('random').SystemRandom().randint(1, 1024), root := tk.Tk(), left := tk.Frame(root), right := tk.Frame(root), right_cent := tk.Frame(right), user_input := tk.Entry(right_cent), output := tk.Label(right, text=''), upValue := [1024], downValue := [1], up := tk.Label(left, text=upValue), down := tk.Label(left, text=downValue), valid := list(map(str, range(1, 1025))), submit_func := lambda *_: output.config(text="invalid input") if user_input.get() not in valid else (answer := int(user_input.get()), output.config(text={(v := answer == target): ["猜对了", done := v, user_input.config(state='disabled') if v else None], (v := answer < target): ["太小了", down.config(text=(downValue.append(answer), downValue[-1])[-1]) if v and downValue[-1] < answer else None], (v := answer > target): ["太大了", up.config(text=(upValue.append(answer), upValue[-1])[-1]) if v and upValue[-1] > answer else None], (v := times[-1] > 10 and not done): ["游戏结束,答案是{}".format(target), user_input.config(state='disabled') if v else None]}.get(True)[0]), times.append(times[-1] + 1)), user_input.bind('<Return>', submit_func), up.pack(side='top'), tk.Label(left, text='').pack(side='top'), output.pack(side='top'), user_input.pack(side='left'), tk.Button(right_cent, text='猜', command=submit_func).pack(side='left'), down.pack(side='bottom'), tk.Button(right, text='关闭', command=lambda: root.destroy()).pack(side='bottom'), right_cent.pack(side='top'), left.pack(side='left'), right.pack(side='left'), root.title('猜数字游戏'), root.mainloop())
Hello world
实验一 Python 运算符、内置函数
#1、编写程序,输入任意大的自然数,输出各位数字之和。 print(sum(map(int, input('请输入一个自然数:')))) #2、编写程序,输入两个集合 setA 和 setB,分别输出它们的交集、并集和差集 setA-setB。 a = set(input('请输入第1个集合:').split()) b = set(input('请输入第2个集合:').split()) print('交集', a & b) print('并集', a | b) print('差集', a - b) #3、编写程序,输入一个自然数,输出它的二进制、八进制、十六进制表示形式。 x = int(input('请输入一个自然数:')) print('二进制', bin(x)) print('八进制', oct(x)) print('十六进制', hex(x))
实验二 Python程序设计的结构
#1.编写一个程序,其功能为:求1-100之间的奇数之和。 total = 0 for i in range(1, 101): if i % 2 == 1: total += i print(total) #2、编写一个程序,其功能为:计算并输出一年12个月的总降雨量和平均降雨量。 total = 0 for i in range(1, 13): total += float(input('请输入{}月份的降水量:'.format(i))) print('总降雨量', total) print('平均降雨量', total / 12) #3、编写一个程序,求1+2!+3!+…+20!的和。 total = 0 for i in range(1, 21): fac = 1 for x in range(1, i + 1): fac *= x total += fac print(total)
实验三 爬楼梯
#假设一段楼梯共 15 个台阶,小明一步最多能上 3 个台阶。编写程序计算小明上这段楼梯一共有多少种方法。要求给出递推法和递归法两种代码。 #递推法 p, n, n2 = 0, 1, 1 for i in range(16): p, n, n2 = n, n2, p + n + n2 print(p) #递归法 def fib(x): if x < 2: return max(0, x) return fib(x - 1) + fib(x - 2) + fib(x - 3) print(fib(16))
实验四 抓狐狸游戏
#编写程序,模拟抓狐狸小游戏。假设一共有一排 5 个洞口,小狐狸最开始的时候在其中一个洞口,然后玩家随机打开一个洞口,如果里面有狐狸就抓到了。如果洞口里没有狐狸就第二天再来抓,但是第二天狐狸会在玩家来抓之前跳到隔壁洞口里。 import random target = random.randint(0, 4) while True: try: x = int(input('在哪(1-5):')) if not 1 <= x <= 5: raise ValueError() if x == target + 1: print('抓住') break else: print('没抓住') target = (5 + target + -1 ** random.randint(1, 2)) % 5 except: print('无效值')
实验五 猜数字游戏开发
#使用tkinter开发猜数字游戏,运行效果如下图所示。 #程序运行时,系统生成一个1024以内的随机数,然后提示用户进行猜测并根据用户输入进行必要的提示(猜对了、太大了、太小了),如果猜对则提前结束程序。程序要统计玩家猜的次数,如果次数用完仍没有猜对,提示游戏结束并给出正确答案。 from tkinter import * import random done = False times = 1 target = random.SystemRandom().randint(1, 1024) root = Tk() left = Frame(root) right = Frame(root) right_cent = Frame(right) user_input = Entry(right_cent) output = Label(right, text='') upValue = 1024 downValue = 1 up = Label(left, text=upValue) down = Label(left, text=downValue) def submit_func(*_): try: global times, done, downValue, upValue if done: return answer = int(user_input.get()) if not (1 <= answer <= 1024 and answer % 1 == 0): raise ValueError() if answer == target: output.config(text="猜对了") done = True elif answer < target: output.config(text="太小了") if downValue < answer: downValue = answer down.config(text=answer) else: output.config(text="太大了") if upValue > answer: upValue = answer up.config(text=answer) times += 1 if times > 10: output.config(text="游戏结束,答案是{}".format(target)) done = True except: output.config(text="无效值") user_input.bind('<Return>', submit_func) up.pack(side='top') Label(left, text='').pack(side='top') output.pack(side='top') user_input.pack(side='left') Button(right_cent, text='猜', command=submit_func).pack(side='left') down.pack(side='bottom') Button(right, text='关闭', command=lambda: root.destroy()).pack(side='bottom') right_cent.pack(side='top') left.pack(side='left') right.pack(side='left') root.title('猜数字游戏') root.mainloop()
五子棋
from tkinter import * from math import * from tkinter.messagebox import * from threading import * root = Tk() white = set() black = set() count = 0 lock = Lock() step = 30 board = Canvas(root, bg='white', height=step * 16, width=step * 16) for i in range(15): board.create_line(step + i * step, step, step + i * step, step * 15) for i in range(15): board.create_line(step, step + i * step, step * 15, step + i * step) def judge(player_): for x_, y_ in player_: why = {(x_, y_)} while (x_ + 1, y_) in player_: x_ += 1 why.add((x_, y_)) if len(why) == 5: return why why = {(x_, y_)} while (x_, y_ + 1) in player_: y_ += 1 why.add((x_, y_)) if len(why) == 5: return why why = {(x_, y_)} while (x_ + 1, y_ + 1) in player_: x_ += 1 y_ += 1 why.add((x_, y_)) if len(why) == 5: return why why = {(x_, y_)} while (x_ - 1, y_ + 1) in player_: x_ -= 1 y_ += 1 why.add((x_, y_)) if len(why) == 5: return why return None def board_click(ev): lock.acquire() global count clamp = lambda x: max(1, min(15, x)) pos = clamp(floor(ev.x / step + 1 - 0.5)), clamp(floor(ev.y / step + 1 - 0.5)) if pos not in black and pos not in white: x, y = pos if count & 1 == 1: white.add(pos) color = 'white' flag = judge(white) else: black.add(pos) color = 'black' flag = judge(black) board.create_oval(x * step - step / 2, y * step - step / 2, x * step + step / 2, y * step + step / 2, fill=color) count += 1 if flag is not None: board.unbind('<Button-1>') win = sorted(list(flag)) x0, y0 = win[0] x1, y1 = win[-1] board.create_line(x0 * step, y0 * step, x1 * step, y1 * step, fill='red') showinfo(message=f'{color} win') lock.release() board.bind('<Button-1>', board_click) board.pack() root.mainloop()
五子棋(swap2)
Gomoku.py
from math import * from tkinter.messagebox import * from tkinter.simpledialog import * from threading import * from socket import * import json game_id = 'Gomoku(swap2)' inited = False root = Tk() is_black = False black_white = set() count = 0 swap2 = False lock = Lock() skt = socket(AF_INET, SOCK_DGRAM) user_id = askstring(game_id, 'plz input your id') addr = askstring(game_id, 'plz input server\'s address') def req(data): res = json.dumps({'data': (user_id, data)}) skt.sendto(res.encode('utf-8'), (addr, 27015)) print(req.__name__, res) def recv(): res = json.loads(skt.recvfrom(1024)[0].decode('utf-8')) print(recv.__name__, res) return res['data'] step = 30 board = Canvas(root, bg='white', height=step * 16, width=step * 16) for i in range(15): board.create_line(step + i * step, step, step + i * step, step * 15) for i in range(15): board.create_line(step, step + i * step, step * 15, step + i * step) def update_title(): root.title(f'{game_id} - {addr} - {user_id} - {"black" if is_black else "white"}') def draw_call(x, y): global count lock.acquire() player = count & 1 board.create_oval(x * step - step / 2, y * step - step / 2, x * step + step / 2, y * step + step / 2, fill='white' if player == 1 else 'black') count += 1 lock.release() def init_swap2(): global is_black, swap2, inited resp = recv() if resp == 'cont': swap2 = True for _ in range(2): x, y = recv() draw_call(x, y) res = ask_swap2() req(res) swap2 = False inited = True if res == 'white': is_black = False update_title() else: is_black = True update_title() recv_next() elif resp == 'white': is_black = True update_title() inited = True recv_next() else: inited = True is_black = False update_title() def swap2_comp(): global is_black, inited resp = recv() update_title() if resp == 'black': is_black = False inited = True update_title() else: is_black = True inited = True update_title() recv_next() def recv_next(): re_ = recv() if len(re_) == 7: user, x, y, x0, y0, x1, y1 = re_ board.unbind('<Button-1>') if user != user_id: draw_call(x, y) board.create_line(x0 * step, y0 * step, x1 * step, y1 * step, fill='red') showinfo(message=f'{user} win') else: x, y = re_ draw_call(x, y) def board_click(ev): # lock.acquire() global count, is_black, swap2 clamp = lambda x: max(1, min(15, x)) pos = clamp(floor(ev.x / step + 1 - 0.5)), clamp(floor(ev.y / step + 1 - 0.5)) if pos not in black_white: player = count & 1 if (is_black and count < 3) or (swap2 and not is_black and 3 <= count < 5) or ( inited and is_black and player == 0) or ( inited and not is_black and player == 1): x, y = pos black_white.add(pos) req(pos) if count == 2: if is_black: Thread(target=init_swap2).start() elif swap2 and count == 4: if not is_black: Thread(target=swap2_comp).start() draw_call(x, y) if inited: Thread(target=recv_next).start() # lock.release() def ask_swap(): return {True: 'black', False: 'white', None: 'cont'}[ askyesnocancel('swap', 'yes to black, no to white, cancel to swap2')] def ask_swap2(): return {True: 'black', False: 'white'}[ askyesno('swap', 'yes to black, no to white')] board.bind('<Button-1>', board_click) board.pack() def init(): global is_black, swap2, inited req('join') res = recv() print(res) if res == 'black': is_black = True update_title() else: for _ in range(3): fk = recv() x, y = fk draw_call(x, y) res = ask_swap() req(res) if res == 'black': inited = True is_black = True update_title() recv_next() elif res == 'cont': swap2 = True else: inited = True is_black = False update_title() update_title() Thread(target=init).start() root.mainloop()
GomokuServer.py
from socket import * from threading import * import json import traceback def judge(player_): for x_, y_ in player_: if (x_ - 1, y_) not in player_: why = {(x_, y_)} while (x_ + 1, y_) in player_: x_ += 1 why.add((x_, y_)) if len(why) == 5: if (x_ + 1, y_) not in player_: return why else: break if (x_, y_ - 1) not in player_: why = {(x_, y_)} while (x_, y_ + 1) in player_: y_ += 1 why.add((x_, y_)) if len(why) == 5: if (x_, y_ + 1) not in player_: return why else: break if (x_ - 1, y_ - 1) not in player_: why = {(x_, y_)} while (x_ + 1, y_ + 1) in player_: x_ += 1 y_ += 1 why.add((x_, y_)) if len(why) == 5: if (x_ + 1, y_ + 1) not in player_: return why else: break if (x_ + 1, y_ - 1) not in player_: why = {(x_, y_)} while (x_ - 1, y_ + 1) in player_: x_ -= 1 y_ += 1 why.add((x_, y_)) if len(why) == 5: if (x_ - 1, y_ + 1) not in player_: return why else: break return None inited = False white = set() black = set() count = 0 lock = Lock() users = [] addrs = [] swap = False swap2 = False skt = socket(AF_INET, SOCK_DGRAM) skt.bind((gethostname(), 27015)) while True: rawData, addr = skt.recvfrom(1024) lock.acquire() def resp(data_, addr_=addr): res = json.dumps({'data': data_}) skt.sendto(res.encode('utf-8'), addr_) print(resp.__name__, addr_, res) try: jsonData = json.loads(rawData.decode('utf-8')) print(addr, jsonData) user, data = jsonData['data'] if len(users) < 2: if data == 'join': users.append(user) addrs.append(addr) resp('black' if len(users) == 1 else 'white') elif user not in users: raise ValueError() elif swap: if data == 'white' or data == 'black': resp(data, addrs[1] if swap2 else addrs[0]) if swap2: if data == 'white': users.reverse() addrs.reverse() else: if data == 'black': users.reverse() addrs.reverse() swap = False swap2 = False inited = True elif data == 'cont' and not swap2: resp(data, addrs[0]) swap = False swap2 = True else: raise ValueError() count += 1 else: data_ = data[0], data[1] if data_ not in black and data_ not in white: x, y = data_ player = count & 1 if (inited and user == users[(player + 1) % 2]) \ or (count < 3 and user != users[0]) \ or (not inited and 3 <= count < 5 and user != users[1]): raise ValueError() else: (white if player == 1 else black).add(data_) flag = judge(white if player == 1 else black) if count == 2 or (swap2 and count == 4): swap = True else: count += 1 if flag is not None: win = sorted(list(flag)) x0, y0 = win[0] x1, y1 = win[-1] for addr_ in addrs: resp((user, x, y, x0, y0, x1, y1), addr_) inited = False white = set() black = set() count = 0 users = [] addrs = [] swap = False swap2 = False else: if count < 3: dest = addrs[1] elif count < 5: dest = addrs[0] else: dest = addrs[(player + 1) % 2] resp(data, dest) except UnicodeDecodeError: pass except: traceback.print_exc() finally: lock.release()
网络五子棋
1 题目概述
五子棋是一种两人对弈的纯策略型棋类游戏,通常双方分别使用黑白两色的棋子,轮流下在棋盘直线与横线的交叉点上,先在横线、直线或斜对角线上形成5子连线者获胜。因为棋子在落子后不能移动或拿掉,所以也可以用纸和笔来进行游戏。
2 设计目的
实现现代五子棋(Swap2规则)。
假先方在棋盘任意下三手(二黑一白)假后方有三种选择。
1.选黑。
2.选白。
3.下四、五两手(一黑一白)再假先方选择黑或白。
此后按Standard Gomoku规则继续进行。
Standard Gomoku规则:
黑子先行,黑白双方轮流落子。
首先在横、竖、斜方向上成五(连续五个己方棋子)者为胜。
3 总体设计
4 详细设计
包括Gomoku和GomokuServer。
Gomoku有req, recv, update_title, draw_call, init_swap2, swap2_comp, recv_next, board_click, ask_swap, ask_swap2, init。
GomokuServer有judge。
def req(data: Any) -> None
向服务器发送数据,以JSON封装,采用UTF-8
def recv() -> Any
接受服务器JSON数据,并返回data的值
def update_title() -> None
修改窗口标题
def draw_call(x: {__mul__}, y: {__mul__}) -> None
线程安全,绘制一个棋子,并且步数加一
def init_swap2() -> None
假先手的swap2
def swap2_comp() -> None
假后手的swap2
def recv_next() -> None
接受下一步并处理
def board_click(ev: {x, y}) -> None
处理鼠标点击输入事件,钳位,验证,并处理
def ask_swap() -> str
获取用户swap的选择
def ask_swap2() -> str
获取用户swap2的选择
def init() -> None
初始化swap
def judge(player_: {__iter__}) -> Optional[Set[Tuple[Any, Any]]]
判断胜负
4.2 模块流程图
5 执行结果
输入用户名
输入服务器ip
Swap
Swap2
获胜界面
结论与心得
现代Python以大卫·韦勒的“任何计算机科学领域的问题都能通过增加一个间接层来解决。然而这通常会带来其他问题。”为嚆矢。滥觞于哲学与数学的期望正失去它们的借鉴意义。但面对看似无垠的未来天空,我想循林纳斯·托瓦兹“技术标准就是纸。我每天都用纸擦屁股。这就是这些纸的价值所在。”好过过早地振翮。
我们怀揣热忱的灵魂天然被赋予对超越性的追求,不屑于古旧坐标的约束,钟情于在别处的芬芳。但当这种期望流于对逻辑主义不假思索的批判,乃至走向直觉与构造主义时,便值得警惕了。与秩序的落差、错位向来不能为越矩的行为张本。而纵然我们已有翔实的蓝图,仍不能自持已在浪潮之巅立下了自己的沉锚。
“好的代码本身就是最好的文档。当你打算加注释的时候,问问自己’我如何改善代码以至于不需要注释?’”史蒂夫·迈克康奈尔之言可谓切中了肯綮。人的离散性是不可祓除的,而我们欲上青云也无时无刻不在因风借力。数学与哲学暂且被我们把握为一个薄脊的符号客体,一定程度上是因为我们尚缺乏体验与阅历去支撑自己的认知。而这种偏见的傲慢更远在知性的傲慢之上。
在孜孜矻矻以求Python意义的道路上,对自己的期望本就是在与数学与哲学对接中塑型的动态过程。而我们的底料便是对不同最大流最小割定理、不同最近公共祖先的觉感与体认。西恩·帕伦特为马丁·福勒送去P=NP猜想,又维系哈密顿通路的证明。他的Python观念是厚实的,也是实践的。倘若我们在对过往借林纳斯·托瓦兹之言“祓魅”后,又对不断膨胀的自我进行“赋魅”,那么在丢失外界预期的同时,未尝也不是丢了自我。
毫无疑问,从哲学与数学角度一觇的自我有偏狭过时的成分。但我们所应摒弃的不是对此的批判,而是其批判的廉价,其对批判投诚中的反智倾向。在林纳斯·托瓦兹的观念中,如果在成为狮子与孩子之前,略去了像骆驼一样背负前人遗产的过程,那其“永远重复”洵不能成立。
蓝图上的落差终归只是理念上的区分,在实践场域的分野也未必明晰。譬如当我们追寻网络流时,在途中涉足轮廓动态规划,这究竟是伴随着期望的泯灭还是期望的达成?在我们塑造Python的同时,Python也在浇铸我们。既不可否认原生的有限性与无后效性,又承认自己的图景有轻狂的失真,不妨让体验走在言语之前。用不被禁锢的头脑去体味艾伦·J·佩利的大海与风帆,并效尼尔·福特,对无法言说之事保持沉默。
用在Python上的生活方式体现个体的超越性,保持婞直却又不拘泥于所谓“遗世独立”的单向度形象。这便是林纳斯·托瓦兹为我们提供的理想期望范式。生活在Python上——始终热爱大地——升上天空。