diff --git a/Solitaire.png b/Solitaire.png new file mode 100644 index 0000000..7042563 Binary files /dev/null and b/Solitaire.png differ diff --git a/shenzhen_solitaire/board_cv.py b/shenzhen_solitaire/board_cv.py new file mode 100644 index 0000000..8a7e292 --- /dev/null +++ b/shenzhen_solitaire/board_cv.py @@ -0,0 +1,97 @@ +import cv2 +import numpy +from typing import Optional +from dataclasses import dataclass + +A = cv2.imread("Solitaire.png") + + +@dataclass +class Adjustment: + x: int + y: int + w: int + h: int + dx: int + dy: int + + +def adjust_squares( + image: numpy.ndarray, + count_x: int, + count_y: int, + preset: Optional[Adjustment]) -> Adjustment: + result = preset + if not result: + result = Adjustment(0, 0, 0, 0, 0, 0) + while True: + B = image.copy() + for ix in range(count_x): + for iy in range(count_y): + cv2.rectangle(B, (result.x + + result.dx * + ix, result.y + + result.dy * + iy), (result.x + + result.w + + result.dx * + ix, result.y + + result.h + + result.dy * + iy), (0, 0, 0)) + cv2.imshow('Window', B) + k = cv2.waitKey(0) + print(k) + if k == 27: + break + elif k == 81: + result.x -= 1 + elif k == 83: + result.x += 1 + elif k == 82: + result.y -= 1 + elif k == 84: + result.y += 1 + elif k == 104: + result.x -= 10 + elif k == 115: + result.x += 10 + elif k == 116: + result.y -= 10 + elif k == 110: + result.y += 10 + elif k == 97: + result.w -= 1 + elif k == 111: + result.h -= 1 + elif k == 101: + result.h += 1 + elif k == 117: + result.w += 1 + elif k == 59: + result.dx -= 1 + elif k == 44: + result.dy -= 1 + elif k == 46: + result.dy += 1 + elif k == 112: + result.dx += 1 + + cv2.destroyWindow('Window') + return result + + +def adjust_field(image) -> Adjustment: + return adjust_squares(image, 8, 5, Adjustment(50, 200, 16, 14, 120, 25)) + +def adjust_bunker(image) -> Adjustment: + return adjust_squares(image, 3, 1) + +def adjust_hua(image) -> Adjustment: + return adjust_squares(image, 1, 1) + +def adjust_goal(image) -> Adjustment: + return adjust_squares(image, 3, 1) + + +print(adjust_field(A)) diff --git a/shenzhen_solitaire/solver.py b/shenzhen_solitaire/solver.py index e73bc87..f1eda01 100644 --- a/shenzhen_solitaire/solver.py +++ b/shenzhen_solitaire/solver.py @@ -3,7 +3,11 @@ from typing import List, Iterator, Optional from .board import Board from . import board_actions from .board_possibilities import possible_actions -from .board_actions import MoveAction +from .board_actions import ( + MoveAction, + GoalAction, + HuaKillAction, + DragonKillAction) class ActionStack: @@ -48,7 +52,13 @@ def solve(board: Board) -> Iterator[List[board_actions.Action]]: stack = ActionStack() stack.push(board) + count = 0 while stack: + count += 1 + if count > 5000: + count = 0 + print(f"{len(stack)} {sum(board.goal.values())}") + if len(stack) == -1: stack.pop() stack.action_stack[-1].undo(board) @@ -68,10 +78,11 @@ def solve(board: Board) -> Iterator[List[board_actions.Action]]: if isinstance(action, MoveAction): drop = False - for prev_action in stack.action_stack[-2:-21:-1]: + for prev_action in stack.action_stack[-2::-1]: if isinstance(prev_action, MoveAction): if prev_action.cards == action.cards: drop = True + break if drop: continue @@ -79,6 +90,14 @@ def solve(board: Board) -> Iterator[List[board_actions.Action]]: if board.solved(): yield stack.action_stack + stack.action_stack[-1].undo(board) + while isinstance( + stack.action_stack[-1], (GoalAction, + HuaKillAction, + DragonKillAction)): + stack.pop() + stack.action_stack[-1].undo(board) + continue if board.state_identifier in state_set: action.undo(board) diff --git a/test/helper.py b/test/helper.py index 70f54f7..bb1173e 100644 --- a/test/helper.py +++ b/test/helper.py @@ -8,7 +8,7 @@ def main() -> None: A = solver.solve(my_board) for _, B in zip(range(1), A): print(*B, sep='\n') - print(len(B)) + print(f"Solution: {len(B)}") if __name__ == "__main__":