//========================================================= // フルハウス ( P6 16点 ) //========================================================= int Full_house( const int hd[], int cg, int us ){ int i, j, k; // 反復変数 int a, b; int ret = -1; double hand_pro[5] = {0}; double min = 1; int chng_num = 0; struct card deck[13] = {0};// 山札の構造体 for( i=0; i< 4; i++ ){ deck[i].mark = 13-(sut[i] + udsut[i]); } // (手札と捨て札から)山札のマーク残り数を求める for( i=0; i<13; i++ ){ deck[i].num = 4-(Num[i] + udNum[i]); } // (手札と捨て札から)山札の数字の残り数を求める if( poker_point(hd) > P6 ){ return -1; } /* 2ペア,3ペアが既に揃っている */ if( poker_point(hd) == P0){ One_pair(hd,cg,us); } // ワンペアもできていない if( poker_point(hd) == P1){ Two_pair(hd,cg,us); } // ツーペアもできていない /* 以下は2ペア以上ができていれば入る */ /*----- 既に 3枚揃っている場合 (ただ、 ツーペア以下は無視 より無意味)--------------- */ //* for( i=0; i<13; i++ ){ if( Num[i] == 3 ){ // 1組目(i番目)が 3枚ある for( k=0; k<HNUM; k++ ){ if( hand[k].num != i ){ // 手札中の 3枚セットの数字以外の手札を交換 hand_pro[k] = (double)deck[hand[k].num].num/(52-us-HNUM); }else{ hand_pro[k] = 1.0; } } for( i=0; i<HNUM; i++ ){ // 出る確率の低いマークを探す if( hand_pro[i] < min ){ min = hand_pro[i]; chng_num = i; } } ret = chng_num; return ret; } } //*/ /*----- 2枚が2組ある場合 -------------------- */ //* for( i=0; i<13; i++ ){ if( Num[i] == 2 ){ // 1組目(i番目の数)が 2枚ある for( j=i+1; j<13; j++ ){ if( Num[j] == 2 ){ // 2組目(j番目の数)が 2枚ある for( k=0; k<HNUM; k++ ){ if( hand[k].num != i && hand[k].num != j ){ // 手札中の 1組目 と 2組目 の数字以外の手札を交換 return k; } } } } } } return -1; }
void calcexp( int hd[], int cg, int tk, int pointhd[], int pointnum, int deck[], int decknum, int recursioncount, int starthd ) { int nexthd[HNUM]; int nextdeck[CNUM]; int point = 0; int i, j; for ( i = starthd; i < HNUM; i++) { if ( pointnum != -1 ) { //printf("%d, %d, %d\n", pointnum, i, decknum); } for ( j = 0; j < CNUM; j++) { if ( deck[j] == 0 ) { arr_copy( nexthd, hd, HNUM ); nexthd[i] = j; arr_copy( nextdeck, deck, CNUM ); nextdeck[j] = -1; if ( pointnum == -1 ) { // 一手目の期待値の加算 //pointhd[i] += poker_point(nexthd)*(decknum*(LIMIT+1-recursioncount)); pointhd[i] += poker_point(nexthd)*decknum; //pointhd[i] += pointconvert(poker_point(nexthd))*decknum; } else { // 二手目以降の期待値の加算 point = poker_point(nexthd); //point = pointconvert(poker_point(nexthd)); pointhd[pointnum] += point; if ( pointnum < i ) { pointhd[i] += point; } } //if ( tk < 1 || tk > 3 ) { continue; } if ( cg > 7 - LIMIT ) { continue; } if ( recursioncount >= LIMIT ) { continue; } if ( pointnum == -1 ) { calcexp( nexthd, cg+1, tk, pointhd, i, nextdeck, decknum-1, recursioncount+1, i ); } else { calcexp( nexthd, cg+1, tk, pointhd, pointnum, nextdeck, decknum-1, recursioncount+1, i ); } } } } }
int strategy( const int hd[], const int fd[], int cg, int tk, const int ud[], int us) { int myhd[HNUM]; int select = -1; int hdcopy[CNUM]; int udcopy[us]; int currentpoint = 0; int deck[CNUM] = { 0 }; int decknum = CNUM; int k; int lastchangehd = 0; // 最初から高い点なら手札を変えずに終了 arr_copy( hdcopy, hd, HNUM); currentpoint = poker_point(hdcopy); if ( currentpoint >= P6 ) { return -1; } arr_copy( udcopy, ud, us ); decknum = make_deck( hdcopy, udcopy, us, deck ); if ( tk == 4 && decknum <= 7 - cg ) { //LAST_RECURSION_LIMIT = decknum; select = select_card_last( hdcopy, cg, tk, udcopy, us, deck, decknum ); } else { select = select_card( hdcopy, cg, tk, udcopy, us, deck, decknum ); } return select; }
//========================================================= // ツーペア ( P2 2点 ) //========================================================= int Two_pair( const int hd[], int cg, int us ){ int i, j, k; // 反復変数 int ret = -1; double hand_pro[5] = {0}; double min = 1; int chng_num = 0; struct card deck[13] = {0};// 山札の構造体 for( i=0; i< 4; i++ ){ deck[i].mark = 13-(sut[i] + udsut[i]); } // (手札と捨て札から)山札のマーク残り数を求める for( i=0; i<13; i++ ){ deck[i].num = 4-(Num[i] + udNum[i]); } // (手札と捨て札から)山札の数字の残り数を求める if( poker_point(hd) > P2 ){ return -1; } for( i=0; i<13; i++ ){ if( Num[i] == 2 ){ // i番目が2枚ある for( k=0; k<5; k++ ){ if( hand[k].num != i ){ // 手札中の 2枚セットの数字以外の手札を交換 hand_pro[k] = (double)deck[hand[k].num].num/(52-us-HNUM); }else{ hand_pro[k] = 1.0; } } for( i=0; i<HNUM; i++ ){ // 出る確率の低いマークを探す if( hand_pro[i] < min ){ min = hand_pro[i]; chng_num = i; } } ret = chng_num; return ret; } } return -1; }
int strategy( int hd[], int fd[], int cg, int tk, int ud[], int us) { int myhd[HNUM]; int select = -1; int point; int i; //高い役の時終了 point = poker_point( hd ); //手札の点数 if ( point == P9 ) { return -1; } //ロイヤルストレートフラッシュ if ( point == P8 ) { return -1; } //ストレートフラッシュ if ( point == P7 ) { return -1; } //フォーカード if ( point == P5 ) { return -1; } //フラッシュ if ( point == P6 ) { return -1; } //フルハウス if ( point == P4 ) { return -1; } //ストレート //フラッシュ select = flash_judge( hd ); if ( select != -1 ) { return select; } //ストレート select = straight( hd ); if ( select >= 0 ) { return select; } //ペア select = pair_count( hd ); return select; //-1=交換を止める return -1; }
int select_card( int hd[], int cg, int tk, int ud[], int us, int deck[], int decknum ) { int hightexp = ( decknum > 1 ) ? poker_point(hd)*decknum*(decknum-1) : poker_point(hd)*decknum; int select = -1; int recursioncount = 1; int pointhd[HNUM] = { 0 }; // 期待値を格納 int i; calc_exp( hd, cg, tk, pointhd, -1, deck, decknum, recursioncount, 0); for ( i = 0; i < HNUM; i++) { if ( pointhd[i] > hightexp ) { hightexp = pointhd[i]; select = i; } } return select; }
int take6_hand(int hd[], int ud[], int us) { int i, j, k, a, b, c, d, find_flag, point; int maxpoint = 0; int remain_cards[25] = {-1}; int hand_a[5]; int hand_remain[5]; k = 0; for (i=0; i<51; i++) { find_flag = 0; for (j=0; j<us; j++) { if (ud[j] == i) { find_flag = 1; break; } } if (find_flag == 0) { remain_cards[k] = i; k++; } } for (i=0; i<k-4; i++) { for (j=i+1; j<k-3; j++) { for (a=j+1; a<k-2; a++) { for (b=a+1; b<k-1; b++) { for (c=b+1; c<k; c++) { hand_a[0] = remain_cards[i]; hand_a[1] = remain_cards[j]; hand_a[2] = remain_cards[a]; hand_a[3] = remain_cards[b]; hand_a[4] = remain_cards[c]; point = poker_point(hand_a); if (point > maxpoint) { for (d=0; d<5; d++) { hand_remain[d] = hand_a[d]; } maxpoint = point; } } } } } } if (maxpoint <= poker_point(hd)) { return -1; } for (i=0; i<HNUM; i++) { find_flag = 0; for (j=0; j<5; j++) { if (hd[i] == hand_remain[j]) { find_flag = 1; break; } } if (find_flag == 0) { return i; } } return -1; }
// テイクによる制限をかける関数 制限する必要が無いならDEFAULT_NUM(10)を返す int limit_take(int cg, int tk, Handcard hands[], Cards remain_card, Cards hand_card, Cards deck_card, int hd[]) { int t; int k; // 反復変数 int flag = 0; if ( tk == 0 ) { if ( check_straight(remain_card, hand_card) >= 1 ) { flag = 1; } for ( k = 0; k < 4; k++ ) { if ( hand_card.sut[k] >= 4 ) { flag = 1; } } if ( poker_point(hd) >= P3 ) { flag = 1; } if ( flag == 0 ) { return -1; } } if ( tk == 1 ) { for ( k = 0; k < 4; k++ ) { if ( hand_card.sut[k] >= 4 ) { flag = 1; } } if ( check_straight(remain_card, hand_card) >= 3 ) { flag = 1; } if ( poker_point(hd) >= P3 ) { flag = 1; } if ( flag == 0 ) { return -1; } } if ( tk == 4 && deck_card.amount <= 11 ) { return -1; } if ( tk == 3 && deck_card.amount <= 22 ) { return -1; } /* if ( tk == 2 && deck_card.amount <= 33 ) { return -1; } */ // テイクによる交換回数の制限 if ( tk < 3 && cg >= 4 ) { for ( k = 0; k < 4; k++ ) { if ( hand_card.sut[k] >= 4 ) { return flush(hands, hand_card, deck_card, cg); } } if ( check_straight(remain_card, hand_card) >= 1 ) { return straight(hands, remain_card, hand_card, deck_card, cg); } if ( poker_point(hd) >= P3 ) { return pair(hands, hand_card, deck_card, remain_card); } return -1; } // 最後のtakeは別関数 if ( tk == 5 ) { return final_attack(hands, remain_card, hand_card, deck_card, cg); } return DEFAULT_NUM; }
void calc_exp( int hd[], int cg, int tk, int pointhd[], int pointnum, int deck[], int decknum, int recursioncount, int starthd ) { int nexthd[HNUM]; int nextdeck[CNUM]; int point = 0; int i, j; for ( i = starthd; i < HNUM; i++) { for ( j = 0; j < CNUM; j++) { // 山札にカードがあれば if ( deck[j] == 0 ) { // 手札とデッキの複製 arr_copy( nexthd, hd, HNUM ); nexthd[i] = j; arr_copy( nextdeck, deck, CNUM ); nextdeck[j] = -1; if ( recursioncount == 1 ) { // 一手目の期待値の加算 pointhd[i] += point_convert(poker_point(nexthd))*decknum; } else { // 二手目の期待値の加算 point = point_convert(poker_point(nexthd)); pointhd[pointnum] += point; if ( pointnum < i ) { pointhd[i] += point; } } if ( cg > 7 - RECURSION_LIMIT ) { continue; } if ( recursioncount >= RECURSION_LIMIT ) { continue; } // 再帰呼び出し if ( pointnum == -1 ) { calc_exp( nexthd, cg+1, tk, pointhd, i, nextdeck, decknum-1, recursioncount+1, i ); } else { calc_exp( nexthd, cg+1, tk, pointhd, pointnum, nextdeck, decknum-1, recursioncount+1, i ); } } } } }
int strategy(const int hd[], const int fd[], int cg, int tk, const int ud[], int us) { int i, k, decide; int sut[4] = {0}; int num[13] = {0}; int usut[4] = {0}; int unum[13] = {0}; for ( k = 0; k < HNUM; k++ ) { i = hd[k] / 13; sut[i]++; } for ( k = 0; k < HNUM; k++ ) { i = hd[k] % 13; num[i]++; } for ( k = 0; k < us; k++ ) { i = ud[k] / 13; usut[i]++; } for ( k = 0; k < us; k++ ) { i = ud[k] % 13; unum[i]++; } if (tk == 5 && us-cg >= 37) { return take6_hand(hd, ud, us); } if (poker_point(hd) >= 16) { return -1; } if (poker_point(hd) >= 8 && tk < 4) { return -1; } decide = flashreach(hd, sut, usut); if (decide != -1) { return decide; } decide = straight(hd, num, unum, sut, usut); if (decide != -1) { return decide; } if (tk < 2) { return -1; } decide = flash(hd, num, unum, sut, usut); if (decide != -1) { return decide; } if (tk == 4 && 52-5-us <= 11) { return -1; } if (tk == 3 && 52-5-us <= 22) { return -1; } decide = pair(hd, num, unum,sut); if (decide != -1) { return decide; } return -1; }
//========================================================= // スリーカインズ ( P3 8点 ) //========================================================= int Three_of_a_kind( const int hd[], int cg, int us ){ int i, j; // 反復変数 if( poker_point(hd) > P3 ){ return -1; } for( i=0; i<13; i++ ){ // 2枚1組 の数字を探す if( Num[i] == 2 ){ break; } // i番目の手札が 2枚1組 になっている } for( j=0; j<5; j++ ){ // 小さい数字から手札の番号を導く if( hand[j].num == i ){ return j; } } return -1; }
int final_attack(Handcard hd[], Cards remain_card, Cards hand_card, Cards deck_card, int cg) { int k1; int len = 0; int flag; int disc_num; int hand[HNUM]; // 特別 役判定に用いる // 判定用の手札を作成 for ( k1 = 0; k1 < HNUM; k1++ ) { hand[k1] = hd[k1].num_val; } // ロイヤルストレート if ( poker_point(hand) >= P9 ) { return -1; } disc_num = royal_straight_flush(hd, remain_card, deck_card, cg); if ( disc_num != -1 ) { return disc_num; } // ストレートフラッシュ if ( poker_point(hand) >= P8 ) { return -1; } disc_num = straight_flush(hd, hand_card, deck_card, cg); if ( disc_num != -1 ) { return disc_num; } // フォーカード if ( poker_point(hand) >= P7 ) { return -1; } disc_num = four_of_a_kind(hd, remain_card, hand_card, deck_card, cg); if ( disc_num != -1 ) { return disc_num; } // ストレート flag = 0; if ( poker_point(hand) >= P4 ) { return -1; } for ( k1 = 0; k1 < 13; k1++ ) { if ( remain_card.num[k1] >= 1 ) { len++; } else { len = 0; } if ( len >= 5) { flag = 1; } } if ( flag ) { return straight(hd, remain_card, hand_card, deck_card, cg); } flag = 0; // フラッシュ if ( poker_point(hand) >= P5 ) { return -1; } for ( k1 = 0; k1 < 4; k1++ ) { if ( remain_card.sut[k1] >= 5 ) { flag = 1; } } if ( flag ) { disc_num = flush(hd, hand_card, deck_card, cg); return disc_num; } // フルハウス ペア系 if ( poker_point(hand) >= P6 ) { return -1; } for (k1 = 0; k1 < HNUM; k1++ ) { if ( remain_card.num[hd[k1].num] == 1 ) { return k1; } } for (k1 = 0; k1 < HNUM; k1++ ) { if ( remain_card.num[hd[k1].num] == 2 ) { return k1; } } return disc_num; }
int poker_take(const int stock[], int tk, int used[], int *us) { //---- 局所変数 int field[FNUM]; // 場札 int hand[HNUM]; // 手札 int state[CHNG+1][HNUM]; // 局面(手札の列) int ope[CHNG]; // 打手札 int the; // 打手 int cg; // チェンジ回数 int take_p; // テイク得点 int k; // 反復変数 //---- テイクの準備 if ( *us +5 < CNUM ) { arr_copy(hand, &stock[*us], HNUM); // 手札の配布(5枚) arr_copy(state[0], hand, HNUM); // 局面の記録 } else { return 0; } //---- テイクの最中(チェンジの繰返し) for ( cg = 0; cg < CHNG; cg++ ) { if ( *us < CNUM-5 ) { the = strategy(hand, field, cg, tk, used, *us); // 戦略により捨札を決定 } else { the = -1; break; } ope[cg] = hand[the]; // 打手札の記録 if ( the < 0 ) { break; } // 手札を交換せずにテイク終了 field[cg] = ope[cg]; // 捨札を場札に追加 used[(*us)++] = ope[cg]; // 捨札を捨札配列に追加 hand[the] = stock[HNUM-1+(*us)]; // 手札を交換 arr_copy(state[cg+1], hand, HNUM); // 局面の記録 } //---- テイクの後処理 take_p = poker_point(hand); // テイク得点 for ( k = 0; k < HNUM; k++ ) { used[*us] = hand[k]; // 手札を捨札配列に追加 (*us)++; } //---- テイクの経過表示 if ( Disp_Mode ) { take_show(state, ope, field, cg, take_p); } return take_p; }
//========================================================= // フラッシュ ( P5 24点 ) //========================================================= int Flush( const int hd[], int cg, int us ){ int target; // 対象とするマーク(SHDC) struct card deck[13] = {0};// 山札の構造体 double Mark[4] = {0}; // 各マークの出る確率(0=S 1=H 2=D 3=C) double hand_pro[5] = {0}; // 各手札のマークの出る確率(1枚目,2枚目,...) double min = 1; // 最小値を格納 int chng_mark = 0; // 捨てるマーク int sut_max = 0; // 手持ちカードの最大組のマークを示す int ret=0; // 交換するカード int i, j; // 反復変数 int a, b; // 一時変数 if( poker_point(hd) >= P5 ){ return -1; } for( i=0; i< 4; i++ ){ deck[i].mark = 13-(sut[i] + udsut[i]); } // (手札と捨て札から)山札のマーク残り数を求める for( i=0; i<HNUM; i++ ){ if( CHNG-cg < HNUM-sut[i] || deck[hand[i].mark].mark == 0 ){ // 残りチェンジ数が必要枚数よりも多い場合 か 山札に対象マークカードがない hand_pro[i] = 0; }else{ a = Combi( deck[hand[i].mark].mark, HNUM - sut[hand[i].mark] ); // 13C4 など 13枚のうち、5枚に足りない4枚が出る確率を求める b = Combi( (52-us-HNUM), HNUM - sut[hand[i].mark] ); // 山札の中から 5枚に足りない4枚が出る確率を求める hand_pro[i] = (double)a/b; } } for( i=0; i<4; i++ ){ // 手札の中からマークの数が最大の物を探す if( sut_max < sut[i] ){ sut_max = sut[i]; target = i; } } if( sut[target] == 2 || sut[target] == 3 || sut[target] == 4 ){ // 既に出来ているペアは(確率を最大にして)崩さない for( j=0; j<HNUM; j++ ){ if( hand[j].mark == target ){ hand_pro[j] = 1.0; } } } for( i=0; i<HNUM; i++ ){ // 出る確率の低いマークを探す if( hand_pro[i] < min ){ min = hand_pro[i]; chng_mark = i; } } ret = chng_mark; return ret; }
int select_card_last( int hd[], int cg, int tk, int ud[], int us, int deck[], int decknum ) { int hightexp = poker_point(hd); int exp; int select = -1; int recursioncount = 1; int i; for ( i = 0; i < HNUM; i++ ) { MAX_EXP = 0; seek_hightest( hd, cg, tk, i, deck, recursioncount); if ( hightexp < MAX_EXP ) { hightexp = MAX_EXP; select = i; } } MAX_EXP = hightexp; return select; }
int strategy( const int hd[], const int fd[], int cg, int tk, const int ud[], int us) { int myhd[HNUM]; int select = -1; int hdcopy[CNUM]; int udcopy[us]; int currentpoint = 0; int deck[CNUM] = { 0 }; int decknum = CNUM; int k; // 最初から高い点なら手札を変えずに終了 arr_copy( hdcopy, hd, HNUM); currentpoint = poker_point(hdcopy); if ( currentpoint >= P6 ) { return -1; } arr_copy( udcopy, ud, us ); decknum = makedeck( hdcopy, udcopy, us, deck ); select = selectcard(hdcopy, cg, tk, udcopy, us, deck, decknum ); return select; }
void seek_hightest( int hd[], int cg, int tk, int changecard, int deck[], int recursioncount ) { int nexthd[HNUM]; int nextdeck[CNUM]; int currentpoint; int i, k; for ( i = 0; i < CNUM; i++) { if ( deck[i] == 0 ) { arr_copy( nexthd, hd, HNUM ); nexthd[changecard] = i; arr_copy( nextdeck, deck, CNUM ); nextdeck[i] = -1; currentpoint = poker_point(nexthd); if ( currentpoint > MAX_EXP ) { MAX_EXP = currentpoint; } if ( cg > 7 - LAST_RECURSION_LIMIT ) { continue; } if ( recursioncount >= LAST_RECURSION_LIMIT ) { continue; } for ( k = 0; k < HNUM; k++ ) { seek_hightest( nexthd, cg+1, tk, k, nextdeck, recursioncount+1 ); } } } }
int strategy(const int hd[], const int fd[], int cg, int tk, const int ud[], int us) { int disc_num; // 捨てるカードの番号(-1:捨てない) int t; int k, k1, k2; // 反復変数 Handcard hands[5]; // 手札を保管 Cards hand_card, deck_card, remain_card; // 手札の情報を格納 for (k1 = 0; k1 < HNUM; k1++ ) { hands[k1].num_val = hd[k1]; hands[k1].num = hd[k1] % 13; hands[k1].sut = hd[k1] / 13; hands[k1].pos = k1; for ( k2 = 0; k2 < 11; k2++ ) { hands[k1].exp[k2] = 0; } } calc_card(hands, &remain_card, &deck_card, &hand_card, ud, us); //フルハウス以上は確定 if ( tk != 5 && poker_point(hd) >= P6 ) { return -1; } disc_num = limit_take(cg, tk, hands, remain_card, hand_card, deck_card, hd); if ( disc_num != DEFAULT_NUM ) { return disc_num; } // ストレートリーチならストレートを狙う if ( check_straight(remain_card, hand_card) >= 1 ) { return straight(hands, remain_card, hand_card, deck_card, cg); } // フラッシュリーチならフラッシュを狙う for (k1 = 0; k1 < HNUM; k1++ ) { if ( hand_card.sut[k1] >= 4 && deck_card.sut[k1] >= 2 ) { return flush(hands, hand_card, deck_card, cg); } } /* // 3カード以上ならペア系を狙う */ if ( poker_point_pair(hand_card.num) == P3 ) { return pair(hands, hand_card, deck_card, remain_card); } return decide_discard(hands, remain_card, hand_card, deck_card, cg, tk); }
//========================================================= // ファイナル //========================================================= int Final( const int hd[], int cg, int us ){ struct card deck[13] = {0}; // 山札の構造体 int i, j, k, l, m, n; // 反復変数 int flag[5] = {0}; // 返却カード管理フラグ int max_point = 0; struct card mer_deck[13] = {0}; // 山札と手札を合わせた構造体 struct card ideal_hand[5]= {0}; // 理想手札の構造体 int vir_hand[5] = {0}; // 仮想手札の構造体 int vir_deck[52] = {0}; // 仮想山札 int deck_max = 0; // 仮想山札の最大数 for( i=0; i< 4; i++ ){ deck[i].mark = 13-(sut[i] + udsut[i]); } // (手札と捨て札から)山札のマーク残り数を求める for( i=0; i<13; i++ ){ deck[i].num = 4-(Num[i] + udNum[i]); } // (手札と捨て札から)山札の数字の残り数を求める for( i=0; i< 4; i++ ){ mer_deck[i].mark = deck[i].mark + sut[i] ; } // 山札と手札を合わせる(マーク) for( i=0; i<13; i++ ){ mer_deck[i].num = deck[i].num + Num[i] ; } // 山札と手札を合わせる(数字) for( j=0, i=0; i<52; i++ ){ // 仮想山札に捨て札から計算したカード追加 if( deck_flg[i] == 0 ){ vir_deck[j] = i; j++; } } for( i=0; i<HNUM; i++ ){ // 仮想山札に手札から計算したカード追加 vir_deck[j] = hand[i].orig; j++; } // for( i=0; i<HNUM; i++ ){ printf("hand[%d].orig = %d\n",i ,hand[i].orig ); } // for( i=0; i<j; i++ ){ printf("●vir_deck[%d] = %d\n", i, vir_deck[i] );} deck_max = j; max_point = 0; for( i=0; i<deck_max-4; i++ ){ for( j=i+1; j<deck_max-3; j++ ){ for( k=j+1; k<deck_max-2; k++ ){ for( l=k+1; l<deck_max-1; l++ ){ for( m=l+1; m<deck_max; m++ ){ vir_hand[0] = vir_deck[i]; vir_hand[1] = vir_deck[j]; vir_hand[2] = vir_deck[k]; vir_hand[3] = vir_deck[l]; vir_hand[4] = vir_deck[m]; if( max_point < poker_point(vir_hand) ){ max_point = poker_point(vir_hand); ideal_hand[0].orig = vir_hand[0]; // printf("i=%d ",i ); ideal_hand[1].orig = vir_hand[1]; // printf("j=%d ",j ); ideal_hand[2].orig = vir_hand[2]; // printf("k=%d ",k ); ideal_hand[3].orig = vir_hand[3]; // printf("l=%d ",l ); ideal_hand[4].orig = vir_hand[4]; // printf("m=%d \n",m ); } } } } } } for( i=0; i<HNUM; i++ ){ ideal_hand[i].mark = ideal_hand[i].orig/13; ideal_hand[i].num = ideal_hand[i].orig%13; } /* 仮想手札に近づくように切る(仮想手札以外のものを切る) */ for( i=0; i<HNUM; i++ ){ for( j=0; j<HNUM; j++ ){ if( hand[i].orig == ideal_hand[j].orig ){ // 理想手札のi番目と同じものがある = flag = 1 flag[i] = 1; } } } for( i=0; i<HNUM; i++ ){ if( flag[i] == 0 ){ return i; } } return -1; }
/* i|0 1 2 3 4 5 6 7 8 9 10 11 12 13 ----------------------------------- |A 2 3 4 5 6 7 8 9 T J Q K A */ int Straight( const int hd[], int cg, int us ){ int i, j,k; // 反復変数 int a,b,c; // 計算に使う一時変数 int chng=-1; // 交換するnum int ret = -1; struct card deck[14] = {0}; // 山札の構造体 double deck_pro[14] = {0}; // デッキからストレートのできる各々のnumの確率 deck_pro[0] = A = deck_pro[13] double hand_pro[13] = {0}; // 手札のカードの確率 double min =100; int count = 0; int tmp1, tmp2; if( poker_point(hd) >= P4 ){ return -1; } /*----- 事前処理--------------------- -------------------- */ for( i=0; i< 4; i++ ){ deck[i].mark = 13-(sut[i] + udsut[i]); } // (手札と捨て札から)山札のマーク残り数を求める for( i=0; i<13; i++ ){ deck[i].num = 4-(Num[i] + udNum[i]); } // (手札と捨て札から)山札の数字の残り数を求める deck[13].num = deck[0].num; //------------------------ 手札に同じ数字がある場合、山札に多い方を残す for( i=0; i<4; i++ ){ if( 1 < Num[i] ){ // 同じ数字が2枚ある場合 for( j=0; j<HNUM; j++){ if( hand[j].num == i ){ tmp1 = j; break;} // 数字からマークを調べる } for( k=0; k<HNUM; k++){ if( hand[k].num == i && tmp1 != k ){ tmp2 = k; } // 数字からマークを調べる } if( deck[tmp1].num < deck[tmp2].num ){ // 手札の tmp1 番目 と tmp2 番目が同じ数字 残りマークの少ない方を捨てる return tmp1; }else{ return tmp2; } } } //------------------------ for( i=0; i<HNUM; i++ ){ for( j=0; j<14; j++ ){ if( hand[i].num != j && flg[j] != -1 ){ // 手札にあるものは -1 とする flg[j] = deck[j].num; }else{ flg[j] = -1; } } } flg[13] = flg[0]; for( i=0; i<14-4; i++ ){ // 5つの塊で見ていく a = 1; count = 0; for( j=i; j<i+HNUM; j++ ){ if( flg[j] != -1 && flg[j] != 0 ){ // 手札にない かつ 山札の枚数が 0でない a *= flg[j]; // 手札にないカードについて確率の一部分を求める count++; } } b = Permu( (52-HNUM-us)-count, count); c = Permu( 52-HNUM-us, CHNG-cg ); for( k=i; k<i+HNUM; k++ ){ deck_pro[k] += (double)(a*b)/c; } } deck_pro[0] += deck_pro[13]; // AとKの後のAは同じため // 捨てる捜索範囲は i=0 i<13 まで 仮想Aは 含めない // 手札の番号について確率を格納し、その5つの中から比較する。 for( i=0; i<13; i++ ){ for( j=0; j<HNUM; j++ ){ if( i == hand[j].num ){ hand_pro[i] = deck_pro[i]; } } } // 確率が最小のものを探す。 for( i=0; i<13; i++ ){ if( hand_pro[i] < min && hand_pro[i] != 0 ){ min = hand_pro[i]; chng = i; } } // 手札から交換対象 chng を探す for( i=0; i<HNUM; i++ ){ if( hand[i].num == chng ){ ret = i; } } return ret; }
//==================================================================== // 補助関数 //==================================================================== //========================================================= // フォーカード ( P7 64点 ) //========================================================= int Four_of_a_kind( const int hd[], int cg, int us ){ int i, j; // 反復変数 int num_min; // とりあえず宣言しただけなので使うときに確認を! int target; // 対象とする数字 struct card deck[13] = {0}; // 山札の構造体 int ret = -1; int ret2 = -1; int tmp1 = -1, tmp2 = -1; if( poker_point(hd) > P7 ){ return -1; } for( i=0; i< 4; i++ ){ deck[i].mark = 13-(sut[i] + udsut[i]); } // (手札と捨て札から)山札のマーク残り数を求める for( i=0; i<13; i++ ){ deck[i].num = 4-(Num[i] + udNum[i]); } // (手札と捨て札から)山札の数字の残り数を求める // ここに来たときは既に3枚1組がある状態 で進めていく // 対象となる数字を見つける for( i=0; i<13; i++ ){ if( Num[i] == 3 ){ target = i; } } // 山札に必要な残りの数字が有るか確認 なければフルハウスへ変更 if( deck[target].num < 1 ){ return Full_house(hd,cg,us); } for( i=0; i<13; i++ ){ // フォーカードができると仮定して 捨てる 1組 or 2組 の数字を探す if( Num[i] == 1 || Num[i] == 2 ){ tmp1 = i; for( j=i+1; j<13; j++){ if( Num[j] == 1 || Num[j] == 2 ){ tmp2 = j; break; } } } } if( tmp2 != -1 ){ if( deck[tmp1].num < deck[tmp2].num ){ // 山札に残っている数字の枚数が少ない方を捨てる ret =tmp1; }else if( deck[tmp2].num < deck[tmp2].num ){ ret = tmp2; }else if( deck[tmp1].num == deck[tmp2].num ){ if( deck[hand[tmp1].mark].mark < deck[hand[tmp2].mark].mark ){ // 山札に少ないマークを捨てる ret = tmp1; }else{ ret = tmp2; } } for( i=0; i<HNUM; i++ ){ if( hand[i].num == ret ){ return i; } } }else { // tmp2 = -1 のとき すなわち 2枚1組だった場合 (AAA55)など for( i=0; i<HNUM; i++ ){ if( hand[i].num =! target ){ for( j=i+1; j<HNUM; j++ ){ if( hand[i].num != target ){ if( deck[hand[i].mark].mark < deck[hand[j].mark].mark ){ // 山札に少ないマークを捨てる return i; }else{ return j; } } } } } } /* 手札から数字を探す */ return ret2; }