Hi,
gibt ja öfters mal die Anfrage wie man "Snake" programmiert, deswegen habe ich mal ne einfache "Snake" Klasse gebastelt. Ist nicht so super sauber, aber immerhin (kommt auch ohne Panels etc aus!). Evtl als Grundgerüst geeignet für eigene Versuche.
Spoiler anzeigen
Die anwendung ist im Prinzip super simpel. Komplett leere Form und dann:
Spoiler anzeigen
gibt ja öfters mal die Anfrage wie man "Snake" programmiert, deswegen habe ich mal ne einfache "Snake" Klasse gebastelt. Ist nicht so super sauber, aber immerhin (kommt auch ohne Panels etc aus!). Evtl als Grundgerüst geeignet für eigene Versuche.
VB.NET-Quellcode
- Public Enum FeldStatus
- Frei
- Schlange
- Hindernis
- Futter
- End Enum
- Public Class Feld
- Public Rect As Rectangle
- Public Index_X As Integer
- Public Index_Y As Integer
- Public Status As FeldStatus
- End Class
- Public Enum Richtung
- Rauf
- Runter
- Links
- Rechts
- End Enum
- Public Class Bewegung
- Private _richtung As Richtung = SnakeSample.Richtung.Rauf
- Private _dx As Integer = 0
- Private _dy As Integer = -1
- Public Property Richtung() As Richtung
- Get
- Return _richtung
- End Get
- Set(ByVal value As Richtung)
- _richtung = value
- Select Case _richtung
- Case SnakeSample.Richtung.Rauf
- _dx = 0
- _dy = -1
- Case SnakeSample.Richtung.Runter
- _dx = 0
- _dy = 1
- Case SnakeSample.Richtung.Links
- _dx = -1
- _dy = 0
- Case SnakeSample.Richtung.Rechts
- _dx = 1
- _dy = 0
- End Select
- End Set
- End Property
- Public ReadOnly Property DeltaX() As Integer
- Get
- Return _dx
- End Get
- End Property
- Public ReadOnly Property DeltaY() As Integer
- Get
- Return _dy
- End Get
- End Property
- End Class
- Public Class Schlange
- Public Bewegungsrichtung As New Bewegung
- Public Koerper As New List(Of Feld)
- Public Sub Friss(ByVal sp(,) As Feld, ByVal Futterfeld As Feld)
- Koerper.Insert(0, Futterfeld)
- sp(Futterfeld.Index_X, Futterfeld.Index_Y).Status = FeldStatus.Schlange
- End Sub
- Public Sub SchwanzVor(ByVal sp(,) As Feld)
- If Koerper.Count > 1 Then
- Dim f As Feld = Koerper(Koerper.Count - 1)
- sp(f.Index_X, f.Index_Y).Status = FeldStatus.Frei
- Koerper.RemoveAt(Koerper.Count - 1)
- End If
- End Sub
- Public ReadOnly Property Kopf() As Point
- Get
- Return New Point(Koerper(0).Index_X, Koerper(0).Index_Y)
- End Get
- End Property
- Public ReadOnly Property Schwanz() As Point
- Get
- Return New Point(Koerper(Koerper.Count - 1).Index_X, Koerper(Koerper.Count - 1).Index_Y)
- End Get
- End Property
- End Class
- Public Class SnakeGame
- Private picture As PictureBox
- Private spielfeld(,) As Feld
- Private die_schlange As New Schlange
- Private WithEvents tm As New Timers.Timer
- Public Sub New(ByVal pbox As PictureBox, ByVal width As Integer, ByVal height As Integer)
- picture = pbox
- ' Spielfeld bauen
- Dim w As Integer = pbox.Width \ width
- Dim h As Integer = pbox.Height \ height
- Dim f As Feld
- ReDim spielfeld(width - 1, height - 1)
- For x = 0 To width - 1
- For y = 0 To height - 1
- f = New Feld With {.Index_X = x, .Index_Y = y, .Status = FeldStatus.Frei}
- f.Rect = New Rectangle(x * w, y * h, w - 1, h - 1)
- spielfeld(x, y) = f
- Next
- Next
- ' Rand setzen
- For x = 0 To width - 1
- spielfeld(x, 0).Status = FeldStatus.Hindernis
- spielfeld(x, height - 1).Status = FeldStatus.Hindernis
- Next
- For y = 0 To height - 1
- spielfeld(0, y).Status = FeldStatus.Hindernis
- spielfeld(width - 1, y).Status = FeldStatus.Hindernis
- Next
- ' Schlange setzen:
- die_schlange.Bewegungsrichtung.Richtung = Richtung.Rauf
- die_schlange.Friss(spielfeld, spielfeld(width \ 2, height \ 2))
- spielfeld(width \ 2, height \ 2).Status = FeldStatus.Schlange
- ' Futter platzieren
- SetzeFutter()
- ' Timer setzen
- tm.Enabled = False
- tm.Interval = 500
- tm.AutoReset = True
- End Sub
- Public Sub Start()
- tm.Enabled = True
- End Sub
- Private ran As New Random
- Private Sub SetzeFutter()
- Dim rx, ry As Integer
- Do
- rx = ran.Next(1, spielfeld.GetUpperBound(0) - 1)
- ry = ran.Next(1, spielfeld.GetUpperBound(1) - 1)
- If spielfeld(rx, ry).Status <> FeldStatus.Frei Then Continue Do
- ' Schlangenkopf muss mehr als drei Felder weg sein!
- If Math.Abs(rx - die_schlange.Kopf.X) < 4 Then Continue Do
- If Math.Abs(ry - die_schlange.Kopf.Y) < 4 Then Continue Do
- ' feld ok
- Exit Do
- Loop
- spielfeld(rx, ry).Status = FeldStatus.Futter
- End Sub
- Private Sub ThreadSafeDraw()
- Dim d As dlgZeichneSpielfeld = AddressOf ZeichneSpielfeld
- picture.Invoke(d)
- End Sub
- Private Delegate Sub dlgZeichneSpielfeld()
- Public Sub ZeichneSpielfeld()
- Dim b As New Bitmap(picture.ClientRectangle.Width, picture.ClientRectangle.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb)
- picture.Image = b
- Dim g As Graphics = Graphics.FromImage(picture.Image)
- Dim f As Feld
- Dim br As System.Drawing.Brush = Nothing
- For x = 0 To spielfeld.GetUpperBound(0)
- For y = 0 To spielfeld.GetUpperBound(1)
- f = spielfeld(x, y)
- Select Case f.Status
- Case FeldStatus.Frei
- br = New System.Drawing.SolidBrush(Color.White)
- Case FeldStatus.Schlange
- br = New System.Drawing.SolidBrush(Color.Black)
- Case FeldStatus.Hindernis
- br = New System.Drawing.SolidBrush(Color.Red)
- Case FeldStatus.Futter
- br = New System.Drawing.SolidBrush(Color.Green)
- End Select
- g.FillRectangle(br, f.Rect)
- Next
- Next
- End Sub
- Public Sub OnKey(ByVal keycode As Keys)
- Select Case keycode
- Case Keys.A
- die_schlange.Bewegungsrichtung.Richtung = Richtung.Links
- Case Keys.Y
- die_schlange.Bewegungsrichtung.Richtung = Richtung.Runter
- Case Keys.S
- die_schlange.Bewegungsrichtung.Richtung = Richtung.Rechts
- Case Keys.W
- die_schlange.Bewegungsrichtung.Richtung = Richtung.Rauf
- End Select
- End Sub
- Private Sub tm_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs) Handles tm.Elapsed
- ' Prüfe neue Position des Schlangenkopfes
- Dim nx, ny As Integer
- With die_schlange
- nx = .Kopf.X + .Bewegungsrichtung.DeltaX
- ny = .Kopf.Y + .Bewegungsrichtung.DeltaY
- End With
- Dim f As Feld = spielfeld(nx, ny)
- Select Case f.Status
- Case FeldStatus.Frei
- ' nix besonders
- die_schlange.Friss(spielfeld, f)
- die_schlange.SchwanzVor(spielfeld)
- Case FeldStatus.Futter
- die_schlange.Friss(spielfeld, f)
- tm.Interval -= 25
- SetzeFutter()
- Case FeldStatus.Hindernis
- ' game over
- GameEnde()
- Case FeldStatus.Schlange
- If f.Index_X = die_schlange.Schwanz.X AndAlso f.Index_Y = die_schlange.Schwanz.Y Then
- ' Ist ok
- die_schlange.SchwanzVor(spielfeld)
- die_schlange.Friss(spielfeld, f)
- Else
- ' game over
- GameEnde()
- End If
- End Select
- ThreadSafeDraw()
- End Sub
- Private Sub GameEnde()
- tm.Enabled = False
- MessageBox.Show("Game Over")
- Application.Exit()
- End Sub
- End Class
Die anwendung ist im Prinzip super simpel. Komplett leere Form und dann:
VB.NET-Quellcode
- Public Class Form1
- Private sg As SnakeGame
- Private sh As Boolean = False
- Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
- sg.OnKey(e.KeyCode)
- End Sub
- Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
- Me.KeyPreview = True
- Dim p As New PictureBox
- Me.Controls.Add(p)
- p.Dock = DockStyle.Fill
- sg = New SnakeGame(p, 20, 20)
- End Sub
- Private Sub Form1_Shown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Shown
- sg.ZeichneSpielfeld()
- If Not sh Then
- sh = True
- sg.Start()
- End If
- End Sub
- End Class