Reversi KI

Übersicht BlitzBasic Beginners-Corner

Gehe zu Seite Zurück  1, 2, 3, 4  Weiter

Neue Antwort erstellen

Midimaster

BeitragMi, Feb 03, 2010 19:05
Antworten mit Zitat
Benutzer-Profile anzeigen
Bevor du aber an die KI gehst, sollte das Spiel fehlerffei laufen. Dazu kapseln wir alle Funktionen und reduzieren den Code auf ein Minimum. Wenig Code heißt auch wenig Fehler.

Du erkennst jetzt schon an der Scan-Funktion wieviele Deiner Code-Zeilen nun durch eine kurze Funktion ersetzt werden konnten.


Hier mal schnell der neue Header deines Programms. Ich habe ihn auf das nötigste reduziert. Mehr ist nicht nötig!


BlitzBasic: [AUSKLAPPEN]
Graphics 640, 480, 16, 2
Dim Feld%(64,9,9)
Global SpielerFertig%

Arial = LoadFont("Arial",15)
SetFont Arial

Global Schwarz= LoadImage ("schwarz.bmp")
Global Weiss =LoadImage ("weiss.bmp")

FeldReset

Repeat
If SpielerFertig=0 Then
;SpielerSetzt
Else
;ComputerSetzt
EndIf
MaleSpielFeld()
Until KeyHit(1)
End
;-------------ab hier stehen alle Funktionen:









Da du soweit bist, kommt hier die nächste Funktion. Die stellt einfach fest, ob an einem bestimmten Feld das Setzen des Steins erlaubt wäre:

BlitzBasic: [AUSKLAPPEN]
Function IstEsHierErlaubt%(X%,Y%,Ich%)
...
wenn ja Return True
wenn nein Return False

End Function

Erlaubt ist es immer dann, wenn wenigsten in einer der 8 Richtungen um den Stein etwas umgedreht werden könnte.

Stell dir vor wir stünden hier:

Code: [AUSKLAPPEN]
0 0 0 0 0
0 0 0 0 0
0 0 X 0 0
0 0 0 0 0
0 0 0 0 0


und wir wollen alle acht Richtungen testen:

Code: [AUSKLAPPEN]
0 0 0 0 0
0 1 2 3 0
0 4 X 6 0
0 7 8 9 0
0 0 0 0 0


dann könnten wir das dadurch erreichen, die Function ScanneEineRichtung() für alle möglichen Richtungen aufzurufen.

Innerhalb der Funktion testen wir also von Standpunkt X/Y einfach alle 8 Richtungen durch Aufrufen der ScanneEineRichtung():

BlitzBasic: [AUSKLAPPEN]
;nördliche Richtungen:
ScanneEineRichtung( X, Y, -1, -1, ich)
ScanneEineRichtung( X, Y, 0, -1, ich)
ScanneEineRichtung( X, Y, +1, -1, ich)
;West und Ost:
ScanneEineRichtung( X, Y, -1, 0, ich)
;ScanneEineRichtung(X, Y, 0, 0, ich) ;<--Unsinn, weil Bewegung=0
ScanneEineRichtung( X, Y, +1, 0, ich)
;südliche Richtungen:
ScanneEineRichtung( X, Y, -1, +1, ich)
ScanneEineRichtung( X, Y, 0, +1, ich)
ScanneEineRichtung( X, Y, +1, +1, ich)

Durch 8 Kombinationen aus "-1" "0" und "+1" jeweils für XRichtung und YRichtung decken wir alle 8 Richtungen ab.


Jetzt wird es wieder abgefahren:

Das läßt sich zwar schön durch 8 Befehlszeilen schreiben, aber auch durch zwei verschachtelte For/Next-Schleifen:

BlitzBasic: [AUSKLAPPEN]
For i=-1 To 1
For j=-1 To 1
ScanneEineRichtung (X, Y, i, j, Ich)
Next
Next

Dabei tritt zwar auch die Richtung 5 ("keine Bewegung", siehe oben) auf, da sie aber in der ScanneEineRichtung() keinen Schaden anrichtet, lassen wir sie einfach mitlaufen. So wird der Code wieder superkurz.

Änderung: Wir testen alle 9 Richtungen, aber summieren, uns was zurückgemeldet wurde.
BlitzBasic: [AUSKLAPPEN]
For i=-1 To 1
For j=-1 To 1
Ergebnis = ScanneEineRichtung(X, Y, i, j, Ich)
Summe =Summe + Ergebnis
Next
Next

Nur wenn wirklich in keiner der 8 Richtungen etwas gefunden wurde bleibt Summe so null!

Hier nun die gesamte Funktion:

BlitzBasic: [AUSKLAPPEN]
Function IstEsHierErlaubt%(X%,Y%,Ich%)
Local Ergebnis%, Summe%, i%, j%
If Feld(Ebene,X,Y)=0 Then
For i=-1 To 1
For j=-1 To 1
Ergebnis = ScanneEineRichtung(X, Y, i, j, Ich)
Summe =Summe + Ergebnis
Next
Next
EndIf
Return summe
End Function
 

