public class Model {
private static final int FIELD_WIDTH = 4; // размер поля
private Tile[][] gameTiles; // игровое поле
int score; // счет
int maxTile; // значение макимальной плитки
private Stack<Integer> previousScores;
private Stack<Tile[][]> previousStates;
private boolean isSaveNeeded = true;
public Model() {
resetGameTiles();
this.score = 0;
this.maxTile = 2;
}
// вовзращает лист пустых клеток
private List<Tile> getEmptyTiles() {
List<Tile> result = new ArrayList<>();
for (int i = 0; i < FIELD_WIDTH; i++) {
for (int j = 0; j < FIELD_WIDTH; j++) {
if (gameTiles[i][j].value == 0) result.add(gameTiles[i][j]);
}
}
return result;
}
// добавляет рандомно клетку 2 или 4 (соотношение 1 к 9)
void addTile() {
List<Tile> list = getEmptyTiles();
if (list != null && list.size() != 0) {
list.get((int) (list.size() * Math.random())).setValue(Math.random() < 0.9 ? 2 : 4);
}
}
// сброс всех клеток
void resetGameTiles() {
this.gameTiles = new Tile[FIELD_WIDTH][FIELD_WIDTH];
for (int i = 0; i < FIELD_WIDTH; i++) {
for (int j = 0; j < FIELD_WIDTH; j++) {
this.gameTiles[i][j] = new Tile();
}
}
addTile();
addTile();
}
// сжатие одного ряда влево
private boolean compressTiles(Tile[] tiles) {
boolean isChanged = false;
Tile temp;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (tiles[j].getValue() == 0 && tiles[j + 1].getValue() != 0) {
temp = tiles[j];
tiles[j] = tiles[j + 1];
tiles[j + 1] = temp;
isChanged = true;
}
}
}
return isChanged;
}
// сложение клеток
private boolean mergeTiles(Tile[] tiles) {
boolean isChanged = false;
for (int j = 0; j < 3; j++) {
if (tiles[j].getValue() != 0 && tiles[j].getValue() == tiles[j + 1].getValue()) {
tiles[j].setValue(tiles[j].getValue() * 2);
tiles[j + 1].setValue(0);
if (tiles[j].getValue() > maxTile) maxTile = tiles[j].getValue();
score += tiles[j].getValue();
isChanged = true;
}
}
if (isChanged) {
Tile temp;
for (int j = 0; j < 3; j++) {
if (tiles[j].getValue() == 0 && tiles[j + 1].getValue() != 0) {
temp = tiles[j];
tiles[j] = tiles[j + 1];
tiles[j + 1] = temp;
}
}
}
return isChanged;
}
// методы для сдвига в четырех направлениях
public void left() {
boolean isChanged = false;
for (int i = 0; i < FIELD_WIDTH; i++) {
if (compressTiles(gameTiles[i]) | mergeTiles(gameTiles[i])) {
isChanged = true;
}
}
if (isChanged) {
addTile();
isSaveNeeded = true;
}
}
public void up() {
rotate();
left();
rotate();
rotate();
rotate();
}
public void right() {
rotate();
rotate();
left();
rotate();
rotate();
}
public void down() {
rotate();
rotate();
rotate();
left();
rotate();
}
// поворот матрицы на 90 градусов против часовой стрелки
private void rotate() {
int len = FIELD_WIDTH;
for (int k = 0; k < len / 2; k++) // border -> center
{
for (int j = k; j < len - 1 - k; j++) // left -> right
{
Tile tmp = gameTiles[k][j];
gameTiles[k][j] = gameTiles[j][len - 1 - k];
gameTiles[j][len - 1 - k] = gameTiles[len - 1 - k][len - 1 - j];
gameTiles[len - 1 - k][len - 1 - j] = gameTiles[len - 1 - j][k];
gameTiles[len - 1 - j][k] = tmp;
}
}
}
// геттер для поля
public Tile[][] getGameTiles() {
return gameTiles;
}
// проверка возможности хода
public boolean canMove() {
if (!getEmptyTiles().isEmpty())
return true;
for (int i = 0; i < gameTiles.length; i++) {
for (int j = 1; j < gameTiles.length; j++) {
if (gameTiles[i][j].value == gameTiles[i][j - 1].value)
return true;
}
}
for (int j = 0; j < gameTiles.length; j++) {
for (int i = 1; i < gameTiles.length; i++) {
if (gameTiles[i][j].value == gameTiles[i - 1][j].value)
return true;
}
}
return false;
}
private void saveState(Tile[][] tiles) {
Tile[][] fieldToSave = new Tile[tiles.length][tiles[0].length];
isSaveNeeded = false;
for (int i = 0; i < tiles.length; i++) {
for (int j = 0; j < tiles[0].length; j++) {
fieldToSave[i][j] = new Tile(tiles[i][j].getValue());
}
}
previousStates.push(fieldToSave);
int scoreToSave = score;
previousScores.push(scoreToSave);
}
public void rollback(){
if(!previousScores.isEmpty()&&!previousStates.isEmpty()) {
gameTiles = previousStates.pop();
score=previousScores.pop();
}
}
}
package com.javarush.task.task35.task3513;
import javax.swing.*;
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
Model model = new Model();
Controller controller = new Controller(model);
JFrame game = new JFrame();
game.setTitle("2048");
game.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
game.setSize(450, 500);
game.setResizable(false);
game.add(controller.getView());
game.setLocationRelativeTo(null);
game.setVisible(true);
}
}