カード合成シミュレーター作成(その1)

Java

Javaでカード合成シュミレーターを作成してみよう!
題材としてドラゴンクエストウォークのミルドラースの排出率と合成必要枚数を使ってシミュレートしていく。

仕様

○カードはS,A,B,C,Dの5種類のランクが存在している
○カードの排出確率は

S:3%
A:5%
B:10%
C:30%
D:52%

○カードを合成することでランクアップすることができる。ランクアップに必要な枚数は以下

Dを3枚でC
Cを4枚でB
Bを4枚でA
Aを5枚でS

○Dしかひけなかった場合Sを作るのには240枚必要になる。このD換算した枚数は以下である
(つまりSはDの240倍の価値)

S:240
A:48
B:12
C:3
D:1

作成

一度にすべて作るとしんどいので部分的に作成していこう。

アプリケーションクラスDQWを作成する

最初にアプリケーションクラスとなるDQWクラスを作成する。
今回はこのファイル1枚でアプリを作成していく。

import java.util.*;
public class DQW {
 public static void main(String[] args) {
 }
}

Cardクラス作成

DQW.javaの下部にカードを表すCardクラスを作成する。
○インスタンスフィールド
Character rank;//S,A,B,C,Dのいずれかが入る
int ratio;//排出確率が入る。30は30%を意味することとする
int point://D換算時の枚数が入るSは240,Dは1
○コンストラクタ
引数3つのコンストラクタを作成する

import java.util.*;
public class DQW {
 public static void main(String[] args) {
 }
}
class Card{
  Character rank;
  int ratio;
  int point;
  Card(Character rank,int ratio,int point){
    this.rank=rank;
    this.ratio=ratio;
    this.point=point;
  }
}

主役のMap<Card,Integer>の作成

今回はMapを使って<Cardの種類,枚数>という形で扱っていく。5種類のカードインスタンスを作ってそれぞれ0枚で初期化しよう。あわせてScannerインスタンスも作成しておく。(SCに再代入されることはないのでfinalとした)

import java.util.*;
public class DQW {
 public static void main(String[] args) {
   //Scannerインスタンス作成
   final Scanner SC=new Scanner(System.in);
   //Mapを作成今回はこのmapが主役<Cardの種類,枚数>
   Map<Card,Integer> cards=new LinkedHashMap<>(){
     {
      put(new Card('S',3,240),0);
      put(new Card('A',5,48),0);
      put(new Card('B',10,12),0);
      put(new Card('C',30,3),0);
      put(new Card('D',52,1),0);
     }
   };
 }
}
class Card{
  Character rank;
  int ratio;
  int point;
  Card(Character rank,int ratio,int point){
    this.rank=rank;
    this.ratio=ratio;
    this.point=point;
  }
}

現在の状態を表示するshowCards()メソッドの作成

現在のカードの取得状況を以下のように一覧するメソッド

S(0)A(0)B(0)C(0)D(0)
static void showCards(Map<Card,Integer> cards){}

をDQWクラスに作成してみよう。

作成例

Mapのforループは色々あるが、ここはキーの集合を回す方法を採用した。
1件1件キーとなっているカードインスタンスを取り出して、情報を表示すればよい。(今回LinkedHashMapを使っているので格納順序が保持されている。つまりSから順番に表示される)

static void showCards(Map<Card,Integer> cards){
   for(Card c:cards.keySet()){
      System.out.printf("%s(%d)",c.rank,cards.get(c));
   }
   System.out.println();
 }

確認

メインメソッドからshowCardsを呼び出して、上記のような表示がでることを確認すること。

引かれたカードを特定するdrawCard()の作成

それでは排出確率に基づいて何が引かれたかを決定するメソッド

static Card drawCard(Map<Card,Integer> cards){}

を作成してみよう。

作成例

static Card drawCard(Map<Card,Integer> cards){
   Card card=null;
   int n=(int)(Math.random()*100);
   for(Card c:cards.keySet()){
    if(n - c.ratio < 0){
      card=c;
      break;
    }
    n-=c.ratio;
   }
   return card;
 }

