クリスマスに競技プログラミングといた/その2
その1はこちらクリスマスに競技プログラミングといた/その1 - 負け犬がいろいろとかたったら
その1からの続き。↓
==
[Volume0]0007: Debt Hell
問題
Your friend who lives in undisclosed country is involved in debt. He is borrowing 10-man yen from a loan shark. The loan shark adds 5% interest of the debt and rounds it to the nearest sen above week by week.
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0007
回答
import java.util.Scanner; class Debt { public static void main (String args[]) { Scanner scn = new Scanner(System.in); int n = scn.nextInt(); double debt = 100000; for(int i=0;i<n;i++) { debt = debt + debt/100*5; debt = Math.ceil(debt/1000); debt = debt*1000; } System.out.println(debt); } }
感想
なんだろう。「1000円未満を切り上げる」っていうのが一応味噌になってるんだと思う。
「一度1000で割ってから小数点以下を切り上げる関数を適用」→「1000をかけてもとに戻す」っていう形でやってます。
==
[Volume0]0008: Sum of 4 Integers
問題
Write a program which reads an integer n (n ≤ 50) and identifies the number of combinations of a, b, c, and d (0 ≤ a, b, c, d ≤ 9) which meet the following equality: a + b + c + d = n
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0008
回答
import java.util.*; class SumInteger { public static void main (String args[]) { int a,b,c,d,n,count; a = b = c = d = 9; Scanner scn = new Scanner(System.in); n = scn.nextInt(); count = 0; for (int i=0;i<=a+b;i++) { if (i<=n && n<=i+c+d) { count += mesureLength(a+b,0,i) * mesureLength(c+d+i,i,n); } } System.out.println(count); } static int mesureLength (int max,int min,int n) { if ((max + min) / 2 > n) { return n - min + 1; } else { return max - n + 1; } } }
感想
今回個人的に一番頑張ったところです。この問題は0~9までのiterateを4回続けてもかけるんですが(たぶん)、それじゃあまりにも面白くないし美しくないなと思ったので別のやり方を模索しました。結論から言えば上のやり方だとiterateは20回で済みます。iterateのネストだと10000回ループしなきゃいけないから、だいぶ早いし少し書き方を変えればもっと別のことにも応用できる形になっているはず。
なんかこのアルゴリズムの説明がちょっと面倒くさそうなので別の機会にちゃんとしますが、キモはmesureLengthです。たぶんメソッドの中身が意味不明だと思うんですが、これはExcelかなんかで一辺が0~9までの正方形を作って、正方形の中に縦の辺と横の辺の合計値をあてはめていってみてくれればわかると思います。
例えば合計値が3になるパターンは、「3-その四角形の最小値+1」で求められます。そして16みたいにその四角形の最大値と最小値の平均を超えた値が何回出てくるかは「(その四角形の最大値)-16+1」で求められます。って何言ってるかわかりづらいですね。すいません。説明面倒くさいです。
これはこの前の「場合分けの数を数える http://d.hatena.ne.jp/gong023/20111103/1320335832」にも共通する話題なので、また今度書きます。
==
[Volume0]0009: Prime Number
問題
Write a program which reads an integer n (n ≤ 999999) and prints the number of prime numbers which are less than or equal to n. A prime number is a natural number which has exactly two distinct natural number divisors: 1 and itself. For example, the first four prime numbers are: 2, 3, 5, 7.
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0009
回答
import java.util.*; public class PrimeNum { public static void main (String args[]) { Scanner scn = new Scanner(System.in); int n = scn.nextInt(); double sqrt_n = Math.ceil(Math.sqrt(n)); ArrayList<Integer> skip = new ArrayList<Integer>(); ArrayList<Integer> prime_num = new ArrayList<Integer>(); for(int i=0;i<=n;i++) { skip.add(0); } for(int i=3;i<=n;i+=2) { skip.set(i,1); } if (n%2 == 0) { prime_num.add(2); } for(int i=3;i<=n;i+=2) { if (skip.get(i) == 0) { continue; } for(int a=i+i;a<=n;a+=i) { skip.set(a,0); } prime_num.add(i); } System.out.println(prime_num.size()); } }
感想
6桁以下の任意の数に含まれる素数の個数を全てはじきだせという問題。なんだよこれ意味分かんねーよと思いましたが、ここは「エラトステネスのふるい」というアルゴリズムで解くのが正しいようです。
wikipedia:エラトステネスのふるいhttp://ja.wikipedia.org/wiki/%E3%82%A8%E3%83%A9%E3%83%88%E3%82%B9%E3%83%86%E3%83%8D%E3%82%B9%E3%81%AE%E7%AF%A9
ほんとに昔の人はすごいですね・・・。さっきのユーグリッド互除法に比べると丁寧に説明しているサイトがいくつかあったのでなんでこうなるのかっていうのをそこそこ理解しながら書けました。回答では素数であれば0、素数でなければ1という風にして判定することにしています。
全体を通しての感想
ユーグリッド互除法やらエラトステネスのふるいやら数学的なアルゴリズムがいくつか出てきてなんだか焦った所存。数学コワイヨ。
あとはjavaを書いてる気は全くしないですね。phpで考えて翻訳している感じ。僕が配列とかをやたら使いたがるのはそのせいだと思います。javaで書かれたコードをもっと読んで勉強すべきかもしれません。
あとプライベートな部分でいえば、今日はクリスマスですね!今回の回答はイブの昼間ギークハウス高円寺で僕が死んだ顔して書いていたものプラスギークハウス水道橋でみんなが寝静まったあとひとりでこそこそ書いてたものです。いやぶっちゃけもっと時間はかかってたな•••。すいません。もっとパパっとテンポよく解けるといいですね。
もう少し書こうかと思ったが日付またいで26日になってしまうのでここで終わり。
【AOJ】Java童貞&文系な俺が卒論そっちのけで競技プログラミングの問題といてみた。【vol0の0000~0004まで】
marugrammingの一環でAizu Online Judgeの問題をといてます。なんでこうなってるか詳細はこちら
marugrammingことはじめ - 負け犬がいろいろとかたったら
この記事は淡々と答えだけ載せます。
今回は簡単な問題5問だけ解いたので晒します。あまり難しくなさそうな問題なはずなのにクソい回答ばかりで恥ずかしいです。
でもぎーまるのみんながエレガントな解答してくれるはず!w
==
[Volume0]0000: QQ
問題
Write a program which prints multiplication tables in the following format:
リンク:QQ | Aizu Online Judge
回答
public class QQ { public static void main (String[] args) { for(int a=1; a<=9; a++){ for(int b=1; b<=9; b++){ System.out.printf(String.valueOf(a) + "*" + String.valueOf(b) + "=%d", a * b); } } } }
感想
問題自体特にどうってことないけど掛け算を行う回数が2回じゃなくて3回、4回となっていったときfor文をネストしないで書く方法ないかなぁ。この前の「サイコロの場合分け」にも言えることだけど。
==
[Volume0]0001: List of Top 3 Hills
問題
There is a data which provides heights (in meter) of mountains. The data is only for ten mountains.
List of Top 3 Hills | Aizu Online Judge
回答
public class Top3Hills { static int[] hight = {1819, 2003, 876, 2840, 1723, 1673, 3776,2848,1592,922}; public static void main (String[] args) { java.util.Arrays.sort(hight); for(int i=hight.length-1;i>hight.length-4;i--) { System.out.println(hight[i]); } } }
[Volume0]0002: Digit Number
問題
Write a program which computes the digit number of sum of two integers a and b
Digit Number | Aizu Online Judge
回答
public class DigitNumber { public static void main (String args[]) { int inputA = 5;int inputB = 7; double i = 1;double by = 10; while (i>0) { by = Math.pow(by,i); if (inputA + inputB - by < 0) { System.out.println(i); break; } i++; } } }
感想
だからinputの扱い(ry
==
[Volume0]0003: Is it a Right Triangle?
問題
Write a program which judges wheather given length of three side form a right triangle. Print "YES" if the given sides (integers) form a right triangle, "NO" if not so.
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0003
回答
public class RightTriangle { static int[][] input = { {4,3,5},{4,3,6},{8,8,8} }; public static void main(String[] args) { for(int i=0;i<input.length;i++) { //念のためソートする java.util.Arrays.sort(input[i]); int a = input[i][0] * input[i][0]; int b = input[i][1] * input[i][1]; int c = input[i][2] * input[i][2]; if (c==a+b) { System.out.println("YES"); } else { System.out.println("NO"); } } } }
[Volume0]0004: Simultaneous Equation
問題
Write a program which solve a simultaneous equation
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0004
回答
import java.math.BigDecimal; public class Simultaneous { static double a = 1;static double b = 2;static double c = 3; static double d = 4;static double e = 5;static double f = 6; public static void main (String[] args) { BigDecimal x = new BigDecimal((b*f - e*c) / (b*d - a*e)); BigDecimal y = new BigDecimal((a*f - d*c) / (a*e - d*b)); BigDecimal resultX = x.setScale(4,BigDecimal.ROUND_HALF_UP); BigDecimal resultY = y.setScale(4,BigDecimal.ROUND_HALF_UP); System.out.println(resultX); System.out.println(resultY); } }
感想
今回の中で一番酷い回答。hintを全く活かしていないという意味で。
==
全体を通しての感想
inputの扱いをどうしていいのかわかりますん。
てか俺卒論やろうな?な?
marugrammingことはじめ
「プログラミングは目的だろうか手段だろうか?」
と聞かれたとき、間違いなく半年ぐらい前の僕なら「手段だ」と答えていたと思います。
でも最近プログラミングとかする時間が増えて、毎日あーでもないこーでもないと考えているうちに、
案外プログラミングそれ自体も楽しいなと思うようになりました。
という訳で最近こんなものを始めました。
marugramming
http://marugramming.tumblr.com/(以下記事抜粋)
Hello,marugramming!ギーまるのごんげです。
marugrammigできました。
このブログはギーまるの人たちがプログラミングを勉強するために共有する目的で使います。
現在のところmarugrammingのコンセプトは非常にシンプルです。
①言語はjavaを用いる
②会津プログラミングコンテストの過去問をjavaで書くことを目標とする
http://judge.u-aizu.ac.jp/onlinejudge/index.jsp?lang=ja#
以上です。
書いてあるとおりです。主にぎーまるの住人でプログラミングを勉強しましょうという活動です。
プログラミングを純粋に楽しんでみようかなという意図で、他にはなにもありません。
スキルアップしたいとか別の言語を覚えたいとかそういうのを目標にしてないので、毎日どれぐらいやるとかいうノルマも立てずにのろのろとやっております。ゆるゆるでございます。
参加者はid:@x5gtrn id:@soramugi id:@mojaieです。
ぎーまるの人以外でも、ギークハウスの人じゃなくても大歓迎なのでいつでもお声がけくださいませませ。
僕自身Javaは初めてなので四苦八苦しております。多分ちゃんとした経験者は id:@x5gtrn だけな予感・・・。
頑張ってJava覚えて簡単な問題5問解いたのでそれあげますねー。長くなるのアレなんで別記事であげます。
【PHP】場合分けの数を数える
思い出したかのようにブログ更新してみる。
2ヶ月ちょいぐらいギークハウス高円寺というところに住んでいます。
先日@soramugiさんがボードゲームをなにやらたんまりと持ってきて
ボードゲームなんて中学生の時にやってたMTG以来なんですが、めっちゃおもろかったです。
昨日やったのはカタンっていうゲームで、無人島をどんどん開拓してポイントためましょうってやつ。
単純に単純にポイント貯めてくだけじゃなくて、カードを交渉でゲットしたりできたりできます。
かなり自由度高く交渉できて、そういう政治的要素が濃く絡んでくるっていうのはボードゲームならではって感じ。
で、この中ゲームは進行上「サイコロを二つふる」アクションがあって、その出目もかなり大事になってます。
自分の陣取った地域には1から12の数字が割り振られていて、2つのサイコロの出目を合計した数の地域を所有している人が恩恵を受けられるんです。
例えば「2」の陣地を所有していても、「2」はサイコロ2つが「1,1」となった一通りでしかでてこないので、「2」の陣地を持っていてもあまり意味が無いとかそういう話です。
==
ここから本題。
サイコロ2つを同時にふった場合、その出目の合計で一番出やすいのは「7」だそうです。
ゲーム中は「ふーん」と思って聞いてましたが、あとになって「ほんとにそうなの?」という疑問がふつふつとww
確かめて見るには数学といてとけばいい。でも僕は純粋培養の文系なので数学とくいじゃない。
数学得意じゃなくても数えてみればわかる。でもそんな面倒くさいことしたくない。
「数学でとけなければプログラムを書けばいいじゃない。」
ということで、プログラムを書いてみました。
2つの数字の合計を数えてくれるプログラムです。
<?php define("COUNT",12); define("DICE_A",6); define("DICE_B",6); $all_number = array(); for ($x=1;$x<=DICE_A;$x++) { for ($y=1;$y<=DICE_B;$y++) { $all_number[] = $x + $y; } } for ($i=1;$i<=COUNT;$i++) { $count_number = array(); foreach($all_number as $key) { if ($key == $i) { $count_number[] = $key; } } echo 'cout'.$i.':'.count($count_number).PHP_EOL; }
こんな感じでやってみました
①どんな数字が出るのかを全て配列に突っ込む
②どの数字が何回出てきているのかを数える
一応気をつけたのはこんなところ
①1〜12で条件分岐するとかいうイケてないことしない
②定数値を用いて拡張性を高く
12個if文を続けていいなら、今回の目的は簡単に達成できますが、まぁ、仮にもプログラマならそんなダサいことはけしてやっちゃあいけないですね。イケてないですね。
あとは定数をの中身を差し替えればどんな数字も数えれるようになってるところ?まぁ拡張なんてする機会ないと思いますが、可読性高く、拡張性高くっていう基本姿勢を忘れると先輩に怒られちゃうね。
あと、ここまで計算すると確率の計算をするのも楽なんですが、今回は面倒なのでやりませんw
このプログラムの実行結果はこんな感じです。
count1:0
count2:1
count3:2
count4:3
count5:4
count6:5
count7:6
count8:5
count9:4
count10:3
count11:2
count12:1
うん、7が一番多いから大丈夫そうw
最後に反省点
①for($x=1;...)はどう考えてもイケてない
②そもそも全部の場合を書きだそうっていう発想が文系wwwwwwww
まぁfor文の方はループ回数を一個減らせばいいのでそんなに大きな問題ではないんですが
全部の場合を書きだそうっていうのしか思い浮かばなかったのはいかにも数学できない人の発想だなと思うwwwww
コンピューターは繰り返しの処理が得意だからそれをうまく使ったといえば聞こえはいいけど
アルゴリズムの段階からもう少し頭いい感じで作れたらもっと良かったっすね。
2つの数字の合計を書きだしてみるとある程度の法則性あるし・・・。
【PHP】【MYySQL】半角/全角スペース区切りで複数語句検索できるようにする
Googleで検索をかけるときに、スペースで区切ると検索語句を2つでも3つでも検索できます。
あれやりたいなーと思って調べてたらこんな記事を見かけました。
MySQLでの検索に関する質問です。例えば単語一つだけで検索する ...
http://q.hatena.ne.jp/1199349138
↑これだと配列つくって中でごにょごにょしてるんだけど、
こんなことせんでもstr_replace使えばできんじゃねと思った。
$search = 'orrange apple grape';//検索対象語句 $search = mysql_real_escape_string($search); $escape = '%" AND clumn LIKE "%'; $where_phrase = array(' '=>$escape,' '=>$escape);//全角と半角を変換 $where_phrase = 'SELECT * FROM table WHERE clumn LIKE"%'.str_replace(array_keys($where_phrase),array_values($where_phrase),$search).'%";';
clumnを変数$clumnとかにしてうまいことやればもっと動的に作れそう。
このほうが短くすむ上に、あと投げるクエリがわかりやすい気がする。
あんまり詳しく調べてないけど、ググったらこれと同じやり方でてきそう。
あ。でも検索語句の最後に半角/全角スペースが入ってたらstr_replaceしない処理は書かないとダメかも。
今度やってみよ
【PHP】テニスの確率論
突然ですがこの前ネットでおもろい話を見つけました
テニスの確率論:http://hamakazuchan.web.infoseek.co.jp/tennis/tennis3.html
ここで言ってることは、例えばAさんがポイントを取る確率が55%、Bさんが45%で結構実力的には張り合っていても、最終的にBさんが勝てる確率は0.043%にまで落ち込んでしまうという話です。
自分はテニスをサークルでやってたんですが、確かにみんなが思う「アイツが勝つだろうな」っていう予想は結構外れない感じはありました。
要はテニスって結構番狂わせが起こりづらいスポーツなんですね。
面白そうだったのでPHPでこのアルゴリズムどんな感じになるのか書いてみました。
<?php class Tennis { function step_cul($a,$b,$c){//階乗 $escape_zero = array($a,$b,$c); foreach ($escape_zero as $key){ if ($key == 0){$key = 1;} } $a_num = $b_num = $c_num = 1; for($i = $a;$i == 1;$i--){ $a_num = $a_num * $i; } for($i = $b;$i == 1;$i--){ $b_num = $b_num * $i; } for($i = $c;$i == 1;$i--){ $c_num = $c_num * $i; } return $a_num/$b_num/$c_num; } function multiple ($point,$duce) {//乗算 $escape_zero = array($point,$duce); foreach ($escape_zero as $key){ if ($key == 0){$key = 1;} } $num_mlt = $point; for ($i=0;$i<=$duce-1;$i++) { $num_mlt = $num_mlt * $point; } return $num_mlt; } function probability ($duce,$b_point) { $a_point = 1 - $b_point; $ary = array(); for ($i=0;$i<=$duce;$i++) { if($i == $duce){ $ary[] = $this->multiple($b_point,$duce+2) *$this->multiple($a_point,$i) *$this->step_cul($duce+$i,$duce,$i); } else { $ary[] = $this->multiple($b_point,$duce+1) *$this->multiple($a_point,$i) *$this->step_cul($duce+$i,$duce,$i); } } $prob = '0'; foreach ($ary as $key){ $prob = $prob + $key; } return $prob; } static public function instantiate ($game) { $class = 'Tennis_'.$game; return new $class; } } class Tennis_Game extends Tennis { function cul(){ return $this->probability(3,0.49); } } class Tennis_Set extends Tennis { function cul(){ $game = new Tennis_Game; return $this->probability(5,$game->cul()); } } class Tennis_Match extends Tennis { function cul(){ $set = new Tennis_Set; return $this->probability(3,$set->cul()); } } $tennis = new Tennis; $game = $tennis->instantiate('Game'); $set = $tennis->instantiate('Set'); $match = $tennis->instantiate('Match'); $cul = array($game,$set,$match); foreach ($cul as $key) { echo $key->cul(); }
書いといてなんなんですがこのコード不完全な点が幾つかありますw
一つはデュースになった際の扱いです。
僕はBさんが2ポイント連取してゲームを取る確率しか考えられていません。
しかし実際AさんとBさんが交互にポイントをとり続ければデュースというのは無限に続く確率があるわけで、
本当はその確率も考えなければならないはずです。
それを上記リンクのページでは無限級数の和で導いています。
もちろん僕もそれでやろうとしたのですが、純正文系バカなので途中で諦めたというw数Ⅲとかしらねーしw
プログラムをかくのが目的だったのでいっかなーみたいな言い訳もしつつ
まぁ今度ゆっくり時間をかけて再チャレンジしたいと思います。
あとセットを取るときにタイブレークを考えられていないのも不完全な点ですね・・・。
あと階乗はともかく乗算に関しては普通にPHPの関数でなんかあるような気がしてきた。
ポイントとしてはゲームを取る確率、セットを取る確率、勝利する確率を同じ計算方法でやっているという点と、その計算方法を単なる継承ではなくポリモーフィズムでやってることですかね。計算方法に関してはゲームだろうとセットだろうと何ポイント目に「デュース現象」がおこるかという話なので。あとポリモーフィズムは前から気になってたんで無理やり使った感ありますが、なんというかこういう設計のやり方にプログラマの性格でるんだろうなと思いました。
実を言うと後半の部分は多重継承で書くべきだなと思ってました。ゲーム、セット、マッチとそれぞれ前のクラスを呼んでから計算しているので。でもPHPは基本的に多重継承しちゃいけないし、まぁ形としてわかりやすいのでポリモーフィズムでいくか、みたいな。あとそもそも無理やりクラスに分けなくてもfunctionだけ作ってその都度呼べばいいんじゃねーの的な話もありますね。オブジェクト指向ガン無視で邪道中の邪道ですがw 計算の量自体は実はクラスを設定してやるよりも減る・・・かなたぶん。
あとはabstractで書くとか・・・あ。タイブレークはこれでかくといいかも・・・。
そんな感じで試行錯誤してるのがちょっと楽しかったです。
あともはやはてな記法で綺麗に見せようというやる気がない。
よし寝るか
【iPhone】自作iPod/AVAudioPlayerを使って複数の曲を扱う
前回のブログで「今度は複数の曲を扱えるようにする」とかいっときながら一ヶ月以上書いてなかったね。
弱小エントリだし、そんな急いで書かなくていいかなーと思ってたんだけど
リアル知人の何人かから「お前が書いたの読んでるよ(ニヤニヤ)」みたいな感じで言われてしまったので
サボらず書こうと思います。
機能自体はもうとうの昔に作ってたので、自分のコード覚えているか心配w
今日の目標はこれです。
<<前回作った自作iPodで、複数の曲を扱えるようにする>>
1:下準備
2:「次の曲」「前の曲」に移行するボタンを作る/ついでに曲の再生が終わったら次の曲を再生する
以上です。それでは早速。
<<1:下準備>>具体的にボタンとかの機能を実装する前に、下準備します。
今回AVAudioPlayerで複数の曲を扱うにあたっては
「どの曲が選択されているかを知る『タグ』のようなものを作って、それに応じて作成するAVAudioPlayerの内容を変える」
っていうシステムにします。
何言ってるかわかりづらいと思うので、コードで説明します。
どの曲が選択されているかを知る『タグ』はこれです。
int senkyoku;
そして、このintに応じて作成するAVAudioPlayerを変えるというアプローチになります。
-(void)chooseMusic{
if (audio.playing==YES) {
[audiostop];
[audiorelease];
}
switch (senkyoku) {
case1:{
NSString *path=[[NSBundlemainBundle]pathForResource:@"music1"ofType:@"mp3"];
NSURL *url=[NSURLfileURLWithPath:path];
audio = [[AVAudioPlayeralloc] initWithContentsOfURL:url error:nil];
kyokumei.text=@"曲名1";
break;}
case2:{
/*
*省略
*/
default:
break;
}
timeslider.maximumValue=audio.duration;
}
また、曲数は定数を作っておくと後々すごく便利です。
#define MusicNumber 10 //←扱う曲数
これで下準備は完了です。このchooseMusicを然るべきところで呼んであげれば、複数曲を扱うことが可能です。
・・・しかし動くことは動くんですが、問題点もあるので記しておきます。
1:全体的に名前がイケてないイケてるエンジニアのみなさんは、間違ってもint senkyokuとかやんないですよねwww
メソッド名とかもデザインパターンを全く意識できてなかったですね。恥ずかしいですが戒めの意味をこめてそのまま載せます。
2:膨大な曲数を扱えない今回は10曲ぐらいを想定してswitchで場合分けしていますが、この構造のままだと曲数が膨大になったときに困ります。
じゃあ
for(int i=0;i<=MusicNumber;i++){
NSString *path=[[NSBundlemainBundle] pathForResource:@"music%d",i ofType:@"mp3"];
NSURL *url=[NSURLfileURLWithPath:path];
audio = [[AVAudioPlayeralloc] initWithContentsOfURL:url error:nil];
}
とかでいいじゃん、って話ですが、これじゃダメなんです。てゆーか僕も最初はこれで書いてました。
なんでかっていうとforで作ってるpathとurlが同じ名前なので、最終的にどの曲を選んでもsenkyoku=MusicNumbebrのもの(最後の曲のもの)が再生されてしまうんです。
じゃあその辺の名前を動的にすればいいじゃんって話で、それはその通りです。releaseが若干面倒になりますが。
viewDidLoadのタイミングで曲数分のAVAudioPlayerを作成しておき、呼ぶAVAudioPlayerをその都度決めればいいですね。
ユーザーが曲の再生途中で「次の曲」に送ってしまった場合にちゃんとreleseするとか、
releaseする対象はその都度変わるからめんど臭いとかいう点に気をつければいけると思います。
その修正は今度しておこう。すいませんここまで完全にメモ。
<<2:「次の曲」「前の曲」に移行するボタンを作る>>ようやく目に見える部分を作ります。一応イメージとして画像を。
ボタンの実装は下準備してあるので簡単です。
-(IBAction)nextMusic{
senkyoku++;
[selfchooseMusic];
[audio.play];
}
-(IBAction)aheadMusic{
senkyoku=senkyoku-1;
[selfchooseMusic];
[audio.play];
}
ついでに曲の再生が終わったら「次の曲」ボタンを押したときの処理と同じことをしてあげるといいです。
再生終了時に次の曲を再生してくれるので。
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
// Music completed
if (flag) {
//nextMusixボタンが押された時と同じ処理をする
senkyoku++;
[selfchooseMusic];
[audio.play];
[audio setDelegate:self];
}
}
要はint senkyokuの値を変えてあげれば中身が変わるのでその処理を割当てます。
ただ、senkyokuが「範囲外」になってしまうとだめなので以下を追記します。
-(void)chooseMusic{
//↓追記
if (audio.playing==YES) {
[audiostop];
[audiorelease];
}
if(senkyoku==0){
senkyoku=MusicNumber;
}
if(senkyoku==MusicNumber+1){
senkyoku=1;}
以上で目標達成です。(多分)
次はこんな機能を追加してあげるといいですね。
・シャッフル再生できるようにする(乱数作ってint senkyokuに突っ込むだけ。楽勝。)
・iPhoneがスリープ状態でも音楽の再生ができるようにする(AVAudioSessionの設定をいじくるだけ。楽勝。)
・こんどこそたくさんの曲を扱っても破綻しない構造にする
感想としてはAVAudoPlayerをreleaseするタイミングがほんとにめんどくさい。ObjectiveCの宿命なんだろうけど。
あと破滅的に見づらいのではてぶ記法に慣れたい←