;left arrow                        25
;up arrow                            26
;right arrow                          27
;down arrow                        28
;space bar                          20
#include <GuiConstants.au3>
#include <Array.au3>
opt("GuiOnEventMode", 1)

MsgBox(64, "Anleitung", "Benutze die Pfeiltasten um das Spiel zu starten, die Schlange und das Spiel weiter zu spielen. Benutze die Leertaste um das Spiel zu pausieren.")

$gui = GUICreate("Snake", 400, 400)
GuiSetBkColor(0x000099) 
GUISetState()
GUISetOnEvent($gui_event_close, "_Exit")

Global $clientsize = WinGetClientSize($gui)
Global $speedder = 150
Global $food
Global $snakelength = 0
Dim $board[40][40] ; tracks the board
Dim $snake[$snakelength + 1][3] ; positions and parts of the snake
Dim $food_location[2] ; not possible for multiple food locations?

DllOpen("user32.dll")
_start()
Global $dx = 1
Global $dy = 0
_sleep()
While 1
    Sleep($speedder)
    
    If _IsPressed(25) Then
        $dx = -1
        $dy = 0
    EndIf
    If _IsPressed(27) Then
        $dx = 1
        $dy = 0
    EndIf
    If _IsPressed(26) Then
        $dx = 0
        $dy = -1
    EndIf
    If _IsPressed(28) Then
        $dx = 0
        $dy = 1
    EndIf
    move()
    If _IsPressed(20) Then
        _sleep()
    EndIf
WEnd
Func _start()
    $snakelength = 0
    ReDim $snake[$snakelength + 1][3]
    Local $x, $y, $a, $b, $pos
    For $x = 0 To 39
        For $y = 0 To 39
            $board[$x][$y] = 1 ; empty
        Next
    Next
    $a = Int(Random(3, 36))
    $b = Int(Random(3, 36))
    $snake[0][2] = GUICtrlCreateLabel("", $a * 10, $b * 10, 10, 10)
    GUICtrlSetBkColor($snake[0][2], 16777215)
    $pos = ControlGetPos($gui, "", $snake[0][2])
    $snake[0][0] = Int($pos[0] / 10)
    $snake[0][1] = Int($pos[1] / 10)
;MsgBox (0, "Diagnostic", $snake[0][0] & ", " & $snake[0][1])
    $board[$a][$b] = 0 ; snake  simplifies the "can I go there?" logic
    
    Do
        $a = Int(Random(0, 39))
        $b = Int(Random(0, 39))
    Until $board[$a][$b] = 1 ; empty
    $food = GUICtrlCreateLabel("", $a * 10, $b * 10, 10, 10)
    $pos2 = ControlGetPos($gui, "", $food)
    $food_location[0] = $pos2[0] / 10
    $food_location[1] = $pos2[1] / 10
    GUICtrlSetBkColor($food, 39219)
    $board[$a][$b] = 2 ; food
EndFunc  ;==>_start

Func move()
    
    Local $newhead[3]
    $newhead[0] = $snake[0][0] + $dx
    $newhead[1] = $snake[0][1] + $dy
    
    Local $oldtail[3]
    $oldtail[0] = $snake[$snakelength][0]
    $oldtail[1] = $snake[$snakelength][1]
    $oldtail[2] = $snake[$snakelength][2]
    
    Select
        Case $newhead[0] < 0 Or $newhead[0] > 39 Or $newhead[1] < 0 Or $newhead[1] > 39
            If $snakelength > 0 Then
                MsgBox(64, "Die Schlange prallte gegen die Mauer!", "Deine Schlange war "& ($snakelength + 1) & "Pixel lang!")
            Else
                MsgBox(64, "Deine Schlange fuhr gegen die Wand!", "Du solltest öfter mit deiner Schlange spielen!")
            EndIf
            _cleanup()
            
        Case $board[$newhead[0]][$newhead[1]] ; OK to go there
            $newhead[2] = GUICtrlCreateLabel("", $newhead[0] * 10, $newhead[1] * 10, 10, 10)
            GUICtrlSetBkColor($newhead[2], 16777215)
            If $board[$newhead[0]][$newhead[1]] = 2 Then ; Ate Food
            ; Move food
                Do
                    $a = Int(Random(0, 39))
                    $b = Int(Random(0, 39))
                Until $board[$a][$b] = 1 ; empty
                $board[$a][$b] = 2 ; food
                GUICtrlSetPos($food, $a * 10, $b * 10)
                $snakelength = $snakelength + 1
                ReDim $snake[$snakelength + 1][3]
            Else
                GUICtrlDelete($oldtail[2])
                $board[$oldtail[0]][$oldtail[1]] = 1
            EndIf
            $board[$newhead[0]][$newhead[1]] = 0
            For $i = $snakelength To 1 Step - 1; Array shift
                $snake[$i][0] = $snake[$i - 1][0]
                $snake[$i][1] = $snake[$i - 1][1]
                $snake[$i][2] = $snake[$i - 1][2]
            Next
            $snake[0][0] = $newhead[0]
            $snake[0][1] = $newhead[1]
            $snake[0][2] = $newhead[2]
        Case Else
        ;eat self
            MsgBox(64, "Deine Schlange hat sich selbst gefressen!", "Die Schlange war "& ($snakelength + 1) & " Pixel lang.")
            _cleanup()
    EndSelect
EndFunc  ;==>move

Func _cleanup()
    For $x = 0 To 39
        For $y = 0 To 39
            $board[$x][$y] = 1 ; empty
        Next
    Next
    GUICtrlDelete($food)
    For $i = 0 To $snakelength
        GUICtrlDelete($snake[$i][2])
    Next
    _start()  ; This is going to choke after 300 something calls
    _sleep()
EndFunc  ;==>_cleanup

Func _Exit()
    DllClose("user32.dll")
    Exit
EndFunc  ;==>_Exit
Func _sleep()
    Do
        Do
            Sleep(100)
        Until _IsPressed(25) Or _IsPressed(26) Or _IsPressed(27) Or _IsPressed(28)
        If _IsPressed(25) Then
            $dx = -1
            $dy = 0
        EndIf
        If _IsPressed(27) Then
            $dx = 1
            $dy = 0
        EndIf
        If _IsPressed(26) Then
            $dx = 0
            $dy = -1
        EndIf
        If _IsPressed(28) Then
            $dx = 0
            $dy = 1
        EndIf
    Until _IsPressed(25) Or _IsPressed(26) Or _IsPressed(27) Or _IsPressed(28)
EndFunc  ;==>_sleep
Func _IsPressed($hexkey)
    Local $ar, $brv
    $hexkey = '0x' & $hexkey
    $ar = DllCall("user32", "int", "GetAsyncKeyState", "int", $hexkey)
    
    If $ar[0] <> 0 Then
        $brv = 1
    Else
        $brv = 0
    EndIf
    
    Return $brv
EndFunc  ;==>_IsPressed

