Visar inlägg med etikett Inlämningsuppgift. Visa alla inlägg
Visar inlägg med etikett Inlämningsuppgift. Visa alla inlägg

måndag 15 april 2013

Rörelse och interaktion

Automatisk rörelse

Tkinter har metoden after( tid, funktion) som anropar en funktion efter tiden tid som anges i millisekunder. Denna kan användas för att skapa rörelse i ett grafisk program.

Övning 3.9
Skriv in och testa programmet nedan:

from tkinter import *


class Dot_Canvas(Canvas):
    
    def __init__(self, root):
        super().__init__(root, width=400, height=300, bg="white")
        self.running=False
        self.bind("<Button-1>", self.start_stop)
        self.x=30
        self.y=30
        self.dx=5
        self.dy=5
        self.photo = PhotoImage(file="../greendot.gif")
        self.dot_id=self.create_image(self.x, self.y, image=self.photo)
        self.pack()
    
    def start_stop(self, event):
        if not self.running :
            self.running=True
            self.move_dot()
        else :
            self.running=False
        
    def move_dot(self):
        self.move(self.dot_id, self.dx, self.dy)
        self.x=self.x+self.dx
        self.y=self.y+self.dy
        if self.x < 10 or self.x > 390 : 
            self.dx=-self.dx
        if self.y < 10 or self.y > 290 : 
            self.dy=-self.dy
        if self.running :
            self.after(50, self.move_dot)

root = Tk()
root.title('Moving dot')
Dot_Canvas(root)
mainloop()

Notera funktionen hos programmet. När användaren klickar på musen sätts variabeln running till sant och metoden move_dot kallas på. Sist i metoden move_dot finns raden self.after(50, self.move_dot) denna kallar på move_dot efter 1/20 sekund. Alltså kommer move_dot att köras varje 1/20 sekund. En funktion eller metod som kallar på sig själv kallas rekursiv. När användaren klickar på musen igen blir running falskt och metoden move_dot slutar att kalla på sig själv.

 En mask

Genom att skapa en lista av gröna punkter och deras positioner man göra en studsande mask:

Övning 3.10
Skriv och testa:

from tkinter import *


class Dot_Canvas(Canvas):
    
    def __init__(self, root):
        super().__init__(root, width=400, height=300, bg="white")
        self.running=False
        self.bind("<Button-1>", self.start_stop)
        self.x=[10,20,30,40,50]
        self.y=[10,20,30,40,50]
        self.dx=[5,5,5,5,5]
        self.dy=[5,5,5,5,5]
        self.photo = PhotoImage(file="../greendot.gif")
        self.dot_id=[]
        for i in range(len(self.x)) :
            self.dot_id.append(self.create_image(self.x[i], self.y[i], image=self.photo))
        self.pack()
    
    def start_stop(self, event):
        if not self.running :
            self.running=True
            self.move_dot()
        else :
            self.running=False
        
    def move_dot(self):
        for i in range(len(self.dot_id)) :
            self.move(self.dot_id[i], self.dx[i], self.dy[i])
            self.x[i]=self.x[i]+self.dx[i]
            self.y[i]=self.y[i]+self.dy[i]
            if self.x[i] < 10 or self.x[i] > 390 : 
                self.dx[i]=-self.dx[i]
            if self.y[i] < 10 or self.y[i] > 290 : 
                self.dy[i]=-self.dy[i]
        if self.running :
            self.after(50, self.move_dot)

root = Tk()
root.title('Mask')
Dot_Canvas(root)
mainloop()


 Dra saker med musen

Genom att skilja på händelserna när man trycker ner och drar med musknappen nedtryckt kan man dra saker över en Canvas med musen. Programmet nedan använder också metoden find_closest för att välja den närmaste av de två punkterna.

Övning 3.11
Skriv och testa:

from tkinter import *


