Seite 1 von 2
Nur glatt teilbare Zahlen erzeugen (random)
Verfasst: Mittwoch 19. Februar 2014, 19:36
von chris5790
Hallo liebes Python-Forum,
ich besuche den Infokurs der 9. Klasse auf einem Gymnasium. Unser Thema momentan ist (wer hätte es gedacht) Python. Ich schreibe das nur, damit sich keiner über meinen "Programmierstil" wundert. Dementsprechend kenne ich mich auch natürlich nicht sehr gut in Python aus usw.
Ich habe ein Programm geschrieben, das dem Benutzer eine Matheaufgabe mit beliebeigen Operator stellt. Die beiden Zahlen dafür werden zufällig erzeugt. Jedoch sollten die gestellten Matheaufgaben immer eine glatte Lösung ergeben. Das Problem tritt natürlich nur bei der Division auf. Mein bisheriges Programm sieht so aus:
Code: Alles auswählen
# Python 3.2.3
# Import
from math import *
import sys
import random
############################################################### DEF ###############################################################
def plus(zahl1,zahl2):
print(zahl1,"+",zahl2,"=")
global ergebnis
ergebnis = zahl1+zahl2
durchlauf()
#################################
def mal(zahl1,zahl2):
print(zahl1,"*",zahl2,"=")
global ergebnis
ergebnis = zahl1*zahl2
durchlauf()
#################################
def durch(zahl1,zahl2):
print(zahl1,"/",zahl2,"=")
global ergebnis
ergebnis = zahl1/zahl2
durchlauf()
#################################
def minus(zahl1,zahl2):
print(zahl1,"-",zahl2,"=")
global ergebnis
ergebnis = zahl1-zahl2
durchlauf()
#################################################################################
def quizfrage(zahl1,zahl2,operator):
##########################
if operator=="*":
mal(zahl1,zahl2)
elif operator=="/":
durch(zahl1,zahl2)
elif operator=="+":
plus(zahl1,zahl2)
elif operator=="-":
minus(zahl1,zahl2)
###########################
def durchlauf():
antwort = input()
antwort = int(antwort)
if antwort == ergebnis:
print("Richtig!")
global punkte
punkte=punkte+1
else:
print("Falsch!")
########################################################## Hauptprogramm ##########################################################
name=input("""Hallo, dies ist ein Quiz, wie heisst du?
""")
print("Hallo", name)
operator=input("Welchen Rechenoperator moechtest du benutzen?(+ - * /): ")
print("Hier kommen deine 10 Fragen:")
punkte = 0
for i in range(10):
quizfrage(random.randint(1,20),random.randint(1,20),operator)
Ich bin grundsätzlich natürlich offen für Verbesserungen, ich bin ja nur ein Schüler
Nun, es ist ja durchaus möglich zu jeder zahl von 2 - 20 die entsprechenden Teilbaren Zahlen aufzuschreiben und zufällig auswählen zu lassen, das ist aber (leider) selbst bei 20 Zahlen ein ziemlich großer Code. Ich hoffe mal, ich werde jetzt nicht gehated, weil ich Schüler mit einem Problem ohne Python-Sonderkenntnisse bin, der fragt, aber ich bin zuversichtlich

Bin für jede Hilfe dankbar
Grüße
Re: Nur glatt teilbare Zahlen erzeugen (random)
Verfasst: Mittwoch 19. Februar 2014, 20:13
von Sirius3
@chris5790: Du hast ja schon richtig erkannt, dass bei anderen Operationen, zum Beispiel Multiplizieren, es kein Problem gibt, mit nicht ganzen Zahlen. Wie kann man jetzt eine Division in eine Multiplikation umwandeln

