有名人と対戦してる気分が味わえるオセロアプリ作ってみた

対戦相手の名前を入力するとランダムで画像を持ってくるオセロアプリを作りました。
![ダウンロード (3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566570/bacc40f3-24c2-24b7-9ff2-8eeb2fe1dcd6.png)　⇒　![ダウンロード (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566570/acaf382a-ddf4-cf4d-3339-495cfcac9aa5.png)

名前を入力するとgoogleの検索結果から画像を取得してきます。
これを使えば憧れの「石原さとみ」さんや「綾瀬はるか」さんとオセロで対戦気分を味わえる！
カワイイ！ヤッター！

#遊んでみた感想
こみ上げる虚無感。
作り始めた時は素晴らしいアイデアだと思っていたのですが・・・。

#使用したもの
Google Custom Search API
　画像取得のために使ってみました。

遅延処理（Handler)
　黒番（人間）が打ってから白番（CPU）が打つまでに少し間を空けるために使いました。

非同期処理（AsyncTask)
　インターネット接続するために非同期処理が必要でした。

#苦労したところ
・オセロの裏返しロジック。
できたと思ってもバグが沢山見つかって大変でした。

・CPU戦の実装
地味なところだけど、黒番（人間）が打ってから白番（CPU）が打つまでに少し間を空けるのに1番苦労しました。Handlerを使って何とか実装。

#良かったところ
・HashMapを初めて使えた。
・APIに触れることができた。
・Androidはアニメーションが比較的簡単に作れる。

#反省点
・設計の重要性を感じた
設計をしないで作り始めたため、途中で何度も修正が入ってしまった。
　
・コードが汚い
オセロ盤のマス（8×8=64）が全てImageViewでできていて、全てにidを付けているためコードが大変なことに。
さらに1マスにつきImageViewを2枚重ねている。
つまりImageViewが128枚ある！
恐ろしい。
他に何か良い方法があったら教えてください。

#参考サイト
・Google Custom Search APIについて
[Custom Search APIを使ってGoogle検索結果を取得する](https://qiita.com/zak_y/items/42ca0f1ea14f7046108c)
[Google Custom Search APIを使って画像収集](https://qiita.com/onlyzs/items/c56fb76ce43e45c12339)

・遅延処理
[Androidにおける遅延実行の実装方法](http://accelebiz.hatenablog.com/entry/2016/09/02/074545)

・非同期処理
[[Android] 非同期処理 AsyncTaskの使い方](https://akira-watson.com/android/asynctask.html)

#ソースコード
Google Custom Search APIのとこだけ。

```java:CustomSearch.java
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.Log;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class CustomSearch extends AsyncTask<String, Bitmap, Bitmap> {
    String key = "APIキー";
    String cx = "検索エンジン ID";
    String link = null;
    String path = null;
    List<String> linkList = new ArrayList<>();
    private Listener listener;

    @Override
    protected Bitmap doInBackground(String... qry) {
        //URLを取得
        getLink(qry[0]);

        //10秒に1回画像を切り替える（9回まで）
        for(int i = 0; i < 9; i++) {
            try {
                publishProgress(downloadImage(qry[0]));
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
        return downloadImage(qry[0]);
    }

    // 途中経過をメインスレッドに返す
    @Override
    protected void onProgressUpdate(Bitmap... bmp) {
        if (listener != null) {
            listener.onSuccess(bmp[0]);
        }
    }

    // 非同期処理が終了後、結果をメインスレッドに返す
    @Override
    protected void onPostExecute(Bitmap bmp) {
        if (listener != null) {
            listener.onSuccess(bmp);
        }
    }

//APIにリクエストを投げてレスポンスを取得する
    List<String> getLink(String qry) {
        try {
            URL url = new URL(
                    "https://www.googleapis.com/customsearch/v1?key=" + key + "&cx=" + cx + "&q=" + qry + "&searchType=image");
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setRequestProperty("Accept", "application/json");
            BufferedReader br = new BufferedReader(new InputStreamReader(
                    (conn.getInputStream())));

    //レスポンスはjson
    //jsonからURLを抜き出す処理
            String output;
            System.out.println("Output from Server .... \n");
            while ((output = br.readLine()) != null) {

                if (output.contains("\"link\": \"")) {

                    link = output.substring(output.indexOf("\"link\": \"") + ("\"link\": \"").length(), output.indexOf("\","));
                    System.out.println(link);
                    linkList.add(link);
                }
            }
            conn.disconnect();
            return linkList;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    //URLから画像をダウンロードする処理
    private Bitmap downloadImage(String address) {
        Bitmap bmp = null;
        HttpURLConnection urlConnection = null;
        Random random = new Random();

        try {
            // linkListの中からランダムでURLを選択する
            URL url = new URL(linkList.get(random.nextInt(10)));

            // HttpURLConnection インスタンス生成
            urlConnection = (HttpURLConnection) url.openConnection();

            // タイムアウト設定
            urlConnection.setReadTimeout(10000);
            urlConnection.setConnectTimeout(20000);

            // リクエストメソッド
            urlConnection.setRequestMethod("GET");

            // リダイレクトを自動で許可しない設定
            urlConnection.setInstanceFollowRedirects(false);

            // ヘッダーの設定(複数設定可能)
            urlConnection.setRequestProperty("Accept-Language", "jp");

            // 接続
            urlConnection.connect();

            int resp = urlConnection.getResponseCode();

            switch (resp){
                case HttpURLConnection.HTTP_OK:
                    try(InputStream is = urlConnection.getInputStream()){
                        bmp = BitmapFactory.decodeStream(is);
                    } catch(IOException e){
                        e.printStackTrace();
                    }
                    break;
                case HttpURLConnection.HTTP_UNAUTHORIZED:
                    break;
                default:
                    break;
            }
        } catch (Exception e) {
            Log.d("debug", "downloadImage error");
            e.printStackTrace();
        } finally {
            if (urlConnection != null) {
                urlConnection.disconnect();
            }
        }
        return bmp;
    }

    void setListener(Listener listener) {
        this.listener = listener;
    }

    interface Listener {
        void onSuccess(Bitmap bmp);
    }
}