Modificar script que usa PixelGetColor

Tire suas dúvidas sobre programação em AutoHotkey

Moderator: Gio

c0de5
Posts: 2
Joined: 19 May 2022, 12:56

Modificar script que usa PixelGetColor

Post by c0de5 » 19 May 2022, 13:03

Olá, tudo bem?
Eu tenho um script de campo minado que resolve o jogo automaticamente e funciona bem no jogo original.
O script usa PixelGetColor para detectar e resolver, mas preciso adaptá-lo para usar o imagesearch para resolver o jogo.
É possível fazer isso? Também estou disposto a pagar por esta modificação (não sei se é contra as regras do fórum).

Código do script:

Code: Select all

F10::

;===============================常量========================================

;延时常量
delayer := 50

;鼠标速度
SetDefaultMouseSpeed, 0
SetMouseDelay, 2 ; 设为小于2时会出现卡死bug,尚未解决

blocksize := 16
left_x := 16
top_y := 100
right_x := left_x + blocksize * 9
bottom_y := top_y + blocksize * 9
halfsize := blocksize // 2

;颜色常量
color_to_num := {0xC0C0C0: 0, 0x0000FF: 1, 0x008000: 2, 0xFF0000: 3, 0x000080: 4, 0x800000: 5, 0x008080: 6, 0x000000: 7, 0x808080: 8}

;用于循环的数组
thirty := [1,2,3,4,5,6,7,8,9]
sixteen := [1,2,3,4,5,6,7,8,9]

;第一个方块的坐标
firstblock_x := left_x + halfsize
firstblock_y := top_y + halfsize


;=================================END=======================================


初始化面板: 
blocktable := {}
for r in sixteen {
    for c in thirty {    
        blocktable[r, c] := new Block(r, c)
    }
}


第一步: ;点开中间的一个
blocktable[9, 9].Open()


第二步: ;遍历单数字推断,直到无法插旗无法点开 
loop {
    dealed := 0
    for r in sixteen {
        for c in thirty {
            check_block := blocktable[r, c]
            if (check_block.num > 0) {
                if (!check_block.finalled) { 

                    ; 数数数字周围旗子的数量和没开的block的数量
                    flags := 0 
                    close_block_num := 0
                    close_blocks := []
                    for i, block in SurroundingBlocks(check_block) {
                        if (!block.openned) {
                            close_block_num++
                            close_blocks.Insert(block)
                            if (block.flagged) {
                                flags++
                            }
                        }
                    }
                    ; msgbox, % "旗子数:" flags "`r关闭的格子数:" close_block_num "`r数字:" check_block.num


                    ;如果旗子数量等于数字,打开数字周围
                    if (check_block.num == flags && flags < close_block_num) {
                        for i, block in close_blocks {
                            block.Open()
                            dealed++
                        }
                        check_block.finalled := True
                    }

                    ;如果没开的的数量等于数字,就把周围插上旗子
                    if (check_block.num == close_block_num && flags < close_block_num) {
                        for i, block in close_blocks {
                            block.Flag()
                            dealed++
                        }
                        check_block.finalled := True
                    }
                }    
            }
        }
    }
    ; msgbox, %dealed%
} Until dealed == 0


第三步: ;找到边缘所有block
edge_blocks := []
for r in sixteen {
    for c in thirty {  
        if (blocktable[r, c].num > 0 && !blocktable[r, c].finalled) {
            for i, block in SurroundingBlocks(blocktable[r, c]) {
                if (!block.openned && !block.flagged) {
                    if (!IsIn(block, edge_blocks)) {
                        edge_blocks.Insert(block)
                    }
                }
            }                                
        }
    }
}

; 没有了就结束
if (edge_blocks == []) {
    Reload
}


第四步: ;概率最小的点开
possible_panels := PossiblePanels(edge_blocks)
ToolTip

;用于累加每个block出现雷的次数
counts := [] 
for step in possible_panels[1] {
    counts[step] := 0
}

for i, panel in possible_panels { ;对所有block出现雷的次数累加
    for step, mark in panel {
        counts[step] += mark
    }
}

did_flag := False
for step, marks in counts { ;如果有block在所有panel中都有雷,插旗子
    if (marks == possible_panels.Length()) {
        step.Flag()
        did_flag := True
    }
}

;如果有block在所有panel中都没有出现过雷,点开
did_open := False
for step, marks in counts { 
    if (marks == 0) {
        step.Open()
        did_open := True
    }
}

;如果没有一个绝对安全的block可以点开,那就点开概率最小的
if (!did_open && !did_flag) { 
    ; msgbox, % "边缘长度:" edge_blocks.length() "`r插旗子:" did_flag "`r打开过:" did_open "`r开始蒙"
    min_marks := possible_panels.Length() + 1 ;初始值设置为比最大可能值大1
    for step, marks in counts {
        if (marks <= min_marks) {
            min_marks := marks 
            min_marks_step := step ;找出雷出现次数最少的一个block
        }    
    } 
    min_marks_step.Open()

    ; 检查有没有猜错,猜错了就结束
    PixelGetColor, Getcolor, min_marks_step.x - 6, min_marks_step.y - 6, RGB
    if (Getcolor == 0xFF0000) { 
        MsgBox, 5, , Bad luck. 
        IfMsgBox, Retry 
        {
            Click 257, 75 ; 点笑脸重新开始
            Goto, 初始化面板
        }
        Reload
    }
}

Goto, 第二步

;===============================子过程======================================

PrintList(list1) {
    s := ""
    for i, v in list1 {
        s := s " " v
    }
    ToolTip, %s%, 960, 800, 1
}

PrintListOfList(list2) {
    l := "length: " list2.Length()
    for i, list1 in list2 {
        s := ""
        for i, v in list1 {
            s := s " " v
        }
        l := l "`r" s
    }
    ToolTip, %l%, 1300, 0, 2
}

class Block {
    __New(r, c) {
        this.r := r
        this.c := c
        this.x := xOfc(c)
        this.y := yOfr(r)
        this.flagged := False
        this.openned := False
        this.num := ""
        this.finalled := False
    }

    Open(really_oppend := False) {
        if (!this.openned && !this.flagged) {
            if (!really_oppend) {
                Mousemove, this.x, this.y
                Click
            }
            this.openned := True
            if (this.num == "") { ;没有检查过数字的话就检查一下
                PixelGetColor, Getcolor, this.x, this.y, RGB
                this.num := ColorToNum(Getcolor)
                if (this.num == 0) { ;如果点开发现是空的,就会打开四周
                    for i, block in SurroundingBlocks(this) {
                        block.Open(True)
                    }
                }
            }
        }   
    }

    Flag() {
        if (!this.flagged) {
            Mousemove, this.x, this.y
            Click Right
            this.flagged := True
        }
    }

    MouseOn() {
        Mousemove, this.x, this.y
    }
}

ColorToNum(color1) {
    global color_to_num
    return color_to_num[color1]
}

LengthOfList(collection) {
    l := 0
    for i, v in collection{
        l++
    }
    return l
}

IsIn(item, collection){
    for i, v in collection{
        if (v == item) {
            return 1
        }
    }
    return 0
}

xOfc(c) { ; 根据列找x坐标
    global
    return (c - 1) * blocksize + firstblock_x
}

yOfr(r) { ; 根据行找y坐标
    global
    return (r - 1) * blocksize + firstblock_y
}

SurroundingBlocks(block) {
    global blocktable
    surrounding_blocks := []
    for i, small_r in [-1, 0, 1] {
        for i, small_c in [-1, 0, 1] {
            if (!(small_r == 0 && small_c == 0)) {
                real_r := block.r + small_r
                real_c := block.c + small_c
                if (real_r > 0 && real_r <= 16 && real_c >0 && real_c <= 30) {
                        surrounding_blocks.Insert(blocktable[real_r, real_c])
                }
            }
        }
    }
    return surrounding_blocks
}

PossiblePanels(blocks) {
    global edge_blocks
    if (blocks.Length() == 0) {
        return [[]]
    } else {
        new_possible_panels := []
        less_blocks := blocks.Clone()
        less_blocks.Remove()
        for n, panel in PossiblePanels(less_blocks) {
            reject0 := False ; 初始化两个拒绝状态
            reject1 := False

            now_step := blocks[LengthOfList(panel)+1]
            for i, num_block in SurroundingBlocks(now_step) { ;走到当前这一块,它的周围8个遍历
                if (num_block.num > 0) { ;有数字的block

                    ; 计算未点开的block的数量、旗子的数量、标记过的1或0的数量
                    close_block_num := 0
                    flags := 0
                    marked_zeros := 0 
                    marked_ones := 0
                    for i, block in SurroundingBlocks(num_block) { ;数字周围的block
                        if (!block.openned) {
                            close_block_num++
                        }
                        if (block.flagged)
                            flags++
                        if (panel.HasKey(block)) { ; 如果数字周围的block在之前走过的路径中
                            if (panel[block] == 1) {
                                marked_ones++
                            }
                            if (panel[block] == 0) {
                                marked_zeros++
                            }
                        }
                    }
                    if (num_block.num == close_block_num - marked_zeros) { ;满足条件一,不可以无雷
                        reject0 := True                    
                    }
                    if (num_block.num == marked_ones + flags) { ;满足条件二,不可以有雷
                        reject1 := True 
                    }
                }
            }

            if (!reject0) {
                panel0 := panel.Clone()
                panel0.Insert(now_step, 0)
                new_possible_panels.Insert(panel0)
            }
            if (!reject1) {
                panel1 := panel.Clone()
                panel1.Insert(now_step, 1)
                new_possible_panels.Insert(panel1) 
            }
        }

        ;PrintListOfList(new_possible_panels)
        ToolTip, % "Step: " LengthOfList(new_possible_panels[1]) " / " edge_blocks.Length() "`rPossible panels found: " new_possible_panels.Length()

        return new_possible_panels
    }
}


;=================================END=======================================

Return

F11:: Pause
F12:: Reload 

Return to “Ajuda e Suporte Geral”