Lecture Notes

Praca w środowisku Unix

  • Podstawy pracy w środowisku Unix

Wprowadzenie do programowania

  • Podstawy programowania w języku Python

Programowane obiektowe

  • Programowane i projektowanie obiektowe
  • Kilka przykładów
    • Prosta hierarchia klas: obliczenia statystyczne
    • Graf : przykład projektowania klasy
    • Kompletny program: gra w warcaby
    • Kompletny program: interpreter Logo
      • Kompletny program
  • Przykładowe zadania
  • Ćwiczenia I
  • Ćwiczenia II

Programowane funkcyjne

  • Programowane funkcyjne
Lecture Notes
  • Programowane i projektowanie obiektowe
  • Kompletny program: interpreter Logo
  • View page source

Kompletny program: interpreter Logo¶

Logo jest językiem programowania stworzonym w latach 60. XX wieku. Jego głównym celem było umożliwienie dzieciom nauki podstaw programowania poprzez interakcję z komputerem. Programowanie w Logo sprowadza się do wydawania komend żółwiowi, kierując jego ruchem po ekranie. Wynikiem programu jest obrazek - ślad narysowany przez poruszającego się żółwia.

Poniższej znajdziesz opis prostego interpretera tego języka. Rozróżnia on następujące komendy:

  • L n - obróć żółwia o n stopni w lewo, np L 10 obraca żółwia w lewo o 10 stopni

  • R n - obróć żółwia o n stopni w prawo, np R 15 obraca żółwia w prawo o 15 stopni

  • UP - podnieś rysik

  • DOWN - opuść rysik

  • F n - przesuń żółwia naprzód o n; żółw narysuje linię, o ile rysik jest aktualnie opuszczony

  • JUMP x y - przenieś żółwia w położenie x, y na ekranie, np JUMP 100 100 przenosi żółwia w położenie 100, 100

  • REPEAT n [commands] – powtarza n razy komendy podane w nawiasie, np REPEAT 4 [F 10; R90] rysuje kwadrat o boku 10

  • DEF name := [commands] – definiuje procedurę o podanej nazwie, np DEF kwadrat := [ REPEAT 4 [F 10; R90] ]

  • FASTER n - dodaje n do długości kroku żółwia; początkowa długość kroku to 1.0

  • SLOWER n - odejmuje n od długości kroku żółwia

Interpreter pozwala na zagnieżdżanie procedur w pętlach; nie jest jednak możliwe deklarowanie zmiennych. Zauważ, że jedynie komenda F (forward) powoduje rysowanie, i to o ile rysik jest opuszczony. Poniższy program w Logo rysuje kwadrat o boku 10:

DOWN
F 10
R 90
F 10
R 90
F 10
R 90
F 10

Żółw rysuje cztery odcinki, każdy o długości 10 (F 10), za każdym razem odpowiednio obraca się w prawo o 90 stopni R 90. Ten sam program można zapisać, wykorzystując pętlę:

DOWN
REPEAT [ F 10; R 90 ]

Kompletny program¶

from __future__ import annotations

import math
import re
from abc import ABC, abstractmethod


class GraphicsDevice(ABC):
    @abstractmethod
    def line(self, xb, yb, xe, ye): pass


class EchoDevice(GraphicsDevice):
    def line(self, xb, yb, xe, ye):
        print(f"L {xb:.2f},{yb:.2f} : {xe:.2f},{ye:.2f}")


class SVGDevice:
    def __init__(self, width, height, fname:str):
        self.__width = width
        self.__height = height
        self.__file = open(fname, "w")
        self.__file.write(f"""<svg viewBox="0 0 {width} {height}" xmlns="http://www.w3.org/2000/svg">\n""")

    def line(self, xb, yb, xe, ye):
        print(f"<line x1='{xb}' y1='{yb}' x2='{xe}' y2='{ye}' stroke='black' />", file=self.__file)

    def __del__(self):
        self.__file.write("</svg>\n")
        self.__file.close()


class Turtle:
    def __init__(self, gd: GraphicsDevice):
        """ Creates a new turtle """
        self.__device = gd
        self.__x = 0
        self.__y = 0
        self.__a = 0
        self.__step = 1.0
        self.__if_drawing = False

    def up(self):
        self.__if_drawing = False

    def down(self):
        self.__if_drawing = True

    def jump(self, new_x, new_y):
        self.__x = new_x
        self.__y = new_y

    def right(self, d_alpha_deg):
        self.__a -= d_alpha_deg

    def left(self, d_alpha_deg):
        self.__a += d_alpha_deg

    def angle(self, alpha_deg):
        self.__a = alpha_deg
    @property
    def step_size(self): return self.__step

    @step_size.setter
    def step_size(self, new_step): self.__step = new_step

    def forward(self, displacement):
        new_x = self.__step * displacement * math.cos(self.__a/180.0 * math.pi) + self.__x
        new_y = self.__step * displacement * math.sin(self.__a/180.0 * math.pi) + self.__y
        if self.__if_drawing:
            self.__device.line(self.__x, self.__y, new_x, new_y)
        self.__x = new_x
        self.__y = new_y

