game_state.dart 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. import 'dart:math';
  2. import 'package:flutter_2048/model/block_info.dart';
  3. import 'package:flutter_2048/model/game_status.dart';
  4. class GameState {
  5. GameState({required this.data, required this.status, required this.mode});
  6. int mode;
  7. GameStatus status;
  8. List<List<BlockInfo>> data;
  9. /// 初始化
  10. static GameState initial(int mode) {
  11. var random = Random(DateTime.now().millisecondsSinceEpoch);
  12. var gamesize = mode * mode;
  13. var block1 = random.nextInt(gamesize);
  14. var block2 = random.nextInt(gamesize);
  15. while (block1 == block2) {
  16. block2 = random.nextInt(gamesize);
  17. }
  18. var newdata = <List<BlockInfo>>[];
  19. for (var i = 0; i < mode; i++) {
  20. var row = <BlockInfo>[];
  21. for (var j = 0; j < mode; j++) {
  22. var current = i * mode + j;
  23. row.add(BlockInfo(
  24. before: current,
  25. value: current == block1 || current == block2 ? 2 : 0,
  26. current: current));
  27. }
  28. newdata.add(row);
  29. }
  30. return GameState(
  31. mode: mode,
  32. status: GameStatus(end: false, scores: 0, total: 0, adds: 0, moves: 0),
  33. data: newdata,
  34. );
  35. }
  36. BlockInfo getBlock(int i, int j) {
  37. return this.data[i][j];
  38. }
  39. void update() {
  40. // 获取空格数, 将上一次的所有格子设成旧的
  41. int count = 0;
  42. for (var i = 0; i < mode; i++) {
  43. for (var j = 0; j < mode; j++) {
  44. var block = getBlock(i, j);
  45. block.myis = false;
  46. if (block.value == 0) {
  47. count++;
  48. }
  49. }
  50. }
  51. // 有空格
  52. if (count > 0) {
  53. // 生成新的数字
  54. var random = Random(DateTime.now().millisecondsSinceEpoch);
  55. var newpos = getBlankPosition(random.nextInt(count));
  56. var newblock = getBlock(newpos ~/ mode, newpos % mode);
  57. newblock.value = (random.nextInt(2) + 1) * 2;
  58. newblock.before = newblock.current = newpos;
  59. newblock.myis = true;
  60. newblock.needCombine = newblock.needMove = false;
  61. }
  62. // 检测
  63. status.end = false;
  64. if (count <= 1) {
  65. status.end = isEnd();
  66. }
  67. }
  68. bool isEnd() {
  69. int i, j;
  70. for (i = 0; i < mode; i++) {
  71. for (j = 0; j < mode - 1; j++) {
  72. if (data[i][j].value == data[i][j + 1].value) {
  73. return false;
  74. }
  75. }
  76. }
  77. for (j = 0; j < mode; j++) {
  78. for (i = 0; i < mode - 1; i++) {
  79. if (data[i][j].value == data[i + 1][j].value) {
  80. return false;
  81. }
  82. }
  83. }
  84. return true;
  85. }
  86. int getBlankPosition(int blank) {
  87. var index = 0;
  88. for (int i = 0; i < mode; i++) {
  89. for (int j = 0; j < mode; j++) {
  90. if (getBlock(i, j).value == 0) {
  91. if (index == blank) {
  92. return i * mode + j;
  93. } else {
  94. index++;
  95. }
  96. }
  97. }
  98. }
  99. return -1;
  100. }
  101. void swapBlock(int block1, int block2) {
  102. data[block1 ~/ mode][block1 % mode].current = block2;
  103. data[block1 ~/ mode][block1 % mode].before = block1;
  104. data[block2 ~/ mode][block2 % mode].current = block1;
  105. data[block2 ~/ mode][block2 % mode].before = block2;
  106. var temp = data[block1 ~/ mode][block1 % mode];
  107. data[block1 ~/ mode][block1 % mode] = data[block2 ~/ mode][block2 % mode];
  108. data[block2 ~/ mode][block2 % mode] = temp;
  109. }
  110. GameState clone() {
  111. var newdata = <List<BlockInfo>>[];
  112. for (var i = 0; i < mode; i++) {
  113. var row = <BlockInfo>[];
  114. for (var j = 0; j < mode; j++) {
  115. row.add(BlockInfo(
  116. current: data[i][j].current,
  117. value: data[i][j].value,
  118. myis: false,
  119. before: data[i][j].before,
  120. ));
  121. }
  122. newdata.add(row);
  123. }
  124. return GameState(
  125. data: newdata,
  126. mode: this.mode,
  127. status: GameStatus(
  128. adds: this.status.adds,
  129. end: this.status.end,
  130. moves: this.status.moves,
  131. scores: this.status.scores,
  132. total: this.status.total,
  133. ),
  134. );
  135. }
  136. }