gobang.py 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. from collections import defaultdict
  2. class GobangSolver:
  3. def __init__(self, ques: list[list[int]]):
  4. self.board = ques
  5. self.n = len(ques)
  6. def find_four_in_line(self) -> list[list[int]] | None:
  7. for line in self._iterate_lines():
  8. elements = [self.board[r][c] for r, c in line]
  9. freq = self._count_freq(elements)
  10. if self.n - 1 not in freq.values() or freq.get(0) == self.n - 1:
  11. continue
  12. correct_num = next(num for num, cnt in freq.items() if cnt == self.n - 1)
  13. try:
  14. zero_idx = elements.index(0)
  15. except ValueError:
  16. continue
  17. fill_pos = line[zero_idx]
  18. remove_pos = self._find_remove_candidate(correct_num, line)
  19. if remove_pos:
  20. return [[remove_pos[0], remove_pos[1]], [fill_pos[0], fill_pos[1]]]
  21. def _iterate_lines(self):
  22. for row in range(self.n):
  23. yield [(row, c) for c in range(self.n)]
  24. for col in range(self.n):
  25. yield [(r, col) for r in range(self.n)]
  26. for start_row in range(self.n):
  27. yield [(start_row + i, i) for i in range(self.n - start_row)]
  28. for start_col in range(1, self.n):
  29. yield [(i, start_col + i) for i in range(self.n - start_col)]
  30. for start_row in range(self.n):
  31. yield [(start_row - i, i) for i in range(start_row + 1)]
  32. for start_col in range(1, self.n):
  33. yield [(self.n - 1 - i, start_col + i) for i in range(self.n - start_col)]
  34. @staticmethod
  35. def _count_freq(elements):
  36. freq = {}
  37. for num in elements:
  38. freq[num] = freq.get(num, 0) + 1
  39. return freq
  40. def _find_remove_candidate(self, target, exclude):
  41. exclude_set = set(exclude)
  42. for r in range(self.n):
  43. for c in range(self.n):
  44. if (r, c) not in exclude_set and self.board[r][c] == target:
  45. return r, c