Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Задача с перебором двух массивов (http://www.flasher.ru/forum/showthread.php?t=172101)

PainKiller 01.12.2011 19:40

Задача с перебором двух массивов
 
Начну с описания задачи. Имеется 18 предметов (класс Value), которые надо расставить по 18 гнездам (класс Target).Соответственно, предметы содержатся в массиве termValueArray, а гнезда в массиве targetsArray. Когда предмет встает в гнездо, справа от него появляется галочка (метод checkShow принимает булево значение и отрисовывает галочку). Когда предмет вынимается из гнезда или переставляется в др. гнездо галочка должна исчезать и появляться только у занятого предметом гнезда. Перетаскивание предметов осуществляется драг-энд-дропом, при отпускании мыши (событие MOUSE_UP) в классе Value диспатчится событие, по которому начинается проверка занятых и свободных гнезд. Проблема как раз и возникла с алгоритмом этой проверки. Поначалу я думал, что задача достаточно тривиальная, и с ходу написал примерно такой код (это только одна из моих многочисленных версий):

Код AS3:

function checkHit(e:Event):void
{
    for (var j:Number = 0; j < termValueArray.length; j++)
                        {
                                for (var i:Number = 0; i < targetsArray.length; i++)
                                {
                                        if (termValueArray[i].hitTestObject(targetsArray[j]))
                                        {
                                                trace("Hitting");
                                                termValueArray[i].rank = targetsArray[j].targetRank;
                                                termValueArray[i].x = targetsArray[j].x;
                                                termValueArray[i].y = targetsArray[j].y;
                                                targetsArray[j].checkShow = true;
                                                trace (targetsArray[j].checkShow + " ветвь if" + " i=" + i + " j=" + j);
                                        }
                                        else
                                        {
                                                trace (targetsArray[j].checkShow + " ветвь else" + " i=" + i + " j=" + j);
                                                if (targetsArray[j].checkShow)
                                                {
                                                      targetsArray[j].checkShow = false;
                                                }
 
                                        }
 
                                }

Естественно этот код не работает т.к. отрисованная галочка закрывается при последующих прохождениях цикла. Если же вывести код закрытия галочки за цикл с i то она все равно закрывается. Я ломал над этой задачей голову полдня, честно говоря уже ничего не соображаю, начал приходить к выводу, что перебором двух массивов эту задачу решить нельзя вообще. Видимо надо писать какой то внешний контроллер, но он опять же должен проверять занятые и свободные гнезда, и опять же это надо делать перебором! В общем буду рад хоть какому намеку на пути решения этой задачи.

KBAC 01.12.2011 20:08

Можно сделать ссылку на объект Target у объекта Value если они соприкасаются.
И по идее если перемещение делается drag and drop'ом, то e.target будет как раз нужный для проверки объект. Тогда достаточно одного цикла:

Код AS3:

private function onMouseUp(e:MouseEvent):void 
{
        if (!e.traget is Value) return;
        var item:Value = e.target as Value;
 
        if (item.target) {
                item.target.checkShow = false;
                item.target = null;
        }
 
        for (var i:int = 0; i < targetsArray.length; ++)
        {
                if (item.hitTestObject(targetsArray[i]))
                {
                        trace("Hitting");
 
                        item.target = targetsArray[i];
                        item.target.checkShow = true;
 
                        item.rank = targetsArray[i].targetRank;
                        item.x = targetsArray[i].x;
                        item.y = targetsArray[i].y;
 
                        //чтобы реагировало только на один объект Target
                        return;
                }                       
        }
}


PainKiller 01.12.2011 20:45

По моему тут сумбур небольшой - событие onMouseUp наступает в классе Value, но идея понятна, насчет e.target я тоже думал, но ничего хорошего не придумал, попробую ваш код спасибо.

KBAC 01.12.2011 21:00

Основная суть такая:
- делать проверку только для перетаскиваемого объекта
- сбрасывать галочку у гнезда в котором он лежал, если он лежал в каком-то из гнёзд.
- проверять положили ли объект куда-нибудь.

Если проверяете на MOUSE_UP в самом Value, то можете в метод проверки передавать ссылку именно на этот объект.

PainKiller 01.12.2011 21:04

только в самом Value массив targetsArray не объявлен. Мне кажется надо просто сохранять в Value ссылку на e.target, и перебирать массив уже в основном классе. Попробую, отпишусь о результатах.

Добавлено через 3 часа 32 минуты
Пока не пробовал кодить, займусь этим завтра, но пока я думал над использованием e.target мне начало казаться что этот метод не сработает. Какой то бред получается, событие диспатчит экземпляр Value и он сам на себя ссылку сохраняет? А потом есть же другие предметы, и они тоже могут занимать на момент проверки гнезда - по любому надо проверять 2 массива. Хотя есть еще идея нечто подобное сделать с dropTarget

Все решил проблему. Всем спасибо за помощь :-). В общем развел выставление галочки и стирание её по двум событиям (одно на MOUSE_UP другое на MOUSE_DOWN)
Вот итоговый код, вроде все работает как надо:
Код AS3:

function checkUP(e:Event):void
                {
                        if (! e.target is Value)
                        {
                                return;
                        }
                        var item:Value = e.target as Value;
                        for (var j:Number = 0; j < targetsArray.length; j++)
                        {
                                if (item.rank == targetsArray[j].targetRank)
                                {
                                        trace (item.rank +" " + targetsArray[j].targetRank)
                                        if (targetsArray[j].checkShow)
                                        {
                                                targetsArray[j].checkShow = false;
                                                trace (targetsArray[j].checkShow + " ветка UP" + " j=" + j);
                                                item.rank = null;
                                        }
                                }
                        }
                }
                function checkHit(e:Event):void
                {
                        if (! e.target is Value)
                        {
                                return;
                        }
                        var item:Value = e.target as Value;
                        for (var j:Number = 0; j < targetsArray.length; j++)
                        {
                                if (item.hitTestObject(targetsArray[j]))
                                {
                                        trace("hitting");
                                        item.rank = targetsArray[j].targetRank;
                                        item.x = targetsArray[j].x;
                                        item.y = targetsArray[j].y;
                                        targetsArray[j].checkShow = true;
                                        trace (targetsArray[j].checkShow + " ветка Hit" + " j=" + j);
                                }
 
                        }
 
 
                }



Часовой пояс GMT +4, время: 11:08.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.