Übersicht verloren - Fehler versteckt sich

Bild

Betrifft: Übersicht verloren - Fehler versteckt sich
von: Dennis
Geschrieben am: 12.08.2015 16:33:53

Hallo liebes Forum,
ich bin momentan bei der Programmierung von SchiffeVersenken Phase 2.
Man kann bereits gegen einen realen Spieler spielen, jetzt soll man auch noch gegen den PC spielen können. Chris und Rudi haben mir hierbei schon sehr geholfen.
Soweit läuft das ganze auch, jedoch soll der PC noch eine Art "KI" bekommen. Trifft er, so soll er in ein Feld daneben schießen.
Ich habe das mit folgendem Code versucht:

Sub GegnerSpielt()
    Dim a As String
    Dim b As Integer
    Dim c As Integer
    Dim d As Variant
    Dim e As String
    Dim j As Long
    Dim f As Integer
    Dim g As String
    Dim h As Variant
    Dim x As Integer
    Dim IntC As Integer
    Dim IntC2 As Integer
    Dim IntC3 As Integer
    Dim IntC4 As Integer
    j = 3
       
    Do
        b = Int(10 * Rnd + 1) + 64
        a = Chr(b)
        c = Int((10 * Rnd) + 1)
        c = c + 14
                          
        d = a & c
                          
        IntC = Application.CountIf(Range("C3:C100"), d)
'diese Range bekommt den Zellwert, in den geschossen wird.
'durch ein Change event wird dieser Wert weiterverarbeitet
        IntC2 = Application.CountIf(Worksheets("Spielfeld").Range("C17:L26"), "x")
        If IntC2 = 30 Then Exit Sub
'dann ist das Spiel vorbei
        If IntC = 0 Then
        Worksheets("PC").Cells(1, 3).End(xlDown).Offset(1, 0).Value = d
        IntC3 = Application.CountIf(Worksheets("Spielfeld").Range("C17:L26"), "X")
            If IntC3 > IntC2 Then GoTo sprungziel
'zählt durch, ob es jetzt mehr "x" gibt als vorher, also getroffen wurde
        Exit Sub
        Else
        End If
        
sprungziel:
        
        x = 3
        Do While IsEmpty(Cells(x, 3)) = False
        
        Worksheets("PC").Cells(1, 3).End(xlDown).Select
        e = Mid(Selection, 1, 1)
        f = Asc(e)
        f = f + 1
        g = Chr(f)
        
            h = g & c
            IntC4 = Application.CountIf(Worksheets("PC").Range("C3:C100"), h)
            If IntC4 = 0 Then
            Worksheets("PC").Cells(1, 3).End(xlDown).Offset(1, 0).Value = h
            Exit Do
            End If
'meine idee: er liest den letzten Wert aus der Range(C3:C100) aus und da dies
'ein Treffer war, nimmt er sich den ersten Buchstaben und zählt ihn hoch
                      
            f = f - 2
            g = Chr(f)
            h = g & c
            IntC4 = Application.CountIf(Worksheets("PC").Range("C3:C100"), h)
            If IntC4 = 0 Then
            Worksheets("PC").Cells(1, 3).End(xlDown).Offset(1, 0).Value = h
            Exit Do
            End If
'hat er bereits dorthin geschossen, verändert er auch die Zeilen
            f = f + 1
            c = c + 1
            g = Chr(f)
            h = g & c
            IntC4 = Application.CountIf(Worksheets("PC").Range("C3:C100"), h)
            If IntC4 = 0 Then
            Worksheets("PC").Cells(1, 3).End(xlDown).Offset(1, 0).Value = h
            Exit Do
            End If
            
            c = c - 2
            h = g & c
            IntC4 = Application.CountIf(Worksheets("PC").Range("C3:C100"), h)
            If IntC4 = 0 Then
            Worksheets("PC").Cells(1, 3).End(xlDown).Offset(1, 0).Value = h
            Exit Do
            End If
            
        x = x + 1
        Loop   
    Loop
End Sub
Anmerkung:
Wie gesagt werden die Werte in die Range(C3:C100) geschrieben. Ein Changeevent wertet die Zellen aus und markiert in einem anderen Tabellenblatt den Schuss (als Niete oder Treffer).
Soweit die Theorie. Leider erhalte ich einen "400"er Fehler, sobald er in die Sprungmarke hüpft.
Wahrscheinlich ist das viel zu kompliziert gedacht und ich seh den Wald vor lauter Bäumen nicht.
Liebe Grüße,
Dennis

