var Grid = require('./grid.js');
var Tile = require('./tile.js');
function GameManager(size) {
this.size = size;
this.startTiles = 2;
}
GameManager.prototype = {
setup: function() {
this.grid = new Grid(this.size);
this.score = 0;
this.over = false;
this.won = false;
this.addStartTiles();
return this.grid.cells;
},
// 初始化数据
addStartTiles: function() {
for (var x = 0; x < this.startTiles; x++) {
this.addRandomTiles();
}
},
// 在一个随机单元格中随机填充2或4
addRandomTiles: function() {
if (this.grid.cellsAvailable()) {
var value = Math.random() < 0.9 ? 2 : 4;
var cell = this.grid.randomAvailableCell();
var tile = new Tile(cell, value);
this.grid.insertTile(tile); // 插入一个单元格
}
},
actuate: function() {
return {
grids: this.grid.cells,
over: this.over,
won: this.won,
score: this.score
}
},
// 偏移向量
getVector: function(direction) {
var map = {
0: { // 上
x: -1,
y: 0
},
1: { // 右
x: 0,
y: 1
},
2: { // 下
x: 1,
y: 0
},
3: { // 左
x: 0,
y: -1
}
};
return map[direction];
},
buildTraversals: function(vector) {
var traversals = {
x: [],
y: []
};
for (var pos = 0; pos < this.size; pos++) {
traversals.x.push(pos);
traversals.y.push(pos);
}
// 为什么要加这个,看findFarthestTail
if (vector.x === 1) {
// 向右时
traversals.x = traversals.x.reverse();
}
if (vector.y === 1) {
// 向下
traversals.y = traversals.y.reverse();
}
return traversals;
},
// 把当前单元格挪至下一个可放置的区域
moveTile: function(tile, cell) {
this.grid.cells[tile.x][tile.y] = null;
this.grid.cells[cell.x][cell.y] = tile;
tile.updatePosition(cell);
},
// 特定方向移动单元格
move: function(direction) {
// 0: up, 1: right, 2: down, 3: left
var self = this;
var vector = this.getVector(direction);
var traversals = this.buildTraversals(vector);
var cell;
var tile;
var moved = false;
self.prepareTiles();
traversals.x.forEach(function(x) {
traversals.y.forEach(function(y) {
// console.log('x:', x, 'y:', y);
cell = {
x: x,
y: y
};
tile = self.grid.cellContent(cell);
if (tile) { // 单元格有内容
var positions = self.findFarthestTail(cell, vector);
var next = self.grid.cellContent(positions.next);
if (next && next.value === tile.value && !next.mergedFrom) {
// 当前格子和其移动方向格子内容相同,需要合并
var merged = new Tile(positions.next, tile.value * 2); // 合并后的格子信息
merged.mergedFrom = [tile, next];
self.grid.insertTile(merged); // 把合并的盒子插入到当前格子数据中
self.grid.removeTile(tile); // 删除当前格子内容
tile.updatePosition(positions.next);
self.score += merged.value;
if (merged.value === 2048) self.won = true;
} else {
self.moveTile(tile, positions.farthest);
}
// 是否从当前位置移到当前位置
if (!self.positionsEqual(cell, tile)) {
moved = true;
}
}
});
});
if (moved) {
this.addRandomTiles();
if (!this.movesAvailable()) {
this.over = true;
}
return this.actuate();
}
// return this.grid.cells
},
prepareTiles: function() {
var tile;
for (var x = 0; x < this.size; x++) {
for (var y = 0; y < this.size; y++) {
tile = this.grid.cells[x][y];
if (tile) {
tile.mergedFrom = null;
tile.savePosition();
}
}
}
},
positionsEqual: function(first, second) {
return first.x === second.x && first.y === second.y;
},
movesAvailable: function() {
return this.grid.cellsAvailable() || this.tileMatchesAvailable();
},
tileMatchesAvailable: function() {
var self = this;
var tile;
for (var x = 0; x < this.size; x++) {
for (var y = 0; y < this.size; y++) {
tile = this.grid.cellContent({ x: x, y: y });
if (tile) {
for (var direction = 0; direction < 4; direction++) {
var vector = self.getVector(direction);
var cell = { x: x + vector.x, y: y + vector.y };
var other = self.grid.cellContent(cell);
if (other && other.value === tile.value) {
return true;
}
}
}
}
}
return false;
},
// 找到当前偏移方向存在最远的空单元格
// 如:向右偏移,那么返回当前行最靠右的空单元格及其右侧距离其最远的一个格子,向下一样
findFarthestTail: function(cell, vector) {
var previous;
// 当前单元格在范围内且存在可用单元格
do {
previous = cell;
cell = {
x: previous.x + vector.x,
y: previous.y + vector.y
};
}
while (this.grid.withinBounds(cell) && this.grid.emptyCell(cell));
return {
farthest: previous,
next: cell
}
},
// 重新开始
restart: function() {
return this.setup();
}
}
module.exports = GameManager;