вторник, 17 апреля 2012 г.

3. Модель

В предыдущей статье мы составили план работ, в соответствии с которым, первой задачей является разработка Модели. Модель описывает основную логику приложения, не связанную со спецификой используемой платформы.

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 по совпадению заданных координат с координатами какого либо из его элементов.

Пока-что, единственное, что мы можем сказать о нашей модели, это то, что она компилируется :) Как-то запустить или отладить ее мы не можем. В следующей статье мы исправим этот недостаток, создав Представление, задачей которого будет отображение текущего состояния нашей модели Пользователю.

Комментариев нет:

Отправить комментарий