Tracks
/
Python
Python
/
Übungen
/
Kartenspiele
Kartenspiele

Kartenspiele

Lernübung

Einführung

Eine list ist eine veränderbare Sammlung von Elementen in einer Sequenz. Wie die meisten Sammlungen (siehe die eingebauten tuple, dict und set) können Listen Referenzen auf beliebige (oder mehrere) Datentypen enthalten, auch auf andere Listen. Wie bei jedem Sequenztyp kannst du auf Elemente über 0-based index von links und -1-based index von rechts zugreifen. Listen können vollständig oder teilweise über die Slice-Notation oder <list>.copy() kopiert werden.

Listen unterstützen sowohl allgemeine als auch veränderbare Sequenzoperationen wie min()/max(), <list>.index(), <list>.append() und <list>.reverse(). Über die Elemente einer Liste kannst du mit dem Konstrukt for item in <list> iterieren. for index, item in enumerate(<list>) kannst du verwenden, wenn du sowohl den Index als auch den Wert eines Elements brauchst.

Unter der Haube sind lists als dynamische Arrays implementiert, ähnlich wie Javas ArrayList-Typ, und werden meist verwendet, um Gruppen ähnlicher Daten (Strings, Zahlen, Mengen usw.) unbekannter Länge zu speichern. Listen sind eine extrem flexible und nützliche Datenstruktur, und viele eingebaute Methoden und Operationen in Python liefern Listen als Ergebnis.

Erstellung

Eine list kannst du als Literal mit eckigen [] Klammern und Kommas zwischen den Elementen deklarieren:

>>> no_elements = []

>>> no_elements
[]

>>> one_element = ["Guava"]

>>> one_element
['Guava']

>>> elements_separated_with_commas = ["Parrot", "Bird", 334782]

>>> elements_separated_with_commas
['Parrot', 'Bird', 334782]

Zur besseren Lesbarkeit kannst du Zeilenumbrüche verwenden, wenn eine list viele Elemente oder verschachtelte Datenstrukturen enthält:

>>> lots_of_entries = [
      "Rose",
      "Sunflower",
      "Poppy",
      "Pansy",
      "Tulip",
      "Fuchsia",
      "Cyclamen",
      "Lavender"
   ]
   
>>> lots_of_entries
['Rose', 'Sunflower', 'Poppy', 'Pansy', 'Tulip', 'Fuchsia', 'Cyclamen', 'Lavender']

# Each data structure is on its own line to help clarify what they are.
>>> nested_data_structures = [
      {"fish": "gold", "monkey": "brown", "parrot": "grey"},
      ("fish", "mammal", "bird"),
      ['water', 'jungle', 'sky']
   ]
   
>>> nested_data_structures
[{'fish': 'gold', 'monkey': 'brown', 'parrot': 'grey'}, ('fish', 'mammal', 'bird'), ['water', 'jungle', 'sky']]

Der Konstruktor list() kann leer oder mit einem Iterable als Argument verwendet werden. Der Konstruktor durchläuft die Elemente des Iterables und fügt sie der list der Reihe nach hinzu:

>>> no_elements = list()

>>> no_elements
[]

# The tuple is unpacked and each element is added.
>>> multiple_elements_from_tuple = list(("Parrot", "Bird", 334782))

>>> multiple_elements_from_tuple
['Parrot', 'Bird', 334782]

# The set is unpacked and each element is added.
>>> multiple_elements_from_set = list({2, 3, 5, 7, 11})

>>> multiple_elements_from_set
[2, 3, 5, 7, 11]

Die Ergebnisse, wenn du den list()-Konstruktor mit einem string oder einem dict verwendest, können überraschend sein:

# String elements (Unicode code points) are iterated through and added *individually*.
>>> multiple_elements_string = list("Timbuktu")

>>> multiple_elements_string
['T', 'i', 'm', 'b', 'u', 'k', 't', 'u']

# Unicode separators and positioning code points are also added *individually*.
>>> multiple_code_points_string = list('अभ्यास')

>>> multiple_code_points_string
['अ', 'भ', '्', 'य', 'ा', 'स']

# The iteration default for dictionaries is over the keys, so only key data is inserted into the list.
>>> source_data = {"fish": "gold", "monkey": "brown"}

>>> multiple_elements_dict_1 = list(source_data)
['fish', 'monkey']

Weil der list()-Konstruktor nur Iterables (oder nichts) als Argumente akzeptiert, lösen Objekte, die nicht iterierbar sind, einen Typfehler aus. Folglich ist es viel einfacher, eine list mit einem einzigen Element über die Literal-Schreibweise zu erstellen.

# Numbers are not iterable, and so attempting to create a list with a number passed to the constructor fails.
>>> one_element = list(16)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable

# Tuples *are* iterable, so passing a one-element tuple to the constructor does work, but it's awkward
>>> one_element_from_iterable = list((16,))