neolein

BeitragDo, Feb 04, 2010 10:40
Antworten mit Zitat
Benutzer-Profile anzeigen
was ist FeldReset? macht reset Alles auf 0? Die Repeat Schleife im Header: Ist die für die ersten 4 Steine? Da sie ja 64 Ebenen groß ist, oder die Schleife für das setzen aller Steine für das ganze Spiel? Die Schleife ist gut, wenn ich nicht setzen kann (was oft passiert besonders am Ende), dann setzt der Gegner

OK- das heißt die Summe ist die Summe der Möglichkeiten, also maximal 8, wir brauchen auch noch die summe der Steine, die umgedreht wurde. Wenn wir beide Zahlen haben kann man damit schon sehr viel anfangen
  • Zuletzt bearbeitet von neolein am Do, Feb 04, 2010 14:46, insgesamt einmal bearbeitet

Midimaster

BeitragDo, Feb 04, 2010 12:01
Antworten mit Zitat
Benutzer-Profile anzeigen
FeldReset()

ja, das ist eigentlich dein Code 1:1 übernommen. Ich hab nur alles für einen Start Relevante in eine Funktion FeldReset() zusammengefasst. Den Code findest du in meinem Beitrag vom 01.02. um 18:10. In der Funktion werden alle Felder in allen Ebenen auf 0 gesetzt und gleich noch die 4 Anfangsteine positioniert. Dann kann man später leicht ein neues Spiel beginnen. Sollte uns später noch irgendetwas einfallen, was vor dem ersten Spiezug noch justiert werden muss, können wir es immer in diese Funktion schreiben.


Repeat-Schleife

Nein, sie ist das eigentliche Hauptprogramm. Dort findet, wie man schon jetzt etwas erkennen kann, der Wechsel zwischen den beiden Spielern (Spieler und Computer) statt und das Spielfeld wird neu gemalt. Solche Main-Schliefen sind oft so kurz und präzise. Wir können aber, wenn uns später noch was einfällt, auch hier weitere Zeilen einfügen. Typischerweise läuft diese Mainschleife im Dauerbetrieb und wird jede 1/60-tel Sekunde durchlaufen. Die Variable SpielerFertig% weiss immer, wer als nächstes dran ist. Ist sie gerade 0 gibt sie dem Spieler eine Chance zu agieren. Der setzt sie auf 1, sobald er gezogen hat und der Zug erlaubt war. Jetzt wechselt das ganze zum Computer, der seine Aktion vollendet und die Variable dann wieder auf 0 setzen wird.


Summe der Steine
Zitat:
...OK- das heißt die Summe ist die Summe der Möglichkeiten, also maximal 8, wir brauchen auch noch die summe der Steine...

Nicht ganz richtig. Die Variable Ergebnis liefert ja in jedem der 8 Aufrufe zurück, wieviele Gegner hier umgedreht werden könnten. Also enthält Summe die Summe dieser Steine. Das können auch mehr als 8 sein. Würde der Akteur seinen Stein dort wirklich setzen, könnten wir Summe gleich verwenden, um die Anzahl der wirklich umgedrehten Steine zu wissen.

Allerdings.. In der ScanneEineRichtung() wird noch gar kein einziger Stein umgedreht. Diese Funktion sieht nur nach, ob und wieviel umgedreht werden könnte.


Erstelle eine Dreh-Funktion
(an die anderen: lasst das bitte mal Neolein machen! Bitte keinen Code posten)

Bitte erstelle doch aus einer Kopie von ScanneEineRichtung() eine Funktion DreheEineRichtung(), die das Umändern der Steinfarbe wirklich für 1 Richtung tut.

Aus einer Kopie von IstEsHierErlaubt() müsste sich ebenfalls leicht eine Funktion AllesDrehen() entwickeln lassen, die durch 8-maliges Aufrufen der neuen DreheEineRichtung() alle Steine in alle 8 Richtungen auf die eigene Farbe ich% setzt.

Diese beiden Funktionen brauchen wir als nächstes. Um diese Funktion zu erhalten sind nur wenig Änderungen an den Ausgangsfunktionen nötig. Probiers bitte mal und stell dein Ergebnis dann rein.

Wichtige Bitte
Bitte zitiere nie den gesamten Text des vorherigen Posts in deinem Beitrag. Wir bekommen sonst Ärger mit den Forum-Moderatoren.


SpielerSetzt()

so jetzt noch eine weitere Funktion von mir. Ich habe alles, was für den Spielerzug (nicht Computer) nötig ist, in dieser Funktion zusammengefasst:

BlitzBasic: [AUSKLAPPEN]
Function SpielerSetzt()
Local Mausx%, MausY%
MausX=MouseX()/50
MausY=MouseY()/50

If MouseHit(1) Then
If IstEsHierErlaubt(MausX,MausY,1)
Feld(Ebene,MausX,MausY)=1
AllesDrehen(MausX,MausY,1)
SpielerFertig=1
EndIf
EndIf
End Function

