Как получить индекс массива по значению??

TimePlay

Новичок
Регистрация
3 Май 2023
Сообщения
90
значит есть у меня два массива интересных:
массив locations
#1 Location{world=CraftWorld{world_plot_123_plot},x=1,y=2,z=3,pitch=0,yaw=0}
#2 Location{world=CraftWorld{world_plot_123_plot},x=5,y=2,z=10,pitch=0,yaw=0}
массив blocks
#1 ItemStack{GRASS x 1}
#2 ItemStack{STONE x 1}

идея в том, что когда ставишь блоки в игре, то в эти массивы добавляется локация блока и сам блок, и всё бы ничего, только вот когда игрок ломает блок, то из этих массивов должны убраться локация и блок, но как если "Удалить элемент массива" работает только по индексам?

когда ты добавляешь в массив, то тебе нужен только массив и то что добавляешь, а вот чтобы удалить что-то из массива, то тебе надо массив и ИНДЕКС!
ну то-есть мне нужно найти индекс из "Location{world=CraftWorld{world_plot_123_plot},x=5,y=2,z=10,pitch=0,yaw=0}", вот только как я его найду? как мне получить это самое значение 2? ведь благодаря только индексу я смогу удалить саму локацию и блок из массивов.

если вы знаете, то напишите и поделитесь лайфхаком!!!
 

maxim34a

Эксперт
Регистрация
10 Июн 2023
Сообщения
551
значит есть у меня два массива интересных:
массив locations
#1 Location{world=CraftWorld{world_plot_123_plot},x=1,y=2,z=3,pitch=0,yaw=0}
#2 Location{world=CraftWorld{world_plot_123_plot},x=5,y=2,z=10,pitch=0,yaw=0}
массив blocks
#1 ItemStack{GRASS x 1}
#2 ItemStack{STONE x 1}

идея в том, что когда ставишь блоки в игре, то в эти массивы добавляется локация блока и сам блок, и всё бы ничего, только вот когда игрок ломает блок, то из этих массивов должны убраться локация и блок, но как если "Удалить элемент массива" работает только по индексам?

когда ты добавляешь в массив, то тебе нужен только массив и то что добавляешь, а вот чтобы удалить что-то из массива, то тебе надо массив и ИНДЕКС!
ну то-есть мне нужно найти индекс из "Location{world=CraftWorld{world_plot_123_plot},x=5,y=2,z=10,pitch=0,yaw=0}", вот только как я его найду? как мне получить это самое значение 2? ведь благодаря только индексу я смогу удалить саму локацию и блок из массивов.

если вы знаете, то напишите и поделитесь лайфхаком!!!
Не успел протестить удаление если положить вместо числа текст, но вот такая идея есть. В блоках yaw и pitch нету, так что даже если мы сделаем yaw 100 то все равно можно будет манипулировать с блоками. Так вот, как насчет присваивать в yaw +1 и использование как индекс? То есть, мы поставили в массив с локациями координаты на индекс 1, добавили в yaw 1 и по значению из yaw поставили блок в массив с блоками. А блин, нет, это не сработает, пусть и идея хорошая. Другая идея: сделать через миллион энтити. 1 блок - 1 энтити. насколько я помню, тебе надо было при ломании блока удалять оба значения из обоих массивов а вообще это вроде невозможно на 1.12.2, потому что к блокам нельзя присваивать переменные.

UPD: Олсо, выдумывай что-то с координатами. Либо есть еще идея, под блоком ставь сундук и ложи туда число с индексом, а когда игрок ломает блок - открывай сундук под блоком и получай индекс.

UPD2: Стало интересно, блоки хранятся не айтемстаком. Айтемстак - класс для предметов, а для блоков другой. А есть еще и Material..

UPD3: Проверьте, пожалуйста, работает ли удаление чисто по тексту. Такая возможность в самой джаве присутствует, так что возможно и на мл можно.
 
Последнее редактирование:

maxim34a

Эксперт
Регистрация
10 Июн 2023
Сообщения
551
UPD3: Проверьте, пожалуйста, работает ли удаление чисто по тексту. Такая возможность в самой джаве присутствует, так что возможно и на мл можно.
Проверил только что, все работает. Кому надо - пользуйтесь.
 

maxim34a

Эксперт
Регистрация
10 Июн 2023
Сообщения
551
Плохо проверил, удаляется первый элемент массива.
Понятно. Ну, возвращаемся к способу с сундуками. Можно ещё на два мира сделать, @TimePlay, типа в одном мире - блоки, а в другом мире на том же месте - сундук с индексами. Бтв на джаве вроде бы удаляется по Object, т.е может быть и Integer(число), и String(Строка)
 

maxim34a

