質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

91.35%

  • Java

    10450questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • Android

    5158questions

    Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

  • Android Studio

    2711questions

    Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

ゲーム的なアプリ スタートボタンについて

解決済

回答 2

投稿 2017/11/20 16:32 ・編集 2017/11/25 17:15

  • 評価
  • クリップ 0
  • VIEW 150

S.I

score 23

画面右側は問題、操作画面(上下左右)、左側でねこが動きます。現段階では、操作ボタン(button1…うえ、button2…した、button3…ひだり、button4…みぎ)を押したら猫が一マスずつ移動します。また、障害物である犬の位置に到達すると初期位置に戻るためのダイアログが発生し、家に到達すると「せいかい!」のダイアログが発生します。さらに、ボタンを押した際、プログラムの流れの欄に矢印マーク(↑↓→←)が順番に表示されます。
ここでは、猫の位置を管理するために変数xと変数yを使用しています。

実現したいことは、猫をうえ、した、ひだり、みぎのボタンを押した際に動かすのではなく、「スタートボタン」を押した際に、「プログラムの流れ」欄に表示された通りに猫を動かし、ダイアログを発生させることです。
データベースを用いる必要はあるのか…

public class MainActivity extends AppCompatActivity implements Animator.AnimatorListener {
    final static float TRANSLATE_X = 310.0f;    // 1回の操作でX軸方向にいくつ動かすか
    final static float TRANSLATE_Y = 310.0f;    // 1回の操作でY軸方向にいくつ動かすか

    // 盤面上の開始座標を初期値として設定する
    private int x = 0;
    private int y = 0;
    private String text;
    private ArrayList<Integer> arrayList ;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button btn1 = (Button) findViewById(R.id.button1);  // うえ
        Button btn2 = (Button) findViewById(R.id.button2);  // した
        Button btn3 = (Button) findViewById(R.id.button3);  // ひだり
        Button btn4 = (Button) findViewById(R.id.button4);  // みぎ
        Button btn5 = (Button) findViewById(R.id.button5);  // やりなおし
        Button btn6 = (Button) findViewById(R.id.button6);  // スタート

        text = "";
        final TextView result = (TextView) findViewById(R.id.result);
        result.setText("");

        arrayList = new ArrayList<>();


