Jump to content
Sign in to follow this  
Jex

4 Corner game

Recommended Posts

Posted Image

In this game objective is click 4 different box and create rectangle. And that 4 box need same color. Screenshot showing how to play ( White lines )

After select 4 box, "Check" function determine that 4 box creating rectangle and same color. But my check method not working good, some times giving strange errors ^_^

I'm searching a better way for check that 4 box creating renctangle or not. I can't find better solution or fix errors. I hope someone will help me :)

#include <GUIConstants.au3>
#include <Array.au3>

Global $Box[16][16], $Color[4] = [0xFF0000, 0x00FF00, 0x0000FF, 0xFFFF00], $PressCount = 0, $CheckBoxX[4], $CheckBoxY[4], $BoxSplit[5][3], $CountY = 0, $WhichY[5], $CountX = 0, $WhichX[5]
Global $LeftUpCorner, $LeftDownCorner, $RightUpCorner, $RightDownCorner, $BoxColor[16][16]
$GUI = GUICreate("Game", 500, 500)
$BoxSize = 25

For $x = 1 To 15
    For $y = 1 To 15
        $Box[$x][$y] = GUICtrlCreateGraphic(($BoxSize + 1) * $x, ($BoxSize + 1) * $y, $BoxSize, $BoxSize, BitOR($SS_NOTIFY, $WS_BORDER))
    Next
Next

Start()
GUISetState()
While 1
    $msg = GUIGetMsg()
    For $x = 1 To 15
        For $y = 1 To 15
            If $msg = $Box[$x][$y] Then Pressed($x, $y)
        Next
    Next
    If $msg = $GUI_EVENT_CLOSE Then Exit
WEnd

Func Start()
    For $x = 1 To 15
        For $y = 1 To 15
            $Colors = $Color[Random(0, 3, 1)]
            GUICtrlSetBkColor($Box[$x][$y], $Colors)
            $BoxColor[$x][$y] = $Colors
        Next
    Next
EndFunc   ;==>Start

Func Pressed($px, $py)
    GUICtrlSetPos($Box[$px][$py], (($BoxSize + 1) * $px) + ($BoxSize / 8), (($BoxSize + 1) * $py) + ($BoxSize / 8), $BoxSize - (($BoxSize / 8) * 2), $BoxSize - (($BoxSize / 8) * 2))
    $PressCount += 1
    $CheckBoxX[$PressCount - 1] = $px
    $CheckBoxY[$PressCount - 1] = $py
    If $PressCount = 4 Then
        $Check = Check()
        If $Check = 0 Then
            ;MsgBox("", "", "Error!")
            SoundPlay(@WindowsDir & "\media\chord.wav")
            For $z = 0 To 3
                GUICtrlSetPos($Box[$CheckBoxX[$z]][$CheckBoxY[$z]], ($BoxSize + 1) * $CheckBoxX[$z], ($BoxSize + 1) * $CheckBoxY[$z], $BoxSize, $BoxSize)
            Next
        Else
            SoundPlay(@WindowsDir & "\media\notify.wav")
            ;MsgBox("", "", $LeftUpCorner & "<- LeftUp  " & $LeftDownCorner & "<- LeftDown  " & $RightUpCorner & "<- RightUp  " & $RightDownCorner & "<- RightDown")
            DeleteBox($LeftUpCorner, $RightDownCorner)
        EndIf
        $CountY = 0
        $CountX = 0
        $PressCount = 0
    EndIf
EndFunc   ;==>Pressed

