game_state.dart 3.9 KB

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