LINUX.ORG.RU

[Java] помогите сделать конструктор

 


0

1

Есть класс «направление», откуда нужно получить координату (x, y) в нужном направлении, их восемь:

class Direction {
	
	static final Direction NORTH = new Direction(0, -1),
							SOUTH = new Direction(0, +1),
							WEST = new Direction(+1, 0),
							EAST = new Direction(-1, 0),
							SOUTH_EAST = new Direction(-1, +1),
							SOUTH_WEST = new Direction(+1, +1),
							NORTH_EAST = new Direction(-1, -1),
							NORTH_WEST = new Direction(+1, -1);

	private int x, y;


	Direction(int x, int y) {
     
        }
}

вопрос, как правильно сделать этот конструктор, чтобы программа могла циклом пройтись по всем направлениям?


У тебя в объекте только две примитивные переменные. Что такого волшебного с ними должен делать цикл в конструкторе?

anonymous
()

Сонси, ты опять говоришь загадками.

Я так понял ты хочешь сделать такой вот хитрый синглтон, тогда прячь конструктор в private, пиши в нём this.x=x; this.y=y; и делай метод getInstance(int x, int y); и в него пихай обычный перебор, я ничего другого придумать не могу.

RedPossum ★★★★★
()
Ответ на: комментарий от RedPossum
public static Direction getInstance(int x, int y){
   if(x==1 && y==y) return SOUTH_WEST;
   else if(...
}

Хотя если честно, извращение какое-то.

RedPossum ★★★★★
()

А какие, собственно, сложности и в чем проблема?

Можно так, например, сделать:

class Direction {
   static final Direction NORTH = new Direction(0, -1),
                     SOUTH = new Direction(0, +1),
                     WEST = new Direction(+1, 0),
                     EAST = new Direction(-1, 0),
                     SOUTH_EAST = new Direction(-1, +1),
                     SOUTH_WEST = new Direction(+1, +1),
                     NORTH_EAST = new Direction(-1, -1),
                     NORTH_WEST = new Direction(+1, -1);

   final int x, y;


   Direction(int x, int y) {
       this.x = x;
       this.y = y;
   }
}

Циклом пройтись по всем направлениям? Самый простой способ - добавить туда поле:

static final Direction[] AllDirections = { NORTH, SOUTH, WEST, EAST, SOUTH_EAST, SOUTH_WEST, NORTH_EAST, NORTH_WEST };
А если нужно во что бы то ни стало запретить изменение массива, можно метод:
static getAllDirections() {
    return new Direction[] { NORTH, SOUTH, WEST, EAST, SOUTH_EAST,
        SOUTH_WEST, NORTH_EAST, NORTH_WEST };
}
Можно также реализовать Iterable, но поскольку у вас массив «всех направлений» на самом деле никогда не меняется, семантика Iterable здесь вряд ли подойдет.

Да, а зачем вам, собственно, отдельный класс для направлений?

proud_anon ★★★★★
()
Ответ на: комментарий от proud_anon

static getAllDirections() {

Ну, в смысле:

static Direction[] getAllDirections() { ... }

proud_anon ★★★★★
()
Ответ на: комментарий от anonymous

Что такого волшебного с ними должен делать цикл в конструкторе?

Цикл не в кнострукторе, вне класса.

Т.е. Есть класс «Доска», где методы ставят камни на доску, но это не так важно. Дальше, есть метод, который смотрит «всех соседей» у определённого камня. Например (доска 8х8), камень стоит на (3, 4), эти две цифры (читай x и y) мы опускаем в метод (в классе Доска), который смотрит соседние ячейки и если условие совпадает, то он идёт дальше в этом направлении. - Если он скажем нашёл в левой-верхней соседней ячейке, то он дальше идет в NORTH_EAST (читай отнимает от x и от y по одному), но это уже дрогой вопрос, и этот метод у меня есть. Мне нужно, чтобы я мог циклом (получается 8 итераций) из этого класса пройти по всем направлениям (соседним ячейкам).

Но как сделать, чтобы я в цикле мог просто указать, скажем:

for (int i = 0; i < Direction.ARRAY.length; i++) {
     Direction direction = Direction.ARRAY[i];
} 

и чтобы при этом класс Направление (читай Direction.ARRAY) мне возвращал соседнюю координату? т.е., если мы начинаем например с 4, 4, то на первой итерации он мне вернул NORTH (0, -1) = 4, 3

Sonsee
() автор топика
Ответ на: комментарий от proud_anon

Да, а зачем вам, собственно, отдельный класс для направлений?

Да убил бы этого препода!

У меня было элементарно два for-цикла:

for (int y = 0; y < 3; y++) {
    for (int x = 0; x < 3; x++) {
        Coordinate new = new Coordinate(clicked.X + x - 1, clicked.Y + y - 1);  
}
}

и оно замечательно мне возвращало всех соседей!, но нет, он это назвал каким-то hack'ом, и типа нужен класс направление, откуда ты всё это получишь.

p.s. спасибо вам, похоже на то, а я думал, что нужно с enum что-то делать..

Sonsee
() автор топика
Ответ на: комментарий от Sonsee

>p.s. спасибо вам, похоже на то, а я думал, что нужно с enum что-то делать.

С enum тоже можно. Даже, наверное, будет лучше. Как-то так:

enum Direction {
    NORTH (0, -1),
    SOUTH (0, +1),
    WEST (+1, 0),
    EAST (-1, 0),
    SOUTH_EAST (-1, +1),
    SOUTH_WEST (+1, +1),
    NORTH_EAST (-1, -1),
    NORTH_WEST (+1, -1);

    final int x, y;

    Direction(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

А пройтись по всем направлениям можно как-то так:

for(Direction d : Direction.values()) {
    System.out.println(String.format("x = %d; y = %d", d.x, d.y));
}

proud_anon ★★★★★
()
Ответ на: комментарий от Sonsee

> Есть класс «Доска»

Логичнее всего у неё и сделать List<Cell> getNearestCells() или forEachNearest(SomeInvokable).

anonymous
()
Ответ на: комментарий от Sonsee

>и чтобы при этом класс Направление (читай Direction.ARRAY) мне возвращал соседнюю координату? т.е., если мы начинаем например с 4, 4, то на первой итерации он мне вернул NORTH (0, -1) = 4, 3

Если у вас каждая клетка как отдельный объект, то, может быть, либо сделать у клетки метод, возвращающий коллекцию соседей, либо какой-нибудь Iterable, который по next() будет возвращать очередного соседа?

proud_anon ★★★★★
()
Ответ на: комментарий от proud_anon

> либо сделать у клетки метод, возвращающий коллекцию соседей

Клетка, сама по себе, в общем случае этого знать не может.

anonymous
()
Ответ на: комментарий от anonymous

>Клетка, сама по себе, в общем случае этого знать не может.

Да, правильно. Лучше у доски. Хотя клетка ведь может знать, в какой доске находится. Почему-то Cell.getNeighbours() выглядит красивше, чем Board.getNeighbours(Cell), хотя это ничем не обосновано и может противоречить всей идеологии.

Что касается forEachNearest(SomeInvokable), то это было бы хорошо, не будь язык Жабой.

proud_anon ★★★★★
()
Ответ на: комментарий от proud_anon

> Почему-то Cell.getNeighbours() выглядит красивше

Кто продилегирует работу доске не важно на самом деле. Главное реализация должна быть на своем месте.

anonymous
()
Ответ на: комментарий от Sonsee

Это какая-то теоретическая работа, или что-то прикладное? Если второе, то зачем опять столько ООП?
Если не бывает направлений, кроме тех, что в списке, можно использовать Enum, или вообще int:

class DirectionUtil
{
    public static final int NORTH = 1;
    public static final int EAST = 2;
    ...
    public static final int NORTHEAST = NORTH | EAST;
    
    public static int getDirection (int x, int y)
    {
        return (x == 0 ? 0 : (x < 0 : WEST : EAST)) | (y == 0 ? 0 : (y < 0 ? SOUTH : NORTH));
    }

    public static int advanceX (int x, int direction)
    {
        return x + ((direction & EAST) != 0 ? -1 : ((direction & WEST)  != 0) ? 1 : 0);
    }
}
Может, я не очень понял, что требуется.

note173 ★★★★★
()
Ответ на: комментарий от note173

Это какая-то теоретическая работа, или что-то прикладное? Если второе, то зачем опять столько ООП?

это игра Othello (реверси)
затем, что перпод так сказал
у меня уже 7 классов :)

я могу всю игру выложить, но не думаю что будет кому-то интересно..

Sonsee
() автор топика
Ответ на: комментарий от note173

Если не бывает направлений

попрубую как можно понятней..

Представьте себе 2-dimensional (как это по русски?) int-массив (доска 8x8). Матрицу. Представим, что GUI у меня уже есть, и я кликаю на клетку (4, 4), и получаю соот-ю координату, которую посылаю в метод, чтобы проверить по всем линиям (диагональ, вертикаль и т.д.) наличие камней противника (т.к. по правилам игры они становятся моими, если по линии за ними лежит мой камень). Т.е. грубо говоря сначала мне нужно проверить восемь соседних ячеек на наличие камней противника, и если я нашёл (скажем в направлении NORTH, где «х» остаётся тем же, а от «y» отняли 1, - т.б. на клетку выше), то я продолжаю идти в этом направлении, чтобы «перевернуть» камни противника.

Так понятней? :)

Sonsee
() автор топика
Ответ на: комментарий от proud_anon

Если у вас каждая клетка как отдельный объект, то, может быть, либо сделать у клетки метод, возвращающий коллекцию соседей, либо какой-нибудь Iterable, который по next() будет возвращать очередного соседа?

да ну проще всего было с двумя for-циклами, как я показывал выше, но нужно сделать так, как я описал (преподу так хочется). Т.е. с таким вот классом и for-циклом, который будет возвращать новую коориднату. Что-то типа вот этого в классе Доска:

for (int i = 0; i < Direction.ARRAY.length; i++) {
     Direction direction = Direction.ARRAY[i];
} 
Sonsee
() автор топика
Ответ на: комментарий от Sonsee

Зачем тогда придумывать лишние сущности (направления)?
в той функции - проверить, что щелкнули на диагонали (abs(x0 - x1) == abs(y0 - y1)) или на прямой, на основании этого вычислить шаг в виде смещения по x и y, в цикле: сделать приращение, посмотреть камень, проверить, что он может лежать на этой позиции, дойти до точки, в которую щелкнули. Если все нормально - пройтись еще раз, но применяя изменения (ставя свои камни).
Как привыкшего считать затраты на чтение поля и вызов интерфейса, меня пугает наличие ненужных классов и методов...)

note173 ★★★★★
()
Ответ на: комментарий от note173

Зачем тогда придумывать лишние сущности (направления)? ... меня пугает наличие ненужных классов и методов...

говорю же, препод так хочет.

в общем, чтоб понятней было то, что я писал выше, вот это в коде (три метода в классе Доска (класс Направление уже понятно какой, думаю)):

public CoordinateRow getInclosed(Coordinate click, int player1, int player2) {
		CoordinateRow inclosed = new CoordinateRow();	       
		
		for (int i = 0; i < Direction.AllDirections.length; i++) {

			Direction d = Direction.AllDirections[i]; // берём из класса направление
			Coordinate s = new Coordinate(click.getX() + d.x, click.getY() + d.y); // создаём координату соседней ячейки по отношению к click
			
			if (!(nextOnBoard(s.getX(), s.getY(), player2) && foundInclosed(s, d, player1, player2))) { // если оно выходит за пределы доски, там нету камня противника, или нету массива камней противника, continue;
				continue;
				
			} else { // если таки есть, "собираем" массив камней, которые будем переворачивать.
			
					int sX = s.getX(), sY = s.getY();
			
					do {
						Coordinate in = new Coordinate(sX, sY);
						inclosed.addOneAfterRow(in);
						
						sX += d.x;
						sY += d.y;
						
					} while (nextOnBoard(sX, sY, player2));
			} 
		}
		
		return inclosed;
	}
	boolean foundInclosed(Coordinate side, Direction d, int p1, int p2) {
		int sX = side.getX(), sY = side.getY();
		
		while (nextOnBoard(sX, sY, p2)) {
			sX += d.x;
			sY += d.y;
			
			if (nextOnBoard(sX, sY, p1)) {
				return true;
			}
		}
		
		return false;
	}
	boolean nextOnBoard(int x, int y, int player) {
		if (x > 0 && y > 0 && x < 8 && y < 8 && board[y][x] == player) {
			return true;
		}
		
		return false;
	}
Sonsee
() автор топика
enum Direction {
   NORTH(0, -1),
   SOUTH(0, +1),
   WEST(+1, 0),
   EAST(-1, 0),
   SOUTH_EAST(-1, +1),
   SOUTH_WEST(+1, +1),
   NORTH_EAST(-1, -1),
   NORTH_WEST(+1, -1);

   private int x, y;


   Direction(int x, int y) {
     this.x=x;this.y=y;
   }
}
anonymous
()
Ответ на: комментарий от Sonsee

> 2-dimensional (как это по русски?)

Двумерный же.

Norgat ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.