Android Studioを使用して開発アプリケーションを作成する

はじめに



こんにちは、紳士さん! 私は11年生の生徒であり、USEの準備をしたくないという理由だけで開発に携わっています。 アプリケーションのアイデアは、見た、思い出した、繰り返した、という3つの言葉で説明できます。 プレーヤーが表示される前に、一定数の網掛け要素を持つ正方形のフィールドが表示されます。 しばらくすると、フィールドはクリアされます。 どの要素を塗りつぶすかを選択する必要があります。 ゲームのレベルを進むにつれて、フィールドが大きくなり、より多くを記憶する必要があります。



理論



最初に、ソフトウェアインターフェイスのアーキテクチャを決定する必要があります。 MVC(モデル-ビュー-コントローラー)が好きです。



画像






このアプローチでは、コントローラーは外部からのイベントをインターセプトし、それに埋め込まれたロジックに従って、適切なメソッドを呼び出してモデルを変更することでこのイベントに応答します。 変更後、モデルは変更されたイベントを使用し、それをサブスクライブし、それを受信したすべてのビューイベントは、更新されたデータをモデルに渡して表示します。 だから、決めた。 次に、プログラミング言語を選択する必要があります。 私はJavaが好きです。 Javaはオブジェクト指向プログラミング言語なので、OOPの原則に従う必要があります。



1)カプセル化は、コードとそれが操作するデータを組み合わせることができるコンポーネントです。

2)ポリモーフィズム-オブジェクトのタイプと内部構造に関する情報がなくても、同じインターフェースを持つオブジェクトを使用できるシステムのプロパティ。

3)継承-部分的または完全に借用した機能を持つ既存のクラスに基づいて、新しいクラスを記述することができるシステムのプロパティ。 継承の派生元のクラスは、基本クラスまたは親クラスと呼ばれます。 新しいクラスは、子孫、子孫、子、または派生クラスです。



次に、サブジェクト領域を次のようなクラスに制限します。



ゲーム(ゲーム)、プレイヤー(プレイヤー)、フィールド(フィールド)。 ゲームは、ゲーム内で直接生成されたデータを管理します。 このフィールドには、どのセルが塗りつぶされているか、塗りつぶされていないかに関する情報が格納されます。 ゲームはフィールドを作成できます。 プレーヤーはユーザーデータを処理できます。 必要に応じてポイントと評価を保存します。



本体



十分な理論。 次の一連のアクションを実行する必要があります。



1) 開発環境JDKをダウンロードします

2)コンピューターに両方のセットをインストールします。

3)開発環境を実行します。



空のプロジェクトを作成して作成を始めましょう。 この方法でパッケージ構造を定義します。









次に、ちょっとしたトリックを行います。 マークアップファイルを作成します。









ルートxmlファイルは、ビューのルートを担当します。 その内部では、すでに作成したフラグメントのレイアウトが動的に変更されます。 したがって、ビューパッケージでは、フラグメントクラスを作成します。









各フラグメントは、1つのゲームモードを担当します。 アプリケーションを開くと、MainActivityクラスのonCreateメソッドが実行されます(これもビューパッケージに含まれています)。 このメソッドを次の状態に変更します。









ここで、アクティビティが初めて作成された場合、フラグメントオブジェクトを作成し、メニューフラグメントを表示する必要があることを確認します。 もちろん、オブジェクトを作成する前に、リンクを与える必要がありますが、これは自分で処理できると思います。



フラグメントは作成されますが、何もしません。 生命を注入する時が来ました。 インターフェイスを作成します。



