MineSweeper-Clone mit Arrays oder OOP?
Übersicht

![]() |
Stephan87Betreff: MineSweeper-Clone mit Arrays oder OOP? |
![]() Antworten mit Zitat ![]() |
---|---|---|
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 ![]() |
||
![]() |
BlitzcoderNewsposter |
![]() Antworten mit Zitat ![]() |
---|---|---|
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
![]() |
TheShadowModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Arrays - da dein Spielfeld ein "Gitter" ist...
ist einfacher |
||
AMD64 3500+ | GeForce6600GT 128MB | 1GB DDR | WinXPsp2 |
![]() |
Markus2 |
![]() Antworten mit Zitat ![]() |
---|---|---|
zum abgucken ![]() 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 |
![]() Antworten mit Zitat ![]() |
---|---|---|
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 |
![]() Antworten mit Zitat ![]() |
---|---|---|
@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 ![]() Type TItem Field Mine:Int Field Aufgedeckt:Int Field Markiert:Int End Type Global Map:TItem[22, 17] |
||
![]() |
Stephan87 |
![]() Antworten mit Zitat ![]() |
---|---|---|
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 |
![]() Antworten mit Zitat ![]() |
---|---|---|
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 ![]() 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 |
![]() Antworten mit Zitat ![]() |
---|---|---|
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. Urbachehemals "Basicprogger" |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Du hast einfach nur ein SetAlpha am Anfang von UpdateRender() vergessen ![]() 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 |
![]() Antworten mit Zitat ![]() |
---|---|---|
ja, vielen dank. das war wirklich das problem ![]() |
||
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group