最初のAndroidアプリケーションを作成しています

いずれにせよ、最も難しい部分は始まりです。 多くの場合、コンテキストに入るのが難しいため、最初にAndroidアプリケーションを開発することにしました。 この記事は、開始したいが、どこからわからない人向けです。



この記事では、アプリケーション開発サイクル全体について説明します。 一緒に、1つの画面(Android OSではアクティビティと呼ばれます)を持つ単純なゲーム「Tic Tac Toe」を作成します。



Java開発経験の不足は、Androidの学習を妨げるものではありません。 そのため、例ではJava固有の構造を使用しません(または、可能な限り最小化します)。 たとえば、PHPで作成し、ソフトウェア開発の基本原則に精通している場合は、この記事が最も役立ちます。 同様に、私はJava開発の専門家ではないため、ソースコードが「Java開発のベストプラクティス」というラベルのふりをしていないと想定できます。







必要なプログラムとユーティリティのインストール





必要なツールをリストします。 それらの3つがあります。

  1. JDK-Java言語での開発用セット
  2. Android SDKおよびAVD Manager-開発+エミュレーター用のユーティリティセット
  3. Androidの開発サポートを備えたIDE:

    • Eclipse + ADTプラグイン。
    • IntelliJ IDEA Community Edition;
    • Netbeans + nbandroidプラグイン;






ユーティリティは上記の順序でインストールされます。 リストされているすべてのIDEを配置しても意味がありません(適切なIDEを選択するのが難しい場合を除く)。 現在、Java用の最も開発されたIDEの1つであるIntelliJ IDEA Community Editionを使用しています。



仮想デバイスの開始



AVD Managerを起動し、追加のパッケージ(さまざまなバージョンのSDK)をインストールすることにより、必要なパラメーターを使用して仮想デバイスの作成を開始できます。 インターフェイスを理解することは難しくありません。







デバイスリスト









プロジェクト作成



IDEでのプロジェクトの作成を含む準備作業を最小限に抑え、特にプロジェクトが教育的であり、実動プロジェクトのふりをしていない場合、仕事に取り掛かりたいと常に思っています。



ファイル->新しいプロジェクト:



































F6ボタンを押すと、プロジェクトがアセンブルされ、コンパイルされ、仮想デバイスで起動されます。



プロジェクト構造



前のスクリーンショットでは、プロジェクト構造が表示されています。 この記事では純粋に実用的な目標を追求しているため、プロセスで使用するフォルダーのみに焦点を当てます。 これらは、 genres 、およびsrcのディレクトリです。



genフォルダーには、プロジェクトのビルド時に自動的に生成されるファイルが含まれています。 手動で変更することはできません。



resフォルダーは、写真、テキスト(翻訳を含む)、デフォルト値、レイアウトなどのリソースを保存するためのものです。



srcは、プログラムのソースコードを含むファイルがここに格納されているため、作業の大部分が行われるフォルダーです。



最初の行





アクティビティ(アプリケーション画面)が作成されるとすぐに、onCreate()メソッドが呼び出されます。 IDEは2行でそれを埋めました:

super.onCreate(savedInstanceState); setContentView(R.layout.main);
      
      





setContentViewメソッド(this.setContentViewと同等)は、現在の画面のxmlレイアウトを設定します。 さらに、xml-layoutsは「レイアウト」と呼ばれ、画面は「Activity」と呼ばれます。 アプリケーションのレイアウトは次のとおりです。

 <?xml version="1.0" encoding="utf-8"?> <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/main_l" android:gravity="center" > </TableLayout>
      
      







TableLayoutはこのアプリケーションに最適です。 Idは任意のリソースに割り当てることができます。 この場合、TableLayoutにはid = main_lが割り当てられます。 findViewById()メソッドを使用して、ビューにアクセスできます。

 private TableLayout layout; //    KrestikinolikiActivity public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); layout = (TableLayout) findViewById(R.id.main_l); buildGameField(); }
      
      







ここで、buildGameField()メソッドを実装する必要があります。 これを行うには、マトリックスの形式でフィールドを生成する必要があります。 これはGameクラスの責任です。 最初に、セルのSquareクラスと、オブジェクトがこれらのセルを埋めるPlayerクラスを作成する必要があります。



Square.java



 package com.example; public class Square { private Player player = null; public void fill(Player player) { this.player = player; } public boolean isFilled() { if (player != null) { return true; } return false; } public Player getPlayer() { return player; } }
      
      







Player.java



 package com.example; public class Player { private String name; public Player(String name) { this.name = name; } public CharSequence getName() { return (CharSequence) name; } }
      
      







アプリケーションのすべてのクラスはsrcフォルダーにあります。