class Dot_Canvas(Canvas):
    
    def __init__(self, root):
        super().__init__(root, width=200, height=200, bg="white")
        self.dra_id=None
        self.dra_x=0
        self.dra_y=0
        self.bind("<ButtonPress-1>", self.ned)
        self.bind("<B1-Motion>", self.dra)
        self.photo = PhotoImage(file="../greendot.gif")
        self.create_image(40, 40, image=self.photo)
        self.create_image(160, 160, image=self.photo)
        self.pack()
    
    def ned(self, event):
        self.dra_id = self.find_closest(event.x, event.y)    
        self.dra_x=event.x
        self.dra_y=event.y
        
    def dra(self, event):
        dx=event.x-self.dra_x
        dy=event.y-self.dra_y
        self.move(self.dra_id, dx, dy)
        self.dra_x=event.x
        self.dra_y=event.y

root = Tk()
root.title('Dot')
Dot_Canvas(root)
mainloop()

Inlämningsuppgift 3.2
Skriv något av följande program och lämna in:

1) En analog klocka. Använd create_line och coords för att få visarna att vridas. Kan kompletteras med möjlighet att ställa klockan med musen.

2) Femtonspel - användaren klickar på den siffra hen vill flytta. Programmet utför flytten om det är möjligt och upptäcker om siffrorna är i rad.

3) Masken - Användaren styr en mask med knapp för sväng 90 grader höger eller vänster. Masken blir längre och längre. Man får inte krocka med väggar eller sig själv. Hinder kan införas och mm.

onsdag 21 november 2012

Moduler


Moduler

För att kunna återanvända funktioner  i olika program kan man samla dem i filer. I Python heter filer med funktionssamlingar moduler. (Även filer med hela program kallas moduler). Vi har tidigare använt modulen math som innehåller många matematiska funktioner samt modulen random som har slumptalsfunktioner.

Modulens namn är samma som filnamnet men utan filnamnstillägget (.py).

När du importerar en modul importeras funktionerna till programmet och kan användas genom  minmodul.minfunktion(). Ex:

#importerar modulen
import minmodul

#Kör en funktion i den importerade modulen
minmodul.minfunktion()

OBS! Om du importerar en modul kommer eventuell programkod utanför funktioner att köras direkt. Se nedan.

Övning 2.4 2.4b
Du ska nu skapa en modul med funktioner för matematik kring division och primtal. Använd nedanstående pseudokod för att skapa funktionerna. Namnge modulen som diskret_matematik

Funktionen primtal(n)
Kontrollerar om ett heltal tal n är ett primtal:

def primtal(n) :
    beräkna roten ur n (högsta möjliga talet som kan vara ett primtal)
    Sätt variabeln primtal till sant

    för alla heltal från och med 2 till och med roten ur n:
        om n är jämnt delbart med talet:
            sätt primtal lika med falskt
            hoppa ur loopen
        
    returnera värdet på primtal

Funktionen sgd(a, b)
Hittar största gemensamma delare hos för två heltal tal a och b:

def sgd(a, b) :
    om a större än b sätt variabeln storst till a och minst till b 
    annars sätt minst till a och storst till b
    
    om storst och minst är delbara returnera minst
    
    bestäm roten ur minsta talet plus 1
    
    för alla tal i från hetalsdelen av minst/2 till och med 1 :
        om både storst och minst går att dela med i :
            hoppa ur loopen
        
    returnera i

Funktionen mgn(a, b)
Hittar minsta gemensamma nämnare för två nämnare a och b:

    
def mgn(a, b) :
    returnera a multiplicerat med b delat med resultatet av sgd(a, b)


Funktionen main()

Ibland vill man ha programkod i en modul som ska importeras i andra program. För att förhindra att koden körs vid import används följande kod:

def minfunktion1()
    ...

def minfunktion2()
    ....

....

def main()
    # Kod som ska köras när modulen körs utan import

if __name__ == "__main__":
    main()

Variablen __name__ är en inbyggd variabel i Python som innehåller namnet på modulen om den importerats av ett program men "__main__" om modulen körs direkt.

Koden gör alltså att det du skrivit i funktionen main() endast körs om koden inte importeras.

Notera att namnet main() inte är något speciellt. Du kan skriva vilket funktionsnamn du önskar men main() har blivit en de facto standard.

