じゃんけんアプリ色々

スポンサーリンク
スポンサーリンク

じゃんけんアプリ

本を読んでいたらじゃんけんアプリの決定表を用いた実装方法が載っていた。目からウロコだったので書いてみたくなった。初学者に教育する流れとしてよく使われるらしいので周知の物みたいだけど。

関係ないけど新しくアプリ作ろうとしたら選択言語でKotlinが上に来てた。。。初めからKotlin使ってればよかったな。

スポンサーリンク

ifで条件分岐したじゃんけんアプリ

普通の、というとちょっと語弊があるけれど、ifで条件分岐するやつを愚直に書いてみる。

public class RPS3Activity extends AppCompatActivity {
    TextView result;
    TextView ophand;
    static final int ROCK = 0;
    static final int SCISSORS = 1;
    static final int PAPER = 2;

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

        result = findViewById(R.id.ResulttextView);
        ophand = findViewById(R.id.OpponentHandtextView);

    }

    public void onClick(View v) {
        Random rand = new Random();
        int num = rand.nextInt(3);

        switch (v.getId()) {
            case R.id.btRock:
                if (num == ROCK) {
                    ophand.setText(R.string.rock);
                    result.setText(R.string.draw);
                } else if (num == SCISSORS) {
                    ophand.setText(R.string.scissors);
                    result.setText(R.string.win);
                } else if (num == PAPER) {
                    ophand.setText(R.string.paper);
                    result.setText(R.string.lose);
                }
                break;

            case R.id.btScissors:
                if (num == ROCK) {
                    ophand.setText(R.string.rock);
                    result.setText(R.string.lose);
                } else if (num == SCISSORS) {
                    ophand.setText(R.string.scissors);
                    result.setText(R.string.draw);
                } else if (num == PAPER) {
                    ophand.setText(R.string.paper);
                    result.setText(R.string.win);
                }
                break;

            case R.id.btPaper:
                if (num == ROCK) {
                    ophand.setText(R.string.rock);
                    result.setText(R.string.win);
                } else if (num == SCISSORS) {
                    ophand.setText(R.string.scissors);
                    result.setText(R.string.lose);
                } else if (num == PAPER) {
                    ophand.setText(R.string.paper);
                    result.setText(R.string.draw);
                }
                break;
        }
    }
}

こんななった。同じようなコードが並んでるねっと。

これでも一応動くは動く。

スポンサーリンク

配列を使ったじゃんけんアプリ

ほんで配列使ったやつ。

public class RPS3Activity extends AppCompatActivity {
    TextView result;
    TextView ophand;
    int[] ihand = {R.string.rock, R.string.scissors, R.string.paper};
    int[][] judge = {
            {R.string.draw, R.string.win, R.string.lose},
            {R.string.lose, R.string.draw, R.string.win},
            {R.string.win, R.string.lose, R.string.draw}
    };

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

        result = findViewById(R.id.ResulttextView);
        ophand = findViewById(R.id.OpponentHandtextView);
    }

    public void onClick(View v) {
        Random rand = new Random();
        int num = rand.nextInt(3);
        int hand = HandtoInt(v);

        result.setText(judge[hand][num]);
        ophand.setText(ihand[num]);
    }

    public int HandtoInt(View v) {
        int rt = 0;

        switch (v.getId()) {
            case R.id.btRock:
                rt = 0;
                break;
            case R.id.btScissors:
                rt = 1;
                break;
            case R.id.btPaper:
                rt = 2;
                break;
        }
        return rt;
    }
}

予め結果の表

相手の手
012
グーチョキパー
自分の手0グー引き分け勝ち負け
1チョキ負け引き分け勝ち
2パー勝ち負け引き分け

こういうの、を、配列として作っておき、どのボタンを押したかを数値化して、その数値を配列の添字にして結果を引っ張り出す。考えた人頭い~ね。

スポンサーリンク

計算で結果を求めるじゃんけんアプリ

表を使わずに、出し手の数値から計算して勝利判定するやつ。本には載ってなかったけど、じゃんけんで他になんかないかなとネットで探してたら見つけた。

public class RPS3Activity extends AppCompatActivity {
    TextView result;
    TextView ophand;
    int[] ihand = {R.string.rock, R.string.scissors, R.string.paper};
    int[] judge = {R.string.draw, R.string.lose, R.string.win};

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

