Ein großer Fortschritt gegenüber meinen bisherigen Ansätzen ist jedenfalls, dass das Spielfeld als eine Liste von Elementen codiert ist und erst in der Ausgabe als Feld (Höhe x Breite) erscheint. Die Repräsentation als Liste ist m. E. einfacher als eine Liste bestehend aus einzelnen Listen zu verwalten.
Hier das Skript:
import random def minenfeld_erzeugen(breite,hoehe,minen): ''' Diese Funktion erzeugt das Spielfeld ''' felder = minen * "*" + (breite * hoehe - minen) * "0" felder = [a for a in felder] random.shuffle(felder) return felder def minenfeld_ausgeben(felder,breite): ''' Das Minenfeld ausgeben ''' for position,feld in enumerate(felder,1): if feld == "0": print(".",end=",") else: print(feld,end=",") if position % breite == 0: print() def minenfeld_zahlen_eintragen(felder): ''' Beispiel .... ..11 ...* 111* *... *322 *.*. *3*1 1 2 3 \|/ 4-X-6 /|\ 7 8 9 ''' for position,feld in enumerate(felder): if feld == "*": pass # Da ist eine Mine drauf else: feld = int(feld) ''' 1 2 3 \|/ 4-X-6 /|\ 7 8 9 ''' positionen = [] ''' Problem Im Augenblick werden Sachen fälschlich ausgewertet, m. E. gibt es 5 Sonderfälle, die abgefangen werden müssen B CCCC D A XXXX E A XXXX E ''' # Fall B if position == 0: positionen = [position + 1, # 6 position + breite, # 8 position + breite + 1] # 9 # Fall A elif position % breite == 0: positionen = [position - breite, # 2 position - breite + 1, # 3 position + 1, # 6 position + breite, # 8 position + breite + 1] # 9 # Fall D elif position == breite -1: # Muss hier stehen, weil sonst die Bedingng # bei Fall C das hier 'überschreibt' # War zuvor Ursache für einen Bug positionen = [position - 1, # 4 position + breite - 1, # 7 position + breite,] # 8 # Fall C elif position < breite: positionen = [position - 1, # 4 position + 1, # 6 position + breite - 1, # 7 position + breite, # 8 position + breite + 1] # 9 # Fall E # Hier hatte ich Pkt. (%) vor Strich uebersehen elif (position + 1) % breite == 0: positionen = [position - breite - 1, # 1 position - breite, # 2 position - 1, # 4 position + breite - 1, # 7 position + breite] # 8 # Fall X else: positionen = [position - breite - 1, # 1 position - breite, # 2 position - breite + 1, # 3 position - 1, # 4 position + 1, # 6 position + breite - 1, # 7 position + breite, # 8 position + breite + 1] # 9 for item in positionen: try: # print(item,felder[item]) if felder[item] == "*": feld += 1 except IndexError: pass felder[position] = str(feld) return felder # Eigentlich breite = 30 hoehe = 15 minen = 60 felder = minenfeld_erzeugen(breite,hoehe,minen) felder = minenfeld_zahlen_eintragen(felder) minenfeld_ausgeben(felder,breite)Hauptprobleme in der Entwicklung waren:
- Die Abhandlung der verschiedenen Fälle war problematisch, weil ich die if-Bedingungen zunächst von A nach E aufgelistet habe und somit einzelne Bedingungen nicht geprüft wurden, weil eine Bedingung zuvor erfüllt war. Dies führte zu Fehlern beim Minen legen.
- Die verschiedenen Fälle zu umgehen ist mir nicht gelungen. Ich hätte gerne gehabt, dass die Fälle einfacher abzufangen gewesen wären, um mir unnötige Tipparbeit zu ersparen. Eine sinnvolle Lösung habe ich hier aber nicht gefunden.
- Eine objektorientierte Umsetzung drängt sich hier m. E. auf. Die drei Funktionen scheinen alle von einer anzulegenden Klasse Spielfeld abhängig.
Nachtrag
Ich habe mir gerade die offizielle Musterlösung in Java angesehen, die von Don Brace stammt. Im entsprechenden Code-Abschnitt, der gewisse Ähnlichkeiten zu meinem Ansatz aufweist, schreibt er:/* * This could be better optimized, but I leave it up to you :) */
Zumindest kommt er zum gleichen Ergebnis wie ich.
Ich finde ja sowohl die flache Liste als auch die vielen handgeschriebenen Sonderfälle nicht so schön. Ich hätte eine verschachtelte Liste genommen, eine Koordinaten-Klasse und immer alle 9 Möglichkeiten getestet. Man kann ja prüfen ob die Koordinate innerhalb des Spielfelds liegt oder nicht.
AntwortenLöschen