Inlämningsuppgift 2.2
Lägg till en main()-funktion med tillhörande if-sats. Skriv kod som testar modulens funktioner.

måndag 19 november 2012

Speciella tal

Nedan följer några speciella tal som kan vara bra att känna till

Största heltalet
Det största heltalet som kan användas som index i till exempel strängar kan du finna med satsen sys.maxsize:

import sys

print(sys.maxsize)

Största flyttalet
Största decimaltalet som datorn klarar av ges av sys.float_info.max

import sys

print(sys.float_info.max)

Oändligheten och Not a Number
Inom matematiken finns det ibland  behov av att använda plus eller minus oändligheten. De skrivs:

float("Infinity")
float("-Infinity")

Funktionen math.isinf(x) returnerar sant om talet x är antingen positiva eller negativa oändligheten. (Du måste importera math-modulen för denna funktion.)
 
Ett annat speciellt "tal" är NaN, Not a Number, som är användbart när funktioner skall returnera ett flyttalsvärde men ett sådant inte går att räkna ut. Exempelvis grund av negativt tal under roten eller division med noll.

import math
x = float(input("Skriv ett tal"))
if x <o :
    x = float("nan")
else :
    x = math.sqrt(x)
print(x)

Det går att prova om talet är NaN med funktionen math.isnan(x) som returnerar sant om x är ett NaN.


Övning 2.4
Skriv om inlämningsuppgift 1.2 så att kontrollen av om det finns rötter och själva rotberäkningen sker i en funktion som returnerar NaN om talet under roten är negativt annars den beräknade roten. Se nedanstående pseudokod:

def roten(p, q) :
    t = talet under roten
    om t är negativt
        return NAN
    annars
        retur roten ur t

input p och q
r = roten(p,q)
om r NaN svara med att den saknar rötter
annars beräkna de två rötterna

Inlämningsuppgift 2.1
Skriv ett program som låter användaren mata in ett valfritt antal tal. Inmatningen avslutas med att användaren skriver ”N”. När alla talen är inmatade skriver programmet ut det största och det minsta av talen.

onsdag 10 oktober 2012

for-loopen

En annan viktig loop är for-loopen. Den används när man vill upprepa en loop ett bestämt antal gånger eller gå igenom en uppsättning data. Vi tittar på några varianter av denna.

Övning 1.33
Testa denna variant av for-loop:
Tips: Om du vill kan du använda interaktiva skalet och skriva hela loopen på en rad. 
 
for i in range(5) :
    print(i)


Hur det fungerar:
  • Funktionen range(5) skapar en lista med fem heltal [0, 1, 2, 3, 4]. Notera att det första talet är 0 och det sista 4.
  • Variabeln i sätts lika med första värdet i listan, alltså 0.
  • Satsen i loopen utförs.
  • Variabeln i sätts till lika med nästa värde i listan och loopen börjar om tills listan är slut.
 Notera: Precis som i while-loopar kan break användas för att hoppa ur en for-loop.

 Varianter på range()

  • range(a) skapar en lista heltal från och med 0 till och med a-1
  • range(a, b) skapar en lista heltal från och med a till och med b-1
  • range(a, b, c) skapar en lista heltal från och med a till b med steg c
Övning 1.34
Gör om övning 33 men ange:
a) range(-5, 5)
b) range(20,  200, 50)
c) range(10, 0, -1)

Uppgift 1.10
Skriv ett program som talar om vilka tal ett givet heltal är jämnt delbart med.
Tips: Ett tal kan endast vara jämnt delbart med tal mindre än eller lika halva talet. Du behöver bara testa upp till hälften (avrundat uppåt).

Loop i loop

Det går utmärkt att sätta loopar inuti andra loopar. Nedanstående visar hur man kan få fram en multiplikationstabell genom denna metod.

Övning 1.35
Skriv och testa. Tänk efter ordentligt så du säkert förstår vad som händer.

#Multiplikationstabell

for i in range(1,11) : # yttre for-loop för vänstra talet i mult.
    for j in range(1,11) : # inre for-loop för högra talet i mult.
        print("{:0d}*{:0d}={:0d}".format(i,j,i*j), end="\t")
    print() # Ny rad
    print() # Tomrad mellan varje nytt vänstertal

