0

クラス名に特定の単語を含む特定のオブジェクトのみを配列に許可する方法を見つけたいと思います。または、少なくともこのようなことを行う最適な方法を見つけてください。詳細はこちら。カートにドロップされたすべてのオブジェクトを格納する配列があります。

function addProductToArray (e:MouseEvent):void{ currMC = (e.target as MovieClip); myCart.itemsInCart.push(currMC); trace(myCart.itemsInCart);}

たとえば、[オブジェクト BreadGrain] と [オブジェクト PastaGrain] をドロップするとします。

trace(myCart.itemsInCart);// would trace [object BreadGrain],[object PastaGrain].

簡単、問題ありません。しかし、Classname に "Grain" を含む 2 つのオブジェクトのみを配列に入れたい場合はどうすればよいでしょうか? ユーザーが「カート」に各タイプの食品を 2 つだけドロップできるように、これを行いたいと考えています。食品の種類は、穀物、果物、野菜、肉などです。クラス名の末尾に食品の種類を追加しました。これを使用して、それがどの種類の食品であるかを検出し、追加されないようにすることができれば幸いです。制限を超え、エラーを表示します。つまり、「あなたはすでに 2 つの穀物製品を持っています」。

それが理にかなっていることを願っています。とにかく、私はそれがある程度うまくいくことを発見しました:

if (currMC is BreadGrain) {
                myCart.itemsInCart.push(currMC);
            } else {
                // error message code here 
            }

しかし、私はいくつかの製品を持っており、それらすべてに対して if/else または switch ステートメントを記述する必要はありません。私はこれを次のようなもので動的に行うことを望んでいました:

//this is an example of the logic
if (currMC classNameContainsTheWord "Grain"  AND myCart.itemsInCart DoesNotContainMoreThan 2 Grain Objects) {

myCart.itemsInCart.push(currMC); } else { // ここにエラー メッセージ コード }

私は困惑しています。「おい、あなたはこれをすべて間違っている」だけでも役に立ちます。ありがとう。

4

3 に答える 3

2

getQualifiedClassName関数を使用して、任意のオブジェクトのクラス名を取得できます。次に、RegExp を使用して文字列を特定のパターンと照合するか、クラス名に部分文字列が含まれているかどうかを確認することもできます。

そうは言っても、共通の基本クラスまたはインターフェイスのいずれかを使用する方がより良いアプローチになると思います。

//  assuming your objects extend MovieClip
public class Grain extends MovieClip{

    public function Grain() {
        super();
    }

    public function someCommonMethodToAllGrains():void {

    }
}

また

//  It's customary to prefix interfaces name with an "I" in AS; 
//  I'm not doing it here so the code works for both a base class and an interface

public interface Grain {

    function someCommonMethodToAllGrains():void;
}

次に、基本クラスを使用した場合:

public class BreadGrain extends Grain {

    public function BreadGrain() {
        super();
    }

    override public function someCommonMethodToAllGrains():void {
        //  if this makes sense for your object...
        super.someCommonMethodToAllGrains();    
    }    

}

public class PastaGrain extends Grain {

    public function PastaGrain() {
        super();
    }

    override public function someCommonMethodToAllGrains():void {
        //  if this makes sense for your object...
        super.someCommonMethodToAllGrains();
    }    
}

または、インターフェイスを使用して

public class BreadGrain extends MovieClip implements Grain {

    public function BreadGrain() {
        super();
    }

    public function someCommonMethodToAllGrains():void {

    }    

}

public class PastaGrain extends MovieClip implements Grain {

    public function PastaGrain() {
        super();
    }

    public function someCommonMethodToAllGrains():void {

    }    
}

これらのオブジェクトが の場合MovieClips、基本クラスを使用する方がおそらく面倒ではありません。そうしないと、オブジェクトを表示リストに追加 (または削除) するたびに、オブジェクトをMovieClip(または) にキャストし直す必要があるためです。DisplayObjectところで、これはIDisplayObjectAdob​​e の誰かがインターフェイスを含めるのを忘れており、表示リスト API に、とにかく直接派生できない中途半端な抽象クラス (別名DisplayObject) の代わりに、このインターフェイスを実装したオブジェクトを受け入れさせるためです。これにより、表示オブジェクトをインターフェイスとして扱いやすくなりますが、余談です)。

とにかく、インターフェイスまたは共通の基本クラスのいずれかを使用して、isオペレーターで検証を行うことができますが、Grain という 1 つのタイプを確認するだけで済みます。

if(theObject is Graing && theArray.lenght <= 2) {
    theArray.push(theObject);
}

これをさらに進めて、配列の代わりにベクターを使用することもできます。Vector は Array とほぼ同じように機能しますが、厳密に型指定されているため、次のようにすることができます。

var items:Vector.<Grain> = new Vector.<Grain>();
items.push(grainObject);

Grain を拡張/実装しないオブジェクトを追加しようとすると、コンパイル時エラーが発生します。

ベクトルは Flash Player 10 で利用できますが、Flash CS4 が必要です (Flash IDE を使用している場合。それ以外の場合は、コンパイルに少なくとも 3.2 SDK が必要になると思います)。

于 2010-10-01T02:27:33.077 に答える
0

うーん。これを正しく機能させるには、もう少し複雑なものが必要になると思います。あなたは実際に2つの部分からなる質問をしている:ものを追跡する方法と、ものを識別する方法。簡単なことから始めて、追跡します。

