BPS #14 TicTacToe, Teil I - Auswertung

Übersicht BlitzBasic Beginners-Corner

Neue Antwort erstellen

Xeres

Moderator

Betreff: BPS #14 TicTacToe, Teil I - Auswertung

BeitragSo, Nov 13, 2011 22:23
Antworten mit Zitat
Benutzer-Profile anzeigen
Die Grundlagen für den nächsten Teil sollten wir zusammen bekommen haben - wer hat's geschafft, wo gibt es Probleme?

Das war die Aufgabe

Postet hier eure Ergebnisse, Codes, Gedanken. Lernt von den anderen, seht euch deren Quelltext an und versucht euren eigenen zu verbessern.

Diskussion
Postet zu euren Codes stets eine kurze Erklärung mit euren Gedanken in denen ihr simpel gesagt die Frage "Wieso habe ich XY auf diese Art gelöst?" beantwortet. Beiträge, die nur den Code enthalten werden wir aus dem Thread entfernen.

Nächste Aufgabe
In einer Woche wird die Musterlösung nach editiert und in 2 die nächste Aufgabe eingestellt.

Viel Spaß & viel Erfolg!

Musterlösung:
BlitzBasic: [AUSKLAPPEN]
;====================================================================
; Project: Tic Tac Toe - Part I
;====================================================================

AppTitle "TicTacToe" ; Dem Fenster einen Namen geben
Graphics 200,200,0,2 ; Grafikmodus initialisieren
SetBuffer BackBuffer() ; Doublebuffering

Dim grid(2,2) ; Speicher für ein 3 x 3 Feld reservieren, Integervariable

Local x,y,timer,player,mx,my,pos_x,pos_y,mh1 ; Allgemeine Variablen im Programm


; Globale Einstellungen
ClsColor 128,0,0 ; Die Löschfarbe setzen
timer=CreateTimer(60) ; Einen Timer erstellen
SeedRnd MilliSecs() ; Damit der Zufall zufällig ist
; Lies dazu auch in der Hilfe nach
player=Rand(1,2) ; Der Zufall entscheidet wer beginnt


Repeat ; Hauptschleife

mx=MouseX() ; Die Mauspositionen zwischenspeichern
my=MouseY() ; Dies wirkt sich positiv auf die Performance aus
; wenn die Werte mehrmals im Programm benötigt werden
mh1=MouseHit(1) ; Mausklick zwischenspeichern, mehr dazu auch im Forum.

Cls ; Der Backbuffer wird "gereinigt", siehe dazu auch "Globale Einstellungen"
Color 0,0,255 ; Blau als Zeichenfarbe festlegen

; Das Spielfeld malen
Line 25,75,175,75
Line 25,125,175,125
Line 75,25,75,175
Line 125,25,125,175

; Mittels 2 verschachtelten Schleifen werden die bereits gesetzten
; Steine ins Spielfeld gemalt
For y=0 To 2
For x=0 To 2
If grid(x,y)>0 Then ; Ist der Wert im Feld größer 0 dann...

Select grid(x,y) ; ...entscheide welche Farbe wir brauchen...
Case 1: Color 255,0,0
Case 2: Color 0,128,0
End Select ; Select-Konstrukt Ende

Oval 30+(x*50),30+(y*50),40,40,1 ; ... und male den Stein
EndIf ; Das EndIf zeigt das Ende des Konstrukts
Next ; Beendet die Schleife
Next ; Man sieht auch schön wie wichtig die Einrückung für die
; Lesbarkeit des Codes ist
; TIPP: IDEal unterstützt das automatische einrücken von Code
; Unter Settings -> Editor Settings -> Tab "Coding Help" findet sich
; ganz unten ein Radiobutton. Wählt dort "Advanced" aus um alle Features
; zu nutzen

; Je nach aktuell zugberechtigtem Spieler Farbe setzen
Select player ; Wieder ein Select-Case-Konstrukt für die Entscheidung
Case 1 ; Spieler 1
Color 255,0,0 ; Rot
Case 2 ; Spieler 2
Color 0,128,0 ; Grün
End Select ; Beendet das Konstrukt

; Hier wird ein Kreis gezeichnet an der Position des Mauszeigers
; Der Kreis ist 40 Pixel breit, 40 Pixel hoch und gefüllt
Oval mx-20,my-20,40,40,1

