ログインしてさらにmixiを楽しもう

コメントを投稿して情報交換!
更新通知を受け取って、最新情報をゲット!

Java質問&情報提供サイトコミュのCardの値を出したいのですが、、

  • mixiチェック
  • このエントリーをはてなブックマークに追加
Java初心者です。
カードの値を設定してそれを使って計算をしたいのですが、どうやって呼び出していいのかわかりません。
Suit: Heart=4, Diamond=3, Club=2, Spade=1
Card:Deuce-Ten=それぞれの数値, Jack Queen King = 10, Ace=11

SpadeのEIGHTなら1x8=8
表示は EIGHT of SPADES (8) と52カード全て同じように計算して出したいのですが、下のDeckのクラスで

strb.append("("+Card.Rank.rValue * Card.Suit.sValue + "), ");
で呼び出そうと思ったのですが出来ず、Cardのクラス内で
public String toString() { return rank + " of " + suit + "(" + rValue()*sValue() + ")"; } もできません。
http://jcp.org/aboutJava/communityprocess/jsr/tiger/enum.html
のV. Usage Examplesのように打ち込んでみたんですが、private finalの設定の意味も良く分かっていないので、アドバイスをいただけると幸せます、、、。

宜しくお願いいたします。

参考にしたページ
http://download.oracle.com/docs/cd/E17476_01/javase/1.5.0/docs/guide/language/enums.html

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

import java.util.*;

