Python手势识别石头剪刀布游戏平局计数器异常问题求助
问题解决:石头剪刀布游戏平局计数器异常递增
问题现象
使用Python结合OpenCV、MediaPipe开发的石头剪刀布游戏中,平局计数器dcounter无法正常累加:1次平局后显示79,2次平局后显示158,每次平局实际被累加了近80次,而非预期的1次。
错误原因
代码中计数逻辑放在了clock < 200的分支内,该分支对应游戏结果展示阶段(从clock=120到clock=199,共80帧)。每经过一帧,代码就会执行一次平局判断并累加计数器,导致一次平局被重复计数80次。
修复方案
将胜负及平局的计数逻辑移至clock == 120的分支中——这是游戏结果唯一确定的时刻,仅会执行一次,确保每次游戏结果只触发一次计数:
- 在
clock == 120获取到双方手势后,立即判断胜负关系并更新计数器 - 将结果文本的拼接逻辑保留在
clock < 200分支中,负责展示结果
修复后的完整代码
import cv2 as cv import mediapipe as mp username1 = input("Enter username:") username2 = input("Enter username:") mp_drawing = mp.solutions.drawing_utils mp_drawing_styles = mp.solutions.drawing_styles mp_hands = mp.solutions.hands # 判断手势是剪刀、石头还是布 def getHandMove(hand_landmarks): landmarks = hand_landmarks.landmark if all([landmarks[i].y < landmarks[i+3].y for i in range(9,20,4)]):return "steen" elif landmarks[13].y < landmarks[16].y and landmarks[17].y < landmarks[20].y:return "schaar" else: return "papier" # 连接摄像头 vid = cv.VideoCapture(0) # 游戏时钟 clock = 0 p1_move = p2_move = None gameText = "" success = True # 胜利计数器 wcounter = 0 # 失败计数器 lcounter = 0 # 平局计数器 dcounter = 0 # 初始化手部追踪模型 with mp_hands.Hands(model_complexity=0, min_detection_confidence=0.5, min_tracking_confidence=0.5) as hands: while True: ret, frame = vid.read() if not ret or frame is None: break frame = cv.cvtColor(frame, cv.COLOR_BGR2RGB) results = hands.process(frame,) frame = cv.cvtColor(frame, cv.COLOR_RGB2BGR) if results.multi_hand_landmarks: for hand_landsmarks in results.multi_hand_landmarks: mp_drawing.draw_landmarks(frame, hand_landsmarks, mp_hands.HAND_CONNECTIONS, mp_drawing_styles.get_default_hand_landmarks_style(), mp_drawing_styles.get_default_hand_connections_style()) # 游戏流程控制 if 0 <= clock < 60: success = True gameText = "Ready?" elif clock < 80: gameText = "schaar" elif clock < 100: gameText = "steen" elif clock < 120: gameText = "papier" elif clock == 120: # 获取手部手势结果 hls = results.multi_hand_landmarks if hls and len(hls) == 2: p1_move = getHandMove(hls[0]) p2_move = getHandMove(hls[1]) # 在此处判断胜负并更新计数器(仅执行一次) if p1_move == p2_move: dcounter += 1 elif (p1_move == "papier" and p2_move == "steen") or \ (p1_move == "steen" and p2_move == "schaar") or \ (p1_move == "schaar" and p2_move == "papier"): wcounter += 1 else: lcounter += 1 else: success = False elif clock < 200: if success: # 展示游戏结果文本 gameText = f"{username1} koos voor {p1_move}. {username2} koos voor {p2_move}." if p1_move == p2_move: gameText = f"{gameText} gelijkspel!" elif (p1_move == "papier" and p2_move == "steen") or \ (p1_move == "steen" and p2_move == "schaar") or \ (p1_move == "schaar" and p2_move == "papier"): gameText = f"{gameText} {username1} wint!" else: gameText = f"{gameText} {username2} wint!" else: gameText = "Ongeldig" # 在帧上绘制文本 cv.putText(frame, f"Clock: {clock}", (50,50), cv.FONT_HERSHEY_PLAIN, 2, (0,255,255), 2, cv.LINE_AA) cv.putText(frame, gameText, (50,80), cv.FONT_HERSHEY_PLAIN, 1, (0,255,255), 2, cv.LINE_AA) clock = (clock + 1) % 200 # 翻转画面,使玩家位置符合直觉 cv.flip(frame, 1) # 显示帧 cv.imshow('frame', frame) # 按q键退出游戏 if cv.waitKey(1) & 0xFF == ord('q'): break vid.release() cv.destroyAllWindows() print(f"胜利次数: {wcounter}, 失败次数: {lcounter}, 平局次数: {dcounter}")
内容的提问来源于stack exchange,提问作者Stef Verniers
相关产品推荐
相关产品推荐

