Python程序设计(第三版)课后题答案 第四章 [约翰·策勒 (著) 人民邮电出版社]

Python程序设计(第三版)课后题答案 第四章

编程练习题

  • 1.修改程序,是它做到:
    a.绘制正方形而不是圆形。
    b.每次连续点击在屏幕上绘制一个额外的方块(而不是移动已有的方块)。
    c.循环之后在窗口上打印消息“Click again to quit”,等待最后一次点击,然后关闭窗口。

答案
程序思路:给出的程序已经能够绘制圆形,而且随着鼠标点击圆形会随之移动。先将图形窗口的单位由像素设置为较为方便的数值,更改程序使用矩形函数绘制一个长度为10(数值可以自由设置)的正方形;在for循环内依次获得鼠标点击位置的坐标,然后计算图形的对角点的坐标,并绘制和修饰图形。结束循环后生成文本显示信息,再次获取点击后退出程序。

from graphics import *


def main():  # 循环点击绘制方块
    win = GraphWin("Rectangle", 600, 600)
    win.setCoords(0.0, 0.0, 100.0, 100.0)  # 将图像坐标统一为宽窄为100的方块
    shape = Rectangle(Point(50, 50), Point(60, 60))  # 绘制方块的边长为10
    shape.setOutline("red")
    shape.setFill("red")
    shape.draw(win)

    for i in range(10):
        p = win.getMouse()
        x1 = p.getX() - 5   # 计算新的位置的方块的对角坐标
        x2 = p.getX() + 5
        y1 = p.getY() - 5
        y2 = p.getY() + 5
        shape = Rectangle(Point(x1, y1), Point(x2, y2))
        shape.setOutline("red")
        shape.setFill("red")
        shape.draw(win)
    t = Text(Point(50, 80), "Click again to quit!")
    t.setSize(20)
    t.setFace("courier")
    t.setStyle("bold")
    t.setTextColor("black")
    t.draw(win)
    win.getMouse()


main()

输出:
图片描述

  • 2.箭靶的中心圆为黄色,围绕着红色、蓝色、黑色和白色的同心环。每个环具有相同的宽度,与黄色圆的半径相同。编写一个绘制这种箭靶的程序。(提示:稍后绘制的对象将出现在先前绘制的对象的上面。)

答案
程序思路:程序思路较为简单,使用圆形函数生成圆心相同,半径依次递增的函数。需要注意的是要先打印最大的底层圆,否则会被后面的圆覆盖。

def main():  # 绘制同心环箭靶
    win = GraphWin("箭靶", 600, 600)
    win.setCoords(0.0, 0.0, 100.0, 100.0)  # 将图像坐标统一为宽窄为100的方块
    shape = Circle(Point(50, 50), 25)  # 绘制最外侧圆
    shape.setOutline("white")
    shape.setFill("white")
    shape.draw(win)

    shape = Circle(Point(50, 50), 20)  # 绘制第四层圆
    shape.setOutline("black")
    shape.setFill("black")
    shape.draw(win)

    shape = Circle(Point(50, 50), 15)  # 绘制第三层圆
    shape.setOutline("blue")
    shape.setFill("blue")
    shape.draw(win)

    shape = Circle(Point(50, 50), 10)  # 绘制第二层圆
    shape.setOutline("red")
    shape.setFill("red")
    shape.draw(win)

    shape = Circle(Point(50, 50), 5)  # 绘制最中心圆
    shape.setOutline("yellow")
    shape.setFill("yellow")
    shape.draw(win)

    win.getMouse()


main()

输出:
图片描述

  • 3.编写一个绘制某种面孔的程序。

答案
程序思路:这个程序的难易程度取决于你设计的面孔的复杂程度。这里仅展示最简单的情况,利用圆形、矩形配合不同的填充颜色生成简单的面孔。注意要计算好每个图形的点的坐标。

