学号 20241202 《Python程序设计》实验四报告
课程:《Python程序设计》
班级: 2412
姓名: 王凯
学号:20241202
实验教师:王志强
实验日期:2025年5月14日
必修/选修: 公选课
1.实验内容
基于所玩游戏需要抢部分商品,鉴于手速过慢,所抢人数过多,想编写一个连点器的代码,从单纯的连点进阶到预设点位连点,具有连点器该有的基本功能,以此帮助自己。
2. 实验过程及结果
(1)先写了一份初版代码,此版代码无法预设点位,只能单纯设置间隔时间与连点(在最后一节python课上帮助我抢到三次回答问题的机会)。
视频链接在下方,此处只插入一张图片为证(强哥应该不会因为我用代码抢答而揍我吧??)。

(2)此为初版代码运行截屏。

(3)按照面向对象的设计思路,实现 AutoClicker 类,包含以下主要方法:(询问了ai)
init():初始化程序状态和参数
start_clicking():控制自动点击的主循环
toggle_clicking():切换点击状态(开始 / 停止)
set_interval():设置点击间隔时间
set_click_type():设置点击类型(左 / 右 / 中键)
add_point():添加当前鼠标位置为预设点位
clear_points():清除所有预设点位
list_points():列出所有预设点位
set_loop_mode():设置循环模式
on_press():处理键盘按键事件
run():启动程序,初始化线程和键盘监听器
(4)由于一些部分自己并不会,是由ai编写改进的代码,因此专门去查询了解了实验原理————动连点器基于 Python 的多个库协同工作实现功能:
pyautogui 库:用于控制鼠标的移动和点击操作,实现自动化点击功能。
pynput.keyboard 库:监听键盘事件,实现快捷键控制程序运行状态、设置参数等功能。
threading 库:实现多线程编程,将点击操作与键盘监听分离,确保程序响应灵敏。
time 库:控制点击间隔时间,实现精确的自动点击频率。
(5)诞生了进阶版连点器代码。代码实现了在提前预设点位的准备下进行游戏内商品的抢取(当然也可用在其它方面)。下图为运行截图,后有视频链接。