Notera: I vanliga fall blir det automatiskt ny rad efter en print-sats. Detta kan vara opraktiskt när man vill skriva ut listor. Det går att göra så att detta inte sker genom att använda en variant av print där man anger vad som ska vara avslutning av utskriften. Satsen print( "xxx", end="\t") skriver ut xxx men avslutar med tab istället för ny rad. För att få ny rad kan ett tomt print() användas.

Nyckelordet continue

Vi har tidigare lärt oss satsen break som hoppar ur en loop. Ett användbart alternativ till break är continue som gör att programmet går vidare direkt till nästa varv i loopen. Se nedanstående övning:

Övning 1.36
Skriv och testa

for num in range(2, 10):
    if num % 2 == 0:
        print("Fann ett jämnt tal ", num)
        continue
    print("Fann ett ojämnt tal ", num)

Notera: continue går även att använda i while-loopar


Inlämningsuppgift 1.4
Ändra uppgift 1.10 så att den skriver ut delbarheten för alla talen 1 till och med 20.

Forsatsen med texter

I Python och flera andra språk kan for-satser användas för att iterera över inte bara en lista med tal utan också andra följder. Till exempel kan for användas för att stega sig genom en sträng. Ex:

for s in "Python" : print(s)

Övning 1.37
Skriv ett program med for-sats som sätter punkt efter varje bokstav i en inmatad sträng och skriver ut resultatet. Ex: "SWAT" blir "S.W.A.T."

Itereringen över en sträng går alltid från första till sista tecknet. Om du vill iterera i en annan ordning, över delar av strängen eller behöver få reda på index för tecknen så får du skapa en range-funktion enligt nedastående övning.

Övning 1.38
Följande skriver ut en inmatad text baklänges

text = input("Skriv en text: ")
for i in range(len(text), 0, -1) :
    print(text[i-1], end="")


Notera:
Stegningen -1 i range-funktionen för att gå från högre till lägre index.
Användningen av i-1 då range går från och med len(text) till 0 medan index går från och med 0 till och med len(text)-1.
Tillägget end="" i print-satsen för att undvika ny rad mellan tecknen.

onsdag 12 september 2012

Månlanda


Månlanda är ett enkelt och klassisk spel inspirerat av Apollo-programmet. Spelaren ska landa en månlandare på månen. När spelet startar är landaren på väg ner och spelaren kan reglera bromsraketernas gaspådrag en gång per sekund för att landa mjukt. Dock har landaren begränsad mängd bränsle så det gäller att inte slösa.

Spelfysiken

Spelet bygger på Newtons fysik och rörelseformlerna som du mött i fysikkurserna.

Spelets simulering tar tidssteg på en sekund och acceleration, hastighet och höjd beräknas för varje tidssteg.

Månens gravitation är inte lika stark som på jorden utan tyngdaccelerationen är ungefär en sjättedel av den på jorden. I spelet kan det vara bekvämt att sätta tyngdaccelerationen lika med 1,5 m/s2.

Bromsraketerna motverkar tyngdaccelerationen. Accelerationen under ett tidssteg kan skrivas som:

a =  fK - G                                     (Ekv. 1)

Där f är bränsleflödet i liter per sekund, K en konstant och G månens tyngdacceleration. Konstanten K är ett mått på kraften från motorn, vid pådraget 1 l/s, i förhållande till landarens massa. Notera att positiv acceleration är uppåt då höjden ökar åt det hållet.

Hastigheten ändras alltså med a under ett tidssteg:

vt = vt-1 + a                                 (Ekv. 2)

Där vt är den nya hastigheten och vt-1 är hastigheten förra tidssteget.

Höjden kommer att ändras med medelhastigheten under tidssteget:

ht = ht-1 + (vt + vt-1) / 2            (Ekv. 3)

vilket kombinerat med Ekv. 2 blir

ht = ht-1 + vt - a/2                     (Ekv. 4)


För varje nytt tidssteg beräknas alltså:

a =  fK - G

vt = vt-1 + a 

