map.ts 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. import { Vec2 } from "cc";
  2. export default class map {
  3. //
  4. private _grid: (number | null)[][];
  5. private _rows: number = 10;
  6. private _cols: number = 10;
  7. private _cw: number = 0;
  8. private _ch: number = 0;
  9. private _width: number = 0;
  10. private _height: number = 0;
  11. private _wx: number = 0;
  12. private _wy: number = 0;
  13. public get rows(): number { return this._rows; }
  14. public get cols(): number { return this._cols; }
  15. public get widht(): number { return this._width; }
  16. public get height(): number { return this._height; }
  17. public get max_count(): number { return this._rows * this.cols };
  18. public get grid(): (number | null)[][] { return this._grid };
  19. public init(rows?: number, cols?: number): void {
  20. if (rows) this._rows = rows;
  21. if (cols) this._cols = cols;
  22. this._grid = Array.from({ length: this._rows }, () => Array.from({ length: this._cols }, () => null));
  23. for (let i = 0; i < this._rows; i++) {
  24. for (let j = 0; j < this._cols; j++) {
  25. this._grid[i][j] = null;
  26. }
  27. }
  28. }
  29. /**空位数量*/
  30. public countNulls(): number {
  31. return this._grid.reduce((acc, row) => {
  32. return acc + row.reduce((rowAcc, cell) => rowAcc + (cell === null ? 1 : 0), 0);
  33. }, 0);
  34. }
  35. public dispose(): void {
  36. this.init();
  37. }
  38. /**设置格子宽高和起始世界坐标*/
  39. public setWH(w: number, h: number, wx: number, wy: number): void {
  40. this._cw = w;
  41. this._ch = h;
  42. this._wx = wx;
  43. this._wy = wy;
  44. this._width = w * this._rows;
  45. this._height = h * this._cols;
  46. }
  47. /**格子坐标转世界坐标*/
  48. public gridToPosV2(rows: number, cols: number): Vec2 {
  49. return new Vec2((rows + 0.5) * this._cw + this._wx, -(cols + 0.5) * this._ch + this._wy);
  50. }
  51. //占格
  52. public set_id(x: number, y: number, id: number) {
  53. this._grid[x][y] = id;
  54. }
  55. /**清空格子*/
  56. public set_empty(x: number, y: number) {
  57. this._grid[x][y] = null;
  58. }
  59. public lock(x: number, y: number) {
  60. this._grid[x][y] = -1;
  61. }
  62. public unlock(x: number, y: number) {
  63. this._grid[x][y] = null;
  64. }
  65. /**是否在格子里*/
  66. private isInBounds(x: number, y: number, bounds: number = 0): boolean {
  67. return x >= bounds && x < this._rows - bounds && y >= bounds && y < this._cols - bounds;
  68. }
  69. /**检测某个格子是否为空 bounds边框宽度一般为0*/
  70. public check_empty(x: number, y: number, bounds: number = 0): boolean {
  71. if (!this.isInBounds(x, y, bounds)) return false;
  72. return this._grid[x][y] == null;
  73. }
  74. public get_id(x: number, y: number, bounds: number = 0): number | null {
  75. if (!this.isInBounds(x, y, bounds)) return null;
  76. return this._grid[x][y];
  77. }
  78. /**检测某个格子是否为锁*/
  79. public check_lock(x: number, y: number, bounds: number = 0): boolean {
  80. if (!this.isInBounds(x, y, bounds)) return false;
  81. return this._grid[x][y] != null && this._grid[x][y] < 0;
  82. }
  83. /**找出有邻居的组合*/
  84. public get_neighbor_list(): number[][] {
  85. let list = [];
  86. for (let i = 0; i < this._rows; i++) {
  87. for (let j = 0; j < this._cols; j++) {
  88. let t = this._grid[i][j];
  89. if (t && t >= 0) {
  90. let neighbors: number[] = this.getNeighbors(i, j);
  91. if (neighbors.length > 0) {
  92. neighbors.push(t);//加入自己
  93. list.push(neighbors);//加到列表
  94. }
  95. }
  96. }
  97. }
  98. return list;
  99. }
  100. //4方法
  101. private readonly directions4 = [
  102. { dx: -1, dy: 0 }, // 上
  103. { dx: 1, dy: 0 }, // 下
  104. { dx: 0, dy: -1 }, // 左
  105. { dx: 0, dy: 1 } // 右
  106. ];
  107. //8方向
  108. private readonly directions8 = [
  109. { dx: -1, dy: 0 }, // 上
  110. { dx: 1, dy: 0 }, // 下
  111. { dx: 0, dy: -1 }, // 左
  112. { dx: 0, dy: 1 }, // 右
  113. { dx: -1, dy: -1 }, // 左上
  114. { dx: -1, dy: 1 }, // 右上
  115. { dx: 1, dy: -1 }, // 左下
  116. { dx: 1, dy: 1 } // 右下
  117. ];
  118. /**邻居是否为空*/
  119. public hasEmptyNeighbor(x: number, y: number): boolean {
  120. //检查上下左右的边界
  121. for (const { dx, dy } of this.directions4) {
  122. const newX = x + dx;
  123. const newY = y + dy;
  124. if (this.check_empty(newX, newY)) return true;
  125. }
  126. return false; //没有空的邻居
  127. }
  128. /**获取所有在存的邻居*/
  129. public getNeighbors(x: number, y: number): number[] {
  130. let list: number[] = []
  131. for (const { dx, dy } of this.directions4) {
  132. const newX = x + dx;
  133. const newY = y + dy;
  134. if (this.isInBounds(newX, newY)) {
  135. let id = this._grid[newX][newY];
  136. if (id && id >= 0) list.push(id);
  137. }
  138. }
  139. return list;
  140. }
  141. }