public class Card {
public enum Rank {
DEUCE(2), THREE(3), FOUR(4), FIVE(5), SIX(6), SEVEN(7),
EIGHT(8), NINE(9), TEN(10), JACK(10), QUEEN(10), KING(10), ACE(11);

Rank(int rValue){this.rValue = rValue;}
private final int rValue;
public int rValue() {return rValue;}
}

public enum Suit {
SPADES(1), CLUBS(2), DIAMONDS(3), HEARTS(4);

Suit(int sValue){this.sValue = sValue;}
private final int sValue;
public int sValue() {return sValue;}

}

private final Rank rank;
private final Suit suit;

Card(Rank rank, Suit suit) {
this.rank = rank;
this.suit = suit;
}

public Rank rank() { return rank; }
public Suit suit() { return suit; }
//public String toString() { return rank + " of " + suit + "(" + rValue()*sValue() + ")"; }
public String toString() { return rank + " of " + suit; }


ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

import java.util.*;

public class Deck
{
private List<Card> cards; // the cards of the deck
private int cardsPerLine; // how many cards to show per line

private static final List<Card> prototypeDeck = new ArrayList<Card>();

// Initialize prototype deck
static {
for (Card.Suit suit : Card.Suit.values())
for (Card.Rank rank : Card.Rank.values())
prototypeDeck.add(new Card(rank, suit));
}

public Deck (int cardsPerLine)
{
cards = new ArrayList<Card>(prototypeDeck);
shuffle();
this.cardsPerLine = cardsPerLine;
}

public void shuffle ()
{
Collections.shuffle(cards);
}

public String toString ()
{
int cardsOnLine = 0;
StringBuffer strb = new StringBuffer();
for (Card card : cards) {
if (cardsOnLine != 0)
strb.append("("+Card.Rank.rValue * Card.Suit.sValue + "), ");
strb.append(card);
if (++cardsOnLine >= cardsPerLine) {
strb.append("\n");
cardsOnLine = 0;
}
}

return strb.toString();
}

public static void main(String[] args)
{
Deck deck = new Deck(3);
System.out.println(deck);
}
}

コメント(11)

今回の呼び出しに関しては、メソッド修飾子(アクセス修飾子)、スコープ辺りの知識を深めることで、
理解できるようになるでしょう。ちょっと前にも質問が出ていたので、そのトピも参考になるかも。

とりあえずのエラーが出る原因やらとその対処について挙げておきます。
※ 処理を詳細まで追っていないため、意図する処理ができているかどうかは未保証です


Card.toString() において rValue() や sValue() がエラーとなるのは
Card クラス自体に rValue() や sValue() の定義が無いからです。

Card では rank を持ち、その rank が rValue() を持つため Card 内に
おいては rank.rValue() と明確に書く必要があります。sValue() も同様です。
そのため、以下のように書けばコンパイルは通るでしょう。

public String toString() { return rank + " of " + suit + "(" + rank.rValue() * suit.sValue() + ")"; }



次に以下が出来ない件
strb.append("("+Card.Rank.rValue * Card.Suit.sValue + "), ");

該当コードは以下の for ループ処理によって
for (Card card : cards) {
cards を順に走査する処理となっていますが、その際のループ変数は
card であり、クラス定義自体を指し示す Card ではありません。

card は Card クラスをインスタンス化したオブジェクトとなるわけですが、
Card 以外から Card クラスの rank や suit のフィールドを触る場合
private であるため、今のコードであれば、アクセサ(getter) として
定義されている rank() メソッド、suit() メソッドを介して
Rank と Suit を取得しなければなりません。

そのため、以下のように書けばコンパイルは通るでしょう。
strb.append("(" + card.rank().rValue() * card.suit().sValue() + "), ");


final については、フィールドに値を設定後、その値を不変(上書禁止)にする。
というもので、普通に使うだけであれば、他言語における『定数』的な扱い。
という理解で十分でしょう。ただし、オブジェクトに使う場合は例外があるため、
詳しく知りたい場合は(難しいですが)『イミュータブル』という概念を調べると良いです。


あと、enum については、ロジックやらも乗せられるため、上手く使うと非常に便利です。
この手のノウハウを勉強したい場合、今だと『Effective Java 第2版』 という書籍が
良いかも。内容は少し難しいので、Java にある程度慣れてからのスキルアップとして
読むのが良いかもしれません。


また、他の解決策としては、Card クラス自体に rValue() や sValue() を
以下のように定義して機能を仲介してあげる方法もあります。

public int rValue() { return rank.rValue(); }
public int sValue() { return suit.sValue(); }

ただし、rank や suit が未定義(null) の場合はエラーとなるため、
場合によっては別途対処が必要かもしれません。
この手法に関しては『委譲』を調べると良いでしょう。

以上

ご参考になれば幸いです。
じ〜るさま

出ました!!!!! 週末からあれやこれや試していましたが、結局それぞれのコードを良く理解していないのでどう繋がっているのかわかっていませんでした。

書籍もどうにかして入手したいと思います。

丁寧に説明していただいて感謝いたします。
本当に有難うございました!!
度々すみません。
http://java.sun.com/j2se/1.5.0/ja/docs/ja/guide/language/enums.html上のコード、
import java.util.*;

public class Deal {
public static void main(String args[]) {
int numHands = Integer.parseInt(args[0]);
int cardsPerHand = Integer.parseInt(args[1]);
List<Card> deck = Card.newDeck();
Collections.shuffle(deck);
for (int i=0; i < numHands; i++)
System.out.println(deal(deck, cardsPerHand));
}

public static ArrayList<Card> deal(List<Card> deck, int n) {
int deckSize = deck.size();
List<Card> handView = deck.subList(deckSize-n, deckSize);
ArrayList<Card> hand = new ArrayList<Card>(handView);
handView.clear();
return hand;
}
}
ですが、int deckSize = deck.size(); のsize()はどのように繋がっているのでしょうか。トピック上のコードのdeckを使って上記のサイト上にあるように出力したいのですが、“size()のメソッドが見つからない”と出てきてコンパイル出来ません。
Javaのサイト上のコードのみ(size()のメソッドは無い?)だと書いてあるように出力できるのですが、トピックのコードと組み合わせると“見つからない”と出てくる、、。サイズをどのようにとっているのか理解したいのですが、アドバイスをお願いいたします。
上記サイト内のsizeメソッドは、Listクラスのメソッドです。
Deckクラスにはsizeメソッドが存在しないので、当然メソッドが見つからず、コンパイルエラーになります。
トピックのコードで同様のことをやりたければDeckクラスにsizeメソッドを追加する必要があります。

public int size(){
return cards.size()
}

seraphさま

ありがとうございました! 
sizeのエラーは消えました。が、他のエラーが出てきました、、。
もう少しじっくり考えてみたいと思います。

ありがとうございました。
コンパイル時のエラーなのか、実行時のエラーなのか?具体的な問題が
よく解らないのですが、示したサイトに載っている Card クラスの定義に
newDeck() に関する内容があるため、その部分が適切に記述されていない
と推測しますが、如何でしょうか?


deck.size() については、サイトに載っているコードでの話を前提に解説しますと、
deck を List<Card> として扱っていることに着目しましょう。要は Card を要素に
持つ List インターフェイスで扱っています。

なので、deck.size() は List.size() を呼んでいる。と捉えれば構いません。
より深く捉えたければ、List の実体に着目する必要があります。具体的には
Card.newDeck() 内で生成されている ArrayList が実体ですので、
deck.size() は ArrayList.size() が最終的には呼び出されます。

List.size() は List 自体がインターフェイスのため、実体は無いわけですが、
普通にプログラムを組み立てる場合の思考としては、ArrayList を意識する
必要はなく、List として扱えば構いません。

これは Java における『クラス』と『インターフェイス』の関係について知識を深め、
インターフェイスの意義が理解できると解るかな?難しい内容かもしれませんが
プログラムを書くだけであれば、厳密な理解が無くても慣れるので大丈夫です。


以下、Java での標準的に使える部品と、List / ArrayList の定義です。
http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/index.html
http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/util/List.html
http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/util/ArrayList.html

読み慣れるまで骨が折れるかもしれませんが、標準の部品で解らない部分があれば
積極的に調べる癖を付けるとよいでしょう。なお、プロであっても、一部の部品しか
使わないため、実用だけを考えるならば、無理して全体や詳細を覚える必要はないです。
それよりも実例と共に、問題毎の部品の使い方を漠然と把握する方が良いでしょう。

以上

ご参考になれば幸いです。
じ〜るさま

丁寧に説明していただいて、色々と理解できるようになりました。ありがとうございます。添付してくださっているショートカットから
public static ArrayList<Card> deal(Deck deck, int n) {
int deckSize = deck.size();
List<Card> handView = deck.subList(deckSize-n, deckSize);
ArrayList<Card> hand = new ArrayList<Card>(handView);
handView.clear();
return hand;
}
の意味がわかった(と思う)のですが、sizeと同じくsubListもListのメソッドのようで、sizeと同じようにDeckの中にメソッドを追加しないといけないということになると思うのですが、Variableが二つあって、どう書くべきなのかよくわからずエラーが消えません、、。

それと、最終的に例として
EIGHT of SPADES (8), THREE of CLUBS (6), SIX of DIAMONDS (18)
score = 32
のように手の合計を出すためにそれぞれの値、8、6、18を取り出す(して計算する)ためにはどういう方法があるのかもまだひらめきません。

おっしゃるように、newDeck()が適切に記述できていないと思います。
すでにdeckが出来ているので
List<Card> deck = Card.newDeck();
Collections.shuffle(deck);
を削除したのですが、、、混乱してきました、、。もう少しじっくり考えてみます。ありがとうございます。
やっぱり呼び方がよくわからないのですが、
public int subList(){
int deckSize = size();
int n;
return cards.subList(deckSize-n, deckSize);
}

では incompatible types - found java.util.Lost<Card> but expected int
というメッセージが出てきます。

それで、コメント3のコードを基にして52のdeck 表示とhand表示をすると下のように表示したいものが [ ] に入っているのですが、それはなぜ出てくるのでしょうか? 本当に基本的な質問だと思うのですが、調べても見つけられないのですみませんがアドバイスを宜しくお願いします。

[8 of hearts, jack of spades, 3 of spades, 4 of spades, king of diamonds]
[4 of diamonds, ace of clubs, 6 of clubs, jack of hearts, queen of hearts]
[7 of spades, 5 of spades, 2 of diamonds, queen of diamonds, 9 of clubs]
[8 of spades, 6 of diamonds, ace of spades, 3 of hearts, ace of hearts]
そのsubListメソッドは何をするメソッドですか?
List#subListは、リストの部分列を返すメソッドであり、その返り値はList<E>(今回の場合はList<Card>)ですが、List#subListを呼び出しているsubListメソッドの返り値はint型です。
List<Card>型はint型と互換性がないので、エラーが発生しています。
あと、nが初期化されてないけど、コンパイルエラーになる気がする。

後段は、ArrayListのtoStringによって文字列化しているからかと。
ArrayList#toStringの仕様です。
seraphさま
返信、ありがとうございます。

handが4で cardが3として、4人の人が三枚ずつカードを52枚のdeckの中から順番にとり、残りのカードをsubListを使って出して削除しているということであっていると思うのですが、コメント3上の例のコードのList<Card> deck = Card.newDeck(); を削除したので、クラスDeck上で教えていただいたようにsize()を加えてその部分のエラーは消えましたが、、、“List<Card>型はint型と互換性がないので、エラーが発生”ということは、size()と同じようには出来ないということでしょうか。

ArrayListのtoString仕様という事は、toStringを使うなら[]を表示させないようには出来ないということでしょうか。

import java.util.*;

public class a
{
public static void main(String[] args)
{
if (args.length < 2) {
System.out.println("args: nHands nCards");
return;
}

int nHands = Integer.parseInt(args[0]);
int cardsPerHand = Integer.parseInt(args[1]);

System.out.println("hands: " + nHands + ", " + "cards per hand: " + cardsPerHand );

Deck deck = new Deck(3);
System.out.print("\ndeck:\n");
System.out.println(deck);
System.out.println("\n");

     for (int i=0; i < nHands; i++)
System.out.println(deal(deck, cardsPerHand));
//System.out.println("score = " +     );
}
public static ArrayList<Card> deal(Deck deck, int n) {
int deckSize = deck.size();
List<Card> handView = deck.subList(deckSize-n, deckSize);
ArrayList<Card> hand = new ArrayList<Card>(handView);
handView.clear();
return hand;
}
}
じ〜るさま & seraphさま

どうにか終了しました!
どうも有り難うございました!!!

ログインすると、みんなのコメントがもっと見れるよ

mixiユーザー
ログインしてコメントしよう!

Java質問&情報提供サイト 更新情報

Java質問&情報提供サイトのメンバーはこんなコミュニティにも参加しています

星印の数は、共通して参加しているメンバーが多いほど増えます。

人気コミュニティランキング