前回のお題でもあったが、0~99の範囲から一つ乱数を生成してその番号によって引かれたインスタンスを特定している。この部分がよくわかない人は前回のお題からやること。

引かれたカードに基づいてMap更新処理

先程のメソッドは何が引かれたかを特定しているだけで、Mapの更新は行っていない。Mapを更新する処理は以下(ついでに何を引いたのかを出力している)

		Card card=drawCard(cards);
		System.out.println(card.rank+"が出ました!");
		cards.put(card,cards.get(card)+1);

実行例

S(0)A(0)B(0)C(0)D(0)
Dが出ました!
S(0)A(0)B(0)C(0)D(1)

ここまでの解答例(全文)

import java.util.*;
public class DQW {
	public static void main(String[] args) {
		//Scannerインスタンス作成
		final Scanner SC=new Scanner(System.in);
		//Mapを作成今回はこのmapが主役<Cardの種類,枚数>
		Map<Card,Integer> cards=new LinkedHashMap<>(){
			{
				put(new Card('S',3,240),0);
				put(new Card('A',5,48),0);
				put(new Card('B',10,12),0);
				put(new Card('C',30,3),0);
				put(new Card('D',52,1),0);
			}
		};
		showCards(cards);
		Card card=drawCard(cards);
		System.out.println(card.rank+"が出ました!");
		cards.put(card,cards.get(card)+1);
		showCards(cards);
	}
	static void showCards(Map<Card,Integer> cards){
		for(Card c:cards.keySet()){
			System.out.printf("%s(%d)",c.rank,cards.get(c));
		}
		System.out.println();
	}
	static Card drawCard(Map<Card,Integer> cards){
		Card card=null;
		int n=(int)(Math.random()*100);
		for(Card c:cards.keySet()){
			if(n - c.ratio < 0){
				card=c;
				break;
			}
			n-=c.ratio;
		}
		return card;
	}
}
class Card{
	Character rank;
	int ratio;
	int point;
	Card(Character rank,int ratio,int point){
		this.rank=rank;
		this.ratio=ratio;
		this.point=point;
	}
}

お題

ではいつものようにここでお題をやってみよう。以下の実行例になるように処理を作成してみてほしい。

実行例

S(0)A(0)B(0)C(0)D(0)
何枚ひく>>10
Bが出ました!
Dが出ました!
Cが出ました!
Dが出ました!
Sが出ました!
Cが出ました!
Cが出ました!
Dが出ました!
Dが出ました!
Dが出ました!
S(1)A(0)B(1)C(3)D(5)

作成例

import java.util.*;
public class DQW {
	public static void main(String[] args) {
		//Scannerインスタンス作成
		final Scanner SC=new Scanner(System.in);
		//Mapを作成今回はこのmapが主役<Cardの種類,枚数>
		Map<Card,Integer> cards=new LinkedHashMap<>(){
			{
				put(new Card('S',3,240),0);
				put(new Card('A',5,48),0);
				put(new Card('B',10,12),0);
				put(new Card('C',30,3),0);
				put(new Card('D',52,1),0);
			}
		};
		showCards(cards);
		/*
		Card card=drawCard(cards);
		System.out.println(card.rank+"が出ました!");
		cards.put(card,cards.get(card)+1);
		showCards(cards);
		*/
		System.out.print("何枚ひく>>");
		int num=SC.nextInt();
		for(int i=0;i<num;i++){
			Card card=drawCard(cards);
			System.out.println(card.rank+"が出ました!");
			cards.put(card,cards.get(card)+1);
		}
		showCards(cards);
	}

	static void showCards(Map<Card,Integer> cards){
		for(Card c:cards.keySet()){
			System.out.printf("%s(%d)",c.rank,cards.get(c));
		}
		System.out.println();
	}
	static Card drawCard(Map<Card,Integer> cards){
		Card card=null;
		int n=(int)(Math.random()*100);
		for(Card c:cards.keySet()){
			if(n - c.ratio < 0){
				card=c;
				break;
			}
			n-=c.ratio;
		}
		return card;
	}
}
class Card{
	Character rank;
	int ratio;
	int point;
	Card(Character rank,int ratio,int point){
		this.rank=rank;
		this.ratio=ratio;
		this.point=point;
	}
}