Func Check()
    For $i = 1 To 3
        If $BoxColor[$CheckBoxX[0]][$CheckBoxY[0]] <> $BoxColor[$CheckBoxX[$i]][$CheckBoxY[$i]] Then Return 0
    Next
    $MinY = _ArrayMin($CheckBoxY, 1, 0)
    For $i = 0 To 3
        If $CheckBoxY[$i] = $MinY Then
            $CountY += 1
            $WhichY[$CountY] = $i
        EndIf
    Next
    If $CountY <> 2 Then Return 0
    $MinX = _ArrayMin($CheckBoxX, 1, 0)
    For $i = 0 To 3
        If $CheckBoxX[$i] = $MinX Then
            $CountX += 1
            $WhichX[$CountX] = $i
        EndIf
    Next
    If $CountX <> 2 Then Return 0
    If $WhichY[1] = $WhichX[1] Then
        Global $LeftUpCorner = $CheckBoxX[$WhichY[1]] & "." & $CheckBoxY[$WhichY[1]]
        Global $RightUpCorner = $CheckBoxX[$WhichY[2]] & "." & $CheckBoxY[$WhichY[2]]
        Global $LeftDownCorner = $CheckBoxX[$WhichX[2]] & "." & $CheckBoxY[$WhichX[2]]
        $CheckLast = ($WhichY[1] + $WhichY[2]) + $WhichX[2]
    Else
        Global $LeftUpCorner = $CheckBoxX[$WhichY[2]] & "." & $CheckBoxY[$WhichY[2]]
        Global $RightUpCorner = $CheckBoxX[$WhichY[1]] & "." & $CheckBoxY[$WhichY[1]]
        Global $LeftDownCorner = $CheckBoxX[$WhichX[1]] & "." & $CheckBoxY[$WhichX[1]]
        $CheckLast = ($WhichY[1] + $WhichY[2]) + $WhichX[1]
    EndIf
    $Split1 = StringSplit($RightUpCorner, ".", 1)
    $Split2 = StringSplit($LeftDownCorner, ".", 1)
    Global $RightDownCorner = $Split1[1] & "." & $Split2[2]
    If $CheckLast = 6 Then $CheckResult = 0
    If $CheckLast = 5 Then $CheckResult = 1
    If $CheckLast = 4 Then $CheckResult = 2
    If $CheckLast = 3 Then $CheckResult = 3
    If $Split1[1] = $CheckBoxX[$CheckResult] And $Split2[2] = $CheckBoxY[$CheckResult] Then
        Return 1
    Else
        Return 0
    EndIf
EndFunc   ;==>CheckCorners

Func DeleteBox($D1, $D2)
    $DSplit1 = StringSplit($D1, ".", 1)
    $DSplit2 = StringSplit($D2, ".", 1)
    For $dx = $DSplit1[1] To $DSplit2[1]
        For $dy = $DSplit1[2] To $DSplit2[2]
            GUICtrlSetPos($Box[$dx][$dy], (($BoxSize + 1) * $dx) + ($BoxSize / 8), (($BoxSize + 1) * $dy) + ($BoxSize / 8), $BoxSize - (($BoxSize / 8) * 2), $BoxSize - (($BoxSize / 8) * 2))
        Next
    Next
    For $dx = $DSplit1[1] To $DSplit2[1]
        For $dy = $DSplit1[2] To $DSplit2[2]
            GUICtrlSetPos($Box[$dx][$dy], ($BoxSize + 1) * $dx, ($BoxSize + 1) * $dy, $BoxSize, $BoxSize)
            $Colors = $Color[Random(0, 3, 1)]
            GUICtrlSetBkColor($Box[$dx][$dy], $Colors)
            $BoxColor[$dx][$dy] = $Colors
        Next
    Next
EndFunc
Edited by Jex

Share this post


Link to post
Share on other sites

I think it will be more accurate and much faster if your loops only test the squares for matches that MUST result in a rectangle. blocks that wouldn't result in a rectangle shouldn't even be checked for color.

For example, assuming the red block in the second row and second column near the top left is (2,2 = red).

Loop through the remaining blocks ONLY ON THE BASE ROW (i.e. $x += 1) until a match is found at (2,9 = red).

- Now loop through the remaing blocks ONLY ON THE BASE COLUMN ( i.e. $y += 1) until a match is found at (5,2 = red)

- - Check the block at the column from the first and the row from the second (5,9 = Blue), not a match.

- Continue checking the rest of the BASE COLUMN until another match is found at (13, 2 = red)

- - Check the block at (13,9 = Yellow), not a match

- Finish checking the rest of the BASE COLUMN, no more red blocks. No rectangle found yet.

Continue checking the rest of the BASE ROW and the next match is at (2,10 = red).

- Loop through the BASE COLUMN again, first match is (5,2 = red) again.

- - Check the block at (5, 10 = red) MATCH = RECTANGLE!!!

At this point you have to decide if a single block can only be part of exactly one rectangle. If the BASE BLOCK currently being tested can be part of multiple rectangles, then you save the found rectangle and continue check the rest of the columns and rows against that block. Otherwise, just move on the next BASE BLOCK and start the loop over.

You only increment $x and $y. Never look back, because if you started from (1,1) and moved forward, those blocks have already been tested. This means the area to test gets smaller as you move through the puzzle and the loops get smaller/faster.

The above point also means there is no point in using any of the squares in the last row or last column as BASE BLOCK, because no rectangle going forward can be made from there, and the ones going backwards will have already been found.

:)

Edited by PsaltyDS

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites

Problem is how to determine which block top left corner. After find top left corner, your idea will be work good i think :)

Thanks for your help.