        result = findViewById(R.id.ResulttextView);
        ophand = findViewById(R.id.OpponentHandtextView);
    }

    public void onClick(View v) {
        Random rand = new Random();
        int num = rand.nextInt(3);
        int hand = HandtoInt(v);

        int res = (hand - num + 3) % 3;

        result.setText(judge[res]);
        ophand.setText(ihand[num]);
    }

    public int HandtoInt(View v) {
        int rt = 0;

        switch (v.getId()) {
            case R.id.btRock:
                rt = 0;
                break;
            case R.id.btScissors:
                rt = 1;
                break;
            case R.id.btPaper:
                rt = 2;
                break;
        }
        return rt;
    }
}

こうするともう表もいらなくなる。コードを書く量がめっちゃ減ってるのがかっこいい。こういうコードを1からパッと書けるとかっこいいなぁ。

スポンサーリンク

RPS-101、じゃんけんのすごいやつ

じゃんけんのことを色々探していたらRPS-101というのを見つけた。

rps101

101手ある。その前に5手のやつはもうあってこのサイトの人は7, 9, 11, 15, 25を作って、101手も作っちゃったということみたい。おー。せっかくなので作ってみようかな。

仕組みを見る

上記ページの左上の方にチャートの見方が載っており読んでみると1は2-51に勝つ。2は3-52に勝つ。以下101は1-51に勝つ、まで。あと勝利の際の文言がそれぞれに用意されてる。例えば1のダイナマイトは

OUTCLASSES TORNADO
CLEARS QUICKSAND
CREATES PIT
EXPLODES CHAIN
OUTCLASSES GUN
BREAKS LAW
EXPLODES WHIP
EXPLODES SWORD
EXPLODES ROCK
CAUSES DEATH
EXPLODES WALL
SMOKE BLOTS OUT SUN

と、相手によって勝利文言を変えてるようだ。余計なことを。凝ってるね。勝利判定部分はすぐできそうなので、文言を集めよう。

ExcelVBA+IEでスクレイピング

スクレイピングは色んな方法があるけど、これしか知らんので、これでいく。

http://www.umop.com/rps101/alloutcomes.htm

ここに文言の一覧があるので取ってこよう。そういえば、Windows10にしてからやってねーな、Edgeになったけどできるのかな?

Sub rps()
 
    Dim objIE As InternetExplorer
    Set objIE = New InternetExplorer
     
    objIE.Visible = True
    objIE.navigate "http://www.umop.com/rps101/alloutcomes.htm"
    
    Do While objIE.Busy = True Or objIE.readyState < READYSTATE_COMPLETE
    DoEvents
    Loop
    
    Dim htmlDoc As HTMLDocument
    Set htmlDoc = objIE.document
    
    Dim b As IHTMLElementCollection
    Set b = htmlDoc.getElementsByTagName("b")
    
    For i = 0 To 100
        Cells(1, i + 1).Value = b(i).innerText
    Next i
    
    Dim table As IHTMLElementCollection
    Set table = htmlDoc.getElementsByTagName("table")
    
    For j = 0 To 100
    
        Dim td As IHTMLElementCollection
        Set td = table(j).getElementsByTagName("td")
    
        Cells(2, j + 1).Value = td(0).innerText
        Cells(3, j + 1).Value = td(1).innerText
        Cells(4, j + 1).Value = td(2).innerText
        Cells(5, j + 1).Value = td(3).innerText
    
    Next j

End Sub

こんな感じでコードを書いた。Win10にもIEあるのね。するとこんな感じになる。

うまく1行ずつ取れんかった。

もうちょい整形

こんなコードを書いて

Sub splitcell()

    Dim arw As Variant
    
    For k = 1 To 101
        For i = 2 To 5
            arw = Split(Cells(i, k).Value, vbLf)
            
            rc = Cells(Rows.Count, k).End(xlUp).Row + 1
            
            For j = 0 To UBound(arw)
                Cells(rc + j, k).Value = Trim(Replace(arw(j), Chr(32), " "))
            Next j
        Next i
    Next k

End Sub

多重Forを書くと心が痛むけどこれしか分からん。こうなる。

ここまでやって、あれ?これ作ったところでどうやってアプリで扱うんだ?となる。

長くなりそうなので、ちょと記事分けよう。

コメント

タイトルとURLをコピーしました