Die Zeilen dürften dir im einzelnen aus deinem Code bekannt vorkommen. Wie du siehst verwendet sie bereits die AllesDrehen(), die du schreiben sollst....

BladeRunner

Moderator

BeitragDo, Feb 04, 2010 12:56
Antworten mit Zitat
Benutzer-Profile anzeigen
Neolein, würdest Du es bitte unterlassen Riesenposts zu zitieren? Das stand alles direkt über deiner Antwort, also kann man sich auch so denken dass Du darauf antwortest.
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92
 

neolein

BeitragDo, Feb 04, 2010 23:51
Antworten mit Zitat
Benutzer-Profile anzeigen
OK, ich wills mal versuchen, da die Felder, die umgedreht werden müssen ja durch die Function ScanneEineRichtung schon feststehen müsste man jedes Feld, was <> Ich ist, zu Ich machen.

0 scheidet ja aus, durch die vorherige Funktion.

Wenn nun in einer Richtung (hier Bsp. Osten) ein Ich auftaucht ist die Funktion zu Ende.

Daher muss dieser Teil zuerst kommen, und dann die Abfrage, ob ein gegnerischer Stein vorliegt.

Bin mir nicht sicher, ob es richtig ist, die Funktion durch Return Ende zu verlassen, ansonsten sollte er in Etwa so aussehen

Code: [AUSKLAPPEN]

Function DreheEineRichtung% (X%, Y%, RichtungX%=1, Ich%=1)
    Local Ende%
    Repeat

        X=X+RichtungX
        Y=Y+RichtungY

        If Feld (Ebene,X,Y)=Ich Then
                ; eigenes Feld gefunden
                Return Ende

        ElseIf Feld(Ebene,X,Y)<>Ich Then
                ; Ich
                Feld(Ebene,X,Y)=Ich

        EndIf
     Forever
  End Function

D2006

Administrator

BeitragDo, Feb 04, 2010 23:53
Antworten mit Zitat
Benutzer-Profile anzeigen
Ist eigentlich schonmal jemandem aufgefallen, dass das so rein gar nix mit den Eigenheiten von BlitzPlus zu tun hat? Very Happy

Arrow ~VERSCHOBEN~
Intel Core i5 2500 | 16 GB DDR3 RAM dualchannel | ATI Radeon HD6870 (1024 MB RAM) | Windows 7 Home Premium
Intel Core 2 Duo 2.4 GHz | 2 GB DDR3 RAM dualchannel | Nvidia GeForce 9400M (256 MB shared RAM) | Mac OS X Snow Leopard
Intel Pentium Dual-Core 2.4 GHz | 3 GB DDR2 RAM dualchannel | ATI Radeon HD3850 (1024 MB RAM) | Windows 7 Home Premium
Chaos Interactive :: GoBang :: BB-Poker :: ChaosBreaker :: Hexagon :: ChaosRacer 2
 

neolein

BeitragFr, Feb 05, 2010 0:20
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich hoffe der Code läuft in BlitzPlus, ein anderes Programm habe ich nicht, außerdem vermisse ich deinen Nebensatz, "....sondern mit den Eigenheiten von BlitzMax, oder Blitz3D".

Othello ist nebenbei gesagt ein immens komplexes Spiel, das Schach in kaum Etwas nachsteht, sollte es nicht möglich sein in BlitzPlus eine ausgefeilte uznd schnelle KI zu programmieren, die bereits im Umlauf befindlichen Othello Programmen paroli bieten kann wäre ich ein wenig ernüchtert, ich bezweifle aber, daß es nicht möglich sein soll, jedes Programm ist immer so gut oder so schlecht, wie der der es schreibt, das ist wie in der Fotografie mit den Fotoapparaten.

Midimaster

BeitragFr, Feb 05, 2010 2:35
Antworten mit Zitat
Benutzer-Profile anzeigen
ja, fast genauso müßte die aussehen, allerdings hattest du als Vorlage nicht die endgültige ScanneEineRichtung() verwendet sondern eine Vorversion bei der oben noch Richtung%=1 festgelegt war und die RichtungY% völlig fehlte:


Zitat:
Function DreheEineRichtung% (X%, Y%, RichtungX%=1, Ich%=1)

muss also werden zu:
BlitzBasic: [AUSKLAPPEN]
Function DreheEineRichtung (X%, Y%, RichtungX%, RichtungY%, Ich%)


Du kannst eine Funktion auch mit einem einfachen RETURN abbrechen und musst nicht unbedingt einen Wert Ende% übergeben. Ist aber eher kosmetisch und auch mit Rückgabe einer 0 möglich.

Auch diese Zeile kann man weglassen. (Aber auch mit ihr würde der Code laufen):
Zitat:
ElseIf Feld(Ebene,X,Y)<>Ich Then

Alle Fälle bei denen Felder = ich waren, wurden ja gerade vorher schon abgezweigt.