>>> one_element_from_iterable
[16]

Zugriff auf Elemente

Auf Elemente in Listen (sowie auf Elemente in anderen Sequenztypen wie str und tuple) kannst du über 0-based index und die Klammer-Notation zugreifen. Indizes können von left --> right (beginnend bei null) oder von right --> left (beginnend bei -1) verlaufen.

Index von links ⟹






0
👇🏾
1
👇🏾
2
👇🏾
3
👇🏾
4
👇🏾
5
👇🏾
P y t h o n
👆🏾
-6
👆🏾
-5
👆🏾
-4
👆🏾
-3
👆🏾
-2
👆🏾
-1





⟸ Index von rechts
>>> breakfast_foods = ["Oatmeal", "Fruit Salad", "Eggs", "Toast"]

# Oatmeal is at index 0 or index -4.
>>> breakfast_foods[0]
'Oatmeal'

>>> breakfast_foods[-4]
'Oatmeal'

# Eggs are at index -2 or 2
>>> breakfast_foods[-2]
'Eggs'

>>> breakfast_foods[2]
'Eggs'

# Toast is at -1
>>> breakfast_foods[-1]
'Toast'

Auf einen Abschnitt der Elemente innerhalb einer list kannst du über die Slice-Notation (<list>[start:stop]) zugreifen. Ein Slice ist eine Elementfolge an der Position index, für die start <= index < stop gilt. Das Slicing gibt eine Kopie der herausgeschnittenen Elemente zurück und verändert die ursprüngliche list nicht.

Ein step-Parameter kann ebenfalls verwendet werden [start:stop:step], um die Elemente der list zu „überspringen" oder zu filtern (zum Beispiel wählt ein step von 2 jedes zweite Element im Bereich aus):

>>> colors = ["Red", "Purple", "Green", "Yellow", "Orange", "Pink", "Blue", "Grey"]

# If there is no step parameter, the step is assumed to be 1.
>>> middle_colors = colors[2:6]

>>> middle_colors
['Green', 'Yellow', 'Orange', 'Pink']

# If the start or stop parameters are omitted, the slice will
# start at index zero, and will stop at the end of the list.
>>> primary_colors = colors[::3]

>>> primary_colors
['Red', 'Yellow', 'Blue']

Arbeiten mit Listen

Die eingebaute Funktion sum() gibt bei einer Liste die Summe aller Zahlen in der Liste zurück:

>>> number_list = [1, 2, 3, 4]
>>> sum(number_list)
10

Du kannst auch die Länge einer Liste mit der Funktion len() ermitteln:

>>> long_list = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"]
>>> len(long_list)
10

Listen können auch auf verschiedene Weise kombiniert werden:

# Using the plus + operator unpacks each list and creates a new list, but it is not efficient.
>>> new_via_concatenate = ["George", 5] + ["cat", "Tabby"]

>>> new_via_concatenate
['George', 5, 'cat', 'Tabby']

# Likewise, using the multiplication operator * is the equivalent of using + n times.
>>> first_group = ["cat", "dog", "elephant"]
>>> multiplied_group = first_group * 3

>>> multiplied_group
['cat', 'dog', 'elephant', 'cat', 'dog', 'elephant', 'cat', 'dog', 'elephant']

Listen stellen einen Iterator bereit und können auf dieselbe Weise wie andere Sequenztypen durchlaufen werden.

#  Looping through the list and printing out each element.
>>> colors = ["Orange", "Green", "Grey", "Blue"]

>>> for item in colors:
...     print(item)
...
Orange
Green
Grey
Blue

Für eine ausführlichere Erklärung von loops und iterators schließe das Konzept loops ab.

Anleitung

Elyse freut sich schon riesig darauf, auf ihrer bevorstehenden Reise nach Vegas Poker (und andere Kartenspiele) zu spielen. Als großer Fan von „Self-Tracking“ möchte sie ein paar kleine Funktionen zusammenstellen, die ihr bei Tracking-Aufgaben helfen, und hat dich gebeten, sie beim Durchdenken dieser Aufgaben zu unterstützen.

1. Pokerrunden verfolgen

Elyse mag Poker besonders gern und möchte nachverfolgen, wie viele Runden sie spielt – und welche Runden das sind. Jede Runde hat ihre eigene Nummer, und jeder Tisch zeigt die Rundennummer an, die gerade gespielt wird. Elyse wählt einen Tisch und setzt sich, um ihre erste Runde zu spielen. Sie plant, drei Runden zu spielen.

Implementiere eine Funktion get_rounds(<round_number>), die die aktuelle Rundennummer entgegennimmt und eine einzelne list zurückgibt, die aus dieser Runde und den nächsten beiden besteht, die als Nächstes kommen:

>>> get_rounds(27)
[27, 28, 29]

2. Alle Runden an einem Ort