class Command(ABC):
    def __init__(self, trtl: Turtle):
        self._turtle = trtl

    @abstractmethod
    def execute(self): pass

class JumpCommand(Command):

    def __init__(self, trtl: Turtle):
        super().__init__(trtl)

    def execute(self, *params):
        x = int(params[0][0])
        y = int(params[0][0])
        self._turtle.jump(x, y)


class UpCommand(Command):

    def __init__(self, trtl: Turtle):
        super().__init__(trtl)

    def execute(self, *params): self._turtle.up()


class DownCommand(Command):

    def __init__(self, trtl: Turtle):
        super().__init__(trtl)

    def execute(self, *params): self._turtle.down()

class ForwardCommand(Command):

    def __init__(self, trtl: Turtle):
        super().__init__(trtl)

    def execute(self, *params):
        self._turtle.forward(float(params[0][0]))

class FasterCommand(Command):
    def __init__(self, trtl: Turtle):
        super().__init__(trtl)

    def execute(self, *params):
        self._turtle.step_size += float(params[0][0])

class SlowerCommand(Command):
    def __init__(self, trtl: Turtle):
        super().__init__(trtl)

    def execute(self, *params):
        self._turtle.step_size -= float(params[0][0])

class LeftCommand(Command):

    def __init__(self, trtl: Turtle):
        super().__init__(trtl)

    def execute(self, *params):
        self._turtle.left(float(params[0][0]))

class RightCommand(Command):

    def __init__(self, trtl: Turtle):
        super().__init__(trtl)

    def execute(self, *params):
        self._turtle.right(float(params[0][0]))

class AngleCommand(Command):

    def __init__(self, trtl: Turtle):
        super().__init__(trtl)

    def execute(self, *params):
        self._turtle.angle(float(params[0][0]))

class Multicommand(Command):
    def __init__(self, trtl: Turtle, commands: str, interpreter: Interpreter):
        super().__init__(trtl)
        self.__commands = commands
        self.__interpreter = interpreter

    def execute(self, *params):
        self.__interpreter.run(self.__commands)


class DefCommand(Command):

    def __init__(self, trtl: Turtle, interpreter: Interpreter):
        super().__init__(trtl)
        self.__interpreter = interpreter

    def execute(self, *params):
        arguments = params[0]

        func_name = arguments[0]
        l = " ".join(arguments[2:]).strip("[").strip("]")
        l = re.sub(r'(?<!\[);(?![^\[]*])', '\n', l )
        multicmd = Multicommand(self._turtle, l, self.__interpreter)
        self.__interpreter.add_command(func_name, multicmd)

class LoopCommand(Command):

    def __init__(self, trtl: Turtle, interpreter: Interpreter):
        super().__init__(trtl)
        self.__interpreter = interpreter

    def execute(self, *params):
        arguments = params[0]
        n_repeat = int(arguments[0])
        l = " ".join(arguments[1:]).strip("[").strip("]").replace(";","\n")
        for _ in range(n_repeat):
            self.__interpreter.run(l)

class Interpreter:
    def __init__(self, turtle):
        self.__my_turtle = turtle
        self.__command_dispatch = {}
        self.add_command("F", ForwardCommand(self.__my_turtle))
        self.add_command("JUMP", JumpCommand(self.__my_turtle))
        self.add_command("DOWN", DownCommand(self.__my_turtle))
        self.add_command("FASTER", FasterCommand(self.__my_turtle))
        self.add_command("SLOWER", SlowerCommand(self.__my_turtle))
        self.add_command("UP", UpCommand(self.__my_turtle))
        self.add_command("L", LeftCommand(self.__my_turtle))
        self.add_command("R", RightCommand(self.__my_turtle))
        self.add_command("A", AngleCommand(self.__my_turtle))
        self.add_command("REPEAT", LoopCommand(self.__my_turtle, self))
        self.add_command("DEF", DefCommand(self.__my_turtle, self))

    def add_command(self, key, command):
        self.__command_dispatch[key] = command

    def run(self, program_text):
        for line in program_text.split("\n"):
            tokens = line.strip().split()
            if len(tokens) > 0:
                cmd_to_run = self.__command_dispatch[tokens[0]]
                cmd_to_run.execute(tokens[1:])


if __name__ == "__main__":
    moj_program = """
    DEF square_50 := [DOWN; REPEAT 4  [F 50; R 90]; UP]
    JUMP 100 100
    REPEAT 18 [R 20; square_50]
    """

    svg_gd = SVGDevice(200, 200, "plik.svg")
    # gd = EchoDevice()
    trtl = Turtle(svg_gd)
    interpreter = Interpreter(trtl)
    interpreter.run(moj_program)
Previous Next

© Copyright D. Gront lab.

Built with Sphinx using a theme provided by Read the Docs.