Die finale Version von DreheEineRichtung() sieht also so aus:
BlitzBasic: [AUSKLAPPEN]
Function DreheEineRichtung (X%, Y%, RichtungX%, RichtungY%, Ich%)
Repeat
X=X+RichtungX
Y=Y+RichtungY
If Feld (Ebene,X,Y)=Ich Then
Return
EndIf
Feld(Ebene,X,Y)=Ich
Forever
End Function



2 Funktionen musst du noch schreiben:

jetzt fehlt noch die AllesDrehen(). (siehe meine letzte Post ).

Und dann entwickelst Du aus der SpielerSetzt() noch die ComputerSetzt() und wir haben alles zusammengetragen. Fertig.

Poste diese beiden Funktionen hier noch rein, damit ich einen Blick darauf werfen kann, oder setze schon alles zu einem Programm zusammen. Theoretisch müßte es laufen....


Das ist, was wir bisher haben:

BlitzBasic: [AUSKLAPPEN]

Graphics 640, 480, 16, 2
Dim Feld%(64,9,9)
Global SpielerFertig%

Arial = LoadFont("Arial",15)
SetFont Arial

Global Schwarz= LoadImage ("schwarz.bmp")
Global Weiss =LoadImage ("weiss.bmp")

FeldReset

Repeat
If SpielerFertig=0 Then
SpielerSetzt
Else
ComputerSetzt
EndIf
MaleSpielFeld()
Until KeyHit(1)
End
;-------------ab hier stehen alle Funktionen:

Function SpielerSetzt()
Local Mausx%, MausY%
MausX=MouseX()/50
MausY=MouseY()/50

If MouseHit(1) Then
If IstEsHierErlaubt(MausX,MausY,1)
Feld(Ebene,MausX,MausY)=1
AllesDrehen(MausX,MausY,1)
SpielerFertig=1
EndIf
EndIf
End Function


Function IstEsHierErlaubt%(X%,Y%,Ich%)
Local Ergebnis%, Summe%, i%, j%
If Feld(Ebene,X,Y)=0 Then
For i=-1 To 1
For j=-1 To 1
Ergebnis = ScanneEineRichtung(X, Y, i, j, Ich)
Summe =Summe + Ergebnis
Next
Next
EndIf
Return summe
End Function

Function ScanneEineRichtung%(X%, Y%, RichtungX%, RichtungY%, Ich%)
Local Erfolg%
Repeat
X=X+RichtungX
Y=Y+RichtungY
If (X>8) Or (X<1) Or (Y>8) Or (Y<1) Then
Return 0
EndIf
If Feld(Ebene,X,Y)=0 Then
; leeres Feld gefunden
Return 0
ElseIf Feld(Ebene,X,Y)<>Ich Then
; Gegner-Feld gefunden
Erfolg=Erfolg+1
ElseIf Feld(Ebene,X,Y)=Ich Then
; eigenes Feld gefunden
Return Erfolg
EndIf
Forever
End Function


Function DreheEineRichtung (X%, Y%, RichtungX%, RichtungY%, Ich%)
Repeat
X=X+RichtungX
Y=Y+RichtungY
If Feld (Ebene,X,Y)=Ich Then
Return
EndIf
Feld(Ebene,X,Y)=Ich
Forever
End Function


Function MaleSpielFeld()
Local X%, Y%
Cls
Color 50, 100, 50 ;grün
Rect 0,0,640,480,1 ;grüner Hintergrund
Color 255, 255, 255
For x = 1 To 8
For y = 1 To 8
Rect x*50, Y*50, 50, 50, 0
If feld (Ebene,X,Y) = 1 Then
DrawImage Schwarz, X*50+2,Y*50+2
ElseIf feld (Ebene,X,Y) = 2 Then
DrawImage Weiss, X*50+2, Y*50+2
EndIf
Next
Next
Flip 1
End Function


Function FeldReset()
Local E%, X%, Y%
For E = 1 To 60
For X = 1 To 8
For Y = 1 To 8
Feld (E,X,Y) = 0
Next
Next
Next
; 4 Start-Steine
Feld(0,4,5)=1
Feld(0,5,4)=1
Feld(0,4,4)=2
Feld(0,5,5)=2
End Function



BlitzPlus oder BlitzBasic?

Das mit dem Verschieben des Thead hat BladeRunner schon richtig gemacht. BlitzPlus (B+) ist eine spezielle Variante von BlitzBasic (BB) . Jeder BB-Code arbeitet auch unter B+.

Aller Code, den wir bisher geschrieben haben, läuft unter BB und auch unter B+. Daher gehört unser Thread in das breitere Forum BB-Anfänger.

In das B+-Forum sollen Beiträge erst rein, wenn sie Themen ansprechen, die reinen BB-Usern unverständlich wären. etwas GUI-Aufrufe.

Mit den Fähigkeiten aus der Sprache eine KI coden zu können, hat dies alles nichts zu tun. Hierzu kommt es nur auf deine Coder-Leistung an und das ist mit reinem BB 100% zu erreichen.
 

neolein

