Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: PHP: Miinaharavan tietojen lukeminen

Sivun loppuun

Triton [10.03.2010 11:08:06]

#

Sain jostakin päähän alkaa tekemään ohjelmaa, joka ennustaisi miinaharavan avattujen luukkujen avulla, että missä ruudussa todennäköisimmin on miina. Tällä hetkellä ohjelmaan täytyy olla kokoajan käsin syöttämässä tietoja sisään (mikä on varsin työlästä), joten olisiko mahdollista jollain tavalla lukea Microsoftin miinaharavan eri vaiheiden tietoja suoraan ohjelmaan?

jalski [10.03.2010 12:27:04]

#

Tuosta Windowsin minesweeperistä en tiedä, mutta alla olevista linkeistä saattaa olla apua itse ongelman ratkaisemiseen.


Minesweeper: Advanced Tactics

Richard Kaye's Minesweeper Pages

Triton [10.03.2010 14:12:30]

#

Varsinainen ongelma todennäköisyyksien laskemiseen on jo ratkaistu. Halusin vain jollain tavalla saada tiedot reaaliaikaisesti miinaharavasta tuohon ohjelmaani.

petrinm [10.03.2010 17:11:22]

#

Yksinkertaisin tapa tähän lienee ottaa screenshot kyseisestä ikkunasta ja lukea siitä eri kohtien värejä ja värin perusteella päätellä mikä numero kyseisessä kohdassa on. Miinaharavassa ruudukko on tasakokoinen ja sen numerot ovat erivärisiä, joten lukeminen on toteutettavissa hyvinkin helposti.

for i = 0 to 20 ' kentän koon lukeminen on sitten toinen pulma....
   for j = 0 to 20
       ' Oletetaan että esimmäinen luettava kohta on kohdassa 20, 100
       ' tavallisen miinaharavan ruudut ovat 16 x 16 kokoisia
       väri = GetColor(22 + 16 * i, 100 + 16 * j)
       if väri = sininen then
          taulu[i][j] = 1
       else if väri = Vihreä then
          taulu[i][j] = 2
       else
          ....
   next
next

Triton [10.03.2010 17:21:21]

#

Eipähän todellakaan olisi tullut tuollaista mieleen. Täytyypähän kokeilla. Kiitos vinkistä :D

Edit. vielä kun keksisi, että miten screenshotteja saa kätevimmin otettua muutosten tapahtuessa...

Macro [10.03.2010 17:31:41]

#

Mitä kieltä käytät?

Triton [10.03.2010 17:39:49]

#

Tää alkuperäinen analysoija on tehty PHP:llä, mutta ajattelin koodata tämän uudelleen Pythonilla tai Javalla...

Macro [10.03.2010 18:07:37]

#

PHP:llä tuskin voi screenshottia ottaa, mutta Javalla ei ainakaan tarvitse edes ottaa sitä. Voit lukea vain tietyistä koordinaateista (?).

neau33 [11.03.2010 01:39:47]

#

Moikka Triton!

tässä VB.NET-pohjalta ideoitua sälää...

' [k]väännelty SharpDevelop 3.2'lla[/k]
Imports Accessibility
Imports [linkki "http://www.kotisivutila.fi/neansivut/downloads/AccLayer.zip"]AccLayer[/linkki]
Imports Microsoft.Win32
Imports System.Threading
Imports System.Windows.Forms