ht = ht-1 + vt - a/2


Gaspådrag och bränsle

Varje nytt tidssteg börjar med att spelaren anger det valda gaspådraget f. Gaspådraget har ett maximalt värde, full gas, som spelaren inte kan överskrida. Naturligtvis kan spelaren inte ange negativt gaspådrag eller använda mer än det kvarvarande bränslet.

Vid varje tidssteg minskas kvarvarande bränsle med pådraget f:

bt = bt-1 - f

Där bt är kvarvarande bränsle.

Landningen

När höjden är noll, eller mindre, sker landningen...eller kraschen. Om farten då är mindre än 2 m/s, alltså vt > - 2 , så anses landningen lyckad annars är det en kraschlandning.

Flödesschema

Nedanstående visar ett förslag på flödesschema för programmet:

Lämpliga startvärden

Följande värden är lämpliga för att få ett fungerande spel:
Tyngdacceleration G=1,5
Full gas MAX=60
Konstant K=0,1
Bränslemängd b=600
Starthöjd h=500
Starthastighet v=-10

Inlämningsuppgift 1.3

Skapa spelet Månlanda och skicka in. Tänk på att hantera eventuella undantag.

Tips: När du fått spelet att fungera så kan du testa olika värden på bränslemängd eller andra variabler för att göra spelet lagom svårt.

Tips: Som standard skrivs alla decimaler ut för höjd och hastighet och bränsle. Detta kan leda till svårlästa rader. Det går att få en snyggare formatering med tex två decimaler genom att använda formaterings-funktionen för texter:

print("Höjd= {0:.2f}".format(h))

Om h=2.248432 ger ovanstående texten: Höjd= 2.25


Överkurs: Läs mer om textformatering här och se om du ytterligare kan snygga upp utskrifterna.

tisdag 28 augusti 2012

Enkla villkor

Räkna med logik

 

Övning 1.6
Direkt i interaktiva fönstret skriver du
3>2
Vad blir svaret?
Skriv nu
2>3
Vad blir svaret?

Svaret True eller False är en ny typ av variabel som heter boolean, förkortas bool i Python. En boolean kan anta två värden: sant eller falskt.

Logiska symboler

Följande symboler används vid logiska jämförelseoperationer
Betydelse Matematik Python
Mindre än < <
Större än > >
Mindre än eller lika <=
Större än eller lika >=
Lika = ==

Skilt från
!=
OBS! Notera == tecken för jämförelse lika med. Vanligt fel att råka använda enkelt lika med istället.

Notera att jämförelsen == mellan två flyttal (float) kräver att de är exakt lika på sista decimalen för att jämförelsen ska vara sann.

Notera även att jämförelse av strängar fungerar på ett annat sätt än tal. Vi återkommer till det.

Övning 1.7
Pröva genom att i interaktiva skalet skriva olika jämförelser med tecknen ovan. Tex: 4 != 3
Visst fungerar det som du tänkt.


Genomgång av if-satsen


If-satsen


If-satser i Pyton skrivs:

if logiskt uttryck : sats

eller

if logiskt uttryck :
    Indragen sats 1
    I
ndragen sats 2
    ...
else :
    I
ndragen sats 1
    I
ndragen sats 2
    ...


Viktigt! Det är indragningen som gör att Python vet vilka satser (rader) som ska köras om if-satsen är sann respektive inte. Du måste använda indragna rader - och det är bra programmeringspraxis också!

De indragna raderna bildar ett block.

Övning 1.8
Skriv följande program och testa funktionen

vikt = float(input("Hur mycket väger din väska i kg? "))
if vikt > 25:
    print("Det kostar 100 kr extra för så tungt bagage.")
print("Välkommen åter.")


Övning 1.9
Skriv följande program och testa funktionen

temperatur = float(input("Vad är temperaturen? "))
if temperatur > 15:
    print("Välj shorts.")
else:
    print("Välj byxor.")
print("Dags att springa en runda.")

Uppgift 1.2
Testa i interaktiva fönstret vad som händer om du skriver följande if-satser.
Notera: Du behöver trycka ENTER två gånger för att if-satsen skall köras. Första ENTER gör att skalet väntar på om du ska skriva else eller en ny rad i satsen.