; Auswerten der Usereingabe
If mh1 ; Die linke Maustaste wurde gedrückt

If mx>=25 And mx<=175 ; Ist der Mauszeiger vertikal im Spielfeld?
If my>=25 And my<=175 ; Ist der Mauszeiger horizontal im Spielfeld?
pos_x=(mx-25)/50
pos_y=(my-25)/50
; In den oberen 2 Zeilen machen wir uns eine Eigenheit von BB zunutze.
; Rechnen wir zunächst anhand von Beispielwerten den Wert von Hand aus:
; Wir nehmen an mx sei 100
; Das ergibt: pos_x=(100-25)/50
; pos_x=75/50
; pos_x=1.5
; Da pos_x aber ein Integerwert ist rundet BB den Wert auf 2
; Selbiges gilt sinngemäß auch für pos_y

If grid(pos_x,pos_y)=0 ; Das Feld ist noch leer
grid(pos_x,pos_y)=player
; Das Feld an eben berechneter Position wird nun mit dem Wert
; für den aktuellen Spieler gefüttert

If player=1 Then player=2 Else player=1 ; Den anderen Spieler wählen
EndIf
EndIf
EndIf
EndIf

Flip 0 ; Die Buffer werden getauscht
WaitTimer(timer) ; Der Rechner "wartet" bis er den nächsten Frame malen darf
; Dies gibt dem Prozessor Zeit noch all die anderen Dinge zu tun die er
; zu erledigen hat
Until KeyHit(1) ; Solange die ESC-Taste nicht gedrückt wurde springen wir zurück
; zum Schleifenanfang

End ; Das Programm beenden
  • Zuletzt bearbeitet von Xeres am So, Nov 27, 2011 22:44, insgesamt 2-mal bearbeitet

ozzi789

BeitragMo, Nov 14, 2011 11:24
Antworten mit Zitat
Benutzer-Profile anzeigen
Hier mein mehr oder weniger schöner Code von nem fertigen Tictactoe Spiel mit KI.
Hoffe der eine oder andere kann etwas daraus lernen Smile

Hier das ganze Packet, mit Source und benötigten Dateien, fertig zum kompilieren

https://www.blitzforum.de/upload/file.php?id=11132


BlitzBasic: [AUSKLAPPEN]
;Coded by ozzi789


;---------------------
;INITIALISATION
;---------------------


;SET VARIABLES
Global width, height, curplayer=0, mh1 , mx ,my ,gameend_v$, colstart, rowstart, playertyp$ , timer = CreateTimer (60) , last_startplayer=0
appname$="TicTacToe - OZ"
AppTitle appname$

;READ CONFIG FILE
config_file=OpenFile("cfg\config.dat")
If config_file=0 RuntimeError("config.dat missing!")
width=ReadLine(config_file)
height=ReadLine(config_file)
windowmode=ReadLine(config_file)
CloseFile(config_file)


;SETTING UP WINDOW
Graphics width,height,32,windowmode
SetBuffer BackBuffer()
SeedRnd MilliSecs()

;LOAD SOUNDS
Global click=LoadSound ("sfx\click.mp3")
Global tada=LoadSound ( GetEnv$ ("systemroot")+"\Media\tada.wav") ; We use the Windows sound here Wink

;LOAD GFX
Global ttt=LoadImage("gfx\tictactoe.png")
Global logo=LoadImage("gfx\ozlogo.png")
MaskImage (logo,0,255,0)
SetFont LoadFont("Verdana",12,False,False,False)



;CREATE ARRAY FOR GAME FIELD (3 height , 3 width)
Dim gfield(2,2)


;---------------------
;START ENGINE
;---------------------

intro()
menu()
reset_gfield()


;---------------------
;MAINLOOP
;---------------------

curplayer=0

While 1
Cls
get_input() ;Get input from devices
draw_check_field() ;draw the field and do the logic
render() ; flip and waittimer
Wend

End




;---------------------
;FUNCTIONS
;---------------------

;GETS KEYBOARD AND MOUSE INPUT
Function get_input()
If KeyHit(1) Then reset_gfield():menu()
mx=MouseX()
my=MouseY()
mh1=MouseHit(1)
End Function

;RENDERS THE SCREEN
Function render()
WaitTimer timer
Flip 0
End Function

;DISPLAYS THE INTRO
Function intro()
x=255
Repeat
If KeyHit(1) End
x=x-2
ClsColor x,x,x
Cls
DrawImage logo, width/2-ImageWidth(logo)/2,ImageHeight(logo)/2
Text width/2,50,"ZGHEB.COM PRESENTS",True ,True
render()
Until x<5
Text 0,0,"ZGHEB.COM PRESENTS"
Delay(1000)
FlushMouse()
FlushKeys()
End Function

;DISPLAYS THE MENU
Function menu()
Repeat
Cls
DrawImage ttt,(width/2)-(ImageWidth(ttt)/2),(height/2)-ImageHeight(ttt)*2
; IF ARROW KEYS PRESSED, TOGGLE PLAYER TYPE
If KeyHit(200) playervar=toggle(playervar)
If KeyHit(208) playervar=toggle(playervar)
If playervar=1 Then playertyp$="Human"
If playervar=0 Then playertyp$="CPU"
Color 255,255,255
Text width/2-20,height/2,"Second player is: ",True,True
Text width/2+45,height/2,playertyp$,True,True
Color 100,100,100
Text width/2,height/2+30,"Use Arrowkeys to choose player type, press Enter when finished.",True,True
Text width/2,height/2+50,"Press ESC to return to this menu, press ESC again to exit the game.",True,True
render()
If KeyHit(1) End ;Exit Game
Until KeyHit(28)
FlushMouse()
FlushKeys()
End Function


;DRAWS GAME FIELD & CHECK FOR INPUTS
Function draw_check_field(jdraw=0)
For columns=0 To 2
For rows=0 To 2
;CALCULATE START POSITIONS
colstart=columns*(width/3)
rowstart=rows*(height/3)

;DRAW GAME FIELD OUTLINES
Color 255,255,255
Rect colstart,rowstart,width/3,height/3,0

;DRAW FILLED FIELDS
If gfield(columns,rows)=1 ;player 1
Color 255,0,0
Rect colstart+1,rowstart+1,width/3-1,height/3-1,1
EndIf
If gfield(columns,rows)=0 ;player 0
Color 0,0,255
Rect colstart+1,rowstart+1,width/3-1,height/3-1,1
EndIf
If gfield(columns,rows)=2 ;debug field
Color 100,255,0
Rect colstart+1,rowstart+1,width/3-1,height/3-1,1
EndIf

;if the function draw_check_field was called with the jdraw (just draw) parameter value = 0 (default) the fields will be checked, else this part will be skiped)
If jdraw=0
;If it is a humanplayer playing aginst you or if it is your turn
If playertyp$="Human" Or curplayer=0
If mx>colstart And mx<(colstart)+(width/3) And my>rowstart And my<(rowstart)+(height/3) ;get the field under the mouse
;current field position
mouseover_c=columns
mouseover_r=rows
Color 0,255,0
Rect columns*(width/3),rows*(height/3),width/3,height/3,0
;if mouse hit was on a empty field
If mh1=1 And gfield(columns,rows)=3
PlaySound click
;go edit field and check if we won, then toggle the player
gfield(columns,rows)=curplayer
checkforwin()
curplayer=toggle(curplayer)
EndIf
EndIf
Else
cpu_move() ;if its the cpu players turn, call the function
EndIf
EndIf
Next
Next
End Function



;THE TICTACTOE AI
Function cpu_move()
Cls
;only go draw the field, not check it (parameter = 1!)
draw_check_field(1)
Color 255,255,255
Rect 0,height/2-10,width,20,1
Color 0,0,0
Text width/2,height/2,"CPU THINKING",True,True
render()
Delay(300)


;Here we now check if the cpu can win in one move

;VERTICALLY CHECK
For cc=0 To 2
For cr=0 To 2
If gfield(cc,cr)=1
counter=counter+1
EndIf
If gfield(cc,cr)=3
fc=cc
fr=cr
counter=counter+10
EndIf
If gfield(cc,cr)=0
counter=counter+30
EndIf
;if there is only one missing field, (1+1+10) go set it
If counter=12 gfield(fc,fr)=1:curplayer=toggle(curplayer)
Next
counter=0
Next