?
Re: Nur glatt teilbare Zahlen erzeugen (random)
Verfasst: Mittwoch 19. Februar 2014, 20:22
von Sirius3
Noch ein paar Anmerkungen zum Code: "global" ist ein Schlüsselwort, das Du am besten gleich wieder vergisst. Es macht mehr Probleme als es löst und sollte in normalen Programmen nicht vorkommen. In Deinem Fall kannst Du »ergebnis« einfach als Argument an »durchlauf« übergeben.
Auf Modulebene dürfen keine Befehle stehen, also alles von Zeile 94 solltest Du auch in eine Funktion schreiben. Diese Funktion heißt normalerweise »main« und wird durch diese beiden Zeilen am Ende des Programms aufgerufen:
Dadurch kann man das Programm auch als Modul in ein anderes Programm importieren, um es z.B. zu testen, oder Teile daraus wiederzuverwenden.
Re: Nur glatt teilbare Zahlen erzeugen (random)
Verfasst: Mittwoch 19. Februar 2014, 20:52
von chris5790
Sirius3 hat geschrieben:@chris5790: Du hast ja schon richtig erkannt, dass bei anderen Operationen, zum Beispiel Multiplizieren, es kein Problem gibt, mit nicht ganzen Zahlen. Wie kann man jetzt eine Division in eine Multiplikation umwandeln

?
Du hast mich auf eine Idee gebracht, jedoch ist die Frage ob mir das was bringt?
Ich möchte ja den Anwender eine Divisionsaufgabe lösen lassen. Ich könnte ja die beiden Zahlen miteinander so lange teilen lassen, bis es keine Nachkommastelle gibt. Erst dann wird die Schleife beendet und das Programm läuft weiter. Ich bin mir nur unsicher, wie ich prüfen lassen kann, ob das Ergebnis Nachkommastellen hat.
Mein Wissensstand ist bei Python für KIDS Kapitel 7, nach der Zeit gingen mir die ganzen Grafischen Sachen so dermaßen auf den Zeiger... Objektorientiert mag ich ja, aber nicht auf dem Niveau von 10-Jährigen...
Nun, entweder stehe ich auf dem Schlauch oder das ist außerhalb meines Wissens: was bedeutet Argument? Ich habe nun alles aus der Modulebene in eine Definition kopiert und jetzt bekomme ich Probleme mit dem Punktezähler. Hier mal das neu geschriebene Programm. Ich habe global überall entfernt, wie kann ich nun das Ergebnis von mal() usw. an durchlauf() weitergeben?
Code: Alles auswählen
# Python 3.2.3
# Import
from math import *
import sys
import random
############################################################### DEF ###############################################################
def plus(zahl1,zahl2):
print(zahl1,"+",zahl2,"=")
ergebnis = zahl1+zahl2
durchlauf()
#################################
def mal(zahl1,zahl2):
print(zahl1,"*",zahl2,"=")
ergebnis = zahl1*zahl2
durchlauf()
#################################
def durch(zahl1,zahl2):
print(zahl1,"/",zahl2,"=")
ergebnis = zahl1/zahl2
durchlauf()
#################################
def minus(zahl1,zahl2):
print(zahl1,"-",zahl2,"=")
ergebnis = zahl1-zahl2
durchlauf()
#################################################################################
def quizfrage(zahl1,zahl2,operator):
##########################
if operator=="*":
mal(zahl1,zahl2)
elif operator=="/":
durch(zahl1,zahl2)
elif operator=="+":
plus(zahl1,zahl2)
elif operator=="-":
minus(zahl1,zahl2)
#####################################################################################################################
def durchlauf():
antwort = input()
antwort = int(antwort)
if antwort == ergebnis:
print("Richtig!")
punkte=punkte+1
else:
print("Falsch!")
def main():
name=input("""Hallo, dies ist ein Quiz, wie heisst du?
""")
print("Hallo", name)
operator=input("Welchen Rechenoperator moechtest du benutzen?(+ - * /): ")
print("Hier kommen deine 10 Fragen:")
punkte = 0
while True:
punkte = 0
for i in range(10):
quizfrage(random.randint(1,20),random.randint(1,20),operator)
########################################################## Hauptprogramm ##########################################################
if __name__ == '__main__':
main()
Jetzt bekomme ich grade einen Fehler, dass Ergebnis nicht definiert ist
Re: Nur glatt teilbare Zahlen erzeugen (random)
Verfasst: Mittwoch 19. Februar 2014, 21:05
von /me
chris5790 hat geschrieben:Ich habe global überall entfernt, wie kann ich nun das Ergebnis von mal() usw. an durchlauf() weitergeben?
Wie gibst du denn Werte an deine Funktionen wie
plus oder
mal weiter?
Re: Nur glatt teilbare Zahlen erzeugen (random)
Verfasst: Mittwoch 19. Februar 2014, 21:11
von chris5790
Über die definierte Funktion per Variable, aber wie soll ich das auf das Ergebnis übertragen? Die Varibale ist ja nur in der jeweiligen Definition existent (mal(), plus()), also lokal, global soll ich ja nicht verwenden. Gibt es einen Befehl um lokale Varibalen für die ganze Definition verfügbar zu machen oder etwas in der Art?
BTW: geiler Name