Эксперт
Регистрация
10 Июн 2023
Сообщения
551
Это чооо будет сохранение плота и удаление блока из массива и замена на AIR? Жду пока мл сделает возможность удалять переменные в коде.
Да, он хочет плоты. Бтв а чем тебя не устраивает установка значения переменной на Null?
 

tokkyo35

Новичок
Регистрация
14 Май 2023
Сообщения
31
Да, он хочет плоты. Бтв а чем тебя не устраивает установка значения переменной на Null?
Я хз, он тоже хочет сделать такую систему которую я бы хотел. И это костыли. 1 элемент массива = 1 переменная но вроде бы можно удалять элемент поэтому это уже более менее идея с массивом.
 

Copter533

Участник
Регистрация
24 Июн 2023
Сообщения
42
Я нашёл способ найьи индекс элемента в массиве по его значению:
1. Переводим массив в строку (переменная A)
2. Переводим значение для поиска тоже в строку (переменная B)
3. В текстовой переменной массива (A) заменяем " = `"+(B)+"`" на кучу символов "-" с "#" в начале
3.1 Можно получить эту кучу как-то так:1688125362108.png
ТУТ ПЕРВАЯ КНИГА ЭТО #, ЦВЕТ НЕ ВАЖЕН
4. Разделить полученный текст на элементы через #, и взять предпоследний элемент - это будет индекс элемента (не забудте к нему прибавить 1 и превратить в число т.к. сейчас это текст)

UPD: Объяснение: у МЛ есть одна особенность - очень длинные строки обрезаются. Мы, заменяя определённую строку в текстовой переменной массива (A) достигаем это лимита, т.е. в конце (A) будет выглядеть как куча минусов, и это нам поможет успешно разделить текст на элементы и получить нужный. Но тут есть и обратная сторона - если массив будет огромным, и если мы захотим найти индекс последнего элемента, то всё сломается.
Сообщение объединено:

значит есть у меня два массива интересных:
массив locations
#1 Location{world=CraftWorld{world_plot_123_plot},x=1,y=2,z=3,pitch=0,yaw=0}
#2 Location{world=CraftWorld{world_plot_123_plot},x=5,y=2,z=10,pitch=0,yaw=0}
массив blocks
#1 ItemStack{GRASS x 1}
#2 ItemStack{STONE x 1}

идея в том, что когда ставишь блоки в игре, то в эти массивы добавляется локация блока и сам блок, и всё бы ничего, только вот когда игрок ломает блок, то из этих массивов должны убраться локация и блок, но как если "Удалить элемент массива" работает только по индексам?

когда ты добавляешь в массив, то тебе нужен только массив и то что добавляешь, а вот чтобы удалить что-то из массива, то тебе надо массив и ИНДЕКС!
ну то-есть мне нужно найти индекс из "Location{world=CraftWorld{world_plot_123_plot},x=5,y=2,z=10,pitch=0,yaw=0}", вот только как я его найду? как мне получить это самое значение 2? ведь благодаря только индексу я смогу удалить саму локацию и блок из массивов.

если вы знаете, то напишите и поделитесь лайфхаком!!!
Проще всего искать локацию в первом массиве, а потом по полученному индексу удалять и локацию, и блок
Сообщение объединено:

У меня подобный код (для поиска индекса) используется для получения индекса введённой команды в событии чата
 
Последнее редактирование:

maxim34a

Эксперт
Регистрация
10 Июн 2023
Сообщения
551
Я нашёл способ найьи индекс элемента в массиве по его значению:
1. Переводим массив в строку (переменная A)
2. Переводим значение для поиска тоже в строку (переменная B)
3. В текстовой переменной массива (A) заменяем " = `"+(B)+"`" на кучу символов "-" с "#" в начале
3.1 Можно получить эту кучу как-то так:Посмотреть вложение 1503
ТУТ ПЕРВАЯ КНИГА ЭТО #, ЦВЕТ НЕ ВАЖЕН
4. Разделить полученный текст на элементы через #, и взять предпоследний элемент - это будет индекс элемента (не забудте к нему прибавить 1 и превратить в число т.к. сейчас это текст)

UPD: Объяснение: у МЛ есть одна особенность - очень длинные строки обрезаются. Мы, заменяя определённую строку в текстовой переменной массива (A) достигаем это лимита, т.е. в конце (A) будет выглядеть как куча минусов, и это нам поможет успешно разделить текст на элементы и получить нужный. Но тут есть и обратная сторона - если массив будет огромным, и если мы захотим найти индекс последнего элемента, то всё сломается.
Сообщение объединено:


Проще всего искать локацию в первом массиве, а потом по полученному индексу удалять и локацию, и блок
Сообщение объединено:

У меня подобный код (для поиска индекса) используется для получения индекса введённой команды в событии чата
в целом твой код неплох, но у таймплея массив для плотов, соответственно он большой. А ещё разве не будет багов если значением массива будет какой-то текст типа "------" или "#1"?

Бтв было бы проще, если бы добавили удаление из массива по объекту
1688128158041.png
 

Copter533

Участник
Регистрация
24 Июн 2023
Сообщения
42
в целом твой код неплох, но у таймплея массив для плотов, соответственно он большой. А ещё разве не будет багов если значением массива будет какой-то текст типа "------" или "#1"?

Бтв было бы проще, если бы добавили удаление из массива по объекту
Посмотреть вложение 1510
Согласен
 

Mee8YT

Эксперт
Регистрация
3 Май 2023
Сообщения
358
Да, он хочет плоты. Бтв а чем тебя не устраивает установка значения переменной на Null?
это фигня полная, переменная после такой установки всё равно существует
 

Flessly

Участник
Регистрация
3 Май 2023
Сообщения
0
Этот способ подойдет, если тебе не нужно в любой момент использовать этот массив, а после того, как игрок уже не ставит/ломает блоки.
Идея в том, чтобы при ломании блока добавлять координаты этого блока в другой массив - массив сломанных блоков.
Когда нужно использовать массив, используя две рекурсивные функции (одна вложена в другую, аналогично вложенным циклам в языках программирования) проходимся по первому и второму массиву, если значения первого и второго совпадают (то есть, координаты поставленного блока совпали с координатами сломанного блока) - удаляем эти значения в обоих массивах, индексы прохода по обоим массивам убавляем на 1, пределы прохода по массивам тоже убавляем на 1 (чтобы не выйти за границу массивов).
Естественно, такой способ занимает довольно много времени, а именно n*m тиков, где n - количество поставленных блоков, m - количество сломанных блоков.

Пример программы на c#:
C#:
// заполненные массивы поставленных и сломанных блоков
string[] putBlocks = new string[] { "abc", "asd", "paisd" };
string[] brokenBlocks = new string[] { "asd" };

// счетчики и пределы прохода по массивам
int i = 0;
int maxI = putBlocks.Length;
int maxJ = brokenBlocks.Length;
// 1-я рекурсивная функция
while (i < maxI)
{
    int j = 0;
    // 2-я рекурсивная функция
    while (j < maxJ)
    {
        // получаем значения массивов в определенных индексах, проверяем, что они равны
        if (putBlocks[i] == brokenBlocks[j])
        {
            // удаляем элементы массивов по индексу
            putBlocks = putBlocks.RemoveAt(i);
            brokenBlocks = brokenBlocks.RemoveAt(j);
            // убавляем на 1 счетчики и пределы прохода по массивам
            i--;
            j--;
            maxI--;
            maxJ--;
        }
        // прибавляем счетчик
        j++;
    }
    // прибавляем счетчик
    i++;
}
// теперь в массиве putBlocks только блоки, которые сейчас поставлены
// вывод массива
foreach (var elem in putBlocks)
{
    Console.Write("{0} ", elem);
}


// расширение, обрабатывающее удаление элемента массива по индексу (на мл вместо этого уже готовая функция)
public static class Extensions
{
    public static T[] RemoveAt<T>(this T[] source, int index)
    {
        T[] dest = new T[source.Length - 1];

        for (int i = 0, j = 0; i < source.Length; i++)
        {
            if (i != index)
            {
                dest[j] = source[i];
                j++;
            }
        }

        return dest;
    }
}
Вывод: abc paisd
При переносе кода не забывай, что на мл индексы массива идут от 1 до длины массива, а в c# от 0 до (длины массива-1)

Есть еще другой вариант - аналогично алгоритму выше сразу удалять элемент массива, как только игрок ломает блок.
В таком случае рекурсия будет только одна, а сравнивать значение элемента массива будем с координатой сломанного блока.
Но такой способ вряд ли сработает, если игрок может ломать блоки чаще, чем (максимальное кол-во поставленных блоков, в тиках), ибо тогда мы начнем удалять новый элемент массива, не удалив со 100% вероятностью старый

А вообще, я бы на твоем месте поискал способы, как обойтись без удаления элементов массива
 

pawsashatoy

Участник
Регистрация
2 Май 2023
Сообщения
4
в целом твой код неплох, но у таймплея массив для плотов, соответственно он большой. А ещё разве не будет багов если значением массива будет какой-то текст типа "------" или "#1"?

Бтв было бы проще, если бы добавили удаление из массива по объекту
Посмотреть вложение 1510
Белая тема😭😭😭
 

Mee8YT