def main():  # 绘制简单面孔
    win = GraphWin("面孔", 600, 600)
    win.setCoords(0.0, 0.0, 100.0, 100.0)  # 将图像坐标统一为宽窄为100的方块
    win.setBackground("white")

    # 绘制脸
    face = Circle(Point(50, 50), 25)
    face.setFill("peachpuff")
    face.draw(win)

    # 绘制左眼
    eye_left = Circle(Point(40, 55), 3)
    eye_left.setFill("white")
    eye_left.draw(win)

    # 绘制右眼
    eye_right = Circle(Point(60, 55), 3)
    eye_right.setFill("white")
    eye_right.draw(win)

    # 绘制鼻子
    nose = Rectangle(Point(48, 42), Point(52, 45))
    nose.setFill("black")
    nose.draw(win)

    # 绘制嘴巴
    mouth = Rectangle(Point(47, 32), Point(53, 34))
    mouth.setFill("red")
    mouth.draw(win)

    win.getMouse()
    win.close()


main()

输出:
图片描述

  • 4.编写一个用圣诞树和雪人绘制冬季场景的程序。
    答案
    程序思路:这个程序主要有两个元素,分别编写两个函数来生成雪人和圣诞树。雪人snowman函数,主要利用圆形表示头部、身体、眼睛等部位,用矩形表示鼻子,嘴巴等位置,填充适当色彩。圣诞树christmas_tree函数主要是利用循环生成大小递减的三角形表示树的树冠,三角形主要利用Polygon函数实现,再绘制一个短的矩形表示树的树干,顶部再加一个五角星用以装饰。再对窗口整体加以修饰,填充一个你喜欢的颜色。
def snowman(win, x, y):
    # 绘制头部
    head = Circle(Point(x, y), 7)
    head.setFill("white")
    head.draw(win)

    # 绘制身体
    body = Oval(Point(x - 15, y - 38), Point(x + 15, y - 7))
    body.setFill("white")
    body.draw(win)

    sign1 = Circle(Point(x, y - 9), 0.8)
    sign1.setFill("red")
    sign1.draw(win)

    sign2 = Circle(Point(x, y - 11), 0.8)
    sign2.setFill("green")
    sign2.draw(win)

    sign3 = Circle(Point(x, y - 13), 0.8)
    sign3.setFill("yellow")
    sign3.draw(win)

    # 绘制左眼
    eye_left = Circle(Point(x - 3, y + 2), 1)
    eye_left.setFill("white")
    eye_left.draw(win)
    eye_leftq = Circle(Point(x - 3, y + 2), 0.1)
    eye_leftq.setFill("black")
    eye_leftq.draw(win)

    # 绘制右眼
    eye_right = Circle(Point(x + 3, y + 2), 1)
    eye_right.setFill("white")
    eye_right.draw(win)
    eye_rightq = Circle(Point(x + 3, y + 2), 0.1)
    eye_rightq.setFill("black")
    eye_rightq.draw(win)
    # 绘制鼻子
    nose = Rectangle(Point(x - 0.5, y - 0.8), Point(x + 0.5, y + 0.2))
    nose.setFill("black")
    nose.draw(win)

    # 绘制嘴巴
    mouth = Rectangle(Point(x - 1.5, y - 4), Point(x + 1.5, y - 2))
    mouth.setFill(color_rgb(255, 100, 100))
    mouth.draw(win)

    # 添加祝福文本
    t = Text(Point(x+2, y - 25), "圣诞节快乐!")
    t.setFill(color_rgb(200, 100, 150))
    t.setSize(15)
    t.setStyle("bold")
    t.draw(win)