Re: Nur glatt teilbare Zahlen erzeugen (random)
Verfasst: Mittwoch 19. Februar 2014, 21:14
von Sirius3
@chris5790: was ist »zahl1« und »zahl2« bei »plus«?
Re: Nur glatt teilbare Zahlen erzeugen (random)
Verfasst: Mittwoch 19. Februar 2014, 21:18
von /me
chris5790 hat geschrieben:Über die definierte Funktion per Variable, aber wie soll ich das auf das Ergebnis übertragen? Die Varibale ist ja nur in der jeweiligen Definition existent (mal(), plus()), also lokal, global soll ich ja nicht verwenden. Gibt es einen Befehl um lokale Varibalen für die ganze Definition verfügbar zu machen oder etwas in der Art?
Schau mal, beim Aufruf von
mal gibst du zwei Parameter (oder auch
Argumente) mit:
zahl1 und
zahl2. Warum sollte das bei anderen Funktionen nicht auch gehen?
Wirf mal einen Blick auf den folgenden Code:
Code: Alles auswählen
def do_something(thing, number):
result = thing * number
show_me(result)
def show_me(value):
print(value)
def main():
do_something(7, 3)
do_something('-', 40)
if __name__ == '__main__':
main()
Re: Nur glatt teilbare Zahlen erzeugen (random)
Verfasst: Mittwoch 19. Februar 2014, 21:36
von chris5790
Ich glaub ich habs:
Code: Alles auswählen
def minus(zahl1,zahl2):
print(zahl1,"-",zahl2,"=")
ergebnis = zahl1-zahl2
durchlauf(ergebnis)
#################################################################################
def durchlauf(ergebnis):
antwort = input()
antwort = int(antwort)
if antwort == ergebnis:
print("Richtig!")
# punkte=punkte+1
else:
print("Falsch!")
Richtig? Beim Durchlauf funktioniert es zumindest
Nun zu den Punkten: so wie es bisher war, funktioniert es natürlich nicht. Die Punkte werden bei durchlauf() addiert, vorher einmal in der while True Schleife auf 0 gesetzt, falls man das Programm neu starten möchte. Muss ich das mit den Punkten genau so wie mit dem ergebnis grade machen? Oder geht das auch anders?
Re: Nur glatt teilbare Zahlen erzeugen (random)
Verfasst: Mittwoch 19. Februar 2014, 21:47
von BlackJack
@chris5790: Auf zur nächsten Eigenschaft von Funktionen: Die können Rückgabewerte haben. Lass die `quizfrage()` zurückgeben ob die Antwort richtig oder falsch war. Oder Alternativ die Anzahl der Punkte die durch die Beantwortung dazu kommen. Also zum Beispiel 0 wenn falsch geantwortet wurde und 1 wenn richtig geantwortet wurde. Das kannst Du dann auf die Gesamtpunkte addieren.
Die `durchlauf()`-Funktion ist eigenartig. Funktionsnamen sollten beschreiben was die Funktion tut, und das macht der Name `durchlauf` nicht wirklich. Normalerweise sollten es auch Tätigkeiten sein die durch den Namen beschrieben werden. Also zum Beispiel `stelle_quizfrage()` statt `quizfrage`. So kann man besser Namen für Funktionen, und Namen für ”Dinge” auseinander halten.
Re: Nur glatt teilbare Zahlen erzeugen (random)
Verfasst: Mittwoch 19. Februar 2014, 21:53
von Hyperion
Lass doch mal die ganzen Leerzeilen und ``************``-Kommentare weg; die stören nur; insbesondere hier im Forum
Du könntest doch ``durchlauf`` (doofer Name übrigens! Was *tut* denn diese Funktion?) einfach ``berechne_ergebnis`` nennen diese das richtige Ergebnis berechnen und zurückliefern lassen (``return ergebnis``). Dann kannst Du *aus* Deiner Schleife erst die Zahlen generieren lassen, das richtige Ergebnis dazuholen, die Benutzerabfrage machen und danach die Auswertung vornehmen. Im Anschluss kannst Du immer noch in der Schleife die Punkte einfach hochzählen.
Also mal im Pseudocode:
Code: Alles auswählen
def run_quiz(operator_):
while True:
# ``berechne_ergebnis`` weiß intern, welche Funktion es
# aufrufen muss (also Dein altes ``quizfrage`` in etwa)
ergebnis = berechne_ergebnis(operator_)
# in dieser Funktion holst Du dir die Antwort
benutzer_antwort = hole_benutzer_antwort()
# und hier einfach die Auswertung
if(ergebnis == benutzer_antwort):
# ausgabe eines Textes; Punkte hochsetzen
# irgend wann abbrechen
Re: Nur glatt teilbare Zahlen erzeugen (random)
Verfasst: Mittwoch 19. Februar 2014, 22:01
von chris5790
BlackJack hat geschrieben:@chris5790: Auf zur nächsten Eigenschaft von Funktionen: Die können Rückgabewerte haben. Lass die `quizfrage()` zurückgeben ob die Antwort richtig oder falsch war.
Code: Alles auswählen
def antwort(ergebnis):
antwort_benutzer = input()
antwort_benutzer = int(antwort_benutzer)
if antwort_benutzer == ergebnis:
print("Richtig!")
punkte=punkte+1
return(punkte)
else:
print("Falsch!")
Meinst du in etwa so? Mein Buch sagt, dass return() verwendet wird, um Werte auch außerhalb der Funktion benutezn zu können
Re: Nur glatt teilbare Zahlen erzeugen (random)
Verfasst: Mittwoch 19. Februar 2014, 22:20
von BlackJack
@chris5790: So nicht, denn wo kommt denn `punkte` her? Und was gibt die Funktion zurück wenn die Antwort falsch war?
Diese Funktion für *eine* Antwort braucht doch gar nichts über die Punkte insgesamt wissen, sondern dem Aufrufer nur mitteilen ob die eine Frage, für die sie Aufgerufen wurde, richtig oder falsch beantwortet wurde, beziehungsweise wie viele Punkte es für die Beantwortung der Frage gibt.
Re: Nur glatt teilbare Zahlen erzeugen (random)
Verfasst: Donnerstag 20. Februar 2014, 07:58
von BlackJack
Ich habe nicht widerstehen können und das mal (für Python 2) umgesetzt:
Code: Alles auswählen
#!/usr/bin/env python
# coding: utf8
from functools import partial
from operator import add, mul, sub
from random import randint
QUESTION_COUNT = 10
def create_question_data(operation_function, max_operand_value=20):
operand_a = randint(1, max_operand_value)
operand_b = randint(1, max_operand_value)
return (operand_a, operand_b, operation_function(operand_a, operand_b))
def create_div_question_data():
# ...
def ask_for_operator_symbol(symbols):
prompt = 'Welchen Rechenoperator ({0}) moechtest Du benutzen? '.format(
' '.join(symbols)
)
while True:
symbol = raw_input(prompt)
if symbol in symbols:
return symbol
else:
print 'Falsche Eingabe!'
def ask_result(prompt):
while True:
try:
return int(raw_input(prompt))
except ValueError:
print 'Fehler: Eingabe ist keine Zahl!'
def ask_question(symbol, create_data_function):
operand_a, operand_b, expected_result = create_data_function()
result = ask_result('{0} {1} {2} = '.format(operand_a, symbol, operand_b))
is_correct = result == expected_result
print 'Richtig!' if is_correct else 'Falsch!'
return 1 if is_correct else 0
def main():
symbol2create_data_function = {
'+': partial(create_question_data, add),
'-': partial(create_question_data, sub),
'*': partial(create_question_data, mul),
'/': create_div_question_data,
}
symbol = ask_for_operator_symbol(symbol2create_data_function.keys())
create_data_function = symbol2create_data_function[symbol]
print 'Hier kommen Deine {0} Fragen:'.format(QUESTION_COUNT)
points = sum(
ask_question(symbol, create_data_function)
for _ in xrange(QUESTION_COUNT)
)
print 'Du hast {0} Punkt(e).'.format(points)
if __name__ == '__main__':
main()
Die zwei Zeilen von `create_div_question_data()` habe ich hier raus genommen um chris5790 nicht das Erfolgsgefühl zu nehmen selbst eine Lösung für die Frage im Betreff dieses Themas zu finden.

