所以我正在尝试制作一个在 humanbenchmark.com 上玩序列记忆迷你游戏的程序,并且在大约 20 次左右的尝试中它确实运行良好。看似随机,程序将无法循环并且不再运行。基本上,程序会检查每个方块顶部的 9 个像素,看看它是否变白。如果是,则会将该方块的索引 : [ 1, 2, 3, 添加到字符串中。每个级别之后的长度 4、5、6、 7、8、9] 您需要记住的序列会变得更长,并且程序也会在级别变量中跟踪它。我这样做是为了节省内存,将其存储在字符串而不是数组中,循环遍历每个字符,并使用字典将字符串中的数字转换为位置。我和 chatgpt 谈过这个问题,机器人说这可能是 pyautogui 的问题,而且它可能不稳定,但我真的不知道。我什至不确定这是否是记忆问题,我只是需要帮助。
我运行了该程序,但它无法循环并在 18 - 24 次左右循环后停止工作。
我的代码如下:
from pyautogui import *
import pyautogui
import time
import keyboard
import win32api, win32con
orderedPositions = ""
pixels = { '1':(1140, 290),
'2':(1270, 290),
'3':(1400, 290),
'4':(1140, 425),
'5':(1270, 425),
'6':(1400, 425),
'7':(1140, 550),
'8':(1270, 550),
'9':(1400, 550), }
def click(mouseX, mouseY):
win32api.SetCursorPos((mouseX, mouseY))
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0)
time.sleep(0.01)
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0)
level = 1
iterations = 0
def checkingLoop():
while True:
global level
global iterations
global orderedPositions
while iterations < level:
if pyautogui.pixel(1140, 290)[0] == 255: # pixel 1
if iterations == level - 1:
orderedPositions += "1"
print("added 1")
time.sleep(0.5)
iterations += 1
continue
elif pyautogui.pixel(1270, 290)[0] == 255: # pixel 2
if iterations == level - 1:
orderedPositions += "2"
print("added 2")
time.sleep(0.5)
iterations += 1
continue
elif pyautogui.pixel(1400, 290)[0] == 255: # pixel 3
if iterations == level - 1:
orderedPositions += "3"
print("added 3")
time.sleep(0.5)
iterations += 1
continue
elif pyautogui.pixel(1140, 425)[0] == 255: # pixel 4
if iterations == level - 1:
orderedPositions += "4"
print("added 4")
time.sleep(0.5)
iterations += 1
continue
elif pyautogui.pixel(1270, 425)[0] == 255: # pixel 5
if iterations == level - 1:
orderedPositions += "5"
print("added 5")
time.sleep(0.5)
iterations += 1
continue
elif pyautogui.pixel(1400, 425)[0] == 255: # pixel 6
if iterations == level - 1:
orderedPositions += "6"
print("added 6")
time.sleep(0.5)
iterations += 1
continue
elif pyautogui.pixel(1140, 550)[0] == 255: # pixel 7
if iterations == level - 1:
orderedPositions += "7"
print("added 7")
time.sleep(0.5)
iterations += 1
continue
elif pyautogui.pixel(1270, 550)[0] == 255: # pixel 8
if iterations == level - 1:
orderedPositions += "8"
print("added 8")
time.sleep(0.5)
iterations += 1
continue
elif pyautogui.pixel(1400, 550)[0] == 255: # pixel 9
if iterations == level - 1:
orderedPositions += "9"
print("added 9")
time.sleep(0.5)
iterations += 1
continue
time.sleep(0.4)
for position in orderedPositions:
tempTuple = pixels.get(position)
click(tempTuple[0], tempTuple[1])
time.sleep(0.05)
pyautogui.moveTo(1530, 425)
level += 1
iterations = 0
checkingLoop() # begin it all
另外,我对 pyautogui 缺乏经验,所以问题可能很明显,但现在我不知道。
我没有对此进行测试,因为我手边没有 Windows 系统,但我怀疑您的程序与 humanbenchmark.com 上运行的程序不同步。
当您学习内循环 (
while iterations < level:
) 中的位置序列时,如果找到匹配项,则使用 time.sleep 休眠 0.5 秒。来自 time.sleep 的文档:
由于系统中其他活动的调度,暂停时间可能比请求的时间长任意量。
所以实际上,系统每次休眠的时间可能略长于超过 0.5 秒。
此外,while 循环内的代码需要非零的时间来运行。因此,每次迭代所需的时间将为 0.5 秒,加上计算机上其他程序引起的任意时间,再加上 while 循环中的代码运行所需的时间。
经过一定次数的迭代后,这可能足以跳过最终变白的方块。您可能会在最后一个方块变白之前检测到倒数第二个方块变白,然后由于延迟稍长,到下一次循环运行时,最后一个方块可能已经开始变暗。如果发生这种情况,
while iterations < level:
循环将继续无限期地迭代,因为没有任何东西可以触发iterations
变量的值增加。
为了使其更可靠,您可以使用 time.perf_counter 来比较序列开始的时间和当前时间。然后,您可以使用它来计算您应该睡眠的时间,以便序列中的每个步骤需要 0.5 秒。
我尝试在下面的代码中实现这一点。 (此代码未经测试,因此您可能需要调整一些内容才能使其正常工作。)
from pyautogui import *
import pyautogui
import time
import keyboard
import win32api, win32con
pixels = {
1: (1140, 290),
2: (1270, 290),
3: (1400, 290),
4: (1140, 425),
5: (1270, 425),
6: (1400, 425),
7: (1140, 550),
8: (1270, 550),
9: (1400, 550),
}
def click(mouseX, mouseY):
win32api.SetCursorPos((mouseX, mouseY))
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0)
time.sleep(0.01)
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0)
def checkingLoop():
sequence = []
level = 1
step = 0
iteration_time = 0.5
max_iterations = 1000
while True:
i = 0
while step < level:
if i >= max_iterations:
raise RuntimeError(f"Could not detect white square after {max_iteration} tries")
for position, coords in pixels.items():
# Check whether the square at this position is white.
# If the red part of the pixel is greater than 200 we assume
# that the square is either white or turning from white to dark.
if pyautogui.pixel(*coords)[0] > 200:
if step == 0:
# We detected the first white square. Use the current
# value of the performance counter as the base time for
# detecting the other white squares in the sequence.
tick = time.perf_counter()
if step == level - 1:
sequence.append(position)
print(f"added {position}")
# Work out how much time we need to sleep given the base
# time we recorded and the number of steps so far in the
# sequence.
tock = time.perf_counter()
time_elapsed = tock - tick
delay = time_elapsed - (iteration_time * step)
sleep_duration = iteration_time - delay
time.sleep(sleep_duration)
step += 1
break
else:
# We didn't find any white squares. Sleep for a little time
# before trying again to give other threads a chance to run.
time.sleep(0.01)
i += 1
time.sleep(0.4)
for position in sequence:
coords = pixels.get(position)
click(*coords)
time.sleep(0.05)
pyautogui.moveTo(1530, 425)
level += 1
step = 0
checkingLoop() # begin it all
根据序列记忆小游戏的实现方式,这也可能在一定数量的步骤后失败。 (即使您的程序使用计时器来跟踪每个步骤的长度,也不能保证迷你游戏会执行相同的操作。)为了使您的程序更加健壮,您需要以某种方式监视迷你游戏以计算出何时序列的每个步骤开始和结束,而不假设它需要一定的时间。