Эксперт
Регистрация
3 Май 2023
Сообщения
358
Этот способ подойдет, если тебе не нужно в любой момент использовать этот массив, а после того, как игрок уже не ставит/ломает блоки.
Идея в том, чтобы при ломании блока добавлять координаты этого блока в другой массив - массив сломанных блоков.
Когда нужно использовать массив, используя две рекурсивные функции (одна вложена в другую, аналогично вложенным циклам в языках программирования) проходимся по первому и второму массиву, если значения первого и второго совпадают (то есть, координаты поставленного блока совпали с координатами сломанного блока) - удаляем эти значения в обоих массивах, индексы прохода по обоим массивам убавляем на 1, пределы прохода по массивам тоже убавляем на 1 (чтобы не выйти за границу массивов).
Естественно, такой способ занимает довольно много времени, а именно n*m тиков, где n - количество поставленных блоков, m - количество сломанных блоков.

Пример программы на c#:
C#:
// заполненные массивы поставленных и сломанных блоков
string[] putBlocks = new string[] { "abc", "asd", "paisd" };
string[] brokenBlocks = new string[] { "asd" };

// счетчики и пределы прохода по массивам
int i = 0;
int maxI = putBlocks.Length;
int maxJ = brokenBlocks.Length;
// 1-я рекурсивная функция
while (i < maxI)
{
    int j = 0;
    // 2-я рекурсивная функция
    while (j < maxJ)
    {
        // получаем значения массивов в определенных индексах, проверяем, что они равны
        if (putBlocks[i] == brokenBlocks[j])
        {
            // удаляем элементы массивов по индексу
            putBlocks = putBlocks.RemoveAt(i);
            brokenBlocks = brokenBlocks.RemoveAt(j);
            // убавляем на 1 счетчики и пределы прохода по массивам
            i--;
            j--;
            maxI--;
            maxJ--;
        }
        // прибавляем счетчик
        j++;
    }
    // прибавляем счетчик
    i++;
}
// теперь в массиве putBlocks только блоки, которые сейчас поставлены
// вывод массива
foreach (var elem in putBlocks)
{
    Console.Write("{0} ", elem);
}


// расширение, обрабатывающее удаление элемента массива по индексу (на мл вместо этого уже готовая функция)
public static class Extensions
{
    public static T[] RemoveAt<T>(this T[] source, int index)
    {
        T[] dest = new T[source.Length - 1];

        for (int i = 0, j = 0; i < source.Length; i++)
        {
            if (i != index)
            {
                dest[j] = source[i];
                j++;
            }
        }

        return dest;
    }
}
Вывод: abc paisd
При переносе кода не забывай, что на мл индексы массива идут от 1 до длины массива, а в c# от 0 до (длины массива-1)

Есть еще другой вариант - аналогично алгоритму выше сразу удалять элемент массива, как только игрок ломает блок.
В таком случае рекурсия будет только одна, а сравнивать значение элемента массива будем с координатой сломанного блока.
Но такой способ вряд ли сработает, если игрок может ломать блоки чаще, чем (максимальное кол-во поставленных блоков, в тиках), ибо тогда мы начнем удалять новый элемент массива, не удалив со 100% вероятностью старый

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

astr34

Эксперт
Регистрация
16 Июл 2023
Сообщения
18
Если координаты преобразовать так что бы минимальная координата была 1, то можно добавлять по индексу X в массив координаты Y и Z (в текстовую переменную). Чтобы найти позицию в массиве (или проверить её присутствие) преобразуем координаты (чтобы начинались с 1), получаем текстовую переменную по индексу X и ищем в ней Y и Z. Но если построить большую линию блоков вдоль оси X - можно достичь лимита размера текстовой переменной.
Лучше за индекс брать остаток от деления суммы преобразованных координат на число (на 100, например) + 1. Тогда координаты будут распределяться равномерно по индексам, но нужно будет добавлять в текстовую переменную по индексу все 3 координаты. Чем больше число - тем меньше будет элементов по каждому из индексов - поиск будет быстрее, система выдержит больше элементов. Но больше пары тысяч я бы не рекомендовал, массивы лагают. Также если это число будет больше возможной суммы координат, то первая ячейка и ячейки массива начиная с максимально возможной суммы координат+1 заполняться не будут. Поэтому (и по другим причинам) остаток от деления лучше взять от суммы домноженных координат на разные числа (не любые! (нужно чтобы изменение одной координатны как можно реже "компенсировалось" изменением другой -> НОК координат должен быть максимальным -> числа должны быть взаимно простыми)).
Например так:
index = (61*x+67*y+73*z) % 2000 + 1.
или так:
index = (11*x+12*y+13*z) % 2000 + 1.
С числами из примеров сохранится равномерное распределение и будут нормально распределяться по ячейкам точки на любых линиях.
 
Последнее редактирование:
Сверху