BlockUitl.ts 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. import { Vec2 } from "cc";
  2. export class BlockUtil {
  3. static isLineConnectedByIndex(startI: number, startJ: number, endI: number, endJ: number,
  4. canPass: (i: number, j: number) => boolean): boolean {
  5. // 同一行
  6. if (startI === endI) {
  7. const minJ = Math.min(startJ, endJ);
  8. const maxJ = Math.max(startJ, endJ);
  9. for (let j = minJ + 1; j < maxJ; j++) {
  10. if (!canPass(startI, j)) {
  11. return false;
  12. }
  13. }
  14. return true;
  15. }
  16. // 同一列
  17. if (startJ === endJ) {
  18. const minI = Math.min(startI, endI);
  19. const maxI = Math.max(startI, endI);
  20. for (let i = minI + 1; i < maxI; i++) {
  21. if (!canPass(i, startJ)) {
  22. return false;
  23. }
  24. }
  25. return true;
  26. }
  27. return false;
  28. }
  29. static isOneLink(
  30. startI: number,
  31. startJ: number,
  32. endI: number,
  33. endJ: number,
  34. canPass: (i: number, j: number) => boolean
  35. ): boolean {
  36. // 检查C点路径
  37. const cI = startI;
  38. const cJ = endJ;
  39. // 确保C点本身可通行
  40. if (canPass(cI, cJ)) {
  41. // 检查从起点到C点的路径(不包含起点,但包含C点)
  42. const path1 = BlockUtil.checkPath(startI, startJ, cI, cJ, canPass, true, true);
  43. // 检查从C点到终点的路径(包含C点和终点)
  44. const path2 = BlockUtil.checkPath(cI, cJ, endI, endJ, canPass, true, true);
  45. if (path1 && path2) return true;
  46. }
  47. // 检查D点路径
  48. const dI = endI;
  49. const dJ = startJ;
  50. //
  51. // 确保D点本身可通行
  52. if (canPass(dI, dJ)) {
  53. // 检查从起点到D点的垂直路径是否畅通
  54. // 检查从起点到D点的路径(不包含起点,但包含D点)
  55. const path1 = BlockUtil.checkPath(startI, startJ, dI, dJ, canPass, true, true);
  56. // 检查从D点到终点的路径(包含D点和终点)
  57. const path2 = BlockUtil.checkPath(dI, dJ, endI, endJ, canPass, true, true);
  58. if (path1 && path2) return true;
  59. }
  60. return false;
  61. }
  62. static getOneLinkCorner(
  63. startI: number,
  64. startJ: number,
  65. endI: number,
  66. endJ: number,
  67. canPass: (i: number, j: number) => boolean
  68. ): { i: number; j: number } | null {
  69. // 检查C点路径 (水平→垂直)
  70. const cI = startI;
  71. const cJ = endJ;
  72. if (canPass(cI, cJ)) {
  73. const path1 = BlockUtil.checkPath(startI, startJ, cI, cJ, canPass, true, true);
  74. const path2 = BlockUtil.checkPath(cI, cJ, endI, endJ, canPass, true, true);
  75. if (path1 && path2) {
  76. return { i: cI, j: cJ }; // 返回C点坐标
  77. }
  78. }
  79. // 检查D点路径 (垂直→水平)
  80. const dI = endI;
  81. const dJ = startJ;
  82. if (canPass(dI, dJ)) {
  83. const path1 = BlockUtil.checkPath(startI, startJ, dI, dJ, canPass, true, true);
  84. const path2 = BlockUtil.checkPath(dI, dJ, endI, endJ, canPass, true, true);
  85. if (path1 && path2) {
  86. return { i: dI, j: dJ }; // 返回D点坐标
  87. }
  88. }
  89. return null; // 无可达路径时返回null
  90. }
  91. static isTwoLink(
  92. startI: number,
  93. startJ: number,
  94. endI: number,
  95. endJ: number,
  96. rows: number,
  97. cols: number,
  98. canPass: (i: number, j: number) => boolean
  99. ): boolean {
  100. // 向上扫描
  101. for (let i = startI - 1; i >= -1; i--) {
  102. if (i >= 0 && !canPass(i, startJ)) break;
  103. if (this.isOneLink(i, startJ, endI, endJ, canPass)) return true;
  104. }
  105. // 向下扫描
  106. for (let i = startI + 1; i <= rows; i++) {
  107. if (i < rows && !canPass(i, startJ)) break;
  108. if (this.isOneLink(i, startJ, endI, endJ, canPass)) return true;
  109. }
  110. // 向左扫描
  111. for (let j = startJ - 1; j >= -1; j--) {
  112. if (j >= 0 && !canPass(startI, j)) break;
  113. if (this.isOneLink(startI, j, endI, endJ, canPass)) return true;
  114. }
  115. // 向右扫描
  116. for (let j = startJ + 1; j <= cols; j++) {
  117. if (j < cols && !canPass(startI, j)) break;
  118. if (this.isOneLink(startI, j, endI, endJ, canPass)) return true;
  119. }
  120. return false;
  121. }
  122. static checkPath(
  123. startI: number,
  124. startJ: number,
  125. endI: number,
  126. endJ: number,
  127. canPass: (i: number, j: number) => boolean,
  128. includeStart: boolean = true,
  129. includeEnd: boolean = true
  130. ): boolean {
  131. // 确保起点和终点在同一直线上
  132. if (startI !== endI && startJ !== endJ) {
  133. return false;
  134. }
  135. // 水平路径检查
  136. if (startI === endI) {
  137. const minJ = Math.min(startJ, endJ);
  138. const maxJ = Math.max(startJ, endJ);
  139. // 确定循环的起始和结束位置
  140. const jStart = includeStart ? minJ : (minJ + 1);
  141. const jEnd = includeEnd ? maxJ : (maxJ - 1);
  142. for (let j = jStart; j <= jEnd; j++) {
  143. if (!canPass(startI, j)) {
  144. return false;
  145. }
  146. }
  147. }
  148. // 垂直路径检查
  149. else if (startJ === endJ) {
  150. const minI = Math.min(startI, endI);
  151. const maxI = Math.max(startI, endI);
  152. // 确定循环的起始和结束位置
  153. const iStart = includeStart ? minI : (minI + 1);
  154. const iEnd = includeEnd ? maxI : (maxI - 1);
  155. for (let i = iStart; i <= iEnd; i++) {
  156. if (!canPass(i, startJ)) {
  157. return false;
  158. }
  159. }
  160. }
  161. return true;
  162. }
  163. // 在BlockUtil中添加
  164. static getTwoLinkCorners1(
  165. startI: number,
  166. startJ: number,
  167. endI: number,
  168. endJ: number,
  169. rows: number,
  170. cols: number,
  171. canPass: (i: number, j: number) => boolean
  172. ): [Vec2, Vec2] | null {
  173. // 这里需要实现两个拐点的查找逻辑
  174. // 示例伪代码,需要根据实际算法实现
  175. for (let i = 0; i < rows; i++) {
  176. if (canPass(i, startJ) && canPass(i, endJ)) {
  177. return [
  178. new Vec2(i, startJ),
  179. new Vec2(i, endJ)
  180. ];
  181. }
  182. }
  183. return null;
  184. }
  185. static getTwoLinkCorners(
  186. startI: number,
  187. startJ: number,
  188. endI: number,
  189. endJ: number,
  190. rows: number,
  191. cols: number,
  192. canPass: (i: number, j: number) => boolean
  193. ): [{ i: number, j: number }, { i: number, j: number }] | null {
  194. // 向上扫描
  195. for (let i = startI - 1; i >= -1; i--) {
  196. if (i >= 0 && !canPass(i, startJ)) break;
  197. const firstCorner = { i, j: startJ };
  198. const secondCorner = this.getOneLinkCorner(i, startJ, endI, endJ, canPass);
  199. if (secondCorner) {
  200. return [firstCorner, secondCorner];
  201. }
  202. }
  203. // 向下扫描
  204. for (let i = startI + 1; i <= rows; i++) {
  205. if (i < rows && !canPass(i, startJ)) break;
  206. const firstCorner = { i, j: startJ };
  207. const secondCorner = this.getOneLinkCorner(i, startJ, endI, endJ, canPass);
  208. if (secondCorner) {
  209. return [firstCorner, secondCorner];
  210. }
  211. }
  212. // 向左扫描
  213. for (let j = startJ - 1; j >= -1; j--) {
  214. if (j >= 0 && !canPass(startI, j)) break;
  215. const firstCorner = { i: startI, j };
  216. const secondCorner = this.getOneLinkCorner(startI, j, endI, endJ, canPass);
  217. if (secondCorner) {
  218. return [firstCorner, secondCorner];
  219. }
  220. }
  221. // 向右扫描
  222. for (let j = startJ + 1; j <= cols; j++) {
  223. if (j < cols && !canPass(startI, j)) break;
  224. const firstCorner = { i: startI, j };
  225. const secondCorner = this.getOneLinkCorner(startI, j, endI, endJ, canPass);
  226. if (secondCorner) {
  227. return [firstCorner, secondCorner];
  228. }
  229. }
  230. return null;
  231. }
  232. }