BeitragFr, Feb 05, 2010 11:53
Antworten mit Zitat
Benutzer-Profile anzeigen
Function DreheEineRichtung (X%, Y%, RichtungX%, RichtungY%, Ich%)

konnte deine Korrekturen sehr gut nachvollziehen, genial, was man alles weglassen kann.

Bei meinem Ansatz damals gab es das Problem, daß ich sehr viel an der grafischen Umsetzung gearbeitet hatte, was ein Kauderwelsch aus irgendwelchen Grafikbefehlen und dem mathematischen Code ergab, ich finde es sehr gut, daß das jetzt so klar getrennt ist.

Die Benennung der Variablen finde ich ebenfalls sehr gut, ich hatte seinerzeit nur 1-2 Buchstaben verwendet, aus der Annahme, daß kurze Variablen schneller verarbeitet werden, wahrscheinlich unterliege ich da einem Irrtum.

An die AllesDrehen() mache ich mich noch.

Wo kann ich schwarz.bmp bzw. weiß.bmp hier hinterlegen?

Midimaster

BeitragFr, Feb 05, 2010 13:11
Antworten mit Zitat
Benutzer-Profile anzeigen
also ich benötige die beiden Bilder nicht. Ich hab es durch Code gelöst:

BlitzBasic: [AUSKLAPPEN]
Global Schwarz
Schwarz = CreateImage (36,36)
SetBuffer ImageBuffer(Schwarz)
Color 3,3,3
Oval 18,18,15,15

Global Weiss
Weiss = CreateImage (36,36)
SetBuffer ImageBuffer(Weiss)
Color 223,223,223
Oval 18,18,15,15

Global Rot
Rot = CreateImage (36,36)
SetBuffer ImageBuffer(Rot)
Color 223,3,3
Oval 18,18,17,17,0
Global RotX%,RotY%

SetBuffer BackBuffer()

wie du siehst kann man Images durch reinen Code erzeugen. Vielleicht fällt dir auch auf, dass es zusätzlich einen roten Ring gibt. Den will ich später dazu nutzen, mir anzeigen zu lassen, über welchem Spielzug der Computer gerade nachdenkt.

Hochladen von Daten ins Forum

Wenn du aber gundsätzlich hier irgend etwas hinterlegen willst gibt es das "Archiv", das jedem Nutzer zur Verfügung steht. Du hast 10MB frei. Klicke oben auf den Menüreiter "Archiv". Dort gibt es "neue Datei hochladen" jetzt kannst du die Bilder hochladen. Anschließend siehst du unter "Deine Uploads" was du schon hochgeladen hast. Jeder Eintrag ist ein Link. So kannst nun in den Beiträgen diese Links erwähnen.
 

neolein

BeitragFr, Feb 05, 2010 15:51
Antworten mit Zitat
Benutzer-Profile anzeigen
OK

Code: [AUSKLAPPEN]

Function AllesDrehen%(X%,Y%,Ich%)
  Local Ergebnis%, Summe%, i%, j%
     If Feld(Ebene,X,Y)=0 Then
     For i=-1 To 1
        For j=-1 To 1
           DreheEineRichtung (X%, Y%, i, j, Ich%)
          Next
     Next
  EndIf
  Return summe
End Function


Code: [AUSKLAPPEN]

Function ComputerSetzt()

       Local Computer%
         
                  If Feld(Ebene,X,Y)=0
                    If IstEsHierErlaubt(X,Y,Computer%)
                        Feld(Ebene,X,Y)=2
                        AllesDrehen(X,Y,Computer%)
                        SpielerFertig=2
                    EndIf
                 EndIf
         End Function

Midimaster

BeitragFr, Feb 05, 2010 18:12
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich hätte bei jeder Richtung nocheinmal vorher gefragt, ob es dort auch was zu drehen gibt:

BlitzBasic: [AUSKLAPPEN]
Function AllesDrehen(X%,Y%,Ich%)
Local Ergebnis%, Summe%, i%, j%
For i=-1 To 1
For j=-1 To 1
If ScanneEineRichtung(X, Y, i, j, Ich)>0 Then
DreheEineRichtung (X%, Y%, i, j, Ich%)
EndIf
Next
Next
End Function


Dafür kannst du dir die Abfrage sparen, ob das Spielerfeld leer ist. Wir kämen gar nicht bis zur AllesDrehen(), wenn diese Feld nicht sowieso ein Leerfeld wäre. Auch auf RETURN-Werte kann man auch verzichten.




In der Computersetzt() fehlt die Zufallsfunktion. Das ist das Gegenstück zur Mouse-Berechnung beim Spieler
BlitzBasic: [AUSKLAPPEN]
Function ComputerSetzt()
Local X%, Y%

X=Rand(1,8)
Y=Rand(1,8)
If Feld(Ebene,X,Y)=0
If IstEsHierErlaubt(X,Y,2)
Feld(Ebene,X,Y)=2
AllesDrehen(X,Y,2)
SpielerFertig=2
EndIf
EndIf
End Function


Da Du die SpielerFertig% nach dem Computer auf 2 gesetzt hast, müssen wir in der Mainschleife zwei Änderungen einbringen.