Edit : I'm wrong understand. You saying try that method for every block so not need find left corner.

Edited by Jex

Share this post


Link to post
Share on other sites

Problem is how to determine which block top left corner. After find top left corner, your idea will be work good i think ^_^

Thanks for your help.

I was under the impression that you would start from (1,1) and loop through ALL of them, looking for rectangle matches (excluding the last row and last column).

If not, what are the rules for picking the first block?

:)


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites

I was under the impression that you would start from (1,1) and loop through ALL of them, looking for rectangle matches (excluding the last row and last column).

If not, what are the rules for picking the first block?

:)

Sorry for my bad english. I think now im understand but still im not sure ^_^

Now i'm adding your method in script, after added i will post here script.

Share this post


Link to post
Share on other sites

Now im tried another method but again have problems, some times determine true sometimes not.. :)

#include <GUIConstants.au3>
#include <Array.au3>

Global $Box[16][16], $Color[4] = [0xFF0000, 0x00FF00, 0x0000FF, 0xFFFF00], $PressCount = 0, $CheckBox[5][3], $BoxSplit[5][3], $CountY = 0, $WhichY[5], $CountX = 0, $WhichX[5], $Left = 0, $Right = 0
Global $LeftUpCorner, $LeftDownCorner, $RightUpCorner, $RightDownCorner, $BoxColor[16][16]
$GUI = GUICreate("Game", 500, 500)
$BoxSize = 25

For $x = 1 To 15
    For $y = 1 To 15
        $Box[$x][$y] = GUICtrlCreateGraphic(($BoxSize + 1) * $x, ($BoxSize + 1) * $y, $BoxSize, $BoxSize, BitOR($SS_NOTIFY, $WS_BORDER))
    Next
Next

Start()
GUISetState()
While 1
    $msg = GUIGetMsg()
    For $x = 1 To 15
        For $y = 1 To 15
            If $msg = $Box[$x][$y] Then Pressed($x, $y)
        Next
    Next
    If $msg = $GUI_EVENT_CLOSE Then Exit
WEnd

Func Start()
    For $x = 1 To 15
        For $y = 1 To 15
            $Colors = $Color[Random(0, 3, 1)]
            GUICtrlSetBkColor($Box[$x][$y], $Colors)
            $BoxColor[$x][$y] = $Colors
        Next
    Next
EndFunc   ;==>Start

Func Pressed($px, $py)
    GUICtrlSetPos($Box[$px][$py], (($BoxSize + 1) * $px) + ($BoxSize / 8), (($BoxSize + 1) * $py) + ($BoxSize / 8), $BoxSize - (($BoxSize / 8) * 2), $BoxSize - (($BoxSize / 8) * 2))
    $PressCount += 1
    $CheckBox[$PressCount][1] = $px
    $CheckBox[$PressCount][2] = $py
    If $PressCount = 4 Then
        $Check = Check()
        If $Check = 0 Then
            ;MsgBox("", "", "Error!")
            SoundPlay(@WindowsDir & "\media\chord.wav")
            For $z = 1 To 4
                GUICtrlSetPos($Box[$CheckBox[$z][1]][$CheckBox[$z][2]], ($BoxSize + 1) * $CheckBox[$z][1], ($BoxSize + 1) * $CheckBox[$z][2], $BoxSize, $BoxSize)
            Next
        Else
            SoundPlay(@WindowsDir & "\media\notify.wav")
            ;MsgBox("", "", $LeftUpCorner & "<- LeftUp  " & $LeftDownCorner & "<- LeftDown  " & $RightUpCorner & "<- RightUp  " & $RightDownCorner & "<- RightDown")
            ;DeleteBox($LeftUpCorner, $RightDownCorner)
            ;MsgBox("", "", "True")
        EndIf
        $Left = 0
        $Right = 0
        $CountY = 0
        $CountX = 0
        $PressCount = 0
    EndIf
EndFunc   ;==>Pressed

Func Check()
    For $i = 2 To 4
        If $BoxColor[$CheckBox[1][1]][$CheckBox[1][2]] <> $BoxColor[$CheckBox[$i][1]][$CheckBox[$i][2]] Then Return 0
    Next
    For $i = 1 To 4     
        For $z = $CheckBox[$i][1] + 1 To 15
            For $p = 1 To 4
                If $CheckBox[$p][1] = $z Then
                    $Right = $z
                    $Right2 = $p
                    MsgBox("", "", $i & "  " & "Top Right true")
                    ExitLoop 2
                EndIf
            Next
        Next
        If $Right <> 0 Then
            For $z = $CheckBox[$i][2] + 1 To 15
                For $p = 1 To 4
                    If $CheckBox[$p][2] = $z Then
                        If $p <> $Right2 Then
                            $Left = $z
                            $Left2 = $p
                            MsgBox("", "", $i & "  " & "Bottom Left true")
                            ExitLoop 2
                        EndIf
                    EndIf
                Next
            Next
        EndIf
        If $Left <> 0 Then
            For $z = 1 To 4
                If $Right = $CheckBox[$z][1] And $Left = $CheckBox[$z][2] Then
                    MsgBox("", "", $i & "  " & "Bottom Right true")
                    Return 1
                EndIf
            Next
        EndIf
        $Left = 0
        $Left2 = ""
        $Right = 0
        $Right2 = ""
    Next
    Return 0
EndFunc   ;==>CheckCorners

Func DeleteBox($D1, $D2)
    $DSplit1 = StringSplit($D1, ".", 1)
    $DSplit2 = StringSplit($D2, ".", 1)
    For $dx = $DSplit1[1] To $DSplit2[1]
        For $dy = $DSplit1[2] To $DSplit2[2]
            GUICtrlSetPos($Box[$dx][$dy], (($BoxSize + 1) * $dx) + ($BoxSize / 8), (($BoxSize + 1) * $dy) + ($BoxSize / 8), $BoxSize - (($BoxSize / 8) * 2), $BoxSize - (($BoxSize / 8) * 2))
        Next
    Next
    For $dx = $DSplit1[1] To $DSplit2[1]
        For $dy = $DSplit1[2] To $DSplit2[2]
            GUICtrlSetPos($Box[$dx][$dy], ($BoxSize + 1) * $dx, ($BoxSize + 1) * $dy, $BoxSize, $BoxSize)
            $Colors = $Color[Random(0, 3, 1)]
            GUICtrlSetBkColor($Box[$dx][$dy], $Colors)
            $BoxColor[$dx][$dy] = $Colors
        Next
    Next
EndFunc
Edited by Jex

Share this post


Link to post
Share on other sites

Well, I completely misunderstood what you were trying to do. I didn't realize you were coding the game, I thought you were writing code TO PLAY THE GAME. I thought you wanted to search for all possible matching rectangles. Just checking if the four selections form a rectangle is much easier.

This mod seems to work:

#include <GUIConstants.au3>
#include <Array.au3>

Global $Box[16][16], $Color[4] = [0xFF0000, 0x00FF00, 0x0000FF, 0xFFFF00], $PressCount = 0
Global $CheckBox[5][3], $BoxSplit[5][3], $CountY = 0, $WhichY[5], $CountX = 0, $WhichX[5], $Left = 0, $Right = 0
Global $LeftUpCorner, $LeftDownCorner, $RightUpCorner, $RightDownCorner, $BoxColor[16][16]
$GUI = GUICreate("Game", 500, 500)
$BoxSize = 25

For $x = 1 To 15
    For $y = 1 To 15
        $Box[$x][$y] = GUICtrlCreateGraphic(($BoxSize + 1) * $x, ($BoxSize + 1) * $y, $BoxSize, $BoxSize, BitOR($SS_NOTIFY, $WS_BORDER))
    Next
Next

Start()
GUISetState()
While 1
    $msg = GUIGetMsg()
    For $x = 1 To 15
        For $y = 1 To 15
            If $msg = $Box[$x][$y] Then Pressed($x, $y)
        Next
    Next
    If $msg = $GUI_EVENT_CLOSE Then Exit
WEnd

Func Start()
    For $x = 1 To 15
        For $y = 1 To 15
            $Colors = $Color[Random(0, 3, 1)]
            GUICtrlSetBkColor($Box[$x][$y], $Colors)
            $BoxColor[$x][$y] = $Colors
        Next
    Next
EndFunc   ;==>Start

Func Pressed($px, $py)
    ; Test for a box already used
    Local $avCtrlPos = ControlGetPos($GUI, "", $Box[$px][$py])
    If $avCtrlPos[2] <> $BoxSize Then Return
    ConsoleWrite("Debug: Pressed $px = " & $px & "  $py = " & $py & @LF)
    
    ; Change size to show selection
    GUICtrlSetPos($Box[$px][$py], (($BoxSize + 1) * $px) + ($BoxSize / 8), (($BoxSize + 1) * $py) + ($BoxSize / 8), $BoxSize - (($BoxSize / 8) * 2), $BoxSize - (($BoxSize / 8) * 2))
    $PressCount += 1
    $CheckBox[$PressCount][1] = $px
    $CheckBox[$PressCount][2] = $py
    If $PressCount = 4 Then
        ; _ArrayDisplay($CheckBox, "Debug: $CheckBox")
        $Check = Check()
        If $Check = 0 Then
            SoundPlay(@WindowsDir & "\media\chord.wav")
            For $z = 1 To 4
                GUICtrlSetPos($Box[$CheckBox[$z][1]][$CheckBox[$z][2]], ($BoxSize + 1) * $CheckBox[$z][1], ($BoxSize + 1) * $CheckBox[$z][2], $BoxSize, $BoxSize)
            Next
        Else
            SoundPlay(@WindowsDir & "\media\notify.wav")
        EndIf
        $Left = 0
        $Right = 0
        $CountY = 0
        $CountX = 0
        $PressCount = 0
    EndIf
EndFunc   ;==>Pressed

Func Check()
    ; Produce a normal array to work with
    Local $avTemp[4][2]
    For $i = 0 To 3
        $avTemp[$i][0] = $CheckBox[$i + 1][1]
        $avTemp[$i][1] = $CheckBox[$i + 1][2]
    Next
    
    ; Sort 2D array
    ; _ArrayDisplay($avTemp, "Debug: $avTemp")
    _ArraySort($avTemp, 0, 1, 0, 2)
    ;_ArrayDisplay($avTemp, "Debug: $avTemp sorted")
    
    ; Test for rectangle
    Local $IsRect = False
    If ($avTemp[0][0] = $avTemp[1][0]) And ($avTemp[2][0] = $avTemp[3][0]) Then
        ; So far, so good two pair of matching x values
        If ($avTemp[0][1] = $avTemp[2][1]) And ($avTemp[1][1] = $avTemp[3][1]) Then
            $IsRect = True
        ElseIf ($avTemp[0][1] = $avTemp[3][1]) And ($avTemp[1][1] = $avTemp[2][1]) Then
            $IsRect = True
        EndIf
    EndIf
    If Not $IsRect Then Return 0
    
    ; Test for matching colors
    For $i = 1 To 3
        If $BoxColor[$avTemp[$i][0]][$avTemp[$i][1]] <> $BoxColor[$avTemp[0][0]][$avTemp[0][1]] Then Return 0
    Next
    
    ; Valid rectangle with matching colors
    Return 1
EndFunc   ;==>Check

Func DeleteBox($D1, $D2)
    $DSplit1 = StringSplit($D1, ".", 1)
    $DSplit2 = StringSplit($D2, ".", 1)
    For $dx = $DSplit1[1] To $DSplit2[1]
        For $dy = $DSplit1[2] To $DSplit2[2]
            GUICtrlSetPos($Box[$dx][$dy], (($BoxSize + 1) * $dx) + ($BoxSize / 8), (($BoxSize + 1) * $dy) + ($BoxSize / 8), $BoxSize - (($BoxSize / 8) * 2), $BoxSize - (($BoxSize / 8) * 2))
        Next
    Next
    For $dx = $DSplit1[1] To $DSplit2[1]
        For $dy = $DSplit1[2] To $DSplit2[2]
            GUICtrlSetPos($Box[$dx][$dy], ($BoxSize + 1) * $dx, ($BoxSize + 1) * $dy, $BoxSize, $BoxSize)
            $Colors = $Color[Random(0, 3, 1)]
            GUICtrlSetBkColor($Box[$dx][$dy], $Colors)
            $BoxColor[$dx][$dy] = $Colors
        Next
    Next
EndFunc   ;==>DeleteBox

In Check() I moved the data to a more normal array because the format of $CheckBox made _ArraySort() not work as expected. Also, I didn't know if you were supposed to be able to select the same square again, so I put in code to prevent it. Just remove those first couple of lines in Pressed() if you want the player to be able to re-select a block.

:)


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites

Posted Image

If you press that numbers ( Look screenshot ), Check function return 0.

Still not work true ^_^

By the way very thanks for your help :)

Edit : Now im noticed if start creating rectangle from top right and bottom right corners, Check function return 0.

Example :

[2] [ ] [1]

[ ] [ ] [ ]

[3] [ ] [4]

[2] [ ] [3]

[ ] [ ] [ ]

[4] [ ] [1]

Edited by Jex

Share this post


Link to post
Share on other sites

If you press that numbers ( Look screenshot ), Check function return 0.

Still not work true :)

By the way very thanks for your help :)

Oops.

Just change the _ArraySort in Check() to: _ArraySort($avTemp, 0, 0, 0, 2)

^_^

Edited by PsaltyDS

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×
×
  • Create New...