        btn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                arrayList.add(upAnimation();
                // 「うえ」を押したときの処理
                if (y > -3) {
                    TextView result = (TextView) findViewById(R.id.result);
                    text += "<font color=#98fb98>↑</font>";
                    result.setText(Html.fromHtml(text));
                }
            }
        });
        btn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                arrayList.add(downAnimation();
                // 「した」を押したときの処理
                if (y < 0) {
                    TextView result = (TextView) findViewById(R.id.result);
                    text += "<font color=#fffacd>↓</font>";
                    result.setText(Html.fromHtml(text));
                }
            }
        });
        btn3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                arrayList.add(leftAnimation();
                // 「ひだり」を押したときの処理
                if (x > 0) {
                    TextView result = (TextView) findViewById(R.id.result);
                    text += "<font color=#ffc0cb>←</font>";
                    result.setText(Html.fromHtml(text));
                }
            }
        });
        btn4.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                arrayList.add(rightAnimation();
                // 「みぎ」を押したときの処理
                if (x < 2) {
                    TextView result = (TextView) findViewById(R.id.result);
                    text += "<font color=#afeeee>→</font>";
                    result.setText(Html.fromHtml(text));
                }
            }
        });
        btn5.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                text = "";
                TextView result = (TextView) findViewById(R.id.result);
                result.setText("");
            }
        });
        btn6.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                for(int i=0; i< arrayList.size(); i++){
                }
        }
        });
    }

    private void animationImageView(String property, float start, float end) {
        ImageView imageView = (ImageView) findViewById(MyCat);
        ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, property, start, end);
        animator.setDuration(1000);
        animator.addListener(this);
        animator.start();
    }

    private void animationImageReset() {
        final ImageView MyCat = (ImageView) findViewById(R.id.MyCat);
        ObjectAnimator.ofFloat(MyCat, "translationX", 0.0f, 0.0f).start();
        ObjectAnimator.ofFloat(MyCat, "translationY", 0.0f, 0.0f).start();
    }

    private void encountDog() {
        if (x == 1 && y == -2) {
            AlertDialog.Builder dl = new AlertDialog.Builder(MainActivity.this);
            dl.setTitle("ざんねん!!");
            dl.setMessage("いぬはしょうがいぶつだよ");
            dl.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    x = 0;
                    y = 0;
                    animationImageReset();

                    text = "";
                    TextView result = (TextView) findViewById(R.id.result);
                    result.setText("");
                }
            });
            dl.show();
        }
        if (x == 2 && y == -3) {
            AlertDialog.Builder dl = new AlertDialog.Builder(MainActivity.this);
            dl.setTitle("せいかい!!");
            dl.setPositiveButton("こたえ", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    AlertDialog.Builder dl = new AlertDialog.Builder(MainActivity.this);
                    dl.setTitle("こたえ");
                    dl.setMessage("①→→↑↑↑②↑↑↑→→③→↑→↑↑など");
                    dl.setPositiveButton("つぎのもんだいへすすむ", null);
                    dl.show();
                }
            });
            dl.setNegativeButton("つぎのもんだいへすすむ", null); //ボタン
            dl.show();
        }
    }
    @Override
    public void onAnimationStart(Animator animation) {
    }

    @Override
    public void onAnimationEnd(Animator animation) {
        // アニメーションが終了するとここが実行される
    }

    @Override
    public void onAnimationCancel(Animator animation) {
    }

    @Override
    public void onAnimationRepeat(Animator animation) {
    }

    private void upAnimation(){
        // 「うえ」を押したときの処理
        if (y > -3) {
            float start = TRANSLATE_Y * y;
            float end = start - TRANSLATE_Y;
            animationImageView("translationY", start, end);
            y--;
            encountDog();
        }
    }
    private void downAnimation(){
        // 「した」を押したときの処理
        if (y < 0) {
            float start = TRANSLATE_Y * y;
            float end = start + TRANSLATE_Y;
            animationImageView("translationY", start, end);
            y++;
            encountDog();
        }
    }
    private void leftAnimation(){
        // 「ひだり」を押したときの処理
        if (x > 0) {
            float start = TRANSLATE_X * x;
            float end = start - TRANSLATE_X;
            animationImageView("translationX", start, end);
            x--;
            encountDog();
        }
    }
    private void rightAnimation(){
        // 「みぎ」を押したときの処理
        if (x < 2) {
            float start = TRANSLATE_X * x;
            float end = start + TRANSLATE_X;
            animationImageView("translationX", start, end);
            x++;
            encountDog();
        }
    }
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • keicha_hrs

    2017/11/20 17:23

    「プログラムの流れの順番通り」というのは、うえ、したなどのボタンで操作して、「プログラムのながれ」欄に記録された操作履歴の通りに動かしたい、という解釈でいいのでしょうか?

    キャンセル

  • S.I

    2017/11/20 17:36

    そうです。

    キャンセル

  • S.I

    2017/11/20 17:44

    わかりにくくてすみません、修正します!

    キャンセル

  • keicha_hrs

    2017/11/20 18:01

    いや、そうとしか受け取れないよな−と思いつつ念の為だったので・・・

    キャンセル

回答 2

+2

私は趣味でC++やっています。

ボタン押すたびに移動...じゃなくて 一括で移動 ( 上上下右... とユーザ側が動かしたい向き? をいくつも入れて、"OK" を押すと そのリスト通りに動く... っていう ) したいっていうことですよね。

それなら、

私なら、Javaなら ArrayListに データを突っ込んでその通りに動かします。

まず、例えば

UML風に書くと

+ moveButtonClicked(...) // "OK"ボタンが押されたとき
+ addDataToArray(...) // 上, 下, ...とかのボタンが押された

  • list : ArrayList<int>

があるとしたら、

addDataToArray:
      上を指定したら list1, 下なら 2, 右なら 3, ...という風に追加していく
      これだけだとわかりにくいので、GUI側にも "上", "下"... を記述する

moveButtonClicked:
      for( Object l : list ){
            // キャラの移動
      }

みたいにする。

そうすれば一度に処理できる。

別に 上: 1, 下: 2 ...みたいにする必要はないですが、思いついたので。

で、moveButtonClickedメソッドの for( Object l... ) は 名称は忘れましたが、

C++だと

for( auto a : 配列 ){

}

みたいに、配列やリストの長さ分行うやつ。

JavaはすべてのクラスはObjectを継承しているようなので、

Objectとして受け取っています。

C++でいうautoはJavaではどうやるか

投稿 2017/11/20 17:33

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/11/20 17:42

    ありがとうございます。ArrayListで試してみようと思います。

    キャンセル

checkベストアンサー

+1

これは意外と厄介ですね。

