Как сделать?
…
Помогите, плиз, понять многомерные массивы. Я, возможно, глупая, но я так и не поняла для чего они. Я читала в справке о них, но так и не поняла. Пожалуйста, объясните зачем они нужны? Как их использовать? Для чего нужны значения, что находятся вместо номеров ячеек? Как их использовать?
Хотя, возможно, я пока замахнулась на слишком сложную тему для себя, поэтому не могу пока понять, но всё же хотелось бы хоть немного понять многомерные массивы
Многомерные массивы полезны в случае, когда какое-либо значение нужно связать не с одним значением, а с несколькими.
Например, если описание какого-то предмета зависит только от порядкового номера предмета (м.б. от его названия?), то это одномерный массив.
Если описание предмета зависит не только от номера предмета, а еще и от локации, где игрок находится, то это уже двухмерный массив (в этом случае предмет с одним порядковым номером может иметь разное описание в зависимости от локации).
Другой пример - у нас есть двухмерная карта с координатами. Тогда содержимое каждой ячейки будет зависеть от 2х координат - это двухмерный массив (как таблица).
Если добавить еще одно измерение (например, содержимое _каждой_ ячейки карты зависит от координаты Z или от другого обязательного параметра), то это будет 3х-мерный массив.
Измерений может быть много, главный критерий создавать их или нет - это от скольких/каких _обязательных_ параметров зависит значение каждого элемента массива.
В QSP с этим немного проще, т.к. в пределах одного массива одна ячейка может зависеть от любого числа параметров (какие-то значения могут быть для 1го, другие для 2х, и т.д.)
Использовать это просто - нужно вместо одного значения-индекса массива, указать несколько через запятую.
Установка значения:
$описание[x,y]='это описание для ячейки x,y'
Использование значения:
pl $описание[x,y]
! другой немного странный пример:
if $локация[x,y]='крыша': pl 'Вы находитесь на крыше высокого здания'
Значение ячейки может зависеть от значений разных типов:
$описание[x,y,$value]='это описание для ячейки по переменным x,y,$value'
$описание['test', x]='это описание для ячейки "test",x'
Конечно, в качестве индексов можно использовать значения из других массивов (то есть, не просто переменные/константы).
ShadowX2,
На мой взгляд самый простой способ понять многомерный массив можно на примере шахматной доски.
Есть некая “Длина” и некая “Ширина”. В шахматах это буквы: A,B,C,D,E,F,G,H и цифры 1,2,3,4,5,6,7,8. Каждая ячейка может быть или черная или белая, и в каждой ячейке у тебя может был какая-то фигура или ячейка пустая.
Тогда, классическая форма многомерного шахматного массива в КуСПе будет выглядеть примерно так (Условно):
$Доска['A',1,'Фигура']=$ЛадьяБел[1]
$Доска['A',1,'Цвет']='Черный'
$Доска['B',1,'Фигура']=$КоньБел[1]
$Доска['B',1,'Цвет']='Белый'
$Доска['С',1,'Фигура']=$СлонБел['Черный']
$Доска['C',1,'Цвет']='Черный'
$Доска['D',1,'Фигура']=$ФерзьБел
$Доска['D',1,'Цвет']='Белый'
$Доска['E',1,'Фигура']=$КорольБел
$Доска['E',1,'Цвет']='Черный'
$Доска['F',1,'Фигура']=$СлонБел['Белый']
$Доска['F',1,'Цвет']='Белый'
$Доска['G',1,'Фигура']=$КоньБел[2]
$Доска['G',1,'Цвет']='Черный'
$Доска['H',1,'Фигура']=$ЛадьяБел[2]
$Доска['H',1,'Цвет']='Белый'
....
$Доска['A',8,'Фигура']=$ЛадьяЧерн[1]
$Доска['A',8,'Цвет']='Белый'
$Доска['B',8,'Фигура']=$КоньЧерн[1]
$Доска['B',8,'Цвет']='Черный'
$Доска['С',8,'Фигура']=$СлонЧерн['Белый']
$Доска['C',8,'Цвет']='Белый'
$Доска['D',8,'Фигура']=$ФерзьЧерн
$Доска['D',8,'Цвет']='Черный'
$Доска['E',8,'Фигура']=$КорольЧерн
$Доска['E',8,'Цвет']='Белый'
$Доска['F',8,'Фигура']=$СлонЧерн['Черный']
$Доска['F',8,'Цвет']='Черный'
$Доска['G',8,'Фигура']=$КоньЧерн[2]
$Доска['G',8,'Цвет']='Белый'
$Доска['H',8,'Фигура']=$ЛадьяЧерн[2]
$Доска['H',8,'Цвет']='Черный'
Лично я стараюсь не использовать многомереки без необходимости. А разбиваю их на понятные одномерные, так проще воспринимать код.
Но, например, если некий предмет способен “переезжать” с локации на локацию и в пределах локации менять свое положение и оставаться там, пока кто-то не переместит его на другую, то в таких случаях можно хранить положение предмета в двумерном массиве.
Опять таки, надо понимать, что и как хранить. Мне проще хранить местонахождение предмета в свойствах самого предмета, или через динамический массив, где индекс массива - код предмета, а значение - локация. При больших массивах данных я привык пользоваться индексами. Каждый предмет, локация, непись (при необходимости) имеет свой уникальный индекс и через этот индекс они связываются.
Обычно я делаю функции-прокладки, которые могут из общего массива данных найти нужное и в любом количестве. Например для “Снаряжения” - по ID “Владельца” найти все Снаряжение, которое принадлежит данному Владельцу.
Доброго времени суток. Такой странный вопрос по предметам, а конкретно по $SELOBJ… Есть ли возможность выделить предметом кодом, через тот же act к примеру, без прямого клика игроком на предмет в инвентаре, чтобы выделить этот самый предмет?
И макро вопрос, как проверить есть ли предмет в инвентаре, а то я что-то в документации не могу найти енто самое.
n3m0,
Чесслово, тут надо дождаться гуру. Реально, не сильно в теме.
Я попробовал пользоваться стандартным набором инвентаря и понял, что он меня совершенно не устраивает. По сути он пустой, оболочка - не более. Можно добавить-убрать и по сути всё. Ни количества, ни других свойств. И я решил, что если все свойства надо хранить отдельно - то нахрена использовать? Я написал свой, сначала было кривовато, но терпимо (Старый пример лежит несколько страниц назад. https://qsp.org/forum/23-kak-sdelat?page=425). А теперь можно применять к любому количеству “предметов” с совершенно разными “внутренними структурами”.
Как проверить, есть ли среди предметов предмет, содержащий такое-то слово — я вот таким кодом пользуюсь:
i=1
yes_its_here=0
:ii
$currentObjectName=$getObj(i)
if instr($currentObjectName,$findname):
yes_its_here=1
end
if i < countObj or i = countObj:
i+=1
jump'ii'
end
n3m0, событие выделения предмета, согласно вики, только по клику мышью. Какая задача стоит? Возможно, можно решить другим способом.
mkir,
этот код обычно и используют.
Если поддержка игры не предполагается на 5.7.0, можно написать его на настоящем цикле, так код будет работать быстрее.
! $findname
yes_its_here = 0
loop local i = 1 while i <= countobj step i += 1:
if instr($findname, $getobj(i):
yes_its_here = 1
jump 'loop_end'
end
end
:loop_end
Но если такой поиск происходит в игре постоянно и часто, более быстрый вариант — это хранить названия предметов в массиве и производить поиск с помощью регулярного выражения по массиву:
pos = arrcomp($objnames, '*\bмеч\b*') & ! найдёт позицию первого предмета, содержащего слово "меч"
yes_its_here = iif(pos = -1, 0, 1)
! $findname не содержит спецсимволов и знаков пунктуации
pos = arrcomp($objnames, '*\b<<$findname>>\b*')
yes_its_here = iif(pos = -1, 0, 1)
Аааа. Я тут запутался в логике вопросов ответов. Это не Марк спрашивал.
n3m0,
да, поясни, пожалуйста, чего ты хочешь добиться? Тебе нужно выделить предмет визуально?
Некоторые вопросы по работе с предметами освещены тут: https://aleksversus.github.io/howdo_faq/docs/howdo/contents/items/add_item. Для плееров последних версий немного неактуальна информация по замене предметов в определённой позиции.
Просто во время писанины кода вспомнил что в куспе есть инвентарь, и хотел вспомнить как и что делать, но вот возник вопрос, можно ли как-то выделить предмет в инвентаре кодом, не зависимо от того кликал на предмет сам игрок.
По ходе изучения возникла идея, если бы можно было выделять предмет кодом, без клика игрока, можно было бы это использовать в тех или иных ситуациях. Да это даст то же самое что и поиск циклом, но наверное было бы удобнее. Да идея абсурдная, просто вот такое вот возникло пока штудировал вики, только и всего.
ShadowX2:
Помогите, плиз, понять многомерные массивы. Я, возможно, глупая, но я так и не поняла для чего они. Я читала в справке о них, но так и не поняла. Пожалуйста, объясните зачем они нужны? Как их использовать? Для чего нужны значения, что находятся вместо номеров ячеек? Как их использовать?
Хотя, возможно, я пока замахнулась на слишком сложную тему для себя, поэтому не могу пока понять, но всё же хотелось бы хоть немного понять многомерные массивы
Я как всегда очень поздно, со своим самоваром, очень у меня большой. Уж извините. Но и тема моя любимая: многомерные массивы в QSP.
Для чего они?
Массивы вообще нужны для хранения однотипных данных в одном месте и под одним именем. С ними так удобнее работать и целиком и по отдельности. В первом случае используем имя и делаем всякое разное сразу со всеми данными. Во втором случае используем имя и номер ячейки, для работы с конкретными данными.
И вот представьте у вас в игре есть книжный магазин и там, что удивительно, продаются книги! У них есть “Название”, “Обложка”, “Цена”. Организуем массив &Книги:
| Название | Обложка | Цена |
|---|---|---|
| Физика | Картинка1 | 800 |
| Сказки | Картинка2 | 600 |
| Журнал | Картинка3 | 300 |
В коде это запишем так:
&Книга[0,0] = 'Физика' & &Книга[0,1] = "Картинка1" & &Книга[0,2] = '800'
&Книга[1,0] = 'Сказки' & &Книга[1,1] = "Картинка2" & &Книга[1,2] = '600'
&Книга[2,0] = 'Журнал' & &Книга[2,1] = "Картинка3" & &Книга[2,2] = '300'
Теперь, когда заходим в магазин, выводим на экран табличку:
! Выводим на экран обложку
<td>
loop local i = 0 while i <= 2 step i += 1
'<tr><<&Книга[i,1]>></tr> '
end
</td>
! Выводим на экран название
<td>
loop local i = 0 while i <=2 step i += 1
'<tr><<&Книга[i,0]>></tr> '
end
</td>
! Выводим на экран цену
<td>
loop local i = 0 while i <=2 step i += 1
'<tr><<&Книга[i,2]>></tr> '
end
</td>
Будет ряд картинок с обложками,, под ними название книг, еще ниже цена Вот примерно так, надеюсь принцип понятен? Когда захотим купить, то сравниваем количество денег:
if деньги>=&Книга[i,2]:
деньги -= &Книга[i,2]
addobj &Книга[i,0]
end
Но мы же писатели, типа гордые творцы и создаем как минимум ‘нетленку’! А поэтому запоминать эти презренные циферки, где у нас там что и под каким числом находится, нам лениво или скажем мягче, не наш путь!
По секрету скажу, что программисты одни из самых ленивых людей на свете! Нам тоже лениво и мы всё давно уже придумали, поэтому я вас понимаю. ;)
Итак, облегчаем себе путь. Дадим колонкам названия!
Name = 0
Pic = 1
Price = 2
Тогда вывод таблички можем сделать так:
! Выводим на экран обложки
<td>
loop local i = 0 while i <=2 step i += 1
'<tr><<&Книга[i,Pic]>></tr> '
end
</td>
! Выводим на экран название
<td>
loop local i = 0 while i <=2 step i += 1
'<tr><<&Книга[i,Name]>></tr> '
end
</td>
! Выводим на экран цену
<td>
loop local i = 0 while i <=2 step i += 1
'<tr><<&Книга[i,Price]>></tr> '
end
</td>
Но и строкам мы тоже можем дать название! Книг много и в какой строке какая книга тоже тяжело отследить.
Fizika = 0
Tales = 1
Magazin = 2
Тогда покупка сказок, например будет выглядеть так:
if деньги>=&Книга[Tales, Price]:
деньги -= &Книга[Tales, Price]
addobj &Книга[Tales, Name]
end
Упс, и никаких этих богопротивных чисел!
А теперь ‘магия’ старого QSP. Кое кто по привычке на нем еще пишет, а кто то и на Нафигаторе, там тоже старый qsp. Итак, запомните:
Двумерных массивов нет нигде и никогда, ни в одном из языков программирования!
Просто есть способ адресации ячейки памяти. И все сводится к одной простой формуле из следующих элементов:
-
начало массива
-
смещение строки относительно начала массива
-
смещение колонки/ячейки относительно начала строки
Начало массива у нас задается именем массива. Смещение колонки задается ее номером. Это как раз второе число в индексе двумерного массива. А как же со смещением строки? При инициализации двумерного массива компилятор запоминает количество колонок в массиве. Обычно мы ему явно об этом сообщаем. На QSP нам надо самим это посчитать, но это просто. Вот это число запомним в переменной Base. Кстати, это традиционное название для этой шняги. И формула выглядит так:
arrey[строка*Base + колонка]
Т.е. все индексы наши остались, только синтаксис изменился. А самое интересное, что во всех языках, все компиляторы преобразуют эти ваши индексы [строка, колонка] в эту формулу, и по ней вычисляют ячейку массива. Вся разница QSP от этих языков в том, что приходится эту формулу явно записать.
И теперь превратим наш двумерный массив &Книги[], в одномерный массив старого qsp. У нас колличество колонок в массиве 3, поэтому:
Base = 3
Вывод таблички ‘в старом qsp’
! Выводим на экран обложки
<td>
loop local i = 0 while i <=2 step i += 1
'<tr><<&Книга[i*Base + Pic]>></tr> '
end
</td>
! Выводим на экран название
<td>
loop local i = 0 while i <=2 step i += 1
'<tr><<&Книга[i*Base + Name]>></tr> '
end
</td>
! Выводим на экран цену
<td>
loop local i = 0 while i <=2 step i += 1
'<tr><<&Книга[i*Base + Price]>></tr> '
end
</td>
Покупка Сказок:
if деньги>=&Книга[Tales*Base + Price]:
деньги -= &Книга[Tales*Base + Price]
addobj &Книга[Tales*Base + Name]
end
И теперь вы, видя текстовые индексы, в том числе и из тутошней справочки:
array[’x, y’]
можете гордо и важно заявить, что это написано безграмотными людьми, которые не понимают что такое массивы! :)))
P.S. Надеюсь сильно ногами бить не станут за эту простынку.