インターフェース
public interface SendingActivity { // ,     void send(int a); // ,         void send(Field field, int level); // ,     ,    void nextLevel(GameModChallenge game); // ,     ,    void nextLevel(GameModSprint game); // ,     ,    void nextLevel(GameModTwisting game); // ,     ,    void nextLevel(GameModEvidence game); //            ,     void next(GameModChallenge game); // ,    void failSprint(GameModSprint game); // ,    void failTwisting(GameModTwisting game); // ,    void failEvidence(GameModEvidence game); // ,      void releaseToolbar(); }
      
      







このインターフェイスのメソッドを介して、オブジェクトはアクティビティアクションについてレポートし、すでに何をすべきかを決定します。



メインメニューのフラグメントを作成します。



メインメニュー
 public final class MainMenuFragment extends Fragment implements View.OnClickListener { Button sprint, challenge, twisting,evidence, exit; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final View view = inflater.inflate(R.layout.menu, container, false); //region findViewById sprint = (Button) view.findViewById(R.id.sprint); challenge = (Button) view.findViewById(R.id.challenge); twisting = (Button) view.findViewById(R.id.twist); evidence = (Button) view.findViewById(R.id.evidence); exit = (Button) view.findViewById(R.id.exit); //endregion //region setOnClickListener sprint.setOnClickListener(this); challenge.setOnClickListener(this); twisting.setOnClickListener(this); evidence.setOnClickListener(this); exit.setOnClickListener(this); //endregion return view; } @Override public void onClick(View view) { int id = view.getId(); switch (id) { case R.id.sprint: { SendingActivity mess = (SendingActivity) getActivity(); mess.send(0); break; } case R.id.challenge: { SendingActivity mess = (SendingActivity) getActivity(); mess.send(1); break; } case R.id.twist: { SendingActivity mess = (SendingActivity) getActivity(); mess.send(2); break; } case R.id.evidence: { SendingActivity mess = (SendingActivity) getActivity(); mess.send(3); break; } case R.id.exit: { SendingActivity mess = (SendingActivity) getActivity(); mess.send(4); break; } } } }
      
      







次に、見つかったボタンを作成し、それらにイベントリスナーを掛けました。 リスナーは、押されたボタンを選択します。 これに応じて、目的のメッセージがインターフェイスオブジェクトに送信されます。 ただし、アクティビティはまだフラグメントによって送信されたメッセージに応答していません。 後で修正し、ゲームのロジックを記述します。 ロジックはモデルパッケージに含まれています。 そこでヘルパークラスフィールドを作成します。



野原
 public final class Field { private int rightAnswer; private int sizeField; private int paintedSquare; private int square[][]; private Random randX; private Random randY; public int[][] getSquare() { return square; } public Field createSquare(int sizeField, int paintedSquare) { this.sizeField = sizeField; this.paintedSquare = paintedSquare; this.square = new int[sizeField][sizeField]; randX = new Random(System.nanoTime()); randY = new Random(System.nanoTime()); for (int i = 0; i < sizeField; i++) { for (int j = 0; j < sizeField; j++) { if (paintedSquare > 0) { paintedSquare--; this.square[i][j] = 1; } else { this.square[i][j] = 0; } } } for (int i = 0; i < sizeField; i++) { for (int j = 0; j < sizeField; j++) { mixing(square); } } return this; } //region mixing private void mixing(int[][] arr) { //,   for (int i = 0; i < arr.length; i++) { for (int j = 0; j < arr.length; j++) { swap(arr, i, j, randX.nextInt(sizeField), randY.nextInt(sizeField)); } } } private void swap(int[][] arr, int i, int j, int newI, int newJ) { int tmp = arr[i][j]; arr[i][j] = arr[newI][newJ]; arr[newI][newJ] = tmp; } //endregion public int getSizeField() { return sizeField; } public int getRightAnswer() { return rightAnswer; } public void setRightAnswer(int rightAnswer) { this.rightAnswer = rightAnswer; } public int getPaintedSquare() { return paintedSquare; } }
      
      







ご覧のとおり、正解の配列を処理するにはこのクラスが必要です。 配列要素に1が含まれている場合、セルは塗りつぶされます。 フィールドは自分自身を作成する方法を知っています。 作成後、すぐに自分自身をミックスします。 次に、ゲームモード用の基本クラスGameを作成します。



ゲーム
 public abstract class Game { private Field field; private int currentLevel; private Activity a; Game(Activity a) { this.a = a; } Activity getActivity() { return a; } public int getCurrentLevel() { return currentLevel; } public void setCurrentLevel(int currentLevel) { this.currentLevel = currentLevel; } public void setField(Field field) { this.field = field; } public Field getField() { return field; } public Field createFieldInLevel(int level) { switch (level) { case 1: { field = new Field().createSquare(3, 2); break; } case 2: { field = new Field().createSquare(3, 3); break; } case 3: { field = new Field().createSquare(4, 4); break; } case 4: { field = new Field().createSquare(4, 6); break; } case 5: { field = new Field().createSquare(4, 8); break; } case 6: { field = new Field().createSquare(5, 10); break; } case 7: { field = new Field().createSquare(5, 12); break; } case 8: { field = new Field().createSquare(6, 14); break; } case 9: { field = new Field().createSquare(6, 16); break; } case 10: { field = new Field().createSquare(7, 18); break; } case 11: { field = new Field().createSquare(7, 20); break; } case 12: { field = new Field().createSquare(7, 22); break; } case 13: { field = new Field().createSquare(7, 24); break; } case 14: { field = new Field().createSquare(8, 26); break; } case 15: { field = new Field().createSquare(8, 28); break; } case 16: { field = new Field().createSquare(8, 30); break; } case 17: { field = new Field().createSquare(8, 32); break; } case 18: { field = new Field().createSquare(9, 34); break; } case 19: { field = new Field().createSquare(9, 36); break; } case 20: { field = new Field().createSquare(9, 40); break; } case 21: { field = new Field().createSquare(10, 42); break; } case 22: { field = new Field().createSquare(10, 44); break; } case 23: { field = new Field().createSquare(10, 46); break; } case 24: { field = new Field().createSquare(10, 48); break; } case 25: { field = new Field().createSquare(10, 50); break; } } return field; } public abstract void createVictoryDialog(LayoutInflater inflater); public abstract void createLooseDialog(LayoutInflater inflater); public abstract void showDialog(); }
      
      







このクラスは、ゲームモードの基本機能を定義します。 彼はフィールドの作成方法、ゲームの現在のレベルの設定方法、ダイアログボックスの作成方法(このためアクティビティへのリンクが必要)、およびそれらを表示する方法を知っています。 このクラスのオブジェクトを作成することはできないため、クラスの相続人を作成します。 たとえば、GameModSprintクラスは次のとおりです。



Gamemodsprint
 private AlertDialog.Builder builder; private AlertDialog alert; public GameModSprint(Activity a) { super(a); } @Override public void createVictoryDialog(LayoutInflater inflater) { builder = new AlertDialog.Builder(getActivity()); builder.setCancelable(false); View dialogV = inflater.inflate(R.layout.dialog_view, null, false); View dialogTitle = inflater.inflate(R.layout.dialog_title, null, false); TextView title = (TextView) dialogTitle.findViewById(R.id.dialog_title); TextView message = (TextView) dialogTitle.findViewById(R.id.message); message.setText(getActivity().getResources().getString(R.string.progress)+ getCurrentLevel()); title.setText(getActivity().getResources().getString(R.string.good)); title.setText(getActivity().getResources().getString(R.string.good)); ImageView imageView = (ImageView) dialogV.findViewById(R.id.image); imageView.setImageResource(R.drawable.victory); ImageButton next = (ImageButton) dialogV.findViewById(R.id.next); ImageButton restart = (ImageButton) dialogV.findViewById(R.id.restart); View.OnClickListener listener = new View.OnClickListener() { @Override public void onClick(View view) { switch (view.getId()) { case R.id.next: { SendingActivity send = (SendingActivity) getActivity(); send.nextLevel(self()); alert.dismiss(); break; } case R.id.restart: { SendingActivity send = (SendingActivity) getActivity(); send.failSprint(self()); alert.dismiss(); break; } case R.id.in_menu: { alert.dismiss(); getActivity().onBackPressed(); break; } } } }; next.setOnClickListener(listener); restart.setOnClickListener(listener); ImageButton inMenu = (ImageButton) dialogV.findViewById(R.id.in_menu); inMenu.setOnClickListener(listener); builder.setView(dialogV); builder.setCustomTitle(dialogTitle); } @Override public void createLooseDialog(LayoutInflater inflater) { builder = new AlertDialog.Builder(getActivity()); builder.setCancelable(false); View dialogV = inflater.inflate(R.layout.dialog_view, null, false); View dialogTitle = inflater.inflate(R.layout.dialog_title, null, false); TextView title = (TextView) dialogTitle.findViewById(R.id.dialog_title); TextView message = (TextView) dialogTitle.findViewById(R.id.message); message.setText(getActivity().getResources().getString(R.string.not_progress)+ getCurrentLevel()); title.setText(getActivity().getResources().getString(R.string.bad)); ImageView imageView = (ImageView) dialogV.findViewById(R.id.image); imageView.setImageResource(R.drawable.loose); ImageButton next = (ImageButton) dialogV.findViewById(R.id.next); ImageButton restart = (ImageButton) dialogV.findViewById(R.id.restart); next.setBackgroundColor(getActivity().getResources().getColor(R.color.background_no_access)); View.OnClickListener listener = new View.OnClickListener() { @Override public void onClick(View view) { switch (view.getId()) { case R.id.restart: { SendingActivity send = (SendingActivity) getActivity(); send.failSprint(self()); alert.dismiss(); break; } case R.id.in_menu: { alert.dismiss(); getActivity().onBackPressed(); break; } } } }; next.setOnClickListener(listener); restart.setOnClickListener(listener); ImageButton inMenu = (ImageButton) dialogV.findViewById(R.id.in_menu); inMenu.setOnClickListener(listener); builder.setView(dialogV); builder.setCustomTitle(dialogTitle); } @Override public void showDialog() { alert = builder.create(); alert.show(); } private GameModSprint self() { return this; } }
      
      







このクラスは、ダイアログボックスの表示方法を決定します。 事実、プレイヤーを次のレベルに移すだけでよいとは限りません。 たとえば、他のゲームモードでは、このゲームモードでのみ実行する必要があるユーザーデータを使用して、プレーヤーやその他の操作を評価したいです。 残りのクラスは同じ方法で作成されます。



最後に、インターフェイスを実装できます。



インターフェイス実装
<img src = " 「alt = "画像" />