Elyse spielte ein paar Runden am ersten Tisch, machte dann eine Pause und spielte noch einige Runden an einem zweiten Tisch ... aber am Ende hatte sie für jeden Tisch eine andere Liste! Sie möchte die beiden Listen zusammenfügen, damit sie alle Pokerrunden an derselben Stelle verfolgen kann.

Implementiere eine Funktion concatenate_rounds(<rounds_1>, <rounds_2>), die zwei Listen entgegennimmt und eine einzelne list zurückgibt, die aus allen Runden der ersten list besteht, gefolgt von allen Runden der zweiten list:

>>> concatenate_rounds([27, 28, 29], [35, 36])
[27, 28, 29, 35, 36]

3. Frühere Runden finden

Als sie über einige der früheren Pokerrunden sprechen, bemerkt ein anderer Spieler, wie ähnlich zwei davon verlaufen sind. Elyse ist sich nicht sicher, ob sie diese Runden gespielt hat oder nicht.

Implementiere eine Funktion list_contains_round(<rounds>, <round_number>), die zwei Argumente entgegennimmt: eine Liste der gespielten Runden und eine Rundennummer. Die Funktion gibt True zurück, wenn die Runde in der Liste der gespielten Runden enthalten ist, und False, wenn nicht:

>>> list_contains_round([27, 28, 29, 35, 36], 29)
True

>>> list_contains_round([27, 28, 29, 35, 36], 30)
False

4. Kartenwerte mitteln

Elyse möchte ein neues Spiel namens Black Joe ausprobieren. Es ähnelt Black Jack, wo dein Ziel ist, dass die Karten auf deiner Hand zusammen einen Zielwert ergeben, aber bei Black Joe ist das Ziel, dass der Durchschnitt der Kartenwerte 7 beträgt. Den Durchschnitt findest du, indem du alle Kartenwerte zusammenzählst und diese Summe dann durch die Anzahl der Karten auf der Hand teilst.

Implementiere eine Funktion card_average(<hand>), die den Durchschnittswert einer Hand bei Black Joe zurückgibt.

>>> card_average([5, 6, 7])
6.0

5. Alternative Durchschnitte

Bei Black Joe ist Geschwindigkeit wichtig. Elyse versucht, einen schnelleren Weg zu finden, um den Durchschnitt zu berechnen.

Sie hat sich zwei Möglichkeiten überlegt, eine durchschnittsähnliche Zahl zu erhalten:

  • Nimm den Durchschnitt der ersten und der letzten Zahl auf der Hand.
  • Verwende den Median (die mittlere Karte) der Hand.

Implementiere die Funktion approx_average_is_average(<hand>). Gegeben ist hand, eine Liste mit den Werten der Karten auf deiner Hand.

Gib True zurück, wenn eine or beide der oben genannten Strategien zu einer Zahl führen, die gleich dem tatsächlichen Durchschnitt ist.

Hinweis: Die Länge aller Hände ist ungerade, damit sich der Median leichter finden lässt.

>>> approx_average_is_average([1, 2, 3])
True

>>> approx_average_is_average([2, 3, 4, 8, 8])
True

>>> approx_average_is_average([1, 2, 3, 5, 9])
False

6. Weitere Durchschnittstechniken

Fasziniert von den Ergebnissen ihres Durchschnittsexperiments fragt sich Elyse, ob der Durchschnitt der Karten an den geraden Positionen und der Durchschnitt der Karten an den ungeraden Positionen dasselbe ergeben würden. Zeit für eine weitere Testfunktion!

Implementiere eine Funktion average_even_is_average_odd(<hand>), die einen booleschen Wert zurückgibt, der angibt, ob der Durchschnitt der Karten an geraden Indizes derselbe ist wie der Durchschnitt der Karten an ungeraden Indizes.

>>> average_even_is_average_odd([1, 2, 3])
True

>>> average_even_is_average_odd([1, 2, 3, 4])
False

7. Regeln für die Bonusrunde

Jede 11. Hand bei Black Joe ist eine Bonushand mit einer Bonusregel: Wenn die letzte Karte, die du ziehst, ein Bube ist, verdoppelst du ihren Wert.

Implementiere eine Funktion maybe_double_last(<hand>), die eine Hand entgegennimmt und prüft, ob die letzte Karte ein Bube (11) ist. Wenn die letzte Karte tatsächlich ein Bube (11) ist, verdopple ihren Wert, bevor du die Hand zurückgibst.

>>> hand = [5, 9, 11]
>>> maybe_double_last(hand)
[5, 9, 22]

>>> hand = [5, 9, 10]
>>> maybe_double_last(hand)
[5, 9, 10]
Über GitHub bearbeiten Der Link öffnet sich in einem neuen Fenster oder Tab
Python Exercism

Bereit, mit Kartenspiele zu starten?

Melde dich bei Exercism an, um Python mit 17 Konzepte146 Übungen und echtem menschlichen Mentoring zu lernen und zu meistern, alles kostenlos.