def christmas_tree(win, x, y, height):
    # 绘制树干
    trunk = Rectangle(Point(x - 1.5, y), Point(x + 1.5, y + 15))
    trunk.setFill("brown")
    trunk.draw(win)

    # 绘制树冠的每一层
    bottom = Point(x, y + 15)
    for i in range(height // 10, 0, -1):  # 根据输入的不同高度设计圣诞树的层数,模10取整
        top_left = Point(x - i**1.5, bottom.getY())  # 让前一个三角形的顶点高度作为下一个三角形的底的高度,三角形的底边宽度递减
        top_right = Point(x + i**1.5, bottom.getY())
        bottom = Point(x, y + height - i**1.9)  # 计算三角形顶点的坐标

        layer = Polygon(top_left, top_right, bottom)
        layer.setFill("green")
        layer.draw(win)

    print(bottom.getX(), bottom.getY())
    # 添加星星到树顶
    star = Polygon(Point(57, 79), Point(63, 79), Point(58, 76), Point(60, 81), Point(62, 76))
    star.setFill("yellow")
    star.setOutline("yellow")
    star.draw(win)


# 创建窗口
win = GraphWin("Snowman and Christmas_Tree", 600, 600)
win.setCoords(0, 0, 100, 100)
win.setBackground("pink")

# 绘制雪人和圣诞树
snowman(win, 28, 65)
christmas_tree(win, 60, 10, 70)

# 等待用户关闭窗口
win.getMouse()
win.close()

输出:
在这里插入图片描述

  • 5.编写一个程序,在屏幕上绘制5个骰子,是一把顺子(1,2,3,4,5,或2,3,4,5,6)。
    答案
    程序思路:编写两个小的函数,一个用来生成骰子的框,一个用来生成点,函数主要简化了填充和绘制的步骤。根据窗口大小,设计骰子的摆放位置,计算中心点坐标,调用五次函数绘制骰子框。再根据骰子显示的点数的不同,计算好每个点的中心位置,调用点函数,调整点的半径大小,在骰子内生成点即可。
def draw_touzi(win, x1, y1, x2, y2):
    t = Rectangle(Point(x1, y1), Point(x2, y2))
    t.setOutline("black")
    t.setFill("white")
    t.draw(win)


def draw_point(win, x, y, r):
    p = Circle(Point(x, y), r)
    p.setFill("red")
    p.draw(win)


def touzi():
    win = GraphWin("touzi", 600, 600)
    win.setCoords(0, 0, 100, 100)
    win.setBackground("green")

    draw_touzi(win, 5, 45, 15, 55)
    draw_point(win, 10, 50, 2)

    draw_touzi(win, 25, 45, 35, 55)
    draw_point(win, 30, 47.5, 1.5)
    draw_point(win, 30, 52.5, 1.5)

    draw_touzi(win, 45, 45, 55, 55)
    draw_point(win, 50, 46.8, 1.1)
    draw_point(win, 50, 49.8, 1.1)
    draw_point(win, 50, 52.8, 1.1)

    draw_touzi(win, 65, 45, 75, 55)
    draw_point(win, 67.5, 47.5, 1.1)
    draw_point(win, 67.5, 52.5, 1.1)
    draw_point(win, 72.5, 47.5, 1.1)
    draw_point(win, 72.5, 52.5, 1.1)

    draw_touzi(win, 85, 45, 95, 55)
    draw_point(win, 90, 50, 1.1)
    draw_point(win, 87.5, 47.5, 1.1)
    draw_point(win, 87.5, 52.5, 1.1)
    draw_point(win, 92.5, 47.5, 1.1)
    draw_point(win, 92.5, 52.5, 1.1)

    win.getMouse()
    win.close()


touzi()

输出:
在这里插入图片描述

  • 6.修改图形终值程序,让输入(本金和APR)也用Entry对象以图形方式完成。
    答案
    程序思路:主要使用Entry文本框来进行参数输入,需要注意对文本框进行赋值和绘制,然后合理设置getMouse暂停,在确保输入了数据之后再进行转换和运算。
    图形终值程序如下:
from graphics import *


def main():
    # Introduction
    print("This program plots the growth of a 10-year investment.")

    # Get principal and interest rate
    principal = float(input("Enter the initial principal: "))
    apr = float(input("Enter the annualized interest rate: "))

    # Create a graphics window with labels on left edge
    win = GraphWin("Investment Growth Chart", 320, 240)
    win.setBackground("white")
    win.setCoords(-1.75, -200, 11.5, 10400)
    Text(Point(-1, 0), ' 0.0K').draw(win)
    Text(Point(-1, 2500), ' 2.5K').draw(win)
    Text(Point(-1, 5000), ' 5.0K').draw(win)
    Text(Point(-1, 7500), ' 7.5k').draw(win)
    Text(Point(-1, 10000), '10.0K').draw(win)

    # Draw bar for initial principal
    bar = Rectangle(Point(0, 0), Point(1, principal))
    bar.setFill("green")
    bar.setWidth(2)
    bar.draw(win)

    # Draw a bar for each subsequent year
    for year in range(1, 11):
        principal = principal * (1 + apr)
        bar = Rectangle(Point(year, 0), Point(year + 1, principal))
        bar.setFill("green")
        bar.setWidth(2)
        bar.draw(win)

    input("Press <Enter> to quit.")
    win.close()


main()

修改后程序如下:(修改语句用长#号标注)

from graphics import *


def main():
    # Create a graphics window with labels on left edge
    win = GraphWin("Investment Growth Chart", 320, 240)
    win.setBackground("white")
    win.setCoords(-1.75, -200, 11.5, 10400)

    p = Entry(Point(3, 10000), 6)  ###########设置Entry输入框,并赋值为0,绘制在图中
    p.setText("0")                 ###########
    p.draw(win)                    ###########
    a = Entry(Point(6, 10000), 4)  ###########
    a.setText("0.0")               ###########
    a.draw(win)                    ###########

    Text(Point(-1, 0), ' 0.0K').draw(win)
    Text(Point(-1, 2500), ' 2.5K').draw(win)
    Text(Point(-1, 5000), ' 5.0K').draw(win)
    Text(Point(-1, 7500), ' 7.5k').draw(win)
    Text(Point(-1, 10000), '10.0K').draw(win)

    win.getMouse()                ###########  设置一次鼠标点击,让用户有时间更改Entry文本框中的值
    principal = int(p.getText())  ###########   点击后将输入的值转换为float类型,进行运算绘图
    apr = float(a.getText())      ###########

    # Draw bar for initial principal
    bar = Rectangle(Point(0, 0), Point(1, principal))
    bar.setFill("green")
    bar.setWidth(2)
    bar.draw(win)

    # Draw a bar for each subsequent year
    for year in range(1, 11):
        principal = principal * (1 + apr)
        bar = Rectangle(Point(year, 0), Point(year+1, principal))
        bar.setFill("green")
        bar.setWidth(2)
        bar.draw(win)

    win.getMouse()      ###########  设置点击窗口后关闭窗口
    win.close()         ###########


main()

输出:
在这里插入图片描述

  • 7.圆的交点。
    编写一个计算圆与水平线的交点的程序,并以文本和图形方式显示信息。
    输入:圆的半径和线的截距。
    输出:在坐标为从(-10,-10)到(10,10)的窗口中,以(0,0)为中心,以给定半径绘制的圆。
    用给定的Y轴截取一根水平线穿过窗口。
    用红色绘制两个交点。
    打印出交叉点的X值。
    公式: x = ± r 2 − y 2 x=±\sqrt{r^2 - y^2 } x=±r2y2
    答案:
    程序思路:利用程序输入直接绘制圆和直线,并计算交点,然后用红色的小圆代替点标注出来,根据公式计算X的正负值,打印输出即可。
def cricle_intersection(r, y):   # 函数的输出是圆的半径和截距
    win = GraphWin("Cricles_intersection", 600, 600)
    win.setCoords(-10, -10, 10, 10)
    win.setBackground("white")

    cricle = Circle(Point(0, 0), r)
    cricle.setOutline("black")
    cricle.draw(win)

    line = Line(Point(-10, y), Point(10, y))
    line.setOutline("black")
    line.draw(win)

    x1 = sqrt(r**2-y**2)          # 调用开平方函数计算x的正负值
    x2 = -x1

    p1 = Circle(Point(x1, y), 0.2)
    p1.setFill("red")
    p1.draw(win)
    pt1 = Text(Point(x1 + 1, y - 1), "x1")
    pt1.draw(win)
    p2 = Circle(Point(x2, y), 0.2)
    p2.setFill("red")
    p2.draw(win)
    pt2 = Text(Point(x2 - 1, y - 1), "x2")
    pt2.draw(win)

    print("x1 =", x1, "   x2 =", x2)

    win.getMouse()
    win.close()


cricle_intersection(5, -4)

输出:
在这里插入图片描述

  • 8.线段信息。
    该程序允许用户绘制线段,然后显示关于线段的一些图形和文本信息。
    输入:两次鼠标点击线段的终点。
    输出:以青色绘制线段的中点。
    绘制线段。
    打印线的长度和斜率。
    公式:
dx = x2 - x1
dy = y2 - y1
slope = dy / dx

l e n g t h = d x 2 + d y 2 length = \sqrt{dx^2 + dy^2 } length=dx2+dy2

答案
程序思路: 利用getMouse函数获点的位置,分别取出坐标绘制线段,再计算得到线段的中点,绘制在窗口中。利用坐标和公式计算线段的斜率和长度,打印输出。

def line_segment():
    win = GraphWin("line_segment", 600, 600)
    win.setCoords(0, 0, 100, 100)
    win.setBackground("white")

    p1 = win.getMouse()  # 通过点击获取点
    p1.draw(win)
    p2 = win.getMouse()
    p2.draw(win)
    x1 = p1.getX()  # 取出两点的坐标
    y1 = p1.getY()
    x2 = p2.getX()
    y2 = p2.getY()
    dx = x2 - x1
    dy = y2 - y1

    line = Line(Point(x1, y1), Point(x2, y2))  # 根据两点坐标绘制直线
    line.draw(win)

    c = Circle(Point((x1 + x2) / 2, (y1 + y2) / 2), 0.8)  # 绘制直线中点,用一个小圆代替,填充青色
    c.setFill("cyan")
    c.draw(win)

    slope = dy / dx  # 计算斜率
    length = sqrt(dx ** 2 + dy ** 2)  # 计算线段长度
    s = round(slope, 3)  # 分别保留三位小数
    lth = round(length, 3)
    print("slope=", s, "  length=", lth)

    win.getMouse()
    win.close()


line_segment()

输出:
在这里插入图片描述

  • 9.矩形信息。
    此程序显示有关用户绘制的矩形信息。
    输入:两次鼠标点击作为矩形的对角。
    输出:绘制矩形。
    打印矩形的周长和面积。
    公式:面积=(长度)(宽度) ;周长=2(长度+宽度)
    答案
    程序思路: 利用鼠标点击获取两个点,作为矩形对角点,分别取出坐标,同时可以得到矩形另外两点的坐标,利用Polygon函数依次连接四点即可绘制矩形;通过对角坐标点可以计算横纵坐标各自的差值,作为矩形的长和宽,即可算得周长和面积,打印输出。
def draw_rectangle():
    win = GraphWin("draw_rectangle", 600, 600)
    win.setCoords(0, 0, 100, 100)
    win.setBackground("white")

    p1 = win.getMouse()  # 通过点击获取点
    p1.draw(win)
    p2 = win.getMouse()
    p2.draw(win)
    x1 = p1.getX()  # 取出两点的坐标
    y1 = p1.getY()
    x2 = p2.getX()
    y2 = p2.getY()
    x3 = x1
    y3 = y2
    x4 = x2
    y4 = y1
    dx = abs(x2 - x1)  # 差值取为绝对值
    dy = abs(y2 - y1)

    rectangle = Polygon(Point(x1, y1), Point(x3, y3), Point(x2, y2), Point(x4, y4))
    rectangle.setFill("pink")
    rectangle.draw(win)

    primeter = dy*2 + dx*2  # 计算周长
    area = dx*dy   # 计算面积
    p = round(primeter, 3)  # 分别保留三位小数
    a = round(area, 3)
    print("周长=", p, "  面积=", a)

    win.getMouse()
    win.close()


draw_rectangle()

输出:
在这里插入图片描述

  • 10.三角形信息。
    与上一个问题相同,但三角形的顶点有三次点击。
    公式:关于周长,可参阅线段问题中的长度。
    面积 = s ( s − a ) ( s − b ) ( s − c ) 面积 = \sqrt{s(s-a)(s-b)(s-c) } 面积=s(sa)(sb)(sc) 其中a,b,c是边长,s = (a + b + c)/2
    答案
    程序思路: 与上一题类似,利用鼠标点击获取三个点,分别取出坐标,通过两点坐标分别求出三条边的长度,利用Polygon函数依次连接三点即可绘制三角形。
def draw_triangle():
    win = GraphWin("draw_triangle", 600, 600)
    win.setCoords(0, 0, 100, 100)
    win.setBackground("white")

    p1 = win.getMouse()  # 通过点击获取点
    p1.draw(win)
    p2 = win.getMouse()
    p2.draw(win)
    p3 = win.getMouse()
    x1 = p1.getX()  # 取出三点的坐标
    y1 = p1.getY()
    x2 = p2.getX()
    y2 = p2.getY()
    x3 = p3.getX()
    y3 = p3.getY()
    dx1 = abs(x2 - x1)
    dy1 = abs(y2 - y1)
    a = sqrt(dx1 ** 2 + dy1 ** 2)  # 计算第一边长度

    dx2 = abs(x2 - x3)
    dy2 = abs(y2 - y3)
    b = sqrt(dx2 ** 2 + dy2 ** 2)  # 计算第二边长度

    dx3 = abs(x3 - x1)
    dy3 = abs(y3 - y1)
    c = sqrt(dx3 ** 2 + dy3 ** 2)  # 计算第三边长度

    triangle = Polygon(Point(x1, y1), Point(x2, y2), Point(x3, y3))    # 画出三角形
    triangle.setFill("pink")
    triangle.draw(win)

    s = (a + b + c) / 2   # 计算s值,便于计算面积
    area = sqrt(s * (s - a) * (s - b) * (s - c))
    s = round(a + b + c, 3)  # 分别保留三位小数
    a = round(area, 3)
    print("周长=", s, "  面积=", a)

    win.getMouse()
    win.close()


draw_triangle()

输出:
在这里插入图片描述

  • 11.通过5次点击的房子。
    编写一个程序,允许用户通过五次点击鼠标,绘制一个简答的房子。
    前两次点击是房子的矩形框架的对角。
    第三次点击指出矩形门的顶部边缘的中心。门的宽度应为房屋框架宽度的1/5。门的边框应从顶部的转角延伸到框架的底部。
    第四次点击指出正方形窗口的中心。窗口的宽度是门的一半。
    最后一次点击指出屋顶的顶点。屋顶的边缘将从顶点延伸到房屋框架的顶部边缘的转角。
    图片描述

答案
程序思路: 按照题目要求分五次点击,每次点击完成不同的工作,注意门和窗户的宽度的计算,多次使用矩形函数,计算好对角点的坐标,按步骤进行即可。

def draw_home():
    win = GraphWin("draw_home", 600, 600)
    win.setCoords(0, 0, 100, 100)
    win.setBackground("white")

    p1 = win.getMouse()  # 第一次点击取点
    p1.draw(win)
    p2 = win.getMouse()  # 第二次点击取点
    p2.draw(win)
    x1 = p1.getX()
    y1 = p1.getY()
    x2 = p2.getX()
    y2 = p2.getY()

    home_box = Rectangle(Point(x1, y1), Point(x2, y2))   # 利用两点绘制矩形
    home_box.draw(win)

    p3 = win.getMouse()    # 第三次点击取点
    p3.draw(win)
    x3 = p3.getX()
    y3 = p3.getY()

    dx1 = abs(x2 - x1)
    door_width = dx1 / 5   # 门的宽度为房屋宽度的1/5
    door = Rectangle(Point(x3 - door_width / 2, y1), Point(x3 + door_width / 2, y3))   # 矩形函数绘制门
    door.draw(win)

    p4 = win.getMouse()     # 第四次点击取点
    x4 = p4.getX()
    y4 = p4.getY()
    windows_width = door_width / 2    # 窗的宽度为门宽度的1/2

    windows = Rectangle(Point(x4 - windows_width / 2, y4 - windows_width / 2),    # 矩形函数绘制窗
                        Point(x4 + windows_width / 2, y4 + windows_width / 2))
    windows.draw(win)

    p5 = win.getMouse()     # 第五次点击取点
    x5 = p5.getX()
    y5 = p5.getY()
    x11 = x1                # 计算房屋的另一个顶点的坐标
    y11 = y2

    line1 = Line(Point(x5, y5), Point(x11, y11))      # 从屋顶顶点向房屋框架的两个顶点连线
    line1.draw(win)
    line2 = Line(Point(x5, y5), Point(x2, y2))
    line2.draw(win)

    win.getMouse()
    win.close()


draw_home()

输出:
在这里插入图片描述





(如有错误,请读者留言指正!)
  • 30
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值