操作の履歴を記録するのは、先に出ている答えの通りArrayListを用いればいいでしょうが、再現を行う処理はいろいろ考える必要がありそうです。当然、アニメーションしながら再現を行うことを考えておられると思いますが、ArrayListから取り出した端から処理をボンボン行うのではなく、1つのアニメーションが終わるのを待ってから次のアニメーションを実行しないと、思ったように再現されないでしょう。そこをうまく考える必要があります。

「1つのアニメーションが終わるのを待つ」というところが、「意外と厄介」になる部分です。Javaには時間稼ぎをするためのメソッドも存在しますが、単純にそれを「待つ」部分に突っ込んでしまうと、アプリが強制終了してしまうことでしょう。onCreateやonClickなどAndroidのイベントによって実行されるメソッドは、迅速に処理を終えて抜けるのが大原則です。それらの中で時間がかかる処理を行うと、強制終了されてしまいます。

それを避けるためには、Handlerを用いたり、ThreadやAsyncTaskのような別スレッドとして動作するオブジェクトを作成して、非同期処理として実装したりといったことが必要になります。まずはその辺りのキーワードを検索して、下調べしてみてはどうでしょうか。


非同期処理は必要なさそうですね。

アニメーション処理には、「アニメーションが始まった」「アニメーションが終わった」のようなイベントを取得するためのAnimator.AnimatorListenerというインターフェイスがあります。それを下のようにして実装します。

// 末尾にimplements Animator.AnimatorListenerを加える
public class MainActivity extends AppCompatActivity implements Animator.AnimatorListener {

    // 中略

    private void animationImageView(String property, float start, float end) {
        ImageView imageView = (ImageView) findViewById(MyCat);
        ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, property, start, end);
        animator.setDuration(1000);
        animator.addListener(this); // この行を加える
        animator.start();
    }

    // 中略

    // 下記の4つのメソッドを加える
    // 実装必須なのですることがなくても空のメソッドを記述する必要あり
    @Override
    public void onAnimationStart(Animator animation) {
    }

    @Override
    public void onAnimationEnd(Animator animation) {
        // アニメーションが終了するとここが実行される
    }

    @Override
    public void onAnimationCancel(Animator animation) {
    }

    @Override
    public void onAnimationRepeat(Animator animation) {
    }
}
  • 履歴を記録するためのArrayList
  • 再生処理中であることを示すフラグ
  • 何手目まで再生したか数えるカウンター

をフィールド変数として用意しておけばいいでしょう。

「スタート」ボタンを押したら

  1. ArrayListが空っぽでなければ
  2. フラグを有効にして
  3. ArrayListから1手目を取り出してアニメーション開始

というところまでをonClickに記述します。

onAnimationEndには、

  1. フラグが有効だったら
  2. ArrayListに格納されている数がカウンターの値未満だったら
  3. カウンターを1増やして
  4. ArrayListからカウンターの値に従った手を取り出してアニメーション開始

という処理を実装すればいいんじゃないですかね。そうすれば、アニメーションが終わる度にonAnimationEndが呼び出され、カウンターの値がArrayListの格納数に満ちるまで繰り返してくれます。

そんな感じでいけるんじゃないかな?


(2017/11/24 15:25追記)
このような感じにしたらというサンプルです。

public class MainActivity extends AppCompatActivity implements Animator.AnimatorListener {

    // 中略

    private ArrayList<Integer> mHistory; // 履歴を格納するリスト
    private boolean mReplayFlag;         // 再生中であることを示すフラグ
    private int mReplayCount;            // 再生経過のカウンター

    // 中略

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 初期値をセット
        mHistory = new ArrayList<>();
        mReplayFlag = false;
        mReplayCount = 0;

        // 中略

        btn6.setOnClickListener(new View.OnClickListener() {
            // スタートボタンを押したときの処理
       @Override
            public void onClick(View v) {
                // isEmpty()でリストが空っぽではない(1手以上の記録がある)か調べる
                if (!mHistory.isEmpty()) {
                    // 猫を最初の位置に戻す
                    x = 0;
                    y = 0;
                    animationImageReset();

                    mReplayFlag = true;  // 再生中にする
                    animationReplay();     // 再生する(ここでは1手目だけ、以後はonAnimationEndに任せる)
                }
            }
        });

