雪星实验室

Python 控制台交互练习

几个 Python 控制台交互练习

用 python 写了个3D旋转三角形

先上效果图!

然后是代码!

import random
# import numpy as np # 
import math
import os
import time
os.system("title welcome to 3D try of snowstar.")
# 今天来做一个 显示 #D 图形的实验
# 好的开始!

# 首先,构造一个三维空间
# ↑ 没错,构造完了

# 给刚才构造的物体连一连线,这样会比较直观一点!
def makePointsFromLine(pointA, pointB):
    t = 0
    step = 1
    points = []

    # 嗯,教科书式的求两点距离公式
    pointDistance = math.sqrt(
        (pointB[0] - pointA[0]) ** 2 +
        (pointB[1] - pointA[1]) ** 2 +
        (pointB[2] - pointA[2]) ** 2 )

    # 百分比步伐。。。这里x0.9的意思是步子小一点点,让点稍微密一点点(当然也会更慢)
    percentStep = (1.0 / pointDistance) * 0.9

    # 基本上就是把这条线切成好多个点,每个点的距离是这条线的 百分之 percent    
    percent = 0
    while percent <= 1:
        x = int(round(pointA[0] + percent * (pointB[0] - pointA[0])))  
        y = int(round(pointA[1] + percent * (pointB[1] - pointA[1])))
        z = int(round(pointA[2] + percent * (pointB[2] - pointA[2])))
        points.append([x, y, z])

        percent += percentStep

    return points

# 我发誓这是我取过的最长的函数名了。。。2016年8月29日17:41:08
def makePointsFromLinesFromPointsToPoints(dongXi):
    pointsFromLines = []
    len = dongXi.__len__()
    for a in range(len):
        for b in range(a + 1, len):
            pointA = dongXi[a]
            pointB = dongXi[b]
            pointsFromLines += makePointsFromLine(pointA, pointB)

    return pointsFromLines


# 嗯好了,来画一个屏幕
w = 59
h = 26

# 这个就是被拍扁的z轴了(看不懂跳过,先看下面
zlist = []

# 用不同的符号表示远近,越粗的越近,模拟近大远小
zsign = ["@@", "88", "OO", ";;","::", "..", " ."]
zsignlen = zsign.__len__()

# 这个函数决定屏幕上的某点显示什么鬼,是整个程序中最核心的部分
def posChar(x, y):
    global zlist
    global zlistlen
    global zsign
    global zsignlen
    global points
    global points2D
    i = 0

    if [x, y] not in points2D: # 去掉那些没有点的地方
        return "  "

    for z in zlist: # 按z轴 从大到小询问,这里有没有人啊!!有没有啊!!
        if [x, y, z] in points: # 如果有的话!!就印出来啦!!
            return zsign[ int(i * zsignlen / zlistlen) ]
        i += 1 # 嗯, i变大的时候,zsign 的图画就会变小了

    return "XX" # 理论上这条不会被运行到,不过。。。万一我蠢呢!!!


# 这个函数是去除重复的点用的
def removeDupes(seq):
    checked = []
    for e in seq:
        if e not in checked:
            checked.append(e)
    return checked

def perpareForPoints():
    # 给上面的那个奇怪的形状,画成线,然后得到一堆点
    global points
    global zlist
    global zlistlen
    global points
    global points2D
    points   = [[int(round(v)) for v in point] for point in pointSource]
    # 画完之后是一堆3D空间上的点,把Z轴拍扁,变成2D空间点集
    points2D = [point[0:2] for point in points]
    # 接下来要抠掉多余的因为拍扁而 叠在一起的2D的点,每个位置留一个就够啦
    points2D = removeDupes(points2D)
    # 聪明的你已经发现。。上面2步只用1行就可以完成...

    # 然后把那个3D的点集排成一个z轴,让它分一分前后
    zlist = [point[2] for point in points]
    zlist.sort(reverse=True) # 从大到小排,大的在前面
    zlistlen = zlist.__len__()

def draw():
    
    # 开始渲染!!
    buf = []
    buf.append("="*45+"welcome to 3D try of snowstar."+"="*44)
    for y in range(-int(h/2), h-int(h/2)):
        # 这么要紧的地方怎么可以没有注释呢!!!!嗯有了
        buf.append("".join([ posChar(x, y) for x in range(-int(w/2), w-int(w/2))] ) + " ")
    buf.append("="*45+"welcome to 3D try of snowstar."+"="*44)

    # 打到屏幕上
    os.system("cls")
    print("\n".join(buf))
    time.sleep( 1.0/61 ) # 设定为 60 fps


# 定义几个矩阵计算用的函数

# 别问我为什么不用numpy.....
# 因为。。。。我要用这东西教小盆友的啊!
# 这样我就不用再教人家装numpy啦!!!(好像更麻烦了呢

def 转置矩阵(矩阵):
    len = 矩阵[0].__len__()
    输出矩阵 = []
    for i in range(len):
        输出矩阵.append([行向量[i] for 行向量 in 矩阵]) 
    return 输出矩阵
 
def 向量点积向量(向量A, 向量B):
    if len(向量A) != len(向量B):
        raise("雪星你又蠢啦两向量点积长度必须相同才行")

    结果 = 0

    for i in range(len(向量A)):
        结果 += 向量A[i] * 向量B[i]

    return 结果 

def 向量点积矩阵(向量A, 矩阵B):
    输出向量 = []
    for 行向量 in 转置矩阵(矩阵B):
        输出向量.append( 向量点积向量(向量A, 行向量) )

    return 输出向量

