В предыдущей статье мы составили план работ, в соответствии с которым, первой задачей является разработка Модели. Модель описывает основную логику приложения, не связанную со спецификой используемой платформы.
3. Модель
Наша игра заключается в перемещении по ограниченному прямоугольному полю плашек, состоящих из единичных квадратиков. При перемещении плашки, должны быть передвинуты все составляющие ее квадратики. При этом, они не должны выходить за пределы игрового поля и накладываться друг на друга.
Как мы видим, модель достаточно простая. Создаем Android Project и, пока не обращая внимания на манифесты активности и прочую Android-специфику, создаем в нем класс Model (вообще говоря, именование объектов в проектах большого объема, обычно вызывает некоторые сложности, но, в любом случае, следует стремиться, чтобы большая часть времени уходила не на выдумывание имен, а на разработку логики приложения). Внутри созданного класса, записываем следующий код:
package com.whiterabbit.tags;
import java.util.HashMap;
import java.util.Map;
public class Model {
private int sizeX = 4;
private int sizeY = 5;
private Map<Long, Tag> tags = new HashMap<Long, Tag>();
public Model() {
Tag t = new Tag(1);
t.addItem(1, 1);
t.addItem(1, 2);
tags.put(t.getId(), t);
t = new Tag(2);
t.addItem(2, 1);
t.addItem(2, 2);
t.addItem(3, 1);
t.addItem(3, 2);
tags.put(t.getId(), t);
t = new Tag(3);
t.addItem(4, 1);
t.addItem(4, 2);
tags.put(t.getId(), t);
t = new Tag(4);
t.addItem(1, 3);
t.addItem(1, 4);
tags.put(t.getId(), t);
t = new Tag(5);
t.addItem(2, 3);
t.addItem(3, 3);
tags.put(t.getId(), t);
t = new Tag(6);
t.addItem(4, 3);
t.addItem(4, 4);
tags.put(t.getId(), t);
t = new Tag(7);
t.addItem(1, 5);
tags.put(t.getId(), t);
t = new Tag(8);
t.addItem(2, 4);
tags.put(t.getId(), t);
t = new Tag(9);
t.addItem(3, 4);
tags.put(t.getId(), t);
t = new Tag(10);
t.addItem(4, 5);
tags.put(t.getId(), t);
}
public Tag getTag(int x, int y) {
for (Tag t: tags.values()) {
for (Item i: t.getItems()) {
if ((i.getX() == x)&&(i.getY() == y)) {
return t;
}
}
}
return null;
}
public boolean moveTag(Tag t, int dx, int dy) {
if (t == null) return false;
if (dx + dy == 0) return false;
if (check(t, dx, dy)) {
for (Item i: t.getItems()) {
i.move(dx, dy);
}
return true;
}
return false;
}
public boolean check(Tag t, int dx, int dy) {
if (t == null) return false;
if ((dx == 0)&&(dy == 0)) return false;
if ((dx != 0)&&(dy != 0)) return false;
for (Item i: t.getItems()) {
int newX = i.getX() + dx;
int newY = i.getY() + dy;
if (newX < 1) return false;
if (newX > sizeX) return false;
if (newY < 1) return false;
if (newY > sizeY) return false;
Tag tag = getTag(newX, newY);
if (tag != null) {
if (tag != t) return false;
}
}
return true;
}
}
Создаем классы, на которые этот код ссылается (Tag - плашка и Item - единичный квадратик). Их наполнение (по крайней мере на текущий момент) достаточно тривиально:
package com.whiterabbit.tags;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
public class Tag {
private long id;
private Set<Item> items = new HashSet<Item>();
public Tag(long id) {
this.id = id;
}
public long getId() {
return id;
}
public void addItem(int x, int y) {
items.add(new Item(x, y));
}
public Collection<Item> getItems() {
return items;
}
}
package com.whiterabbit.tags;
public class Item {
private int x;
private int y;
public Item(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void move(int dx, int dy) {
x += dx;
y += dy;
}
}
Рассмотрим логику, описываемую моделью. Переменные sizeX и sizeY определяют размеры игрового поля. В ассоциативном массиве tags хранятся плашки. Поскольку мы разрабатываем прототип, начальную расстановку плашек (соответствующую головоломке "Рыжий осел") мы определяем непосредственно в конструкторе Model. Каждая плашка имеет уникальный идентификатор и состоит из элементов (квадратиков) с заданными координатами (начиная с 1).
Основным методом модели является moveTag. В него передается ссылка на плашку и приращения координат по вертикали и горизонтали (одна из них должна быть нулевая). Перед выполнением перемещения, производится ряд проверок, после чего, если перемещение возможно, изменяются координаты всех входящих в Tag элементов и возвращается true. Вспомогательный метод getTag возвращает Tag по совпадению заданных координат с координатами какого либо из его элементов.
Пока-что, единственное, что мы можем сказать о нашей модели, это то, что она компилируется :) Как-то запустить или отладить ее мы не можем. В следующей статье мы исправим этот недостаток, создав Представление, задачей которого будет отображение текущего состояния нашей модели Пользователю.
Комментариев нет:
Отправить комментарий