 @Override public void send(int a) { switch (a) { case 0: { sprintFragment = new SprintFragment(); game = new GameModSprint(this); game.createFieldInLevel(1); game.setCurrentLevel(1); sprintFragment.setGame(game); getFragmentManager().beginTransaction().replace(R.id.activity_main, sprintFragment).addToBackStack(null).commit(); break; } case 1: { getFragmentManager().beginTransaction().replace(R.id.activity_main, levelChallengeFragment).addToBackStack(null).commit(); break; } case 2: { twistingFragment = new TwistingFragment(); game = new GameModTwisting(this); game.createFieldInLevel(1); game.setCurrentLevel(1); twistingFragment.setGame(game); getFragmentManager().beginTransaction().replace(R.id.activity_main, twistingFragment).addToBackStack(null).commit(); break; } case 3: { evidenceFragment = new EvidenceFragment(); game = new GameModEvidence(this); game.createFieldInLevel(1); game.setCurrentLevel(1); evidenceFragment.setGame(game); getFragmentManager().beginTransaction().replace(R.id.activity_main, evidenceFragment).addToBackStack(null).commit(); break; } case 4: { finish(); break; } } } @Override public void send(Field field, int level) { challengeFragment = new ChallengeFragment(); game = new GameModChallenge(this); game.setField(field); game.setCurrentLevel(level); challengeFragment.setGame(game); getFragmentManager().beginTransaction().replace(R.id.activity_main, challengeFragment).commit(); } @Override public void nextLevel(GameModChallenge game) { challengeFragment = new ChallengeFragment(); game.setCurrentLevel(game.getCurrentLevel() + 1); game.createFieldInLevel(game.getCurrentLevel()); textPoint.setText(String.valueOf(point)); textRating.setText(String.valueOf(rating)); challengeFragment.setGame(game); getFragmentManager().beginTransaction().replace(R.id.activity_main, challengeFragment).commit(); } @Override public void nextLevel(GameModSprint game) { sprintFragment = new SprintFragment(); textPoint.setText(String.valueOf(point)); game.setCurrentLevel(game.getCurrentLevel() + 1); game.createFieldInLevel(game.getCurrentLevel()); sprintFragment.setGame(game); getFragmentManager().beginTransaction().replace(R.id.activity_main, sprintFragment).commit(); } @Override public void nextLevel(GameModTwisting game) { twistingFragment = new TwistingFragment(); textPoint.setText(String.valueOf(point)); game.setCurrentLevel(game.getCurrentLevel() + 1); game.createFieldInLevel(game.getCurrentLevel()); twistingFragment.setGame(game); getFragmentManager().beginTransaction().replace(R.id.activity_main, twistingFragment).commit(); } @Override public void nextLevel(GameModEvidence game) { evidenceFragment = new EvidenceFragment(); textPoint.setText(String.valueOf(point)); game.setCurrentLevel(game.getCurrentLevel() + 1); game.createFieldInLevel(game.getCurrentLevel()); evidenceFragment.setGame(game); getFragmentManager().beginTransaction().replace(R.id.activity_main, evidenceFragment).commit(); } @Override public void next(GameModChallenge game) { //,     textPoint.setText(String.valueOf(point)); challengeFragment = new ChallengeFragment(); game.createFieldInLevel(game.getCurrentLevel()); challengeFragment.setGame(game); getFragmentManager().beginTransaction().replace(R.id.activity_main, challengeFragment).commit(); } @Override public void failSprint(GameModSprint game) { sprintFragment = new SprintFragment(); game = new GameModSprint(this); game.createFieldInLevel(1); game.setCurrentLevel(1); sprintFragment.setGame(game); getFragmentManager().beginTransaction().replace(R.id.activity_main, sprintFragment).commit(); } @Override public void failTwisting(GameModTwisting game) { twistingFragment = new TwistingFragment(); game = new GameModTwisting(this); game.createFieldInLevel(1); game.setCurrentLevel(1); twistingFragment.setGame(game); getFragmentManager().beginTransaction().replace(R.id.activity_main, twistingFragment).commit(); } @Override public void failEvidence(GameModEvidence game) { evidenceFragment = new EvidenceFragment(); game = new GameModEvidence(this); game.createFieldInLevel(1); game.setCurrentLevel(1); evidenceFragment.setGame(game); getFragmentManager().beginTransaction().replace(R.id.activity_main, evidenceFragment).commit(); }
      
      







これで、ゲームレベルのフラグメントには、作成する必要があるすべてのものが含まれます。 彼は、現在の分野について必要なすべてを知っています。 データをユーザーインターフェイスに接続するだけです。



ゲームコード
 public final class SprintFragment extends Fragment implements View.OnClickListener { private Game game; private Field field; private int fieldSize; private Button sq[][]; private LayoutInflater inflater; private Runnable runner; private View root; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { root = inflater.inflate(R.layout.game, container, false); TextView title = (TextView) root.findViewById(R.id.game_challenge_title); title.setText(String.valueOf(getActivity().getResources().getString(R.string.current_level) + game.getCurrentLevel())); this.inflater = inflater; final View.OnClickListener listener = this; int doNotDuplicateId = 0; final TableLayout fieldView = (TableLayout) root.findViewById(R.id.field); ProgressBar progressBar = (ProgressBar) root.findViewById(R.id.progress_bar); progressBar.setVisibility(View.INVISIBLE); fieldSize = field.getSizeField(); sq = new Button[fieldSize][fieldSize]; fieldView.setWeightSum(fieldSize); TableRow tableRows[] = new TableRow[fieldSize]; TableRow.LayoutParams paramsRow = new TableRow.LayoutParams(); paramsRow.height = TableRow.LayoutParams.MATCH_PARENT; paramsRow.width = TableRow.LayoutParams.WRAP_CONTENT; paramsRow.weight = 1; for (int i = 0; i < fieldSize; i++) { tableRows[i] = new TableRow(getActivity().getApplicationContext()); tableRows[i].setLayoutParams(paramsRow); for (int j = 0; j < fieldSize; j++) { sq[i][j] = (Button) inflater.inflate(R.layout.one_field_button, null, false); sq[i][j].setId(doNotDuplicateId); sq[i][j].setWidth(getActivity().getWindow().getWindowManager().getDefaultDisplay().getWidth() / fieldSize - getActivity().getWindow().getWindowManager().getDefaultDisplay().getWidth() / (fieldSize * fieldSize)); sq[i][j].setHeight(getActivity().getWindow().getWindowManager().getDefaultDisplay().getWidth() / fieldSize - getActivity().getWindow().getWindowManager().getDefaultDisplay().getWidth() / (fieldSize * fieldSize)); doNotDuplicateId++; if (field.getSquare()[i][j] == 1) { sq[i][j].setBackgroundDrawable(getActivity().getApplicationContext().getResources().getDrawable(R.drawable.sq_painted)); } tableRows[i].addView(sq[i][j], j); tableRows[i].setWeightSum(fieldSize); } fieldView.addView(tableRows[i], i); } root.postDelayed(runner = new Runnable() { @Override public void run() { for (int i = 0; i < fieldSize; i++) { for (int j = 0; j < fieldSize; j++) { sq[i][j].setOnClickListener(listener); if (field.getSquare()[i][j] == 1) { sq[i][j].setBackgroundDrawable(getActivity().getApplicationContext().getResources().getDrawable(R.drawable.sq)); } } } } }, 2000L); return root; } public void setGame(Game game) { this.game = game; this.field = game.getField(); } @Override public void onClick(View view) { int id = view.getId(); for (int i = 0; i < fieldSize; i++) { for (int j = 0; j < fieldSize; j++) { if (id == sq[i][j].getId()) { System.out.println(sq[i][j].getId()); if (field.getSquare()[i][j] == 1) { field.setRightAnswer(field.getRightAnswer() + 1); view.setOnClickListener(null); view.setBackgroundDrawable(getActivity().getApplicationContext().getResources().getDrawable(R.drawable.sq_painted)); if (field.getRightAnswer() == field.getPaintedSquare()) { game.createVictoryDialog(inflater); game.showDialog(); } } else if (field.getSquare()[i][j] == 0) { view.setBackgroundDrawable(getActivity().getApplicationContext().getResources().getDrawable(R.drawable.sq_wrong)); game.createLooseDialog(inflater); game.showDialog(); } } } } } @Override public void onStop() { super.onStop(); root.removeCallbacks(runner); } }
      
      







この方法に注意してください:



  public void setGame(Game game) { this.game = game; this.field = game.getField(); }
      
      





それを使用して、アクティビティはゲームオブジェクトへのリンクをフラグメントに転送します。 また、長いドット表記を使用しないために、フィールド用に別のリンクを作成します。



コード全体は非常に単純です。 ボタンの配列が作成され、入力されます。 ボタンの2次元配列のインデックスは、Fieldクラスのオブジェクトの2次元配列のインデックスと一致することがわかります。



したがって、押されたボタンを判別するとき、Fildクラスオブジェクトの配列にある数字を確認する必要があります。 0の場合、ユーザーが誤った入力を行ったため、次を呼び出してゲームを終了する必要があります。



 game.createLooseDialog(inflater); game.showDialog();
      
      





これにより、アクションを選択して目的のダイアログボックスを作成して開きます。



プレーヤーが1に等しいすべての要素を選択した場合、勝利ダイアログボックスが作成されます。 Gameタイプのリンクがあるにもかかわらず、GameModSprintタイプのアクティビティによってオブジェクトが作成されました。つまり、このメソッドの対応するオーバーライドバージョンが呼び出されます。



勝利
 if (field.getRightAnswer() == field.getPaintedSquare()) { game.createVictoryDialog(inflater); game.showDialog(); }
      
      







したがって、Java言語の最も強力なツールであるメソッドの動的ディスパッチを使用します。



おわりに



そこで、私たちはモバイルアプリケーションの開発に出会いました。

スプリントゲームモード
レベル選択:



そしてゲーム自体:





Google Playからゲームをダウンロードするためのリンク

play.google.com/store/apps/details?id=com.thekingames.memorize

皆さんに幸運を!



All Articles