Game.java



 package com.example; public class Game { /** *  */ private Square[][] field; /** *  * */ public Game() { field = new Square[3][3]; squareCount = 0; //   for (int i = 0, l = field.length; i < l; i++) { for (int j = 0, l2 = field[i].length; j < l2; j++) { field[i][j] = new Square(); squareCount++; } } } public Square[][] getField() { return field; } }
      
      







KrestikinolikiActivityコンストラクターでのゲームの初期化。

 public KrestikinolikiActivity() { game = new Game(); game.start(); //    }
      
      







KrestikinolikiActivityクラスのbuildGameField()メソッド。 行と列をテーブルに動的に追加します(プレイフィールド):

 private Button[][] buttons = new Button[3][3]; //(....) private void buildGameField() { Square[][] field = game.getField(); for (int i = 0, lenI = field.length; i < lenI; i++ ) { TableRow row = new TableRow(this); //    for (int j = 0, lenJ = field[i].length; j < lenJ; j++) { Button button = new Button(this); buttons[i][j] = button; button.setOnClickListener(new Listener(i, j)); //  ,      row.addView(button, new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT)); //      button.setWidth(107); button.setHeight(107); } layout.addView(row, new TableLayout.LayoutParams(TableLayout.LayoutParams.WRAP_CONTENT, TableLayout.LayoutParams.WRAP_CONTENT)); //     } }
      
      





8行目は、View.OnClickListenerインターフェイスを実装するオブジェクトを作成します。 ネストされたリスナークラスを作成します。 KrestikinolikiActivityからのみ表示されます。

 public class Listener implements View.OnClickListener { private int x = 0; private int y = 0; public Listener(int x, int y) { this.x = x; this.y = y; } public void onClick(View view) { Button button = (Button) view; } }
      
      





ゲームのロジックを実装することは残っています。

 public class Game { /** *  */ private Player[] players; /** *  */ private Square[][] field; /** *   ? */ private boolean started; /** *   */ private Player activePlayer; /** *     */ private int filled; /** *   */ private int squareCount; /** *  * */ public Game() { field = new Square[3][3]; squareCount = 0; //   for (int i = 0, l = field.length; i < l; i++) { for (int j = 0, l2 = field[i].length; j < l2; j++) { field[i][j] = new Square(); squareCount++; } } players = new Player[2]; started = false; activePlayer = null; filled = 0; } public void start() { resetPlayers(); started = true; } private void resetPlayers() { players[0] = new Player("X"); players[1] = new Player("O"); setCurrentActivePlayer(players[0]); } public Square[][] getField() { return field; } private void setCurrentActivePlayer(Player player) { activePlayer = player; } public boolean makeTurn(int x, int y) { if (field[x][y].isFilled()) { return false; } field[x][y].fill(getCurrentActivePlayer()); filled++; switchPlayers(); return true; } private void switchPlayers() { activePlayer = (activePlayer == players[0]) ? players[1] : players[0]; } public Player getCurrentActivePlayer() { return activePlayer; } public boolean isFieldFilled() { return squareCount == filled; } public void reset() { resetField(); resetPlayers(); } private void resetField() { for (int i = 0, l = field.length; i < l; i++) { for (int j = 0, l2 = field[i].length; j < l2; j++) { field[i][j].fill(null); } } filled = 0; } }
      
      





勝者の決定



K.O.は、フィールドの長さと同じ長さの行にXまたはOを縦、横、または斜めに並べた人が三目並べに死ぬことを提案しています。 頭に浮かぶ最初の考えは、それぞれの場合にメソッドを書くことです。 この場合、Chain of Responsobilityパターンは良いと思います。 インターフェースを定義する

 package com.example; public interface WinnerCheckerInterface { public Player checkWinner(); }
      
      





ゲームには勝者を特定する責任があるため、彼はこのインターフェースを実装しています。 仮想の「ラインマン」を作成し、それぞれが自分の側をチェックします。 それらはすべてWinnerCheckerInterfaceインターフェースを実装しています。

WinnerCheckerHorizo​​ntal.java



 package com.example; public class WinnerCheckerHorizontal implements WinnerCheckerInterface { private Game game; public WinnerCheckerHorizontal(Game game) { this.game = game; } public Player checkWinner() { Square[][] field = game.getField(); Player currPlayer; Player lastPlayer = null; for (int i = 0, len = field.length; i < len; i++) { lastPlayer = null; int successCounter = 1; for (int j = 0, len2 = field[i].length; j < len2; j++) { currPlayer = field[i][j].getPlayer(); if (currPlayer == lastPlayer && (currPlayer != null && lastPlayer !=null)) { successCounter++; if (successCounter == len2) { return currPlayer; } } lastPlayer = currPlayer; } } return null; } }
      
      





WinnerCheckerVertical.java



 package com.example; public class WinnerCheckerVertical implements WinnerCheckerInterface { private Game game; public WinnerCheckerVertical (Game game) { this.game = game; } public Player checkWinner() { Square[][] field = game.getField(); Player currPlayer; Player lastPlayer = null; for (int i = 0, len = field.length; i < len; i++) { lastPlayer = null; int successCounter = 1; for (int j = 0, len2 = field[i].length; j < len2; j++) { currPlayer = field[j][i].getPlayer(); if (currPlayer == lastPlayer && (currPlayer != null && lastPlayer !=null)) { successCounter++; if (successCounter == len2) { return currPlayer; } } lastPlayer = currPlayer; } } return null; } }
      
      





WinnerCheckerDiagonalLeft.java



 package com.example; public class WinnerCheckerDiagonalLeft implements WinnerCheckerInterface { private Game game; public WinnerCheckerDiagonalLeft(Game game) { this.game = game; } public Player checkWinner() { Square[][] field = game.getField(); Player currPlayer; Player lastPlayer = null; int successCounter = 1; for (int i = 0, len = field.length; i < len; i++) { currPlayer = field[i][i].getPlayer(); if (currPlayer != null) { if (lastPlayer == currPlayer) { successCounter++; if (successCounter == len) { return currPlayer; } } } lastPlayer = currPlayer; } return null; } }
      
      





WinnerCheckerDiagonalRight.java



 package com.example; public class WinnerCheckerDiagonalRight implements WinnerCheckerInterface { private Game game; public WinnerCheckerDiagonalRight(Game game) { this.game = game; } public Player checkWinner() { Square[][] field = game.getField(); Player currPlayer; Player lastPlayer = null; int successCounter = 1; for (int i = 0, len = field.length; i < len; i++) { currPlayer = field[i][len - (i + 1)].getPlayer(); if (currPlayer != null) { if (lastPlayer == currPlayer) { successCounter++; if (successCounter == len) { return currPlayer; } } } lastPlayer = currPlayer; } return null; } }
      
      





Gameコンストラクターでそれらを初期化します。

 //(....) /** * "" =).      , *    */ private WinnerCheckerInterface[] winnerCheckers; //(....) public Game() { //(....) winnerCheckers = new WinnerCheckerInterface[4]; winnerCheckers[0] = new WinnerCheckerHorizontal(this); winnerCheckers[1] = new WinnerCheckerVertical(this); winnerCheckers[2] = new WinnerCheckerDiagonalLeft(this); winnerCheckers[3] = new WinnerCheckerDiagonalRight(this); //(....) }
      
      





checkWinner()の実装:

 public Player checkWinner() { for (WinnerCheckerInterface winChecker : winnerCheckers) { Player winner = winChecker.checkWinner(); if (winner != null) { return winner; } } return null; }
      
      





各移動後に勝者を確認します。 ListenerクラスのonClick()メソッドにコードを追加します

 public void onClick(View view) { Button button = (Button) view; Game g = game; Player player = g.getCurrentActivePlayer(); if (makeTurn(x, y)) { button.setText(player.getName()); } Player winner = g.checkWinner(); if (winner != null) { gameOver(winner); } if (g.isFieldFilled()) { //  ,    gameOver(); } }
      
      





gameOver()メソッドは2つのバージョンで実装されています:

 private void gameOver(Player player) { CharSequence text = "Player \"" + player.getName() + "\" won!"; Toast.makeText(this, text, Toast.LENGTH_SHORT).show(); game.reset(); refresh(); } private void gameOver() { CharSequence text = "Draw"; Toast.makeText(this, text, Toast.LENGTH_SHORT).show(); game.reset(); refresh(); }
      
      





Javaの場合、gameOver(プレーヤープレーヤー)とgameOver()は異なるメソッドです。 Builder Toast.makeTextを使用すると、通知をすばやく作成して表示できます。 refresh()は、フィールドの状態を更新します。

 private void refresh() { Square[][] field = game.getField(); for (int i = 0, len = field.length; i < len; i++) { for (int j = 0, len2 = field[i].length; j < len2; j++) { if (field[i][j].getPlayer() == null) { buttons[i][j].setText(""); } else { buttons[i][j].setText(field[i][j].getPlayer().getName()); } } } }
      
      







できた! この記事が、Android OSの開発の世界で快適になるのに役立つことを願っています。 ご清聴ありがとうございました!

すぐに使えるアプリケーションビデオ









ソース



PS:この記事のコメンテーターのリクエストにより、記事が公開されました。



All Articles