第一回終了

今回はここまで、次回はいよいよカードを合成する処理とシミュレーション部分を作成する。最後に完成版イメージを確認しておこう。

完成版イメージ

---合成シミュレーター---
0:カードを引く
1:カードを合成する
2:カードをセットする
3:シミュレーションする
4:終了
>>0
Cが出ました!
S(0)A(0)B(0)C(1)D(0)
0:カードを引く
1:カードを合成する
2:カードをセットする
3:シミュレーションする
4:終了
>>0
Dが出ました!
S(0)A(0)B(0)C(1)D(1)
0:カードを引く
1:カードを合成する
2:カードをセットする
3:シミュレーションする
4:終了
>>0
Cが出ました!
S(0)A(0)B(0)C(2)D(1)
0:カードを引く
1:カードを合成する
2:カードをセットする
3:シミュレーションする
4:終了
>>0
Cが出ました!
S(0)A(0)B(0)C(3)D(1)
0:カードを引く
1:カードを合成する
2:カードをセットする
3:シミュレーションする
4:終了
>>0
Dが出ました!
S(0)A(0)B(0)C(3)D(2)
0:カードを引く
1:カードを合成する
2:カードをセットする
3:シミュレーションする
4:終了
>>0
Dが出ました!
S(0)A(0)B(0)C(3)D(3)
0:カードを引く
1:カードを合成する
2:カードをセットする
3:シミュレーションする
4:終了
>>0
Dが出ました!
S(0)A(0)B(0)C(3)D(4)
0:カードを引く
1:カードを合成する
2:カードをセットする
3:シミュレーションする
4:終了
>>0
Dが出ました!
S(0)A(0)B(0)C(3)D(5)
0:カードを引く
1:カードを合成する
2:カードをセットする
3:シミュレーションする
4:終了
>>0
Bが出ました!
S(0)A(0)B(1)C(3)D(5)
0:カードを引く
1:カードを合成する
2:カードをセットする
3:シミュレーションする
4:終了
>>0
Dが出ました!
S(0)A(0)B(1)C(3)D(6)
0:カードを引く
1:カードを合成する
2:カードをセットする
3:シミュレーションする
4:終了
>>1
合成しました!
S(0)A(0)B(2)C(1)D(0)
0:カードを引く
1:カードを合成する
2:カードをセットする
3:シミュレーションする
4:終了
>>2
カードを任意枚数にセットします
0,2,1,3,4 のように
カンマ区切りでS,A,B,C,Dの枚数を入力してください
>>0,2,2,0,0
指定枚数でセットしました
S(0)A(2)B(2)C(0)D(0)
0:カードを引く
1:カードを合成する
2:カードをセットする
3:シミュレーションする
4:終了
>>0
Cが出ました!
S(0)A(2)B(2)C(1)D(0)
0:カードを引く
1:カードを合成する
2:カードをセットする
3:シミュレーションする
4:終了
>>0
Cが出ました!
S(0)A(2)B(2)C(2)D(0)
0:カードを引く
1:カードを合成する
2:カードをセットする
3:シミュレーションする
4:終了
>>2
カードを任意枚数にセットします
0,2,1,3,4 のように
カンマ区切りでS,A,B,C,Dの枚数を入力してください
>>0,2,2,0,0
指定枚数でセットしました
S(0)A(2)B(2)C(0)D(0)
0:カードを引く
1:カードを合成する
2:カードをセットする
3:シミュレーションする
4:終了
>>3
現在の状況からSが指定枚数できるまでの回数をシミュレーションします
Sの必要枚数を入力>>1
シミュレーション回数を入力>>10
  1(  1):*
  3(  1):*
  8(  1):*
 10(  1):*
 13(  1):*
 15(  2):**
 27(  1):*
 38(  1):*
 40(  1):*