Zitat:
FeldReset
. . ; SpielerFertig wäre zu Beginn =0
Repeat
. . If SpielerFertig=0 Then
. . . . . SpielerSetzt
....
Until KeyHit(1)
End



...wird zu....

BlitzBasic: [AUSKLAPPEN]
FeldReset
SpielerFertig=2
Repeat
If SpielerFertig=2 Then
SpielerSetzt
Else
ComputerSetzt
EndIf
MaleSpielFeld()
Until KeyHit(1)
End




Die "KI" schaut nun so aus, dass der Computer zu 100% zufällig das Feld aussucht, nur darauf achtet, dass hier etwas zu holen ist und sofort das erste Feld nimmt, dass diese Bedingung erfüllt. Jetzt sollte das Spiel laufen.

Ich spiel auch schon selber kräftig. Dabei sind mir 2 Dinge aufgefallen.

1.
Der Zufallsgenerator nimmt während einer Suche mehrfach das gleiche Feld und checkt es immer wieder ab. Das führt aber direkt zu keinem Fehler, es dauert nur etwas länger, bis er etwas findet. Da er sehr schnell sucht, gibt es auch kein Geschwindigkeitsproblem.

Aber eigentlich könnte er, wenn er dran kommt eine Liste aller leeren Felder anlegen, darin per Zufall suchen und dann bereits abgeprüfter Felder dort rausstreichen. So wäre sichergestellt, das er 100% alle leeren Felder checkt,


2.
Wir fangen noch nirgendwo das Problem ab, dass ein Spieler möglicherweise gar nicht ziehen kann und deshalb wieder der Gegner dran ist. D.h. der Spieler muss einen Button "ich kann nicht..." bekommen. (Selber schuld, wenn er den zu früh klickt...) und der Computer muss wissen, wann er alle gecheckt hat und doch nichts fand. Also doch die Zufalls-Verbesserung aus 1. schreiben!
 

neolein

BeitragFr, Feb 05, 2010 21:50
Antworten mit Zitat
Benutzer-Profile anzeigen
Sieht ja schon klasse aus, ich habe nur gleich am Anfang das Problem, daß die schwarzen Steine gar nicht gemalt werden, ich habe Alles schön getrennt, Hauptschleife von den Funktionen (die Reihenfoge der Functon ist doch egal?)

Edit: habe es gefunden, bei Global Schwarz muss die Fare auf mindestens 5,5,5 gesetzt werden, bei 3,3,3 passiert gar nix.
Ich würde die Steine auch gerne größer haben, Oval 5,5,30,30 sieht gut aus, mache ich den Radius noch größer entstehen komischerweise Ecken am Kreis.
Ich bin schonmal begeistert, das mit der Geschwindigkeit ist lustig, wenn man so ziemlich am Ende des Spiels ist dauert die Suche immer länger, da wohl auch die Felder, die schon besetzt sind abgesucht werden

Code: [AUSKLAPPEN]

Graphics 640, 480, 16, 2
Dim Feld%(64,9,9)
Global SpielerFertig%

Arial = LoadFont("Arial",15)
SetFont Arial

Global Schwarz
Schwarz = CreateImage (36,36)
SetBuffer ImageBuffer(Schwarz)
Color 5,5,5
Oval 18,18,15,15

Global Weiss
Weiss = CreateImage (36,36)
SetBuffer ImageBuffer(Weiss)
Color 223,223,223
Oval 18,18,15,15

Global Rot
Rot = CreateImage (36,36)
SetBuffer ImageBuffer(Rot)
Color 223,3,3
Oval 18,18,17,17,0
Global RotX%,RotY%

SetBuffer BackBuffer()

FeldReset

SpielerFertig=2

Repeat
   If SpielerFertig=2 Then
      SpielerSetzt
   Else
      ComputerSetzt
   EndIf   
   MaleSpielFeld()
Until KeyHit(1)
End
;-------------ab hier stehen alle Funktionen:

Function SpielerSetzt()
   Local Mausx%, MausY%
   MausX=MouseX()/50
   MausY=MouseY()/50

   If MouseHit(1) Then
      If IstEsHierErlaubt(MausX,MausY,1)
         Feld(Ebene,MausX,MausY)=1
         AllesDrehen(MausX,MausY,1)
         SpielerFertig=1
      EndIf
   EndIf
End Function

Function ComputerSetzt()
    Local X%, Y%
   
    X=Rand(1,8)
    Y=Rand(1,8)
    If Feld(Ebene,X,Y)=0
        If IstEsHierErlaubt(X,Y,2)
              Feld(Ebene,X,Y)=2
              AllesDrehen(X,Y,2)
              SpielerFertig=2
        EndIf
    EndIf
End Function

Function IstEsHierErlaubt%(X%,Y%,Ich%)
  Local Ergebnis%, Summe%, i%, j%
  If Feld(Ebene,X,Y)=0 Then
     For i=-1 To 1
        For j=-1 To 1
           Ergebnis = ScanneEineRichtung(X, Y, i, j, Ich)
         Summe =Summe + Ergebnis 
        Next
     Next
  EndIf
  Return summe