Public Partial Class MainForm

   Private Structure ClientStruct
      Dim [Object] As Object
      Dim Left As Integer
      Dim Top As Integer
      Dim Width As Integer
      Dim Location As Point
      Dim [Size] As Size
      Dim Height As Integer
      Dim Mines As Integer
      Dim Level As Integer
   End Structure

   'Private Structure CellMapStruct '***

      'Dim X As Integer
      'Dim y As Integer
      'Dim x2 As Integer
      'Dim y2 As Integer
      ' jne...
   'End Structure

   Private WMINE As ClientStruct

   'Private CellMap() As CellMapStruct '***

   Private sKey As String = "Software\Microsoft\Winmine"

   Dim AccProp As Object = Nothing

   Public Sub New()
      Me.InitializeComponent()
   End Sub

   Sub MainFormLoad(sender As Object, e As EventArgs)

      Me.Top = 550
      Me.Left = _
      (Screen.PrimaryScreen.WorkingArea.Width / 2) _
      - (Me.Width / 2)

      Dim procName As String = "winmine"
      Dim NotAccessible As Boolean = False
      Dim appFolder As String = ""

      If appFolder <> String.Empty Then
         appFolder += "\"
      End If

      KillProcess(procName)
      Dim fullPath As String = appFolder + procName + ".exe"
      StartProcess(fullPath)
      Thread.Sleep(200)

      Dim MyObject As IAccessible  = _
      AccLayer.Acc.GetAccessibleObjectFromHandle _
      (GetProcessHandle(procName))

      Try
         MyObject.accHitTest(1, 1)
      Catch ex As Exception
         NotAccessible = True
      End Try

      If NotAccessible Then
         MsgBox("SHIT! It doesn't Work")
         Exit Sub
      End If

      Dim Children As Object = _
      AccLayer.Acc.GetAccessibleChildren(MyObject)
      Dim MyChild As Object = Nothing

      For i As Integer = 0 To Children.GetUpperBound(0)
         If Children(i).accName = MyObject.accName Then
            MyChild = Children(i): Exit For
         End If
      Next

      If Not MyChild Is Nothing Then
         AccProp = New AccPropertySet(MyChild)
         WMINE.[Object] = MyChild
         AccProp = Nothing: MyChild = Nothing
         timer1.Interval = 250
         timer1.Start
      End If

      MyObject = Nothing

   End Sub

   Sub StartProcess(ByVal fullPath As String)

      Dim sInfo As New ProcessStartInfo

      With sInfo
         .FileName = fullPath
         .WindowStyle = ProcessWindowStyle.Normal
      End With

      Dim proc As New Process

      With proc
         .StartInfo = sInfo
         .Start
      End With

   End Sub

   Sub KillProcess(ByVal AppName As String)
      Dim procs() As Process = Process.GetProcesses()
      For Each proc As Process In procs
        With proc
           If .ProcessName.ToLower _
              = AppName.ToLower Then
              .Kill
           End If
        End With
      Next
      procs = Nothing

   End Sub

   Function IsRunningProcess(ByVal AppName As String) As Boolean

      Dim procs() As Process = Process.GetProcesses()
      For Each proc As Process In procs
        With proc
           If .ProcessName.ToLower _
              = AppName.ToLower Then
              Return True
              procs = Nothing
              Exit Function
           End If
        End With
      Next
      procs = Nothing
      Return False

   End Function

   Function GetProcessHandle(ByVal AppName As String) As Object

      Dim procs() As Process = Process.GetProcesses()
      For Each proc As Process In procs
        With proc
           If .ProcessName.ToLower _
              = AppName.ToLower Then
              Return .MainWindowHandle
              procs = Nothing
              Exit Function
           End If
        End With
      Next
      procs = Nothing
      Return Nothing
   End Function

   Sub Timer1Tick(sender As Object, e As EventArgs)

      Timer1.Stop
      If Not IsRunningProcess("winmine") Then
         MsgBox("SHIT! MineSweeper is not running...")
         Me.Close
      End If

      Try
         AccProp = New AccPropertySet(WMINE.[Object])
         WMINE.Left = AccProp.Location.Left
         WMINE.Top = AccProp.Location.Top
         WMINE.Width = AccProp.Location.Width _
         - AccProp.Location.X
         WMINE.Height = AccProp.Location.Height _
         - AccProp.Location.Y
         WMINE.[Size] = New Size(WMINE.Width,WMINE.Height)
         WMINE.Location = New Point( _
         AccProp.Location.X, AccProp.Location.Y)
         WMINE.Mines = GetRegistryValue("Mines")
         WMINE.Level = GetRegistryValue("Difficulty")
      Catch ex As Exception
         MsgBox("SHIT! Can't connect to object...")
         Me.Close
      End Try

      Try
         Using bmp As New Bitmap(WMINE.Width, WMINE.Height)

            Using g As Graphics = Graphics.FromImage(bmp)
               g.CopyFromScreen(New Point(WMINE.Left, _
               WMINE.Top), New Point(0, 0), WMINE.[Size])

               ' tähän kohtaan voi sitten aivan itse rakennella
               ' toiminnon, jolla kartoittaa solualueet kuvasta
               '(bmp) jotta pääsee vertailemaan kuvan solualueiden
               ' mahdollisia värityksen muutoksia, tyyliin ...
               ' Dim LevelTag As Integer
               ' If LevelTag <> WMINE.Level Then
                  ' Select Case WMINE.Level
                      ' Case 1
                        ' Redim Preserve CellMap( _
                        ' tämän_tason_solujen_määrä) '***
                      ' Case 2
                         'jne..
                     ' Case 3
                        'jne..
                  ' End Select
                  'For i As Integer = 0 To CellMap.GetUpperBound(0)
                     'CellMap(i).x = x.piste kuvasta bmp
                     ' jne...
                  'Next
                   'LevelTag = WMINE.Level
               'End If

               'For i As Integer = 0 To CellMap.GetUpprBound(0)
                  'If bmp.GetPixel(CellMap(i).x, _
                  'CellMap(i).y).ToArgb <> Color.Gray.ToArgb Then 'esim.
                      ' Do something...
                  'End If
               'Next

            End Using
         End Using

      Catch ex As Exception
         MsgBox("SHIT! It doesn't work")
      End Try

      Timer1.Start

   End Sub

   Function GetRegistryValue( _
   ByVal sKeyName As String) As Object

      Dim reg As RegistryKey
      Dim strTemp As String = String.Empty
      reg = Registry.CurrentUser.OpenSubKey(sKey)
      reg.OpenSubKey(sKeyName)
      If Not (reg Is Nothing) Then
         Return reg.GetValue(sKeyName)
      Else
         Return Nothing
      End If
      reg.Close()

   End Function

   Sub MainFormFormClosing(sender As Object, e As FormClosingEventArgs)
      KillProcess("winmine")
      WMINE = Nothing
      Me.Dispose
   End Sub

   Sub MainFormFormClosed(sender As Object, e As FormClosedEventArgs)
      End
   End Sub

