Python人工智能

一行流

实验一 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()

网络五子棋

题目概述

五子棋是一种两人对弈的纯策略型棋类游戏,通常双方分别使用黑白两色的棋子,轮流下在棋盘直线与横线的交叉点上,先在横线、直线或斜对角线上形成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。

4.1  模块功能说明

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上——始终热爱大地——升上天空。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注