3.代码
import threading
import pyautogui
from pynput import keyboard
class AutoClicker:
def __init__(self):
self.running = False
self.program_running = True
self.click_interval = 0.1 # 默认点击间隔0.1秒
self.click_type = "left" # 默认左键点击
self.points = [] # 存储预设点位
self.current_point_index = 0 # 当前点位索引
self.loop_mode = "sequence" # 点击模式: sequence(顺序) 或 repeat(重复单点)
def start_clicking(self):
while self.program_running:
while self.running and self.points:
x, y = self.points[self.current_point_index]
pyautogui.moveTo(x, y) # 移动到点位
if self.click_type == "left":
pyautogui.click(button="left")
elif self.click_type == "right":
pyautogui.click(button="right")
elif self.click_type == "middle":
pyautogui.click(button="middle")
# 更新点位索引
if self.loop_mode == "sequence":
self.current_point_index = (self.current_point_index + 1) % len(self.points)
# 延迟
time.sleep(self.click_interval)
time.sleep(0.1)
def toggle_clicking(self):
self.running = not self.running
status = "开始" if self.running else "停止"
print(f"{status}连点,间隔: {self.click_interval}秒,模式: {self.loop_mode}")
def set_interval(self, interval):
try:
self.click_interval = max(0.01, float(interval)) # 最小间隔0.01秒
print(f"设置点击间隔为: {self.click_interval}秒")
except ValueError:
print("输入无效,请输入数字")
def set_click_type(self, click_type):
if click_type in ["left", "right", "middle"]:
self.click_type = click_type
print(f"设置点击按钮为: {self.click_type}键")
else:
print("无效的点击类型,请选择: left, right, middle")
def add_point(self):
"""添加当前鼠标位置为预设点位"""
x, y = pyautogui.position()
self.points.append((x, y))
print(f"已添加点位 {len(self.points)}: ({x}, {y})")
def clear_points(self):
"""清除所有预设点位"""
self.points = []
self.current_point_index = 0
print("已清除所有预设点位")
def list_points(self):
"""列出所有预设点位"""
if not self.points:
print("没有预设点位")
return
print("预设点位列表:")
for i, (x, y) in enumerate(self.points, 1):
print(f"{i}. ({x}, {y})")
def set_loop_mode(self, mode):
"""设置循环模式: sequence(顺序) 或 repeat(重复单点)"""
if mode in ["sequence", "repeat"]:
self.loop_mode = mode
print(f"设置循环模式为: {self.loop_mode}")
else:
print("无效的模式,请选择: sequence 或 repeat")
def exit(self):
self.running = False
self.program_running = False
print("程序已退出")
def on_press(self, key):
try:
if key.char == 's': # S键开始/停止连点
self.toggle_clicking()
elif key.char == 'i': # I键设置间隔
new_interval = input("请输入点击间隔(秒): ")
self.set_interval(new_interval)
elif key.char == 't': # T键设置点击类型
new_type = input("请输入点击类型(left/right/middle): ")
self.set_click_type(new_type)
elif key.char == 'a': # A键添加当前鼠标位置为点位
self.add_point()
elif key.char == 'c': # C键清除所有点位
self.clear_points()
elif key.char == 'l': # L键列出所有点位
self.list_points()
elif key.char == 'm': # M键设置循环模式
new_mode = input("请输入循环模式(sequence/repeat): ")
self.set_loop_mode(new_mode)
elif key.char == 'q': # Q键退出程序
self.exit()
return False
except AttributeError:
pass
def run(self):
print("自动连点器已启动")
print("快捷键:")
print("S: 开始/停止连点")
print("I: 设置点击间隔")
print("T: 设置点击类型")
print("A: 添加当前鼠标位置为预设点位")
print("C: 清除所有预设点位")
print("L: 列出所有预设点位")
print("M: 设置循环模式(顺序/重复)")
print("Q: 退出程序")
click_thread = threading.Thread(target=self.start_clicking)
click_thread.daemon = True
click_thread.start()
with keyboard.Listener(on_press=self.on_press) as listener:
listener.join()
if __name__ == "__main__":
clicker = AutoClicker()
clicker.run()
4. 实验过程中遇到的问题和解决过程
-
问题1:在写代码时,遇到一些配置上的问题。
-
问题1解决方案:询问豆包后,进行了配置。(以下为解决过程的截图)
![]()
![]()
-
问题2:在用户输入设置参数时,可能与自动点击线程产生冲突。
-
问题2解决方案:使用线程锁保护共享资源。(代码如下)
class AutoClicker:
def __init__(self):
self.lock = threading.Lock()
# 其他初始化代码...
def start_clicking(self):
while self.program_running:
while self.running and self.points:
with self.lock:
x, y = self.points[self.current_point_index]
-
问题3:在某些受保护的应用程序中,键盘监听器可能无法工作。
-
问题3解决方案:使用全局热键而非应用内快捷键;图形界面替代命令行输入,使用 tkinter 或 PyQt 创建窗口。
5.运行视频链接
1.https://www.bilibili.com/video/BV1fMTez8EAC/?spm_id_from=333.1387.upload.video_card.click&vd_source=9d355fcfc6d4f05dde0c634c52e6fa8f(初版)
2.https://www.bilibili.com/video/BV1e6TvztECG/?spm_id_from=333.1387.list.card_archive.click&vd_source=9d355fcfc6d4f05dde0c634c52e6fa8f(进阶版)
其他(感悟、思考等)
在经历一个学期的学习后,回想课程的点点滴滴,是一段有趣且收获颇丰的经历,在课程中学到了知识,虽然只是初窥门径,但老师的讲法以及python本身的简便性确实提升了我对python的兴趣。丛老师带着写实验到最后一次的自我发挥,明显感觉到了自己的进步,讲实话,最后一次实验设计成自我发挥简直是神之一手,给了我们自我发挥自己想法的一个很好的机会。希望今后的日子里能继续与python结缘。
参考资料
1.《0基础学python》
2.豆包ai



浙公网安备 33010602011771号