End Class

Triton [11.03.2010 06:34:32]

#

Kiitos, täytynee tutkia tätä mahd. pian.

neau33 [11.03.2010 14:09:02]

#

Moikka taas Triton!

Halutessasi voit impata täältä edellistä hieman pidemmälle ideoidun viritelmän sorsat tutkittavaksesi

Triton [11.03.2010 18:46:19]

#

Nyt täytyy enää jostain repästä VB, niin homma lähtee skulaa ;D

vehkis91 [11.03.2010 19:52:46]

#

Mikkisoftan sivuilta VB:net 2008 express edition.

neau33 [11.03.2010 20:40:39]

#

Moikka taas Triton!

Kokeile VB:net 2008 express'n asemesta SharpDevelop 3.2'ta, on hieman kevyempi...

muille.kiinnostuneille@:
edellisessä viestissäni näkyvä linkki on nyt poissa pelistä, mutta täältä voi impata MineSweeperSpy.dll kirjaston asennusohjeineen + VB.NET testiprojektin, jolla selviää .dll'n käyttö

Deffi [11.03.2010 20:49:40]

#

Itsekin innostuin koodailemaan tällasen, joka lukee pelikentän datan suoraan minesweeper.exe:n muistista. Miinuksena jo esitettyyn "kuvatapaan" on se, että tämä joudutaan päivittämään jokaista minesweeper-versiota varten. Plussana se, että saadaan suoraan selville missä ruudussa on miina ja missä ei. Moi.

Binääri
Kuva

edit. tuli kiire. Unohtui sorsa ja mainita, että toimii jossain vistoissa ja seiskoissa. Tästä voi vielä ladata itse pelin.

edit2. jotain hauskaa xp:n miinaharavasta: Minesweeper, Behind the scenes

neau33 [12.03.2010 08:23:51]

#

Heippa taas!

tässä vielä VB.NET-sovitus tosta Deffi'n xp:n miinaharava linkin takaa löytyvästä viritelmästä

Triton [12.03.2010 16:34:59]

#

Deffi kirjoitti:

Plussana se, että saadaan suoraan selville missä ruudussa on miina ja missä ei.

Tuohan on suoranaista huijaamista :D

Metabolix [12.03.2010 16:39:49]

#

Triton kirjoitti:

Tuohan on suoranaista huijaamista :D

Minusta ei ole kiinnostavaa ratkaista algoritmisesti suhteellisen yksinkertaista ongelmaa, joka usein lopulta päättyy kuitenkin arvaamiseen. Deffin ratkaisu on siitä erinomainen, että se poistaa pelistä satunnaiskomponentin. :)

Triton [12.03.2010 16:46:28]

#

Se satunnaisuus tekee miinaharavasta jännittävän. :)


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta