MineSweeper-Clone mit Arrays oder OOP?

Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Neue Antwort erstellen

Stephan87

Betreff: MineSweeper-Clone mit Arrays oder OOP?

BeitragDi, Jan 23, 2007 18:17
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo alle zusammen!

bin neu in der community und teste gerade die blitzmax-demo aus. nun stehe ich jedoch vor meinem erstem problem. habe erst kleinere programme geschrieben, um wieder in die sprache reinzukommen (habe damals mit qbasic angefangen und bin dann später nach visual basic gewechselt). nun wollte ich mein erstes kleineres spiel, nämlich minesweeper programmieren. nun frage ich mich jedoch, ob ich hier für die felder arrays nehmen soll oder eine klasse feld erstellen soll. habe mal irgendwo hier gelesen, dass OOP bei größeren und variablen mengen an objekten ratsam ist, jedoch nicht z.b. bei der darstellung von einer 2D-map bestehend aus tiles (habe dies ausprobiert und musste feststellen, dass der OOP-code deutlich länger war).

ist also ein minesweeper-spiel vergleichbar mit dem aufbauen einer karte, sodass ich hier getrost arrays verwenden kann...soll?

vielen dank schon im vorraus Smile

Blitzcoder

Newsposter

BeitragDi, Jan 23, 2007 19:06
Antworten mit Zitat
Benutzer-Profile anzeigen
Naja, da man eine Fest Grösse des Feldes hat, halte ich Arrays für sinniger. Sollen allerdings mehr infos gespeichert werden, sind Types zu empfehlen. Man kann das Wunderbar kombinieren.
P4 3 Ghz@3,55Ghz|GF 6600GT 256MB|Samsung 80GB | 2x Samsung 160GB|2048MB DDR-400 RAM|6 Mbit Flatrate | Logitech G15 | Samsung 225BW-TFT | Ubuntu Gutsy Linux | Windows Vista | Desktop | Blog | CollIDE | Worklog
________________
|°°°°°°°°°°°°°°||'""|""\__,_
|______________ ||__ |__|__ |)
|(@) |(@)"""**|(@)(@)****|(@)
  • Zuletzt bearbeitet von Blitzcoder am Di, Jan 23, 2007 21:46, insgesamt einmal bearbeitet

TheShadow

Moderator

BeitragDi, Jan 23, 2007 20:51
Antworten mit Zitat
Benutzer-Profile anzeigen
Arrays - da dein Spielfeld ein "Gitter" ist...
ist einfacher
AMD64 3500+ | GeForce6600GT 128MB | 1GB DDR | WinXPsp2

Markus2

BeitragDi, Jan 23, 2007 23:36
Antworten mit Zitat
Benutzer-Profile anzeigen
zum abgucken Wink

Code: [AUSKLAPPEN]

Strict

Graphics 800,600,0

Type TItem
 Field Mine:Int
 Field Open:Int
 Field Flag:Int
End Type

Global Feld:TItem[10,10] '0-9
Local x:Int,y:Int
For x=0 To 9
For y=0 To 9
 Feld[x,y]=New TItem
Next
Next

Const MineSizeX=32
Const MineSizeY=32

MainLoop()
End

Function MainLoop()

 SetClsColor 0,0,0

 Local mx:Int,my:Int
 Local Mines:Int
 Mines=FeldFuellen()

 'AllOpen

 While Not KeyHit(KEY_ESCAPE)
  Cls
 
  mx=MouseX()
  my=MouseY()

  If MouseDown(1)>0 Then
   Open mx,my,0
  EndIf
  If MouseDown(2)>0 Then
   Open mx,my,1
  EndIf

  FeldZeigen() 
  DrawGrid()

  SetColor 255,255,255
  DrawText "Mines="+Mines,0,10*MineSizeY

  'FlushMem
  Flip
  Delay 20

 Wend
End Function

Function FeldFuellen:Int()

 SeedRnd MilliSecs()
 Local c:Int=0
 Local x:Int,y:Int
 While c<10
  x=Rand(0,9)
  y=Rand(0,9)
  If Feld[x,y].Mine=0 Then Feld[x,y].Mine=1;c=c+1
 Wend

 Return c

End Function

Function FeldZeigen()

 Local x:Int
 Local y:Int
 Local m:Int
 Local t:String

  SetBlend LightBlend 'Alphablend
  SetAlpha 0.5

 For x=0 To 9
 For y=0 To 9
  If Feld[x,y].Open=1 Then
   m=GetMines(x,y)
   t=m
   If Feld[x,y].Mine=1 Then
    'SetColor 255,128,128
    'DrawRect x*MineSizeX,y*MineSizeY,MineSizeX,MineSizeY
    'SetColor 0,0,0
    'DrawTextC "*",x*MineSizeX+(MineSizeX/2),y*MineSizeY+(MineSizeY/2)
    DangerColor 1
    CircleMine x,y
   Else
    DangerColor m
    'DrawRect x*MineSizeX,y*MineSizeY,MineSizeX,MineSizeY
    If m>0 Then
     CircleMine x,y
     'SetColor 255,255,255   
     'DrawTextC t,x*MineSizeX+(MineSizeX/2),y*MineSizeY+(MineSizeY/2)
    EndIf
   EndIf
  Else
   'Close bzw. noch unbekannt
   SetColor 64,64,64
   DrawRect x*MineSizeX,y*MineSizeY,MineSizeX,MineSizeY
  EndIf
 Next
 Next

 '-----------------------------------------------------

 SetBlend Solidblend+MaskBlend

 For x=0 To 9
 For y=0 To 9
  If Feld[x,y].Open=1 Then
   m=GetMines(x,y)
   t=m
   If Feld[x,y].Mine=1 Then
    'SetColor 255,128,128
    'DrawRect x*MineSizeX,y*MineSizeY,MineSizeX,MineSizeY
    SetColor 255,255,0
    DrawTextC "*",x*MineSizeX+(MineSizeX/2),y*MineSizeY+(MineSizeY/2)
   Else
    'DangerColor m
    'DrawRect x*MineSizeX,y*MineSizeY,MineSizeX,MineSizeY
    If m>0 Then
     'CircleMine x,y
     SetColor 255,255,255   
     DrawTextC t,x*MineSizeX+(MineSizeX/2),y*MineSizeY+(MineSizeY/2)
    EndIf
   EndIf
  Else
   'Close bzw. noch unbekannt
   'SetColor 64,64,64
   'DrawRect x*MineSizeX,y*MineSizeY,MineSizeX,MineSizeY
  EndIf
 Next
 Next

 '-----------------------------------------------------

End Function

Function GetMines:Int(x:Int,y:Int)

 Local a:Int
 Local b:Int
 Local c:Int

 For a=x-1 To x+1
 For b=y-1 To y+1
  If a=x And b=y Then
   'drum herum will ich testen
  Else
   If (a=>0 And a<=9) And (b=>0 And b<=9) Then
    If Feld[a,b].Mine=1 Then c=c+1
   EndIf
  EndIf
 Next
 Next

 Return c

End Function

Function AllOpen()

 Local x:Int
 Local y:Int

 For x=0 To 9
 For y=0 To 9
  Feld[x,y].Open=1
 Next
 Next

End Function

Function DrawGrid()

 Local x:Int
 Local y:Int

 SetColor 0,0,0
 For x=0 To 9
  DrawLine x*MineSizeX,0,x*MineSizeX,(9+1)*MineSizeY,True
 Next
 For y=0 To 9
  DrawLine 0,y*MineSizeY,(9+1)*MineSizeX,y*MineSizeY,True
 Next

End Function

Function DrawTextC(t:String,x:Int,y:Int)

 x=x-TextWidth(t)/2
 y=y-TextHeight(t)/2+2

 DrawText t,x,y 
End Function

Function DangerColor(Mines:Int)

 Select Mines
 Case 0
  SetColor 128,128,128
 Case 1,2,3,4,5,6,7,8
  'SetColor 127+(16*Mines),0,0
  SetColor 127,0,0
 End Select

End Function

Function Open:Int(x:Int,y:Int,Flag:Int=0)

 x=x/MineSizeX
 y=y/MineSizeY

 If x<0 Then x=0
 If y<0 Then y=0
 If x>9 Then x=9
 If y>9 Then y=9

 Feld[x,y].Open=1
 Feld[x,y].Flag=Flag

 If (Feld[x,y].Mine=1 And Flag=1) Or Feld[x,y].Mine=0 Then
  Return 1
 Else
  Return 0
 EndIf

End Function

Function CircleMine(x:Int,y:Int)

 x=x*MineSizeX-MineSizeX/2
 y=y*MineSizeY-MineSizeY/2

 DrawOval x,y,MineSizeX*2,MineSizeY*2

End Function

Stephan87

BeitragMi, Jan 24, 2007 19:32
Antworten mit Zitat
Benutzer-Profile anzeigen
sehr sehr interessant. habe das spiel jetzt schon in arrays geschrieben. war gar nicht mal so viel aufwand. hier habt ihr einen kleinen einblick (natürlich nicht bugfrei, sitze gerade am programmieren):

Code: [AUSKLAPPEN]


'   M I N E S W E E P E R

'   1st preview edition

'   Projekt gestartet am 22.01.07

Strict
Const NumberOfMines% = 30
Global MinesMap%[22, 17]
Global Aufgedeckt%[20, 15]
Global Markiert%[20, 15]
Global image_deck:TImage = LoadImage("mine_deck.png")
Global image_right:TImage = LoadImage("mine_right.png")
Global image_fail:TImage = LoadImage("mine_fail.png")
Global Loose% = False


Graphics 640, 480, 32

SeedRnd MilliSecs()


CreateNewGame()


' -------------------
' B O O T S C R E E N
' -------------------
Rem
SetScale 3, 3
DrawText "M I N E S W E E P E R", 60, 150
Flip
WaitKey
Cls
End Rem

' ---------------
' M A I N L O O P
' ---------------

Repeat
   Cls
   If Not Loose Then
      Update()
   Else
      SetScale 2.5, 2.5
      DrawText "Du hast leider verloren!", 75, 220
   End If
   Flip
Until KeyDown(key_escape)






' -----------------
' F U N C T I O N S
' -----------------

Function CreateNewGame()

   For Local n% = 1 To 20
      For Local k% = 1 To 15
         MinesMap[n, k] = 0
         Aufgedeckt[n-1, k-1] = False
      Next
   Next
   
   For Local n% = 1 To NumberOfMines
      Local MineSet% = False
      Repeat
         Local x% = Rand(1, 20)
         Local y% = Rand(1, 15)
         If MinesMap[x, y] < 9 Then MinesMap[x, y] = 9; MineSet = True
      Until MineSet = True
   Next

   For Local n% = 1 To 20
      For Local k% = 1 To 15
         If MinesMap[n, k] < 9 Then MinesMap[n, k] = CheckHowMany(n, k)
      Next
   Next
   
End Function


Function CheckHowMany%(x%, y%)

   Local Counter% = 0         ' Counter auf Null setzen
   If MinesMap[x+1, y+1] = 9 Then Counter:+1
   If MinesMap[x-1, y-1] = 9 Then Counter:+1
   If MinesMap[x, y-1] = 9 Then Counter:+1
   If MinesMap[x+1, y-1] = 9 Then Counter:+1
   If MinesMap[x-1, y] = 9 Then Counter:+1
   If MinesMap[x-1, y+1] = 9 Then Counter:+1
   If MinesMap[x+1, y] = 9 Then Counter:+1
   If MinesMap[x, y+1] = 9 Then Counter:+1
   Return Counter
   
End Function


Function Update()

   If MouseDown(1) Then Aufgedeckt[(MouseX()-MouseX() Mod 32)/32, (MouseY()-MouseY() Mod 32)/32] = True

   If KeyDown(key_f1) CreateNewGame()

   For Local x = 1 To 20
      For Local y = 1 To 15
         If MouseDown(2) Then Markiert[x-1, y-1] = True
         If Not Aufgedeckt[x-1, y-1] Then
            If Not Markiert[x-1, y-1] Then DrawImage image_deck, 32*(x-1), 32*(y-1) Else DrawImage image_fail, 32*(x-1), 32*(y-1)
         Else
            If MinesMap[x, y] = 9 Then
               Loose = True
            Else
               DrawImage image_right, 32*(x-1), 32*(y-1)
               DrawText MinesMap[x, y], 32*(x-1) + 10, 32*(y-1) + 10
            End If
         End If            
      Next
   Next
   
End Function

Markus2

BeitragMi, Jan 24, 2007 19:55
Antworten mit Zitat
Benutzer-Profile anzeigen
@Stephan87
jup,
aber du solltest Bildschirm Ausgaben und Benutzer Eingaben trennen .

Und für sowas

Global MinesMap%[22, 17]
Global Aufgedeckt%[20, 15]
Global Markiert%[20, 15]

gibt es Strukturen Wink

Type TItem
Field Mine:Int
Field Aufgedeckt:Int
Field Markiert:Int
End Type

Global Map:TItem[22, 17]

Stephan87

BeitragMi, Jan 24, 2007 20:07
Antworten mit Zitat
Benutzer-Profile anzeigen
mmh ok, das ich benutzer eingaben und bildschirm ausgaben trennen sollte sehe ich ein, aber warum jetzt doch plötzlich mit types? ich meine, mein code weiter oben ist kürzer als deiner in OOP und enthält schon alles, was das spiel brauch, ausser die überprüfung, ob man gewonnen hat. daran arbeite ich gerade.

mein code ist auch noch ein wenig im chaos weil ich, wie immer ^^, einfach drauf los programmiere. leider wüsste ich nicht, wie ich die variablen strukturieren könnte ausser in OOP.

Markus2

BeitragMi, Jan 24, 2007 21:09
Antworten mit Zitat
Benutzer-Profile anzeigen
Das hat den Sinn das du nur 1 Array hast .
Wenn sich das Array in der größe ändert du nur eins neu dimensionieren mußt .
Du kannst Funktionen und Methoden in der Struktur unterbringen (habe
ich damals auch nicht gemacht weil ungewohnt Embarassed )
Du kannst diese Struktur einer Funktion übergeben .
Dein Quelltext wird übersichtlicher und verständlicher und läßt sich
später einfacher erweitern oder ändern .
Und noch vieles mehr .
Kommt halt auf das Projekt an was man macht .
Ob der Quelltext kürzer oder länger ist spielt keine Rolle,
hauptsache man blickt da durch und das auch wenn man mal
ein paar Monate oder Jahre nix dran gemacht hat und evtl. dran
weiter arbeiten will .
Wenn man von Anfang an sauber arbeitet spart man sich
später bei Änderungen sehr viel Arbeit und Zeit (hab ich so fest gestellt) .

Stephan87

BeitragSo, Jan 28, 2007 22:02
Antworten mit Zitat
Benutzer-Profile anzeigen
ich habe eine frage zu meinem aktuellen code von minesweeper. sicherlich ist er nicht schön geschrieben und auch noch nicht optimiert, aber ich habe ein grundsätzliches problem: wenn ich im spiel auf das rechte, untere feld klicke (rechte maustaste oder linke, völlig egal), so ändert das gesamte spielfeld, scheinbar, seinen Alphablend-wert. wie kommt das? konnte es im code nicht ausfindig machen.

Code: [AUSKLAPPEN]


'   M I N E S W E E P E R

'   dev-code v3

'   Projekt gestartet am 22.01.07

Strict
Global NumberOfMines% = 40
Global MinesMap%[22, 17]
Global Aufgedeckt%[22, 17]
Global Flag%[22, 17]
Global image_deck:TImage = LoadImage("mine_deck.png")
Global image_fail:TImage = LoadImage("image_flag.png")
Global image_back:TImage = LoadImage("back.jpg")
Global image_logo:TImage = LoadImage("logo.png")
'Global sound_lost:TSound = LoadSound("lost.wav", True)
'Global sound_title:TSound = LoadSound("music.mid", True)
Global Lost% = False
Global Won% = False
Global FlagCount% = 0
Global RightMouseHit% = 0

Graphics 640, 480, 32
SetBlend ALPHABLEND

SeedRnd MilliSecs()

'PlaySound sound_title
Mainscreen()


' -------------------
' B O O T S C R E E N
' -------------------



Function Mainscreen()
   SetAlpha(0.1)
   Repeat
      SetScale 1, 1
      DrawImage image_back, 0, 0

      NumberOfMines:+10 * (KeyHit(key_up) - KeyHit(key_down))
      If NumberOfMines < 20 Then NumberOfMines = 20
      If NumberOfMines > 150  Then NumberOfMines = 150

      SetColor 255, 255, 255      
      DrawRect 200, 200, 225, 35
      DrawRect 85, 260, 490, 75
      DrawRect 75, 375, 200, 30
      DrawRect 375, 375, 180, 30
      

      SetScale 0.75, 0.75
      DrawImage image_logo, 60, 50
      
      SetScale 2.5, 2.5
      
      SetColor 0, 0, 0
      DrawText "dev code v3", 200, 200
      
      SetScale 1.5, 1.5
      DrawText "Anzahl der Minen: " + NumberOfMines, 200, 270
      
      SetScale 1, 1
      DrawText "Cursortaste Hoch: +10 Minen, Cursortaste Runter: -10 Minen", 100, 300
      
      SetScale 2, 2
      DrawText "(S)tart Game", 75, 375
      DrawText "(E)xit Game", 375, 375
      
      SetColor 255, 255, 255
      Flip      
   Until KeyDown(key_s) Or KeyDown(key_e)
   If KeyDown(key_s) CreateNewGame(); GameLoop()
   
End Function

' ---------------
' M A I N L O O P
' ---------------

Function GameLoop()
   Repeat
      Cls
      If Lost
         SetColor 255, 0, 0
         UpdateRender()
         SetScale 1.5, 1.5
         DrawRect 160, 220, 190, 15
         SetColor 255, 255, 255
         DrawText "Du hast leider verloren!", 160, 220
         'PlaySound sound_lost
      ElseIf Won
         SetColor 0, 255, 0
         UpdateRender()
         SetScale 1.5, 1.5
         DrawRect 200, 220, 140, 15
         SetColor 255, 255, 255
         DrawText "Du hast gewonnen!", 200, 220
      Else
         UpdateInput()
         UpdateRender()
         CheckIfWon()
      End If
      Flip
   Until KeyDown(key_escape)
   Mainscreen()
End Function






' -----------------
' F U N C T I O N S
' -----------------

Function CreateNewGame()
   Local x%, y%
   FlagCount = 0
   Lost = False
   Won = False
   For x = 1 To 20
      For y = 1 To 15
         MinesMap[x, y] = 0
         Aufgedeckt[x, y] = False
         Flag[x, y] = False
      Next
   Next
   
   For Local n% = 1 To NumberOfMines
      Local MineSet% = False
      Repeat
         x = Rand(1, 20)
         y = Rand(1, 15)
         If MinesMap[x, y] < 9 Then MinesMap[x, y] = 9; MineSet = True
      Until MineSet = True
   Next

   For x = 1 To 20
      For y = 1 To 15
         If MinesMap[x, y] < 9 Then MinesMap[x, y] = CheckHowMany(x, y)
      Next
   Next
   
End Function


Function CheckHowMany%(x%, y%)

   Local Counter% = 0         ' Counter auf Null setzen
   If MinesMap[x+1, y+1] = 9 Then Counter:+1
   If MinesMap[x-1, y-1] = 9 Then Counter:+1
   If MinesMap[x, y-1] = 9 Then Counter:+1
   If MinesMap[x+1, y-1] = 9 Then Counter:+1
   If MinesMap[x-1, y] = 9 Then Counter:+1
   If MinesMap[x-1, y+1] = 9 Then Counter:+1
   If MinesMap[x+1, y] = 9 Then Counter:+1
   If MinesMap[x, y+1] = 9 Then Counter:+1
   Return Counter
   
End Function



Function UpdateInput()

   Local BoxPosX% = (MouseX()-MouseX() Mod 32)/32+1
   Local BoxPosY% = (MouseY()-MouseY() Mod 32)/32+1
   
   If MouseDown(1) Then
      Aufgedeckt[BoxPosX, BoxPosY] = True
      For Local x% = 1 To 20
         For Local y% = 1 To 15
            If Aufgedeckt[x, y] And MinesMap[x, y] = 9 Lost = True
            If Aufgedeckt[x, y] Then
               If MinesMap[x, y] = 0 Then
                  Aufgedeckt[x-1, y+1] = True
                  Aufgedeckt[x-1, y-1] = True
                  Aufgedeckt[x-1, y] = True
                  Aufgedeckt[x, y+1] = True
                  Aufgedeckt[x, y-1] = True
                  Aufgedeckt[x+1, y] = True
                  Aufgedeckt[x+1, y+1] = True
                  Aufgedeckt[x+1, y-1] = True
               End If
            End If
         Next
      Next   
   End If

   If MouseHit(2) = (RightMouseHit + 1) Then
      If Flag[BoxPosX, BoxPosY] = True Then
         Flag[BoxPosX, BoxPosY] = False
         FlagCount:-1
      Else
         If Not Aufgedeckt[BoxPosX, BoxPosY] Then
            Flag[BoxPosX, BoxPosY] = True
            FlagCount:+1
         End If
      End If
   End If
   RightMouseHit = MouseHit(2)   
End Function



Function UpdateRender()
   
   SetScale 1, 1
   DrawImage image_back, 0, 0

   For Local x = 1 To 20
      For Local y = 1 To 15
         If Aufgedeckt[x, y] Then
            SetAlpha(0.4)
            DrawImage image_deck, 32*(x-1), 32*(y-1)
            If Not MinesMap[x, y] = 0 Or MinesMap[x, y] = 9 DrawText MinesMap[x, y], 32*(x-1) + 10, 32*(y-1) + 10
         Else
            If Flag[x, y] = True Then
               SetAlpha(0.5)
               DrawImage image_fail, 32*(x-1), 32*(y-1)
            Else
               SetAlpha(0.8)
               DrawImage image_deck, 32*(x-1), 32*(y-1)
            End If
         End If            
      Next
   Next
   DrawText "Minen uebrig: " + (NumberOfMines - FlagCount), 0, 0   
End Function



Function CheckIfWon()
   Local Counter% = 0
   For Local x% = 1 To 20
      For Local y% = 1 To 15
         If Aufgedeckt[x, y] Then Counter:+1   
      Next
   Next
   If Counter = 300 - NumberOfMines Then Won = True
End Function


hier findet ihr die binär-datei+source-code+grafiken:
http://rapidshare.com/files/13...ode_v3.rar

schöne grüße, stephan
 

E. Urbach

ehemals "Basicprogger"

BeitragMo, Jan 29, 2007 13:07
Antworten mit Zitat
Benutzer-Profile anzeigen
Du hast einfach nur ein SetAlpha am Anfang von UpdateRender() vergessen Wink

Code: [AUSKLAPPEN]
Function UpdateRender()
   
   SetAlpha 1.0
   SetScale 1, 1
   DrawImage image_back, 0, 0

Kannst natürlich auch einen anderen Wert als 1.0 nehmen, wichtig ist nur, dass du ihn setzt.

Merke: Wenn ein Grafik-Fehler bei einem Gitter auftaucht, der mit dem letzen Feld zu tun hat, dann liegt der Fehler zu 99 % darin, dass die Einstellungen nicht zurückgesetzt werden.

Stephan87

BeitragMi, Jan 31, 2007 22:26
Antworten mit Zitat
Benutzer-Profile anzeigen
ja, vielen dank. das war wirklich das problem Embarassed

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group