     // 中略
    }

    private void animationReplay() {
        if (mReplayFlag) {
            int dir = mHistory.get(mReplayCount); // リストから取り出し

            switch (dir) {
                case 0:  // 0は上を意味する
                    upAnimation();
                    break;
                case 1:  // 1は下を意味する
                    downAnimation();
                    break;
                case 2:  // 2は左を意味する
                    leftAnimation();
                    break;
                case 3:  // 3は右を意味する
                    rightAnimation();
                    break;
            }

            mReplayCount++;  // カウンターを増やす

            // 再生終了したらフラグをクリアする
            if (mReplayCount == mHistory.size()) {
                mReplayFlag = false;
                mReplayCount = 0;
            }
        }
    }

   // 中略

    // アニメーションが終了したらこのメソッドが実行される
    @Override
    public void onAnimationEnd(Animator animation) {
        if (mReplayFlag) {
            animationReplay();    // 再生する
        }
    }

投稿 2017/11/20 19:03

編集 2017/11/24 16:08

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/11/20 19:30

    仰る通り、アニメーションで考えています。そのままArrayListを用いたとしても、データが重くてアプリが終了するため別スレッドにて実装する必要があるということですね!(違ったらすみません…)
    コメントいただいたキーワードをもとに調べてみます!

    キャンセル

  • 2017/11/21 19:52

    HandlerやThreadやAsyncTaskなどいずれを使うにしても、操作の履歴を記録するためのArrayListは使用するのでしょうか。

    キャンセル

  • 2017/11/21 22:48

    あー。非同期処理なんか使わなくてもできそうだなあ。ちょっと待ってください、よく考えて例を示すつもりなので・・・。

    記録のためにArrayListを使うというのは変わりないです。

    キャンセル

  • 2017/11/22 01:24

    こう作ってみたらというプランを回答に追記しました。非同期処理は使わなくても実現できますね。混乱させて申し訳ないです。

    キャンセル

  • 2017/11/22 20:41

    コードを変更したのですが、btn1~4のonClick内arrayList.add(upAnimation();部分の「;」に赤線のエラーが発生してしまいました、なにかが足りないのでしょうか…。また、再生処理中であることを示すフラグと何手目まで再生したか数えるカウンターがよくわからないのですが、もう少し詳しく教えていただくことは可能でしょうか…すみません…

    キャンセル

  • 2017/11/23 01:28

    どこから手をつければいいんだろ。参ったな^^;

    ArrayListはこの課題をちょっと離れて、普通のJava学習サイトの課題を勉強した方がいいような気はします。例えばこんなところとか。
    https://www.javadrive.jp/start/arraylist/index1.html

    なんか「メソッドを突っ込もう」としているように感じるのですが、それは無茶ですね。

    private ArrayList<Integer> arrayList ;

    のように宣言されていますが、これも何となくだったのかな?ただ、これで「Integer型の値を格納するArrayList」という宣言になっていますので、この宣言で活用できますよね。例えば0~3の数値にそれぞれ上、下、左、右という意味を持たせることにすれば、例えば上ボタンの処理では

    btn1.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    // 「うえ」を押したときの処理
    if (y > -3) {
    upAnimation();
    TextView result = (TextView) findViewById(R.id.result);
    text += "<font color=#98fb98>↑</font>";
    result.setText(Html.fromHtml(text));
    arrayList.add(0); // 0は上を意味する
    }
    }
    });

    のようにすればいいんじゃないですか。

    残りはちょっと明日にさせてください・・・。

    キャンセル

  • 2017/11/24 13:53

    ご回答ありがとうございます。

    private ArrayList<Integer> arrayList ;

    という宣言は、他サイトを参考にしました。勉強不足なので、Java学習も並行していきます…

    arrayList.add(0);
    という部分に「上」という意味を持たせるためにはどうするのでしょうか…

    キャンセル

  • 2017/11/24 16:08 編集

    遅くなりましたが、このような感じにしたらどうかというサンプルを回答欄に追加しました。ArrayListに追加した数値に意味を持たせるのは、自分のプログラムで行う「仕事」です。それを行っているのがanimationReplayというメソッドですが、0なら上の処理、1なら下の処理というように、取り出した値によって処理を振り分けます。「値に意味を持たせる」というのが誤解を招いたかな?意味は「自分で作る」のです。

    キャンセル

  • 2017/11/25 11:30

    わかりました。ありがとうございます!

    キャンセル

  • 2017/11/25 17:14

    実機で再生できました!説明が本当にわかりやすくて助かります…本当にありがとうございます(T_T);

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

ただいまの回答率

91.35%

関連した質問

同じタグがついた質問を見る

  • Java

    10450questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • Android

    5158questions

    Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

  • Android Studio

    2711questions

    Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。