Re: Nur glatt teilbare Zahlen erzeugen (random)
Verfasst: Donnerstag 20. Februar 2014, 15:08
von chris5790
Boah, der Code überfordert mich jetzt schon in gewisser Weise.
Code: Alles auswählen
def ask_for_operator_symbol(symbols):
prompt = 'Welchen Rechenoperator ({0}) moechtest Du benutzen? '.format(
' '.join(symbols)
)
while True:
symbol = raw_input(prompt)
if symbol in symbols:
return symbol
else:
print 'Falsche Eingabe!'
das '.format(' '.join(symbols), was ist das genau? Und woran erkennt er in der Schleife, ob ein falsches Symbol eingegeben wurde? den Teil nach 'while True' versteh ich nicht, ist symbol eine Variable? Oder prüft das, ob ein Rechensymbol eingegeben wurde? Ich denke mich verwirren nur die englischen Variablen oder ich bin immer noch von den heutigen Eindrücken bei unserem neuen Projekt über Python geschockt. Aber dazu mach ich lieber einen eigenen Thread auf

Re: Nur glatt teilbare Zahlen erzeugen (random)
Verfasst: Donnerstag 20. Februar 2014, 15:22
von Sirius3
@chris5790: symbol ist eine Variablem genauso wie symbols. Wenn Dir etwas unklar ist, dann kannst Du Dir einfach einzelne Teile in der Python-Konsole ausgeben lassen:
Code: Alles auswählen
In [1]: symbols = ['+', '-', '*', '/']
In [2]: ' '.join(symbols)
Out[2]: '+ - * /'
In [3]: prompt = 'Welchen Rechenoperator ({0}) moechtest Du benutzen? '.format(
...: ' '.join(symbols)
...: )
In [4]: prompt
Out[4]: 'Welchen Rechenoperator (+ - * /) moechtest Du benutzen? '
In [5]: symbol = '-'
In [6]: symbol in symbols
Out[6]: True
Re: Nur glatt teilbare Zahlen erzeugen (random)
Verfasst: Donnerstag 20. Februar 2014, 15:56
von Hyperion
@chris5790: Der Code von BlackJack ist auch imho (noch) nicht für Dich gedacht; schön, wenn Du versuchen willst, diesen zu verstehen, aber eigentlich ist das eher eine Fingerübung von BlackJack gewesen, der eine pythonische Lösung des Problems aufzeigt. Darin werden natürlich auch weit fortgeschrittene Konzepte der Sprache verwendet, die Du vermutlich noch nicht kennst

Re: Nur glatt teilbare Zahlen erzeugen (random)
Verfasst: Donnerstag 20. Februar 2014, 16:20
von BlackJack
Jo, was Hyperion gesagt hat. Wobei jetzt gerade die Funktion die den Benutzer nach dem Symbol fragt ja eigentlich nichts wirklich fortgeschrittenes macht. Das müsste alles irgendwo im Tutorial vorkommen, oder?
Re: Nur glatt teilbare Zahlen erzeugen (random)
Verfasst: Donnerstag 20. Februar 2014, 18:46
von chris5790
In welchem Tutorial? In der Documentary? Unser Python-Buch verliert da vielleicht 3 Wörter drüber, am Ende, irgendwo in Kapitel 14. Der Schwerpunkt ist turtle, was zum zeichnen halt, wirkoches programmieren ist das nicht...
Re: Nur glatt teilbare Zahlen erzeugen (random)
Verfasst: Donnerstag 20. Februar 2014, 18:47
von BlackJack
Ja, ich meinte das in der Dokumentation.