「10分でコーディング」で15分かかった件
これ以上かかった人は
自分はかなりプログラミングができない。
とつらい事実を認識しましょう。
http://ameblo.jp/programming/entry-10001721422.html
まぁ、そんなもんですよ。
以下、自分の回答。
package xminits; public class Cards { String[] deal(int numPlayers, String deck) { String[] goal = new String[numPlayers]; String cutdeck = cut(numPlayers, deck); for (int i = 0; i < numPlayers; i++) goal[i] = mydeck(numPlayers, i, cutdeck); return goal; } private String cut(int numPlayers, String deck) { return deck.substring(0, deck.length() - (deck.length() % numPlayers)); } private String mydeck(int numPlayers, int index, String deck) { StringBuilder mine = new StringBuilder(); for (int i = 0; i < deck.length(); i++) { if (i % numPlayers == index) mine.append(deck.charAt(i)); } return mine.toString(); } }
- ってか、配列定義構文とか全く頭から抜けてるw
- 元記事の回答例はif文とローカル変数が多くて、動作が読みにくい。その点ではこちらの方に軍配が上がるはず。
- インタフェース設計的には、プレイヤー数を受け取るコンストラクタと、デッキを受け取ってカードを配るdealメソッドを用意する方が綺麗かも。クラス名は「場」的な感じで。
- numPlayersをインスタンス変数に格納して、dealメソッドで格納してcutメソッドとmydeckメソッドの引数から除外しても動作は同じだろうけど、確実に混乱する。不変オブジェクトとする方を選ぶ。
- んー、「自分はかなりプログラミングができない。」は、少し煽り過ぎかなー。
というわけで、インタフェース変更
- コンストラクタでプレイヤー数を受け取る不変オブジェクトにした。
- 内部クラスを作って、privateメソッドを1個除去。
- 「privateメソッドは不要 - @katzchang.contexts」のいい例かな。
- Deck#mydeckをコンストラクタに移してprivateメソッドを完全除去しようと思ったけど、動作が分かりにくいのでやめた。
- 名前付けに違和感。
- まぁ、漸近的な設計ということで…。
package xminits; import static org.junit.Assert.*; import org.junit.Test; public class CardsTest { @Test public void testDeal() { Cards target = new Cards(3); assertArrayEquals(new String[] {"111","222","333"}, target.deal("123123123")); assertArrayEquals(new String[] {"11","22","33"}, target.deal("12312312")); assertArrayEquals(new String[] {"", "", "" }, target.deal("")); } }
package xminits; public class Cards { private final int numPlayers; public Cards(int numPlayers) { this.numPlayers = numPlayers; } public String[] deal(String deck) { return new Deck(deck).goal; } private class Deck { final String cutDeck; final String[] goal; public Deck(String deck) { cutDeck = deck.substring(0, deck.length() - (deck.length() % numPlayers)); goal = new String[numPlayers]; for (int i = 0; i < numPlayers; i++) goal[i] = mydeck(i); } private String mydeck(int index) { StringBuilder mine = new StringBuilder(); for (int i = 0; i < cutDeck.length(); i++) { if (i % numPlayers == index) mine.append(cutDeck.charAt(i)); } return mine.toString(); } } }
プレイヤー数のチェック追加
コメント欄からの指摘に対応して。
package xminits; import static org.junit.Assert.*; import org.junit.Test; public class CardsTest { @Test public void testDeal() { Cards target = new Cards(3); assertArrayEquals(new String[] {"111","222","333"}, target.deal("123123123")); assertArrayEquals(new String[] {"11","22","33"}, target.deal("12312312")); assertArrayEquals(new String[] {"", "", "" }, target.deal("")); } @Test(expected=IllegalArgumentException.class) public void testNoDeal() { Cards target = new Cards(0); target.deal("123123123"); } }
package xminits; public class Cards { private final int numPlayers; public Cards(int numPlayers) { if (!(numPlayers > 0)) throw new IllegalArgumentException("numPlayers must be > 0"); this.numPlayers = numPlayers; } public String[] deal(String deck) { return new Deck(deck).goal; } private class Deck { private final String cutDeck; private final String[] goal; private Deck(String deck) { cutDeck = deck.substring(0, deck.length() - (deck.length() % numPlayers)); goal = new String[numPlayers]; for (int i = 0; i < numPlayers; i++) goal[i] = mydeck(i); } private String mydeck(int index) { StringBuilder mine = new StringBuilder(); for (int i = 0; i < cutDeck.length(); i++) { if (i % numPlayers == index) mine.append(cutDeck.charAt(i)); } return mine.toString(); } } }