End Function

Function ScanneEineRichtung%(X%, Y%, RichtungX%,  RichtungY%, Ich%)
    Local Erfolg%
    Repeat
        X=X+RichtungX
        Y=Y+RichtungY
        If (X>8) Or (X<1) Or (Y>8) Or (Y<1) Then
               Return 0
        EndIf       
        If Feld(Ebene,X,Y)=0 Then
                ; leeres Feld gefunden
                Return 0
        ElseIf Feld(Ebene,X,Y)<>Ich Then
                ; Gegner-Feld gefunden
                Erfolg=Erfolg+1
        ElseIf Feld(Ebene,X,Y)=Ich Then
                ; eigenes Feld gefunden
                Return Erfolg
        EndIf
     Forever 
End Function


Function DreheEineRichtung (X%, Y%, RichtungX%, RichtungY%, Ich%)
    Repeat
        X=X+RichtungX
        Y=Y+RichtungY
        If Feld (Ebene,X,Y)=Ich Then
                Return
        EndIf
        Feld(Ebene,X,Y)=Ich
     Forever
End Function

Function AllesDrehen(X%,Y%,Ich%)
  Local Ergebnis%, Summe%, i%, j%
     For i=-1 To 1
        For j=-1 To 1
      If ScanneEineRichtung(X, Y, i, j, Ich)>0 Then
               DreheEineRichtung (X%, Y%, i, j, Ich%)
           EndIf
        Next
     Next
 End Function


Function MaleSpielFeld()
    Local X%, Y%
    Cls
    Color 50, 100, 50 ;grün
    Rect 0,0,640,480,1 ;grüner Hintergrund
    Color 255, 255, 255
        For x = 1 To 8
            For y = 1 To 8
                Rect x*50, Y*50, 50, 50, 0
                If feld (Ebene,X,Y) = 1 Then
                    DrawImage Schwarz, X*50+2,Y*50+2
                ElseIf feld (Ebene,X,Y) = 2 Then
                    DrawImage Weiss, X*50+2, Y*50+2
                EndIf
             Next
         Next
    Flip 1
End Function


Function FeldReset()
   Local E%, X%, Y%
   For E = 1 To 60
      For X = 1 To 8     
         For Y = 1 To 8
            Feld (E,X,Y) = 0
         Next
      Next
   Next
   ; 4 Start-Steine
   Feld(0,4,5)=1
   Feld(0,5,4)=1
   Feld(0,4,4)=2
   Feld(0,5,5)=2
End Function


Ja, da ich in meinem Code immer der Reihe nach abgefragt hatte gab es dieses Problem nicht, aber das mit dem Zufall sieht viiel besser aus
  • Zuletzt bearbeitet von neolein am Fr, Feb 05, 2010 22:14, insgesamt einmal bearbeitet

Midimaster

BeitragFr, Feb 05, 2010 22:14
Antworten mit Zitat
Benutzer-Profile anzeigen
also ich hab mir das ganze gerade geholt und bei mir sieht es toll aus und läuft auch! wie meinst du das man sieht nichts von den schwarzen steien? die sind doch zu sehen!

übrigens noch ein trick: setz mal nach dem Flip 1 eine Zeile DELAY 500. dann läuft das ganze langsamer ab.

und noch ein trick: der Gag mit dem roten kreis:

folgende änderungen sind nötig:

ganz oben:
BlitzBasic: [AUSKLAPPEN]
Global SpielerFertig%, MausX%, MausY%


dafür das Local MausX%, MausY% raus

In der ComputerSetzt() viele Änderungen:

BlitzBasic: [AUSKLAPPEN]
Function ComputerSetzt() 
MausX=Rand(1,8)
MausY=Rand(1,8)
If Feld(Ebene,MausX,MausY)=0
If IstEsHierErlaubt(MausX,MausY,2)
Feld(Ebene,MausX,MausY)=2
AllesDrehen(MausX,MausY,2)
SpielerFertig=2
EndIf
EndIf
End Function


und am Ende der MaleSpielFeld()


BlitzBasic: [AUSKLAPPEN]
...
Next
DrawImage Rot, MausX*50+2, MausY*50+2
Flip 1
Delay 500
End Function
  • Zuletzt bearbeitet von Midimaster am Fr, Feb 05, 2010 22:25, insgesamt einmal bearbeitet
 

neolein

BeitragFr, Feb 05, 2010 22:16
Antworten mit Zitat
Benutzer-Profile anzeigen
hab meine Antwort editiert, und sobald die RND Function geändert wurde, dürfte das Spiel sehr schnell werden, das wird wichtig bei der Vorausberechnung, die Möglichkeiten potenzieren sich sehr schnell, je höher die Ebene wird

Midimaster

BeitragFr, Feb 05, 2010 22:28
Antworten mit Zitat
Benutzer-Profile anzeigen
Genau, das ist nun die nächste Aufgabe. Der Zufall muss verbessert werden.