Bild

Betrifft: AW: Übersicht verloren - Fehler versteckt sich
von: Rudi Maintaire
Geschrieben am: 12.08.2015 16:55:01
Das steht doch in
GetPossibleCells
Gruß
Rudi

Bild

Betrifft: AW: Übersicht verloren - Fehler versteckt sich
von: Dennis
Geschrieben am: 13.08.2015 08:25:48
Guten Morgen Rudi,
ich habe zuerst versucht, die Vorlage zu verstehen. Jedoch tue ich mir dabei als Neuling noch sehr schwer und habe es daher auf meine eigene Art versucht.
In der Vorlage wird zwischen so vielen Funktionen gesprungen, dass ich nicht mehr sehe, was ich benötige..daher mein eigener Versuch und der anschließende Beitrag.
Ich hoffe, dass ich den Teil noch in mein Projekt einbauen kann, denn dann wäre das Spiel endgültig fertig. Über jede Hilfe, sei es Anpassung meines Versuchs oder der Erklärung der Vorlage, wäre ich überaus dankbar.
Viele liebe Grüße,
Dennis

Bild

Betrifft: noch offen? Datei...
von: Michael
Geschrieben am: 16.08.2015 14:06:38
Hi Dennis,
ich würde ja mal drüberschauen, aber bitte: mit Datei, alles andere wäre im Trüben fischen...
Schöne Grüße,
Michael

Bild

Betrifft: Datei
von: Dennis
Geschrieben am: 17.08.2015 10:59:12
Hallo Michael,
vielen Dank für deine Unterstützung.
Anbei findest du die Datei. In Tabelle 3 (PC) ist der besagte Code Abschnitt (momentan auskommentiert).
https://www.herber.de/bbs/user/99638.xlsm
Bei weiteren Fragen stehe ich natürlich zur Verfügung.
Vielen Dank und einen guten Start in die neue Woche.
Gruß,
Dennis

Bild

Betrifft: AW: Datei
von: Michael
Geschrieben am: 17.08.2015 17:57:19
Hi Dennis,
jetzt habe ich grad versehentlich den Browsertab geschlossen - alle Eingaben weg - grrrr.
Also nochmal:
a) wie machst Du das, die Spalten auszublenden und blau zu hinterlegen?
b) Benenne bitte Deine Subs um, z.B. von Sub Schaltfläche6_Klicken() auf Sub Btn_Neues_Spiel()
Das wird Dir sehr helfen, die Übersicht wiederzugewinnen.
Hinterher mußt Du dann dem Button das Makro mit dem neuen Namen wieder zuweisen.
Weißt Du, wie das geht?
c) Um einen Codeblock auszukommentieren, markierst Du ihn und klickst auf "Block auskommentieren", mit dem Button rechts daneben kannst Du das wieder rückgängig machen:
Userbild
d) Dein Makro ist bei meinem ersten Test abgeschmiert, so daß ich X neu starten mußte.
Ich kann nicht nachvollziehen, warum, aber ich finde es ungut, die Ereignisse (Worksheet_Change usw.) für etwas zu verwenden, was genauso gut ohne, durch direkten Aufruf geht - oder durch direkte Integration der Logik in die jeweilige Sub.
In Deiner "GegnerSpielt" wird nach Ausführung der Zeile 141 (hochgeladener Stand):

Worksheets("PC").Cells(1, 3).End(xlDown).Offset(1, 0).Value = d

direkt das Worksheet_Change in Tabelle3 gestartet, und von dem aus dann gleich das Worksheet_Change im Spielfeld Tabelle1.
Raus mit den Dingern!
e) eineinhalb offensichtliche Fehler sind im Block (wie d)) in den Zeilen ab 137:
137:        IntC = Application.CountIf(Range("C3:C100"), d)
138:        IntC2 = Application.CountIf(Worksheets("Spielfeld").Range("C17:L26"), "x")
usw.      If IntC2 = 30 Then Exit Sub
        If IntC = 0 Then
        Worksheets("PC").Cells(1, 3).End(xlDown).Offset(1, 0).Value = d
        IntC3 = Application.CountIf(Worksheets("Spielfeld").Range("C17:L26"), "X")

