block.dart 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. import 'gamer.dart';
  2. import 'dart:math' as math;
  3. const blockShapes = {
  4. BlockType.I: [
  5. [1, 1, 1, 1]
  6. ],
  7. BlockType.L: [
  8. [0, 0, 1],
  9. [1, 1, 1],
  10. ],
  11. BlockType.J: [
  12. [1, 0, 0],
  13. [1, 1, 1],
  14. ],
  15. BlockType.Z: [
  16. [1, 1, 0],
  17. [0, 1, 1],
  18. ],
  19. BlockType.S: [
  20. [0, 1, 1],
  21. [1, 1, 0],
  22. ],
  23. BlockType.O: [
  24. [1, 1],
  25. [1, 1]
  26. ],
  27. BlockType.T: [
  28. [0, 1, 0],
  29. [1, 1, 1]
  30. ]
  31. };
  32. ///方块初始化时的位置
  33. const startXy = {
  34. BlockType.I: [3, 0],
  35. BlockType.L: [4, -1],
  36. BlockType.J: [4, -1],
  37. BlockType.Z: [4, -1],
  38. BlockType.S: [4, -1],
  39. BlockType.O: [4, -1],
  40. BlockType.T: [4, -1],
  41. };
  42. ///方块变换时的中心点
  43. const origin = {
  44. BlockType.I: [
  45. [1, -1],
  46. [-1, 1],
  47. ],
  48. BlockType.L: [
  49. [0, 0]
  50. ],
  51. BlockType.J: [
  52. [0, 0]
  53. ],
  54. BlockType.Z: [
  55. [0, 0]
  56. ],
  57. BlockType.S: [
  58. [0, 0]
  59. ],
  60. BlockType.O: [
  61. [0, 0]
  62. ],
  63. BlockType.T: [
  64. [0, 0],
  65. [0, 1],
  66. [1, -1],
  67. [-1, 0]
  68. ],
  69. };
  70. enum BlockType { I, L, J, Z, S, O, T }
  71. class Block {
  72. final BlockType type;
  73. final List<List<int>> shape;
  74. final List<int> xy;
  75. final int rotateIndex;
  76. Block(this.type, this.shape, this.xy, this.rotateIndex);
  77. Block fall({int step = 1}) {
  78. return Block(type, shape, [xy[0], xy[1] + step], rotateIndex);
  79. }
  80. Block right() {
  81. return Block(type, shape, [xy[0] + 1, xy[1]], rotateIndex);
  82. }
  83. Block left() {
  84. return Block(type, shape, [xy[0] - 1, xy[1]], rotateIndex);
  85. }
  86. Block rotate() {
  87. List<List<int>> result =
  88. List.filled(shape[0].length, const [], growable: false);
  89. for (int row = 0; row < shape.length; row++) {
  90. for (int col = 0; col < shape[row].length; col++) {
  91. if (result[col].isEmpty) {
  92. result[col] = List.filled(shape.length, 0, growable: false);
  93. }
  94. result[col][row] = shape[shape.length - 1 - row][col];
  95. }
  96. }
  97. final nextXy = [
  98. xy[0] + origin[type]![rotateIndex][0],
  99. xy[1] + origin[type]![rotateIndex][1]
  100. ];
  101. final nextRotateIndex =
  102. rotateIndex + 1 >= origin[type]!.length ? 0 : rotateIndex + 1;
  103. return Block(type, result, nextXy, nextRotateIndex);
  104. }
  105. bool isValidInMatrix(List<List<int>> matrix) {
  106. if (xy[1] + shape.length > gamePadMatrixH ||
  107. xy[0] < 0 ||
  108. xy[0] + shape[0].length > gamePadMatrixW) {
  109. return false;
  110. }
  111. for (var i = 0; i < matrix.length; i++) {
  112. final line = matrix[i];
  113. for (var j = 0; j < line.length; j++) {
  114. if (line[j] == 1 && get(j, i) == 1) {
  115. return false;
  116. }
  117. }
  118. }
  119. return true;
  120. }
  121. ///return null if do not show at [x][y]
  122. ///return 1 if show at [x,y]
  123. int? get(int x, int y) {
  124. x -= xy[0];
  125. y -= xy[1];
  126. if (x < 0 || x >= shape[0].length || y < 0 || y >= shape.length) {
  127. return null;
  128. }
  129. return shape[y][x] == 1 ? 1 : null;
  130. }
  131. static Block fromType(BlockType type) {
  132. final shape = blockShapes[type];
  133. return Block(type, shape!, startXy[type]!, 0);
  134. }
  135. static Block getRandom() {
  136. final i = math.Random().nextInt(BlockType.values.length);
  137. return fromType(BlockType.values[i]);
  138. }
  139. }