def 矩阵点积矩阵(矩阵A, 矩阵B):
    输出矩阵 = []
    for 行向量 in 矩阵A:
        输出矩阵.append( 向量点积矩阵(行向量, 矩阵B) )

    return 输出矩阵


# 旋转函数
def rotating():
    global wuti
    global pointSource

    theta = 0.05 # 不懂是多少度总之能转起来就行啦
    
    # 这是一个普通的2D旋转矩阵,直接查 wiki 就可以啦
    a, b = math.cos(theta), -math.sin(theta)
    c, d = math.sin(theta),  math.cos(theta)

    # 把y轴方向固定下来,不让它转,让其它轴绕着它转
    rotateMatrix = [[a, 0, b],
                    [0, 1, 0],
                    [c, 0, d]]
    # 怎么转呢?直接点积啦
    wuti = 矩阵点积矩阵(wuti, rotateMatrix)

    # 不够过瘾? 再加个X轴! 以 1/4 的几率旋转,那么它就会得到一个浮动的效果。。。
    if random.random() <= 1/4 and (int(time.time()) % 60) < 20: 
        # 把x轴方向固定下来,不让它转,让其它轴绕着它转
        rotateMatrix = [[1, 0, 0],
                        [0, a, b],
                        [0, c, d]]
        # 怎么转呢?直接点积啦
        wuti = 矩阵点积矩阵(wuti, rotateMatrix)

    pointSource = makePointsFromLinesFromPointsToPoints(wuti)




# 接下来构造一个三维物体,比如说……
# 三棱锥!  P-ABC !!
# 大概长这样
# *-------*
# \\   //
#  \\ //
#   \ * /
#    \|/
#     *
wuti = [
    [-10, -10, -10], # 点A
    [ 10, -10, -10], # 点B
    [  0,  10, -10], # 点C
    [  0,   0,  10], # 点P
]


# 来初始化一下,第一个图形!
pointSource = makePointsFromLinesFromPointsToPoints(wuti)
perpareForPoints()

# 运行啦!!!!
fps = 0
t = time.time()
while(True):
    draw()
    rotating()
    perpareForPoints()

    dt = time.time() - t
    t  += dt
    os.system("title " + "fts: %d" % (1 / dt))

Python 控制台打印函数图像

效果如图 2020 06 27 11 45 12

Python 代码如下,运行环境windows

# 让控制台使用 UTF-8 编码
import os; os.system("chcp 65001 & cls")

import math
import random
def plot(f):
    print("="*89)
    print("现在打印的是", f, "的函数图象")
    
    # 打印范围 x 为正负 20
    w = int(40 / 2)
    # 生成点集
    arrPos = [[x, round(f(x))] for x in range(-w, w+1)]
    
    # 生成y坐标集
    rangelist = [x[1] for x in arrPos]

    for y in range(max(rangelist), min(rangelist)-1,-1):
         print("".join([(
             ([x, y] in arrPos and y == 0 and "-*") or
             [x, y] in arrPos and " *" or
             x == 0 and y == 0 and "-|" or
             x == 0 and " |" or
             y == 0 and "--" or
             "  "
         ) for x in range(-w,w)]))

plot(lambda x: 
    ((15**2) - x ** 2 >= 0) and math.sqrt((15**2) - x ** 2) * random.choice([1,-1])
)
input()

Python 50 行代码写个贪吃蛇

50行python代码写个贪吃蛇

别问我为什么这么无聊,我只是想告诉一个小朋友。。。贪吃蛇真的不需要用150行来写 上图

2020 06 27 11 47 50 嗯,代码

import random
import msvcrt # 读取键盘要用
import os; os.system("chcp 65001 & cls") # 设定控制台编码为UTF8
w, h  = 30, 15 # 沙盘大小设定

directions = {72:[0,-1],77:[1,0],80:[0,1],75:[-1,0]} # 四个方向,用方向键低位编号表示
headpos = [random.randint(0, w-1), random.randint(0, h-1)] # 头部位置
headdpos = directions[random.choice([72,77,80,75])] # 头部位置的变化,相当于头部方向
snake = [headpos] #蛇身,其实就是一堆坐标
foods = [] #食物
def posChar(pos): #决定某个坐标显示的东西
    return ((pos in snake and "*") or 
            (pos in foods and "%") or " " )

def printSnake():
    outputs = []
    outputs.append("欢迎来到雪星实验室 - 贪吃蛇 ================================")
    for y in range(h):
        outputs.append("|" + " ".join([ posChar([x, y]) for x in range(w)] ) + " |")
    outputs.append("欢迎来到雪星实验室 - 贪吃蛇 ================================")

    os.system("cls")
    print("\n".join(outputs))

def go():
    global headdpos
    global headpos
    if random.random() < 0.1 or foods.__len__() == 0:
        foods.append([random.randint(0, w-1), random.randint(0, h-1)])
    printSnake() #先打印当前地图
    userkey = msvcrt.getch() == b'\xe0' and msvcrt.getch() or " " # 等待用户按键
    headdpos = directions.get(ord(userkey), headdpos) # 根据按键设定方向
    headpos = [x+y for x, y in zip(headpos, headdpos)] # 坐标相加
    snake.insert(0, headpos) # 向头部前进一个位置
    if headpos in foods: # 如果吃到了食物
        foods.remove(headpos) # 就移除这个食物
    else: #如果没东西吃
        snake.pop() # 那蛇尾就没掉了

def liveQ():
    return  ((headpos[0] in range(w) and headpos[1] in range(h)) # 没撞墙
             and (not headpos in snake[2:]  ) ) # 也没撞自己

while(liveQ()):
    go()

print("大侠请重新来过 ..................")
input()

Snowstar Miao
Snowstar Miao.