if True : print("sant")
Testa nu
if False: print("falskt")

Förklara resultatet för mig.

Övning 1.10
 Tecknet % ger resten vid division även kallat modulo - alltså är tex. 9 % 4 = 1. Använd detta för att skapa ett program som talar om för användaren om ett tal hen matat in är jämnt delbart med 7. Programmet skall svara med antingen "n är jämnt delbart med sju" eller "n är inte jämnt delbart med sju". Där n är talet användaren angav.

Övning 1.11
Komplettera övning 1.10 så att användaren förutom svaret ovan får reda på hur många gånger sju får plats i det angivna talet. Detta oberoende om det är jämnt delbart eller ej. Tips: Använd gärna //

Inlämningsppgift 1.2
Komplettera programmet i inlämningsuppgift 1.1 så att användaren får svaret "Ekvationen saknar reella rötter" om så är fallet.


söndag 26 augusti 2012

Ett första program

DEL 1

Förberedelse

Källkoden till dina program sparas i filer med ändelsen .py. IDLE sparar som standard filerna i din Dokument-mapp. Men för att hålla reda på dina filer i kursen skapar du en undermapp i Dokument med namnet "Programmering1" (ej mellanslag) som du använder fram över.

Överkurs: Du kan se till att din mapp öppnas som standard genom denna metod. Det förenklar framöver.

Enkla program

För att skriva ett program i IDLE så skapa ett nytt fönster i Fil-menyn.

Övning 1.1
Skriv i det nya fönstret
 
print ("Hej världen")

Färgerna talar om hur Python tolkar det inskrivna. De hjälper dig att se om du skrivit rätt syntax.

Välj Run module, menyn Run eller F5.
Före körning måste du spara programmet. Spara som Ovn1.py i din mapp.
Se i huvudfönstret att det fungerade och skrev "Hej världen".

Övning 1.2
Skriv ett nytt program Ovn2.py enligt nedan

a=2
b=3
c=a+b
print(c)

Kör och kontrollera att det fungerar.


Genomgång olika variabler och input


Program med input


Övning 1.3
Skriv en snyggare version, som även är kommenterad, av övning 2 som Ovn3.py enligt nedanstående
a=2 #Första termen
b=3 #Andra termen
c=a+b #Summan
print("Suman blir " + str(c))

Notera hur funktionen str(c) behövs för att omvandla ett tal till en sträng. Annars blir + obegripligt för Python.

Uppgift 1.1
Gör om programmet i övning 3 så att du istället kan skriva in två tal som programmet summerar. Tips: använd funktionen input() och float(). Spara som Upp1.py innan du kör.

Överkurs: Ovanstående program kan alla minskas med en rad. Hur?

Överkurs: Läs om snygga sätt att använda print() här.

Matematikmodulen

 Just nu kan du endast utföra enklare beräkningar. För att kunna använda roten ur, sinus, cosinus mm. måste du importera Pythons matematikmodul till ditt program.
Detta görs genom att först i programmet skriva import math.
När du sedan använder funktionerna skrivs de som math.xxx() där xxx() är den funktion du vill använda. Exempelvis math.sin(v) beräknar sinus för vinkeln v.

Övning 1.5
Skriv nedanstående program för att testa att använda matematikmodulen. Spara som Ovn5.py. Notera att alla vinklar är i radianer.

import math

vinkeln=float(input("vinkeln="))
sv=math.sin(vinkeln)
print("sin(" + str(vinkeln) + ")=" + str(sv)) #En snygg utskrift av svaret


Kontrollera att allt fungerar med några beräkningar.

Inlämningsuppgift 1.1
Skriv ett program som löser x2+px+q=0 med hjälp av pq-formeln. Kommentera viktiga beräkningar.
Tips: Roten ur x skrivs  math.sqrt(x) och x2 skrivs enklast x*x. Spara som Inl1.py

Överkurs: Skriv om programmet så att det löser den allmänna andragradsekvationen ax2+bx+c=0.