Der halbe: die Ermittlung von IntC ist *möglicherweise* hakelig ohne Angabe von Worksheets(bla).
Der Ganze ist in 138 die Suche nach einem kleinen x, das aber im gesamten Projekt nicht gesetzt wird. Hier muß ein großes "X" rein.
f) ich habe das ewig nicht mehr gespielt; ist es richtig, daß man (oder die KI, hehe) nach einem Treffer nochmal darf?
Zu guter Letzt: es juckt mich ein bißchen in den Fingern, Deinen Code umzuändern und zu vereinfachen; aber Du möchtest es ja gerne selber machen: *wenn* ich mal anfange, sieht es hinterher sicher ziemlich anders aus - ich will Dir nicht den Spaß verderben!
Schöne Grüße,
Michael
P.S.: ich spiele jetzt trotzdem mal ein bißchen herum und melde mich später nochmal

Bild

Betrifft: Fragenkatalog abarbeiten:
von: Dennis
Geschrieben am: 18.08.2015 08:29:36
Hallo Michael!
ich versuche mich mal durch deine Punkte zu arbeiten ;) :
a) Hier verstehe ich leider nicht genau, was du meinst? Welche Spalten blende ich denn aus?
b) Das stimmt, habe ich mir auch schon überlegt. Wie ich die Makros anschließend neu verknüpfe ist mir bekannt.
Allgemein muss ich sagen, dass ich das SchiffeVersenken-Projekt gemacht habe, um vertrauter mit VBA zu werden. Ich schreibe momentan meine Bachelorarbeit und habe ein Projekt mit VBA bearbeitet..um das etwas besser hinzubekommen entstand das Nebenprojekt zum Üben ;)
c) Danke, das ist ein sehr hilfreicher Tipp!
d) Warum das Makro abgeschmiert ist, kann ich leider nicht sagen. Ich hatte damit noch keine Absturzprobleme.
Dass das mit den Changebefehlen nicht so schön ist, mag sein..aber ich war ehrlich gesagt sehr froh, einfach eine funktionierende Lösung zu finden :)
Dennoch danke für den Hinweis.
e) Da hast du Recht, das werde ich direkt mal anpassen!
f) Genau :) So habe ich das auch versucht zu programmieren (Was der PC auch tut..er zählt die Anzahl der X vor und nach seinem Schuss. Ist die Anzahl danach größer, schießt er nochmal, usw.) War sehr froh, als mir der Lösungsweg eingefallen ist und geklappt hat! Jetzt sollte er nur noch "schlau" schießen und nicht auf H8 schießen, wenn er zuvor bei A1 getroffen hat..;)
Sehr gerne kannst du rumbasteln wie du möchtest, denn auf Grund der Bachelorarbeit bin ich momentan leider selbst sehr eingespannt und hätte das Projekt jetzt erstmal auf Eis gelegt.
Viele Grüße und Danke,
Dennis

Bild

Betrifft: AW: Fragenkatalog abarbeiten:
von: Michael
Geschrieben am: 18.08.2015 17:22:12
Hi Dennis,
ich habe gestern dran herumgespielt, bin aber zu keinem vorzeigbaren Ergebnis gekommen.
Deshalb nur kurz ad ..
a) na, auf dem Blatt "Spielfeld" sind doch alle Spalten rechts von Spalte "T" nicht zu sehen, sondern blau.
b) gerade bei ner Bachelor-Arbeit werden sich die Korrektoren freuen, wenn Du solche Konventionen einhältst. Von den Leuten, die hier antworten, sticht vor allem Sepp durch optimal durchgestylten Code heraus; da ist alles drin, was reingehört: errorhandling, Übersichtlichkeit und v.a. auch "sprechende" Namen. Bei Btnxxx steht das Btn für Button, dann sieht man gleich, daß die Sub von einem Button aufgerufen wird usw., aber auch bei Variablennamen richtig lehrbuchmäßig: Long-Variablen beginnen mit lng usw.
Ich persönlich bin mit einem schnell deklarierten i&, j&, k& (& steht für "as long") durchaus zufrieden, derweil es meinen (vielleicht schlechten, zugegeben) Lesegewohnheiten durchaus entgegen kommt (für ne Laufvariable in einer Schleife mag ich einfach nicht lngI, lngK usw. schreiben)(nee, es ist eher die "schnelle", optische Unterscheidbarkeit beim Überfliegen eines Codes: kurze Variablen wie ein i sind innerhalb der allesamt längeren Schlüsselwörter gut als solche erkennbar), aber es sieht in "offiziellen" Programmen vielleicht schräg aus.
Und das war's auch schon wieder; bis vielleicht später,
M.