;HORIZONTALLY CHECK
;pretty much the same as above, just going through the fields horizontally
For cr=0 To 2
For cc=0 To 2
If gfield(cc,cr)=1
counter=counter+1
EndIf
If gfield(cc,cr)=3
fc=cc
fr=cr
counter=counter+10
EndIf
If gfield(cc,cr)=0
counter=counter+30
EndIf
If counter=12 Then gfield(fc,fr)=1:curplayer=toggle(curplayer)
Next
counter=0
Next

;If CPU was not able to win in one move
If curplayer=1
Repeat
xx=Rnd(0,2)
xy=Rnd(0,2)
; generate random moves until there is a valid one
Until gfield(xx,xy)=3
; go set randomized move
gfield(xx,xy)=1
curplayer=toggle(curplayer)
EndIf
checkforwin()
End Function



;CALCULATES IF A PLAYER WON
Function checkforwin()

;Here we scan all possible ways, if a player has won
;If there where 3 set fields of the same player, he won -> gameend(player that won)

;CHECK ROWS HORIZONTALLY
For c=0 To 2
For r=0 To 2
val=gfield(c,r)
If val=0
p1s=p1s+1
EndIf
If val=1
p2s=p2s+1
EndIf
Next
If p1s=3 gameend (1)
If p2s=3 gameend (2)
p1s=0
p2s=0
Next


;CHECK ROWS VERTICALLY
For r=0 To 2
For c=0 To 2
val=gfield(c,r)
If val=0
p1s=p1s+1
EndIf
If val=1
p2s=p2s+1
EndIf
Next
If p1s=3 gameend (1)
If p2s=3 gameend (2)
p1s=0
p2s=0
Next

;CHECK ROWS DIAGONALLY LEFT

For c=0 To 2
val=gfield(c,c)
If val=0
p1s=p1s+1
EndIf
If val=1
p2s=p2s+1
EndIf
Next
If p1s=3 gameend (1)
If p2s=3 gameend (2)
p1s=0
p2s=0


;CHECK ROWS DIAGONALLY RIGHT

For c= 0 To 2
b=Abs(c-2)
val=gfield(b,c)
If val=0
p1s=p1s+1
EndIf
If val=1
p2s=p2s+1
EndIf
Next
If p1s=3 gameend (1)
If p2s=3 gameend (2)
p1s=0
p2s=0

If is_field_full()=1
gameend "DRAW"
EndIf
End Function


;CHECKS IF ALL FIELDS ARE FILLED
;Return 1 if so

Function is_field_full()
Local fieldsfilled=0
For c=0 To 2
For r=0 To 2
If gfield(c,r)<>3
fieldsfilled=fieldsfilled+1
EndIf
Next
Next
If fieldsfilled>=9
Return 1
EndIf
End Function


;DISPLAYS THE GAME FINISHED SCREEN WITH A MESSAGE
Function gameend(message$)
;flush input devices
FlushMouse()
FlushKeys()
PlaySound tada
;display message
If message$<>"DRAW"
message$="PLAYER "+Int(message)+" WINS! PRESS ANY KEY TO PLAY A NEW GAME"
Else
message$=message$+" PRESS ANY KEY TO PLAY A NEW GAME"
EndIf
Cls
draw_check_field(1)
Color 255,255,255
Rect 0,height/2-10,width,20,1
Color 0,0,0
Text width/2,height/2,message$,True,True
render()
WaitKey
reset_gfield()
FlushMouse()
FlushKeys()
End Function

;reset the whole field
Function reset_gfield()
For c=0 To 2 ; go through every field
For r=0To 2
gfield(c,r)=3 ; fill it with 3 (= EMPTY)
Next
Next
last_startplayer=toggle(last_startplayer)
curplayer=last_startplayer
End Function

;toggels a variable from false to true and from true to false
Function toggle(var)
var=var+1
If var>1 Then var=0
Return var
End Function
0x2B || ! 0x2B
C# | C++13 | Java 7 | PHP 5
  • Zuletzt bearbeitet von ozzi789 am Di, Nov 15, 2011 10:54, insgesamt einmal bearbeitet
 

exastion

BeitragMo, Nov 14, 2011 18:53
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich habe auch vor kurzem wieder mit BB angefangen und dieses BPS genutzt um mich wieder einzuarbeiten. Hier ist mein Code:

BlitzBasic: [AUSKLAPPEN]
Global player=0 ;Variable für den Spieler

Dim Feld(3,3) ;2-Dimensionale Array für die 9 Felder

Graphics 600,650,16,2
SetBuffer BackBuffer()

While KeyHit(1)=0

mh1=MouseHit(1)
MX=MouseX()
MY=MouseY()

Cls

Color 255,255,0

Rect 0,50,600,1,1

Text 15,15,"Spieler: " +(player+1)

Color 0,0,255 ;\
Rect 195,60,10,580,1 ; \
Rect 395,60,10,580,1 ; | Malen des Spielfeldes
Rect 10,245,580,10,1 ; /
Rect 10,445,580,10,1 ;/

If mh1 Then player=(player+1) Mod 2 ;Spielerwechsel

If mh1 Then Feld(MX/200,(MY-50)/200)=player+1 ;Zuweisung der Spielerwahl an das Array

Color 255,0,0

Update() ;Spielfeld updaten

Flip

Wend
End

Function Update()

For i=0 To 2
For j=0 To 2

If Feld(i,j)=2 Then
DrawCross i*200+100,j*200+150 ;Anhand des Arrays wird die Kreuz oder Kreis Funktion aufgerufen
ElseIf Feld(i,j)=1 Then
DrawOval i*200+100,j*200+150
EndIf

Next
Next

End Function

Function DrawCross(x,y)

Line x-50,y-50,x+50,y+50 ;2 Linien ergeben ein Kreuz
Line x-50,y+50,x+50,y-50

End Function

Function DrawOval(x,y)

Oval x-50,y-50,100,100,0

End Function


Ich hoffe die Kommentare erklären genug, falls nicht, einfach fragen.

MfG exa

Xeres

Moderator

BeitragMo, Nov 14, 2011 19:59
Antworten mit Zitat
Benutzer-Profile anzeigen
@ozzi789: Es wäre nicht schlecht, wenn du ausgiebiger kommentieren würdest. Mit Bildern & Sound ist das auch so eine Sache: wie wäre es mit einem Code den man kopieren und starten kann?

@exastion: ist doch schon sehr schön! Einmal gesetzt sollte man die Zeichen nicht mehr überschreiben können.

Weiterso!
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)
 

exastion

BeitragMo, Nov 14, 2011 20:41
Antworten mit Zitat
Benutzer-Profile anzeigen
BlitzBasic: [AUSKLAPPEN]

;...

If mh1 And Feld(MX/200,(MY-50)/200)=0 Then
player=(player+1) Mod 2 ;Spielerwechsel
Feld(MX/200,(MY-50)/200)=player+1 ;Zuweisung der Spielerwahl an das Array
EndIf

;...


Das wäre ja dann so. Aber da gibt es bestimmt was besseres?

Xeres

Moderator

BeitragMo, Nov 14, 2011 20:51
Antworten mit Zitat
Benutzer-Profile anzeigen
Mh, nein, ich kann mir da nicht wirklich was besseres vorstellen.
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)
 

exastion

BeitragMo, Nov 14, 2011 21:01
Antworten mit Zitat
Benutzer-Profile anzeigen
Dann lass ich mich mal auf die Musterlösung überraschen.

ozzi789

BeitragDi, Nov 15, 2011 10:56
Antworten mit Zitat
Benutzer-Profile anzeigen
Habe das nötigste noch ergänzt an Kommentaren, entschuldige die Faulheit


Hier hab ich noch den Source mit den benötigten Dateien geupt
https://www.blitzforum.de/upload/file.php?id=11132



Grüsse Smile
0x2B || ! 0x2B
C# | C++13 | Java 7 | PHP 5

Xeres

Moderator

BeitragSo, Nov 20, 2011 14:00
Antworten mit Zitat
Benutzer-Profile anzeigen
Musterlösung steht im Anfangspost.
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)

ozzi789

BeitragDi, Nov 22, 2011 15:13
Antworten mit Zitat
Benutzer-Profile anzeigen
Interessant zu sehen wie es andere Lösen!
0x2B || ! 0x2B
C# | C++13 | Java 7 | PHP 5

Neue Antwort erstellen


Übersicht BlitzBasic Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group