免責事項:私のAS3はかなり錆びていますが、実装が少しずれている場合でも、少なくとも理論は正しいはずです。

まず、食品の種類ごとに制限を定義する必要があります。したがって、次のようになります。

var dctLimits = new Object(); // not really a Dictionary, but we'll use it like one
dctLimits[ "grain" ] = 3;
dctLimits[ "meat" ] = 5;
...

次に、カートに追加するオブジェクトの数を保持する必要があります

var dctCount = new Object();
dctCount[ "grain" ] = 0;
dctCount[ "meat" ] = 0;
...

次に、新しいオブジェクトを追加するときは、最初にそのタイプを関連するカウントと照合します。カウンターが制限よりも小さい場合は、カウンターを入れて、カウンターをインクリメントします。

var type:String = getFoodTypeForObject( currMc );
if( dctCount[ type ] < dctLimit[ type ] ){
    items.push( currMc );
    dctCount[ type ]++;
} else {
    // throw error
}

架空の関数getFoodTypeForObject()を作成したことに気付くでしょう。これはトリッキーなビットです:識別。

次のようにサンプルロジックを実装できます。

function getFoodTypeForObject( currMc ){
    if( getQualifiedClassName( currMc ).indexOf( "Grain" ) > -1 ){
    return( "grain" );
    } else if( getQualifiedClassName( currMc ).indexOf( "Meat" ) > -1 ){
    return( "meat" );
    }
    ...
}

classNameContainsTheWordの組み合わせで達成される場合、Juan Pablo Califanoによって提案されているように、共通の基本クラスを使用することをお勧めします。ただし、少し異なるスタイルをお勧めします。getQualifiedClassNameindexOf

public class CartItem extends MovieClip{

    public var isGrain:Boolean;
    public var isMeat:Boolean;

    public function CartItem() {
        super();
    }
}

これをカートアイテムMCの基本クラスとして使用し、ステージ上のMCのインスタンスにこれらのブールプロパティを設定します。次に、次のようなタイプを検出できます。

function getFoodTypeForObject( object ){
    if( object.isGrain ){
        return( "grain" );
    } else if( object.isMeat ){
        return( "meat" );
    }
    ...
}

すべてのクラス名ビジネスよりもクリーンであり、クラス名とは関係なく何かのプロパティを設定できるという追加の利点があります。

完璧ではありません。たとえば、多くのプロパティが必要な場合は、より高度なものが必要になりますが、続行するにはそれで十分です。

于 2010-10-01T02:55:28.513 に答える
0

Uni はしばらく他のことをさせてくれましたが、ようやくゲーム プロジェクトに戻ることができました。

私はそれが働いている。Juan Pablo Califano の方法を使用しました。最初は Henry Cooke を使用しました。これは、各食品 (つまり、apple.as、cereal.as、bread.as、oranges.as) ごとに .AS ファイルを作成する必要があったためです。ヘンリー・クックの方法で私は

`var foodTypeLimit:Object = new Object(); foodTypeLimit["穀物"]=2; foodTypeLimit["フルーツ"]=2;

そして var foodTypeCount:Object = new Object(); などなど `

食品の種類ごとに。次に使用しました:

var type:String = getFoodTypeForObject( currMc ); if( foodTypeCount[ type ] < foodTypeLimit[ type ] ){ items.push( currMc ); foodTypeCount[ type ]++; } else { // throw error }

提案どおり。関数は文字列と viola を返し、正常に機能しました。ただし、私の foodTypeCount 変数 (たとえば、foodTypeCount["grain"]=0; ) は関数内にあったため、これらを呼び出す関数が 0 に設定されるたびに、呼び出しごとにインクリメントが上がらなかったためです。そこで、 var foodTypeCount:Object = new Object();のインスタンス化とともに、これらの foodTypeCount 変数を関数の外に置くことにしました。しかし、いいえ、私は取得し続けました:

Error #1120: Access of undefined property foodTypeObject.

フリーキン宣言直下だったのに。なぜこれがそうなのか理解するには、私はあまりにも初心者だと思います。とにかく、この理由 (この関数に不可欠な増分の欠如) のために、私は弾丸を噛み、Juan Pablo Califano の方法を使用しました。

まず、クラスを次のように書きました。

public class Bread extends MovieClip implements Grain {

public function Bread() {
    super();
}

public function someCommonMethodToAllGrains():void {

}

}

そして、インターフェースを追加しました

`public interface Grain {

    function someCommonMethodToAllGrains():void;
}
`  

そして今、私の関数は次のようになります。

if(currMC is Grain){
    if(grainCount<2){
        addProductToBasket();
        grainCount++;
    } else {
        notAllowed("Grain");
    }
 }

function addProductToBasket(){
    removeChild(currMC);
    basketArray.push(currMC);
    //remove listeners set mc to null etc
 }

function notAllowed(foodType:String){
    error.text="Sorry but you already have 2"+foodType+"products";
 }

これをすべてスイッチに入れてみました。例えば:

switch(currMC){
   case is Grain:
   //do this
   break;
  }

上記の実装は機能しませんでした。おそらく、switch ステートメントはおそらくそのように使用することを意図していません。わかりました。:S

とにかく、本当に素晴らしい回答をありがとう、これは私のお気に入りのサイトで、宇宙とすべての生命への回答を求めています.

于 2010-10-25T13:05:18.553 に答える