Bild

Betrifft: So, aber jetzt
von: Michael
Geschrieben am: 18.08.2015 21:48:01
Hi Dennis,
so, jetzt habe ich ne ganze Ecke dran herumgebastelt.
Zuvor noch das:
d) Abstürze: die scheinen aufzutauchen, wenn man mehrmals reset oder neues Spiel drückt - dann erscheint kurz so was wie Objekt nicht gefunden, und beim Debuggen landet Ex bei Spielauswahl.Show.
Es scheint auch damit zusammenzuhängen, daß nach der Eingabe der Schiffe beim Klicken auf Fertig noch kurz das Fenster mit klein/groß zu sehen ist...
Um *keine anderen (vorhandenen) Funktionen* zu beeinträchtigen, habe ich in "PC"!Y1 einen Wert eingeführt, der WAHR oder FALSCH ist und der von den WS_Changes abgefragt wird. "Mein" Programm setzt zu Beginn auf FALSCH und am Ende wieder auf WAHR.
Meine hauptsächliche Erweiterung ist im Modul "Michael": Sub GegnerSpielt(), die ich in "Spielfeld"-gegen den PC - auf den Button "Zug" gelegt habe. (Beim Testen habe ich eigentlich NUR die Maschine ziehen lassen)
In "PC" habe ich einige (andere) Spalten für die Logik herangezogen. In U1 steht die Anzahl der Treffer, ab U2 runterwärts die Adressen der Treffer, jeweils rechts daneben wird mit 5 vorbelegt, und sobald Treffer vorhanden sind (Variable u1 größer als 0), wird ermittelt, welche und wie viele Möglichkeiten es gibt, direkt neben einen Treffer zu "setzen". Die Anzahl der Treffer landet wiederum in V (und sobald alle vier Felder abgegrast sind, als0 V(zeile)=0 ist, wird der Treffer nicht mehr ausgewertet), und die Adressen der möglichen Züge in Spalte S.
Intern wird eine Variable s1 mitgeschleppt, die die Anzahl der Züge in S beinhaltet, und mit dieser Anzahl wird der Zufallsgenerator gefüttert.
Falls keine Treffer vorhanden sind bzw. s1=0 ist (alle Felder sind bereits abgegrast), wird die Adresse aus Spalte T gezogen.
Damit hat es folgendes auf sich: in T1 steht, wieviele Adressen vorhanden sind, am Anfang natürlich 100 (das wird in Modul2/Sub SchiffeSetzen() am Ende initialisiert); bei jeder "verbrauchten" Adresse wird die letzte unbenutzte an die Stelle der verbrauchten geschrieben und der Wert in T1 um 1 vermindert.
Dadurch ist der ganze Algorithmus "sauberer", d.h. es werden keine Werte "ins Blaue" gezogen und dann ausgewertet, sondern es wird erst ausgewertet, und der Zufallsgenerator zieht nur aus "validen" Werten.
Wie immer hat sich der Algo dann doch nicht als so einfach herausgestellt wie anfangs gedacht, und wie immer ist er sicher verbesserungswürdig, aber er scheint zu tun, und manchmal sogar erschreckend gut.
Die Datei: https://www.herber.de/bbs/user/99676.xlsm
Happy Exceling,
Michael

Bild

Betrifft: Antwort folgt
von: Dennis
Geschrieben am: 19.08.2015 16:12:20
Hallo Michael,
leider hatte ich bisher noch nicht genug Zeit, mich mit deiner Version ausführlich zu beschäftigen. Dennoch bereits ein großes Dankeschön!
zu
a) ich habe einfach alle Spalten rechts davon ausgeblendet. Bei mir ist da nichts blau, sondern grau :O :)
b) zum Glück kennen sich meine Korrektoren nicht mit VBA aus, sie werden anschließend nur das Ergebnis sehen. Das Ganze dient eher als Übung für mich, um meine eigenes Bachelorprojekt schöner zu gestalten.
Aber natürlich hast du Recht. Ich werde mir deinen Vorschlag zu Herzen nehmen und den Code sauberer schreiben!
Deine verbesserte Version werde ich mir in Ruhe anschauen und mich dann anschließend nochmal melden!
Liebe Grüße und einen schönen Abend,
Dennis

 Bild

Beiträge aus den Excel-Beispielen zum Thema "Übersicht verloren - Fehler versteckt sich"