Hi Community,
ich habe versucht Minesweeper zu programmieren. Allerdings hänge ich zur Zeit an einem Problem. Ich habe es einmal versucht in einem Video ständlich zu zeigen.
Es werden nicht alle Felder, die an freie Felder grenzen, aufgedeckt (extra nochmal ein Bild im Anhang). Im Quellcode ist die Funktion "_OpenField($iY, $iX)" für das Aufdecken verantwortlich.
Funktion: _OpenField($iY, $iX) mit der Funktion "_IsPosRange($iY,$iX)":
[autoit]
Func _OpenField($iY, $iX)
;ConsoleWriteError("+> Row: " & $iY & " Column: " & $iX & @CRLF)
If $aGameField[$iY][$iX] = 0 And $aGameField[$iY][$iX] <> 9 Then
; ------------------------------------------------
; INFO:
;
; - $aGameField[$iY][$iX] = 0 -> freies Feld
; - $aGameField[$iY][$iX] = 9 -> Bombe auf Feld
; - $aGameField[$iY][$iX] = 1 -> Feld hat Nummer 1
; - $aGameField[$iY][$iX] = 2 -> Feld hat Nummer 2
; - ....
; - $aGameField[$iY][$iX] = 8 -> Feld hat Nummer 8
; ------------------------------------------------
; - $aOpenFields[$iY][$iX] = 1 -> Feld ist "offen" und wird angezeigt
; - $aOpenFields[$iY][$iX] = 0 -> Feld ist noch verschlossen und wird nicht angezeigt
; ------------------------------------------------
If $aOpenFields[$iY][$iX] = 0 Then
ConsoleWriteError("+> Debug_Open - " & "X: " & $iX & " - Y: " & $iY & @CRLF)
$aOpenFields[$iY][$iX] = 1
If _IsPosRange($iY, $iX + 1) Then _OpenField($iY, $iX + 1)
If _IsPosRange($iY, $iX - 1) Then _OpenField($iY, $iX - 1)
If _IsPosRange($iY + 1, $iX) Then _OpenField($iY + 1, $iX)
If _IsPosRange($iY - 1, $iX) Then _OpenField($iY - 1, $iX)
If _IsPosRange($iY - 1, $iX - 1) Then $aOpenFields[$iY - 1][$iX - 1] = 1
If _IsPosRange($iY + 1, $iX - 1) Then $aOpenFields[$iY + 1][$iX - 1] = 1
If _IsPosRange($iY - 1, $iX + 1) Then $aOpenFields[$iY - 1][$iX + 1] = 1
If _IsPosRange($iY + 1, $iX + 1) Then $aOpenFields[$iY + 1][$iX + 1] = 1
EndIf
EndIf
EndFunc ;==>_OpenField
Func _IsPosRange($iY, $iX)
If $iX >= 0 And $iY >= 0 And $iX <= $iColumn - 1 And $iY <= $iRow - 1 Then
Return True
Else
Return False
EndIf
EndFunc ;==>_IsPosRange
Der gesamte Spiel-Quellcode:
Spoiler anzeigen
#include <Array.au3>
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <StaticConstants.au3>
Opt("GuiOnEventMode", 1)
[/autoit] [autoit][/autoit] [autoit]HotKeySet("u", "_UnhideMap")
HotKeySet("h", "_HideMap")
Global Const $iRow = 11 ; Reihe
Global Const $iColumn = 11 ; Spalte
Global Const $iMaxY = $iRow - 1
Global Const $iMaxX = $iColumn - 1
Global $aGameField[$iRow][$iColumn]
Global $aOpenFields[$iRow][$iColumn]
Global $aGameFieldPic[$iRow][$iColumn]
Global $iShift_X = 16
Global $iShift_Y = 80
Global $iHSX = 5
Global $iTimer = 0
Global $iMines[3] = [10, 40, 99]
Global $iGameMode = 0
; 0 - Anfänger
; 1 - Fortgeschrittener
; 2 - Profi
Global $iDebug_Partner = 0
[/autoit] [autoit][/autoit] [autoit]Global $hWindow_Main = GUICreate("Minesweeper", 252, 335)
GUISetIcon("C:\Users\johannes\Documents\[Prog] Minesweeper\icons\bomb.ico")
GUISetOnEvent(-3, "_Exit")
$MenuItem = GUICtrlCreateMenu("&Spiel")
GUICtrlCreateLabel("", 36 + $iHSX, 16, 43, 29, $WS_BORDER)
GUICtrlSetBkColor(-1, 0x000000)
$hIcon_Smiley = GUICtrlCreateIcon(@ScriptDir & "\icons\big_smile.ico", -1, 100 + $iHSX, 8, 48, 48, BitOR($SS_NOTIFY, $WS_GROUP))
GUICtrlCreateLabel("", 164 + $iHSX, 16, 43, 29, $WS_BORDER)
GUICtrlSetBkColor(-1, 0x000000)
GUISetState(@SW_SHOW, $hWindow_Main)
_GDIPlus_Startup()
Global $aGraphic_Dig = _CreateImages(@ScriptDir & "\digital_num.gif", 9, 21, 11, 21)
Global $aGraphic_Item = _CreateImages(@ScriptDir & "\items.gif", 12, 20, 20, 20)
$hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWindow_Main)
_GDIPlus_GraphicsDrawImage($hGraphic, $aGraphic_Dig[0], 40 + $iHSX, 20)
_GDIPlus_GraphicsDrawImage($hGraphic, $aGraphic_Dig[0], 52 + $iHSX, 20)
_GDIPlus_GraphicsDrawImage($hGraphic, $aGraphic_Dig[0], 64 + $iHSX, 20)
_GDIPlus_GraphicsDrawImage($hGraphic, $aGraphic_Dig[2], 168 + $iHSX, 20)
_GDIPlus_GraphicsDrawImage($hGraphic, $aGraphic_Dig[3], 180 + $iHSX, 20)
_GDIPlus_GraphicsDrawImage($hGraphic, $aGraphic_Dig[9], 192 + $iHSX, 20)
_CreateGameField(1)
[/autoit] [autoit][/autoit] [autoit];_OpenField()
[/autoit] [autoit][/autoit] [autoit]AdlibRegister("_Timer", 1000)
;_ArrayDisplay($aGameFieldPic)
While 1
Sleep(20000)
WEnd
Func _CreateGameField($iMode = -1)
For $iY = 0 To $iRow - 1
For $iX = 0 To $iColumn - 1
_GDIPlus_GraphicsDrawImage($hGraphic, $aGraphic_Item[0], 20 * $iX + $iShift_X, 20 * $iY + $iShift_Y)
If $iMode = 1 Then
$aGameFieldPic[$iY][$iX] = GUICtrlCreatePic("", 20 * $iX + $iShift_X, 20 * $iY + $iShift_Y, 20, 20)
GUICtrlSetOnEvent(-1, "_ClickField")
EndIf
$aGameField[$iY][$iX] = 0
Next
Next
_SetMines()
Opt("GuiOnEventMode", 1)
EndFunc ;==>_CreateGameField
Func _SetMines()
$i = 0
Do
$iY = Random(0, $iRow - 1, 1)
$iX = Random(0, $iColumn - 1, 1)
If $aGameField[$iY][$iX] <> 9 Then
$aGameField[$iY][$iX] = 9
_SetNeighbors($iY, $iX)
$i += 1
EndIf
Until $iMines[$iGameMode] = $i
EndFunc ;==>_SetMines
Func _GetNeighbors($iY, $iX)
Local $aNeighboars[8]
If $iDebug_Partner = 1 Then ConsoleWrite("________________________________________________________" & @CRLF)
[/autoit] [autoit][/autoit] [autoit];1
If $iY > 0 And $iX > 0 Then
$aNeighboars[0] = $aGameField[$iY - 1][$iX - 1]
If $iDebug_Partner = 1 Then ConsoleWrite("1 - OK!" & @CRLF)
EndIf
;2
If $iY > 0 Then
$aNeighboars[1] = $aGameField[$iY - 1][$iX]
If $iDebug_Partner = 1 Then ConsoleWrite("2 - OK!" & @CRLF)
EndIf
;3
If $iY > 0 And $iX < $iColumn - 1 Then
$aNeighboars[2] = $aGameField[$iY - 1][$iX + 1]
If $iDebug_Partner = 1 Then ConsoleWrite("3 - OK!" & @CRLF)
EndIf
;4
If $iX < $iRow - 1 Then
$aNeighboars[3] = $aGameField[$iY][$iX + 1]
If $iDebug_Partner = 1 Then ConsoleWrite("4 - OK!" & @CRLF)
EndIf
;5
If $iY < $iRow - 1 And $iX < $iColumn - 1 Then
$aNeighboars[4] = $aGameField[$iY + 1][$iX + 1]
If $iDebug_Partner = 1 Then ConsoleWrite("5 - OK!" & @CRLF)
EndIf
;6
If $iY < $iColumn - 1 Then
$aNeighboars[5] = $aGameField[$iY + 1][$iX]
If $iDebug_Partner = 1 Then ConsoleWrite("6 - OK!" & @CRLF)
EndIf
;7
If $iY < $iRow - 1 And $iX > 0 Then
$aNeighboars[6] = $aGameField[$iY + 1][$iX - 1]
If $iDebug_Partner = 1 Then ConsoleWrite("7 - OK!" & @CRLF)
EndIf
;8
If $iX > 0 Then
$aNeighboars[7] = $aGameField[$iY][$iX - 1]
If $iDebug_Partner = 1 Then ConsoleWrite("8 - OK!" & @CRLF)
EndIf
If $iDebug_Partner = 1 Then ConsoleWrite("________________________________________________________" & @CRLF)
[/autoit] [autoit][/autoit] [autoit]Return $aNeighboars
EndFunc ;==>_GetNeighbors
Func _SetNeighbors($iY, $iX)
If $iDebug_Partner = 1 Then ConsoleWrite("________________________________________________________" & @CRLF)
;1
If $iY > 0 And $iX > 0 Then
If _IsMine($iY - 1, $iX - 1) Then $aGameField[$iY - 1][$iX - 1] += 1
If $iDebug_Partner = 1 Then ConsoleWrite("1 - OK!" & @CRLF)
EndIf
;2
If $iY > 0 Then
If _IsMine($iY - 1, $iX) Then $aGameField[$iY - 1][$iX] += 1
If $iDebug_Partner = 1 Then ConsoleWrite("2 - OK!" & @CRLF)
EndIf
;3
If $iY > 0 And $iX < $iColumn - 1 Then
If _IsMine($iY - 1, $iX + 1) Then $aGameField[$iY - 1][$iX + 1] += 1
If $iDebug_Partner = 1 Then ConsoleWrite("3 - OK!" & @CRLF)
EndIf
;4
If $iX < $iRow - 1 Then
If _IsMine($iY, $iX + 1) Then $aGameField[$iY][$iX + 1] += 1
If $iDebug_Partner = 1 Then ConsoleWrite("4 - OK!" & @CRLF)
EndIf
;5
If $iY < $iRow - 1 And $iX < $iColumn - 1 Then
If _IsMine($iY + 1, $iX + 1) Then $aGameField[$iY + 1][$iX + 1] += 1
If $iDebug_Partner = 1 Then ConsoleWrite("5 - OK!" & @CRLF)
EndIf
;6
If $iY < $iColumn - 1 Then
If _IsMine($iY + 1, $iX) Then $aGameField[$iY + 1][$iX] += 1
If $iDebug_Partner = 1 Then ConsoleWrite("6 - OK!" & @CRLF)
EndIf
;7
If $iY < $iRow - 1 And $iX > 0 Then
If _IsMine($iY + 1, $iX - 1) Then $aGameField[$iY + 1][$iX - 1] += 1
If $iDebug_Partner = 1 Then ConsoleWrite("7 - OK!" & @CRLF)
EndIf
;8
If $iX > 0 Then
If _IsMine($iY, $iX - 1) Then $aGameField[$iY][$iX - 1] += 1
If $iDebug_Partner = 1 Then ConsoleWrite("8 - OK!" & @CRLF)
EndIf
If $iDebug_Partner = 1 Then ConsoleWrite("________________________________________________________" & @CRLF)
EndFunc ;==>_SetNeighbors
Func _IsMine($iY, $iX)
If $aGameField[$iY][$iX] = 9 Then
Return False
Else
Return True
EndIf
EndFunc ;==>_IsMine
Func _ClickField()
Opt("GuiOnEventMode", 1)
Local $aNeighboars[8]
$iAktuelleFeldID = @GUI_CtrlId - 7
$iAktuell_X = Mod($iAktuelleFeldID, $iColumn)
$iAktuell_Y = Int($iAktuelleFeldID / $iRow)
;MsgBox(1, "", "Reihe: " & $iAktuell_Y & " Spalte: " & $iAktuell_X)
$aNeighboars = _GetNeighbors($iAktuell_Y, $iAktuell_X)
If $aGameField[$iAktuell_Y][$iAktuell_X] = 9 Then
_GameEnd()
EndIf
If $aGameField[$iAktuell_Y][$iAktuell_X] = 0 And $aGameField[$iAktuell_Y][$iAktuell_X] <> 9 Then
_OpenField($iAktuell_Y, $iAktuell_X)
EndIf
_PrintOpenFields()
EndFunc ;==>_ClickField
Func _OpenField($iY, $iX)
;ConsoleWriteError("+> Row: " & $iY & " Column: " & $iX & @CRLF)
If $aGameField[$iY][$iX] = 0 And $aGameField[$iY][$iX] <> 9 Then
; ------------------------------------------------
; INFO:
;
; - $aGameField[$iY][$iX] = 0 -> freies Feld
; - $aGameField[$iY][$iX] = 9 -> Bombe auf Feld
; - $aGameField[$iY][$iX] = 1 -> Feld hat Nummer 1
; - $aGameField[$iY][$iX] = 2 -> Feld hat Nummer 2
; - ....
; - $aGameField[$iY][$iX] = 8 -> Feld hat Nummer 8
; ------------------------------------------------
; - $aOpenFields[$iY][$iX] = 1 -> Feld ist "offen" und wird angezeigt
; - $aOpenFields[$iY][$iX] = 0 -> Feld ist noch verschlossen und wird nicht angezeigt
; ------------------------------------------------
If $aOpenFields[$iY][$iX] = 0 Then
ConsoleWriteError("+> Debug_Open - " & "X: " & $iX & " - Y: " & $iY & @CRLF)
$aOpenFields[$iY][$iX] = 1
If _IsPosRange($iY, $iX + 1) Then _OpenField($iY, $iX + 1)
If _IsPosRange($iY, $iX - 1) Then _OpenField($iY, $iX - 1)
If _IsPosRange($iY + 1, $iX) Then _OpenField($iY + 1, $iX)
If _IsPosRange($iY - 1, $iX) Then _OpenField($iY - 1, $iX)
If _IsPosRange($iY - 1, $iX - 1) Then $aOpenFields[$iY - 1][$iX - 1] = 1
If _IsPosRange($iY + 1, $iX - 1) Then $aOpenFields[$iY + 1][$iX - 1] = 1
If _IsPosRange($iY - 1, $iX + 1) Then $aOpenFields[$iY - 1][$iX + 1] = 1
If _IsPosRange($iY + 1, $iX + 1) Then $aOpenFields[$iY + 1][$iX + 1] = 1
EndIf
EndIf
EndFunc ;==>_OpenField
Func _IsPosRange($iY, $iX)
If $iX >= 0 And $iY >= 0 And $iX <= $iColumn - 1 And $iY <= $iRow - 1 Then
Return True
Else
Return False
EndIf
EndFunc ;==>_IsPosRange
Func _CreateImages($sF_Path = "", $iImages = -1, $iF_X = -1, $iF_LX = -1, $iF_Y = -1)
Local $aGraphics[$iImages + 1]
If $sF_Path <> "" Then
$hBitmap = _GDIPlus_ImageLoadFromFile($sF_Path)
For $i = 0 To $iImages
$aGraphics[$i] = _GDIPlus_BitmapCloneArea($hBitmap, 0, $i * $iF_X, $iF_LX, $iF_Y, $GDIP_PXF24RGB)
Next
EndIf
_WinAPI_DeleteObject($hBitmap)
Return $aGraphics
EndFunc ;==>_CreateImages
Func _GameEnd()
_PrintAllMines()
Opt("GuiOnEventMode", 0)
ConsoleWrite("-> You lose! .. A new game will start!" & @CRLF)
AdlibUnRegister("_Timer")
ConsoleWrite("-> Please wait ..." & @CRLF & @CRLF)
_CreateGameField()
ConsoleWrite("-> New Game!" & @CRLF)
EndFunc ;==>_GameEnd
Func _PrintAllMines()
For $iY = 0 To $iRow - 1
For $iX = 0 To $iColumn - 1
If $aGameField[$iY][$iX] = 9 Then _GDIPlus_GraphicsDrawImage($hGraphic, $aGraphic_Item[10], 20 * $iX + $iShift_X, 20 * $iY + $iShift_Y)
Next
Next
EndFunc ;==>_PrintAllMines
Func _PrintOpenFields()
For $iY = 0 To $iRow - 1
For $iX = 0 To $iColumn - 1
If $aOpenFields[$iY][$iX] = 1 Then _GDIPlus_GraphicsDrawImage($hGraphic, $aGraphic_Item[$aGameField[$iY][$iX] + 1], 20 * $iX + $iShift_X, 20 * $iY + $iShift_Y)
Next
Next
EndFunc ;==>_PrintOpenFields
Func _UnHideMap()
For $iY = 0 To $iRow - 1
For $iX = 0 To $iColumn - 1
_GDIPlus_GraphicsDrawImage($hGraphic, $aGraphic_Item[$aGameField[$iY][$iX] + 1], 20 * $iX + $iShift_X, 20 * $iY + $iShift_Y)
Next
Next
EndFunc ;==>_UnHideMap
Func _HideMap()
For $iY = 0 To $iRow - 1
For $iX = 0 To $iColumn - 1
$aOpenFields[$iY][$iX] = 0
_GDIPlus_GraphicsDrawImage($hGraphic, $aGraphic_Item[0], 20 * $iX + $iShift_X, 20 * $iY + $iShift_Y)
Next
Next
EndFunc ;==>_HideMap
Func _Timer()
$iTimer += 1
;ConsoleWrite($iTimer & @CRLF)
_GDIPlus_GraphicsDrawImage($hGraphic, $aGraphic_Dig[StringRight($iTimer, 1)], 64 + $iHSX, 20)
If $iTimer >= 10 And $iTimer <= 100 Then
_GDIPlus_GraphicsDrawImage($hGraphic, $aGraphic_Dig[StringTrimRight($iTimer, 1)], 52 + $iHSX, 20)
;ConsoleWrite(StringTrimRight($iTimer, 1)& @CRLF)
Else
_GDIPlus_GraphicsDrawImage($hGraphic, $aGraphic_Dig[StringTrimLeft(StringTrimRight($iTimer, 1), 1)], 52 + $iHSX, 20)
EndIf
If $iTimer >= 100 Then _GDIPlus_GraphicsDrawImage($hGraphic, $aGraphic_Dig[StringTrimRight($iTimer, 2)], 40 + $iHSX, 20)
If $iTimer >= 999 Then
;_GameEnd()
EndIf
EndFunc ;==>_Timer
Func _Exit()
_GDIPlus_GraphicsDispose($hGraphic)
For $i = 0 To 9
_GDIPlus_ImageDispose($aGraphic_Dig[$i])
Next
_GDIPlus_Shutdown()
Exit
EndFunc ;==>_Exit
Func _Shuffle(ByRef $aArray)
Local $n, $k, $tmp
$n = UBound($aArray) - 1
While $n > 1
$k = Random(0, $n - 1, 1)
$tmp = $aArray[$n];
$aArray[$n] = $aArray[$k];
$aArray[$k] = $tmp;
$n -= 1
WEnd
Return True
EndFunc ;==>_Shuffle
Vielen Dank, ist vielleicht etwas kompliziert, aber komme nicht selbst drauf