Jetzt, wo du die Kreise größer gemacht hast, siehst du vielleicht nichts vom roten Rand. Aber der wird jetzt sehr wichtig, da du an ihm die Strategie des Computers beobachten kannst
 

neolein

BeitragFr, Feb 05, 2010 22:38
Antworten mit Zitat
Benutzer-Profile anzeigen
Ok, habe ich gemacht, ich sehe die Kreise trotzdem und habe delay auf 125 gesetzt, damits etwas schhneller geht, interessant, daß die Reihenfolge der Abfrage immer gleich ist.

Müßte man nicht hier etwas einbauen

Code: [AUSKLAPPEN]

Function ComputerSetzt()
    MausX=Rand(1,8)
    MausY=Rand(1,8)
    If Feld(Ebene,MausX,MausY)=0
        If IstEsHierErlaubt(MausX,MausY,2)
              Feld(Ebene,MausX,MausY)=2
              AllesDrehen(MausX,MausY,2)
              SpielerFertig=2
        EndIf
    EndIf
End Function


Wenn IstEsHierErlaubt(MausX,MausY,2) = false ist, dann (MausX,MausY,2) kurzfristig durch eine andere Konstante (als 0) ersetzen?

Midimaster

BeitragFr, Feb 05, 2010 22:58
Antworten mit Zitat
Benutzer-Profile anzeigen
zu deiner eben gestellten Frage....
Ich versteh die Frage nicht. Was willst du damit sagen? Wo soll das was verbessern?
Wenn IstEsHierErlaubt(MausX,MausY,2) FALSE ist, dann werden doch die folgenden Zeilen gar nicht abgearbeitet, sondern gleich mit der nächsten Richtung begonnen.

zu der vorherigen:

das Zufallsverhalten ändert sich mit einem
BlitzBasic: [AUSKLAPPEN]
SeedRnd MilliSecs()

dadurch wird der Zufallsgenerator neu initialisiert. Das ist später für den Spieler wichtig. In der Testphase ist eher eine immer wieder gleiche Zufallskette hilfreich, wenn es um das Überprüfen von Code-Fehlern geht.

Noch einen Gag hab ich für Dich:

Füge mal in der DrehEineRichtung folgendes ein:
BlitzBasic: [AUSKLAPPEN]
Function DreheEineRichtung (X%, Y%, RichtungX%, RichtungY%, Ich%)
Repeat
MaleSpielFeld()
X=X+RichtungX

Damit läuft das Spiel so langsam, dass man den einzelnen Steinen beim "Drehen" zuschauen kann.


Zufalls-Optimierung

Versuchts du eine optimierte Zufalls-Routine zu schreiben?
  • Zuletzt bearbeitet von Midimaster am Sa, Feb 06, 2010 1:37, insgesamt einmal bearbeitet
 

neolein

BeitragFr, Feb 05, 2010 23:29
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich habe es hier eingebaut

Code: [AUSKLAPPEN]

Function ComputerSetzt()
    SeedRnd MilliSecs ()
    MausX=Rnd(1,8)
    MausY=Rnd(1,8)
    If Feld(Ebene,MausX,MausY)=0
        If IstEsHierErlaubt(MausX,MausY,2)
              Feld(Ebene,MausX,MausY)=2
              AllesDrehen(MausX,MausY,2)
              SpielerFertig=2
        EndIf
    EndIf
End Function



oder

Code: [AUSKLAPPEN]

Repeat
        SeedRnd MilliSecs ()
   If SpielerFertig=2 Then
      SpielerSetzt
   Else
         ComputerSetzt
   EndIf   
   MaleSpielFeld()
Until KeyHit(1)



Nun ist jedes Spiel anders, allerdings wesentlich langsamer, und es fällt auf, daß alle Felder von links nach rechts abgetastet werden (folgt man den roten Kreisen)

Midimaster

BeitragFr, Feb 05, 2010 23:50
Antworten mit Zitat
Benutzer-Profile anzeigen
also, das kann nicht sein...

1. funktioniert es bei mir auch mit dem SeedRnd fehlerfrei

2. wird durch ein Seedrnd auch nix langsamer

3. wie kann es sein, das alle Spiele unterschiedlich sein sollen, wenn jetzt immer von links nach rechts gescannt wird.


hast du vielleicht noch was anderes geändert?

außerdem reicht ein einziges SeedRnd am Anfang des Gesamtcodes


Optimierter Zufalls-Routine


Ich habe über die Optimierung der Zufallsroutine nachgedacht und bin zu dem Schluss gekommen, dass man sie am besten über eine Type-Element-Liste verwirklichen sollte. Da kennst Du dich aber wahrscheinlich gar nicht aus...
Deshalb meine Bitte:lies bitte die Kapitel I bis IV meines Type-Tutorial bevor wir das in Angriff nehmen: https://www.blitzforum.de/foru...hp?t=33551

Gehe zu Seite Zurück  1, 2, 3, 4  Weiter

Neue Antwort erstellen


Übersicht BlitzBasic Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group