じゃんけんアプリ
本を読んでいたらじゃんけんアプリの決定表を用いた実装方法が載っていた。目からウロコだったので書いてみたくなった。初学者に教育する流れとしてよく使われるらしいので周知の物みたいだけど。
関係ないけど新しくアプリ作ろうとしたら選択言語で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; } }
予め結果の表
相手の手 | |||||
0 | 1 | 2 | |||
グー | チョキ | パー | |||
自分の手 | 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というのを見つけた。
http://www.umop.com/rps101/rps101chart.html
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を書くと心が痛むけどこれしか分からん。こうなる。
ここまでやって、あれ?これ作ったところでどうやってアプリで扱うんだ?となる。
長くなりそうなので、ちょと記事分けよう。