はじめに
最近トランプゲームを作って解析したりAIを作ったりしているのですが、シャッフルされたカードを順に排出するクラスがそこそこ役に立つので残して置きます。
最大デッキ数などは適当に指定したので、都合に合わせて変更してください。
ソースコード
#include <iostream> //標準出力
#include <random> //乱数生成
#define DECK 52
#define MIN_DECK 1
#define MAX_DECK 10
//カード排出クラス
class Deck_Pcard{
private:
int deck_num; //デッキ数
int card_num; //カード枚数
int *deck; //格納配列
int *p_deck; //配列先頭ポインタ
public:
//コンストラクタ:引数はデッキ数
Deck_Pcard(int input_deck_num = MIN_DECK){
//デッキ数の決定
if(input_deck_num < MIN_DECK){
deck_num = MIN_DECK; //最小値
}else if(input_deck_num > MAX_DECK){
deck_num = MAX_DECK; //最大値
}else{
deck_num = input_deck_num; //入力値
}
card_num = deck_num*DECK;
deck = new int[card_num]; //メモリ確保
p_deck = &deck[0]; //先頭ポインタの設定
//配列の初期化
for(int i = 0; i < card_num; i++){
deck[i] = -1;
}
std::random_device rnd; //乱数生成器
//挿入するカードを順に変える
for(int i = 0; i < card_num; i++){
//挿入位置にカードを挿入するまでループ
while(true){
int place = rnd()%(card_num); //挿入位置の決定
if(deck[place] == -1){
//カードの格納
deck[place] = i%DECK;
break; //ループを抜ける
}
}
}
}
//デストラクタ
~Deck_Pcard(){
delete[] deck; //メモリ解放
}
//カードの排出
int hand_card(){
int hand = p_deck[0]; //排出するカードの数値を確定
//配列処理
p_deck++; //先頭ポインタをずらす
card_num--; //カード枚数を減らす
return hand; //排出するカードの数値を渡す
}
//カードの展開:デバック用
void show_card(){
for(int i = 0; i < deck_num*DECK; i++){
std::cout << deck[i] << " ";
}
std::cout << std::endl;
}
};
クラスからオブジェクトを生成すると自動的にカードがシャッフルされた状態で配列に格納されます。
排出する際には「hand_card()」で返り値にint型で値が引き渡されます。
カードの値は「0」から「51」までの52個です。13で割った余りが数になり、商でマークの区別をするといいと思います。
ジョーカーなどを追加する際には「DECK 52」の部分を増やしたい枚数分増やしてください。
例として次のような使い方ができます。
int main(){
Deck_Pcard card(3); //クラスオブジェクトを生成(3デッキから生成)
int hand;
do{
hand = card.hand_card(); //カードを取得
std::cout << hand << std::endl;
}while(hand != 1); //カードが1でない限り続行
return 0;
}
このプログラムでは「1」が出るまでカードを引き続けます。
最後に
ついこの間まではババ抜きのAIを作っていたのですが、いまいち精度が出ずに止まっています。
最近は趣味としてポーカーにハマっているので、なんかそれに関するプログラミングしたいですね。
ポーカーの方がオッズやらアウツやらでAIとして成功しやすいそうですしね。とにかく就活も頑張りつつプログラミングもやっていきたいと思います。
後自動運転AIチャレンジね。頑張らんと。
コメント