平均:17.0回
0:カードを引く
1:カードを合成する
2:カードをセットする
3:シミュレーションする
4:終了
>>3
現在の状況からSが指定枚数できるまでの回数をシミュレーションします
Sの必要枚数を入力>>1
シミュレーション回数を入力>>1000
  1( 21):*********************
  2( 21):*********************
  3( 34):**********************************
  4( 28):****************************
  5( 30):******************************
  6( 27):***************************
  7( 22):**********************
  8( 27):***************************
  9( 38):**************************************
 10( 30):******************************
 11( 45):*********************************************
 12( 35):***********************************
 13( 43):*******************************************
 14( 36):************************************
 15( 26):**************************
 16( 31):*******************************
 17( 31):*******************************
 18( 18):******************
 19( 44):********************************************
 20( 28):****************************
 21( 37):*************************************
 22( 36):************************************
 23( 31):*******************************
 24( 37):*************************************
 25( 22):**********************
 26( 24):************************
 27( 24):************************
 28( 21):*********************
 29( 23):***********************
 30( 15):***************
 31( 18):******************
 32( 13):*************
 33( 14):**************
 34( 12):************
 35(  8):********
 36(  5):*****
 37(  9):*********
 38(  3):***
 39(  7):*******
 40(  3):***
 41(  4):****
 42(  4):****
 43(  1):*
 44(  2):**
 46(  4):****
 47(  1):*
 48(  1):*
 49(  4):****
 50(  1):*
 52(  1):*
平均:17.6回
0:カードを引く
1:カードを合成する
2:カードをセットする
3:シミュレーションする
4:終了
>>3
現在の状況からSが指定枚数できるまでの回数をシミュレーションします
Sの必要枚数を入力>>2
シミュレーション回数を入力>>1000
  3(  4):****
  4(  1):*
  5(  4):****
  6(  1):*
  7(  2):**
  8(  4):****
  9( 15):***************
 10(  8):********
 11( 10):**********
 12( 19):*******************
 13( 11):***********
 14( 15):***************
 15( 18):******************
 16( 22):**********************
 17( 22):**********************
 18( 18):******************
 19( 27):***************************
 20( 19):*******************
 21( 18):******************
 22( 26):**************************
 23( 29):*****************************
 24( 14):**************
 25( 35):***********************************
 26( 24):************************
 27( 36):************************************
 28( 33):*********************************
 29( 26):**************************
 30( 17):*****************
 31( 29):*****************************
 32( 24):************************
 33( 33):*********************************
 34( 26):**************************
 35( 16):****************
 36( 13):*************
 37( 26):**************************
 38( 17):*****************
 39( 19):*******************
 40( 13):*************
 41(  9):*********
 42( 16):****************
 43( 16):****************
 44(  8):********
 45( 17):*****************
 46(  9):*********
 47( 12):************
 48( 10):**********
 49( 10):**********
 50(  9):*********
 51( 12):************
 52( 13):*************
 53(  8):********
 54(  5):*****
 55(  6):******
 56( 10):**********
 57(  7):*******
 58(  6):******
 59(  8):********
 60(  8):********
 61(  5):*****
 62( 11):***********
 63(  6):******
 64(  5):*****
 65(  6):******
 66(  7):*******
 67(  5):*****
 68(  3):***
 70(  2):**
 71(  1):*
 72(  3):***
 73(  8):********
 74(  5):*****
 75(  2):**
 76(  4):****
 77(  1):*
 78(  1):*
 79(  3):***
 80(  2):**
 81(  3):***
 82(  4):****
 84(  1):*
 85(  2):**
 86(  1):*
 87(  1):*
 89(  6):******
 90(  3):***
 91(  1):*
 92(  1):*
 93(  1):*
 94(  1):*
 96(  1):*
117(  1):*
平均:35.0回
0:カードを引く
1:カードを合成する
2:カードをセットする
3:シミュレーションする
4:終了
>>4
終了

コメント

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