szktty #5183(2008/01/05 06:07 GMT) [ Other ] Rating0/0=0.00
Mac OS X (PowerPC 32bit) アセンブリで。PowerPCアセンブリ読めというのも無茶なので、以下やってることの説明です。先にほとんど同じロジック(#5168)で投稿されてしまいましたけど。
スート役は「すべてのスート役が同じ」場合のみ成り立つので、最初のスートを記録しておき、二枚目以降と比較すれば判断できます。途中に一つでも異なるスートがあれば、スート用レジスタを 0 にします。このレジスタには最初のスートのASCIIコードが入っているので、レジスタが 0 でなければフラッシュ系の役が成立することになります。
ランク役では、重複した枚数ごとにレジスタを用意します。このレジスタは1-13までのランクをビットで表したフラグです。
最初のカードのランクは、ノーペア用レジスタのビット 1<<ランク を立てます(ランクが5なら 1<<4 )。次のカードのランクも同じであれば、ワンペア用レジスタの同ビットを立てて、ノーペア用レジスタの同ビットを下ろします。これでペアは判断できます。
最後にストレートとロイヤルフラッシュですが、ノーペア用レジスタを使います。ロイヤルフラッシュはATJQKの組み合わせが決まっていますから、その箇所のビットを立てたビットマスクで判断できます。ストレートは連続した5つのビット(11111)をシフトしながらAND演算して判断します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382
;; ------------------------------------------------ ;; poker.s for Mac OS X (PowerPC 32bit) ;; % as -o poker.o poker.s && gcc poker.o -o poker ;; ------------------------------------------------ .machine ppc .globl _main ;; レジスタ ;; ;; r4: char *argv[] ;; r5: 残りカードの枚数 ;; r6: スキャンする文字(スートか数字) ;; r7: スート役(フラッシュ)フラグ(役候補スートのASCIIコードが入る) ;; r8: ノーペアの数字用フラグ(13ビット使用) ;; r9: ワンペア、ツーペア用フラグ(13ビット使用) ;; r10: スリーカード用フラグ(13ビット使用) ;; r11: フォーカード用フラグ(13ビット使用) ;; _main: ;; レジスタの初期化 addi r4, r4, 4 ; argv[1] にポインタを進める lwz r4, 0(r4) ; argv[1] の文字列をレジスタにロード li r5, 5 ; 残りカード5枚 li r7, 0 li r8, 0 li r9, 0 li r10, 0 li r11, 0 _scan_card: ;; 一文字目(スート) lbz r6, 0(r4) bl _scan_suit ; サブルーチン addi r4, r4, 1 ;; 二文字目(数字) lbz r6, 0(r4) bl _scan_rank ; サブルーチン ;; 繰り返しの準備 subi r5, r5, 1 cmpli cr7, r5, 0 beq cr7, _show_hand ; 5枚チェックし終えたら役を表示する addi r4, r4, 1 b _scan_card ; 繰り返し ;; スートのスキャン _scan_suit: ;; 最初のカードならそのままフラグをセット cmpli cr7, r5, 5 beq cr7, _scan_first_suit ;; 二枚目以降 cmpli cr7, r7, 0 ; フラグがゼロならフラッシュの可能性もゼロ beqlr cr7 cmpl cr7, r7, r6 ; 前のスートと同じなら戻る beqlr cr7 li r7, 0 ; 前のスートと異なるならフラグをクリア blr ; サブルーチン終了 ;; 最初のカードのスートのスキャン _scan_first_suit: add r7, r0, r6 ; r0 は 0 とみなされるので、r7 = r6 blr ; サブルーチン終了 ;; ランクのスキャン _scan_rank: ;; ASCIIコードを 0-12 の整数にする cmpli cr7, r6, 65 ; 'A' beq cr7, _scan_rank_ace cmpli cr7, r6, 84 ; 'T' beq cr7, _scan_rank_ten cmpli cr7, r6, 74 ; 'J' beq cr7, _scan_rank_jack cmpli cr7, r6, 81 ; 'Q' beq cr7, _scan_rank_queen cmpli cr7, r6, 75 ; 'K' beq cr7, _scan_rank_king ;; 2-9 subi r6, r6, 49 b _scan_rank_body _scan_rank_ace: li r6, 0 b _scan_rank_body _scan_rank_ten: li r6, 9 b _scan_rank_body _scan_rank_jack: li r6, 10 b _scan_rank_body _scan_rank_queen: li r6, 11 b _scan_rank_body _scan_rank_king: li r6, 12 b _scan_rank_body ;; r15: ランクのビット表現 ;; r16: 論理演算結果 _scan_rank_body: li r0, 1 slw r15, r0, r6 ; 左シフト (1<<r6) ;; フォーカード:同ランクのカードが三枚あるかチェック and r16, r10, r15 cmpli cr7, r16, 0 bgt cr7, _switch_four_kind_flag ;; スリーカード:同ランクのカードが二枚あるかチェック and r16, r9, r15 cmpli cr7, r16, 0 bgt cr7, _switch_three_kind_flag ;; ワンペア:同ランクのカードが一枚あるかチェック and r16, r8, r15 cmpli cr7, r16, 0 bgt cr7, _switch_one_pair_flag ;; ノーペア or r8, r8, r15 ; ビットフラグを立てる blr ; サブルーチン終了 ;; ワンペア _switch_one_pair_flag: or r9, r9, r15 ; ビットフラグを立てる xor r8, r8, r15 ; ノーペアのフラグを下ろす blr ; サブルーチン終了 ;; スリーカード _switch_three_kind_flag: or r10, r10, r15 ; ビットフラグを立てる xor r9, r9, r15 ; ワンペアのフラグを下ろす blr ; サブルーチン終了 ;; フォーカード _switch_four_kind_flag: or r11, r11, r15 ; ビットフラグを立てる xor r8, r8, r15 ; スリーカードのフラグを下ろす blr ; サブルーチン終了 ;; 役の表示 _show_hand: ;; フラッシュ、ストレートフラッシュ、 ;; ロイヤルフラッシュのチェック cmpli cr7, r7, 0 bne cr7, _check_flushes ;; フォーカードのチェック andi. r0, r11, 8191 ; (1<<13)-1 cmpli cr7, r0, 0 bgt cr7, _show_four_kind ;; フルハウス、スリーカードのチェック andi. r0, r10, 8191 cmpli cr7, r0, 0 bgt cr7, _check_full_house_or_three_kind ;; ワンペア、ツーペアのチェック andi. r0, r9, 8191 cmpli cr7, r0, 0 bgt cr7, _check_one_or_two_pair ;; ストレートのチェック bl _check_straight cmpli cr7, r2, 0 bne cr7, _show_straight ;; ノーペア b _show_no_pair ;; フラッシュ、ストレートフラッシュ、ロイヤルフラッシュ _check_flushes: ;; ロイヤルフラッシュのチェック ;; ランク ATJQK のビットマスク li r0, 1|(1<<9)|(1<<10)|(1<<11)|(1<<12) and r2, r8, r0 cmpl cr7, r2, r0 beq cr7, _show_royal_flush ;; ストレートフラッシュのチェック bl _check_straight cmpli cr7, r2, 0 bne cr7, _show_straight_flush ;; フラッシュ b _show_flush ;; ストレートのチェック(サブルーチン) ;; ストレートなら r2 > 0 にして戻る _check_straight: ;; ビットマスク 11111 を左にずらしながら9回AND演算する li r0, (1<<5)-1 ; ビットマスク li r2, 0 ; 左シフト数 _find_straight: slw r15, r0, r2 ; 左シフト and r17, r8, r15 ; ノーペア用フラグを調べる cmpl cr7, r17, r15 beq cr7, _found_straight addi r2, r2, 1 ; 次のループの準備 cmpli cr7, r2, 9 ble cr7, _find_straight li r2, 0 ; 5つの連続した数字がなかった blr ; サブルーチン終了 _found_straight: li r2, 1 ; 5つの連続した数字を発見 blr ; サブルーチン終了 ;; フルハウスかスリーカード _check_full_house_or_three_kind: ;; ワンペアがあればフルハウス andi. r0, r9, 8191 cmpli cr7, r0, 0 bgt cr7, _show_full_house b _show_three_kind ;; ワンペアかツーペア _check_one_or_two_pair: li r0, 1 ; これをシフト li r2, 0 ; 左シフト数 li r16, 0 ; ペアの数 ;; ペア用フラグからペアの数をカウントする _find_pairs: slw r15, r0, r2 and r17, r9, r15 addi r2, r2, 1 cmpli cr7, r17, 0 bgt cr7, _found_pair cmpli cr7, r2, 13 ; 0-12 の 13 回チェック ble cr7, _find_pairs ;; ペアの数で分岐 cmpli cr7, r16, 1 beq cr7, _show_one_pair b _show_two_pair ;; 見つけたペアの数を増加 _found_pair: addi r16, r16, 1 b _find_pairs ; 戻る ;; ノーペア _show_no_pair: lis r4, hi16(no_pair) addi r4, r4, lo16(no_pair) li r5, 8 b _print_and_exit ;; ワンペア _show_one_pair: lis r4, hi16(one_pair) addi r4, r4, lo16(one_pair) li r5, 9 b _print_and_exit ;; ツーペア _show_two_pair: lis r4, hi16(two_pair) addi r4, r4, lo16(two_pair) li r5, 9 b _print_and_exit ;; スリーカード _show_three_kind: lis r4, hi16(three_kind) addi r4, r4, lo16(three_kind) li r5, 16 b _print_and_exit ;; ストレート _show_straight: lis r4, hi16(straight) addi r4, r4, lo16(straight) li r5, 9 b _print_and_exit ;; フラッシュ _show_flush: lis r4, hi16(flush) addi r4, r4, lo16(flush) li r5, 6 b _print_and_exit ;; フルハウス _show_full_house: lis r4, hi16(full_house) addi r4, r4, lo16(full_house) li r5, 11 b _print_and_exit ;; ストレートフラッシュ _show_straight_flush: lis r4, hi16(straight_flush) addi r4, r4, lo16(straight_flush) li r5, 15 b _print_and_exit ;; フォーカード _show_four_kind: lis r4, hi16(four_kind) addi r4, r4, lo16(four_kind) li r5, 15 b _print_and_exit ;; ロイヤルフラッシュ _show_royal_flush: lis r4, hi16(royal_flush) addi r4, r4, lo16(royal_flush) li r5, 12 b _print_and_exit ;; 文字列を出力して終了する ;; r4 に文字列のアドレスを、r5 に文字列の長さをセットしておく _print_and_exit: ;; sys_write() li r3, 1 ; 標準出力 li r0, 4 ; sys_write sc ; 呼び出し b _exit _exit: ;; sys_exit() li r3, 0 li r0, 1 sc ;; 定数 .data .align 2 no_pair: .asciz "No pair\n" .align 2 one_pair: .asciz "One pair\n" .align 2 two_pair: .asciz "Two pair\n" .align 2 three_kind: .asciz "Three of a kind\n" .align 2 straight: .asciz "Straight\n" .align 2 flush: .asciz "Flush\n" .align 2 full_house: .asciz "Full house\n" .align 2 four_kind: .asciz "Four of a kind\n" .align 2 straight_flush: .asciz "Straight flush\n" .align 2 royal_flush: .asciz "Royal flush\n" .align 2
Rating0/0=0.00-0+
[ reply ]
szktty
#5183()
[
Other
]
Rating0/0=0.00
Mac OS X (PowerPC 32bit) アセンブリで。PowerPCアセンブリ読めというのも無茶なので、以下やってることの説明です。先にほとんど同じロジック(#5168)で投稿されてしまいましたけど。
スート役は「すべてのスート役が同じ」場合のみ成り立つので、最初のスートを記録しておき、二枚目以降と比較すれば判断できます。途中に一つでも異なるスートがあれば、スート用レジスタを 0 にします。このレジスタには最初のスートのASCIIコードが入っているので、レジスタが 0 でなければフラッシュ系の役が成立することになります。
ランク役では、重複した枚数ごとにレジスタを用意します。このレジスタは1-13までのランクをビットで表したフラグです。
最初のカードのランクは、ノーペア用レジスタのビット 1<<ランク を立てます(ランクが5なら 1<<4 )。次のカードのランクも同じであれば、ワンペア用レジスタの同ビットを立てて、ノーペア用レジスタの同ビットを下ろします。これでペアは判断できます。
最後にストレートとロイヤルフラッシュですが、ノーペア用レジスタを使います。ロイヤルフラッシュはATJQKの組み合わせが決まっていますから、その箇所のビットを立てたビットマスクで判断できます。ストレートは連続した5つのビット(11111)をシフトしながらAND演算して判断します。
;; ------------------------------------------------ ;; poker.s for Mac OS X (PowerPC 32bit) ;; % as -o poker.o poker.s && gcc poker.o -o poker ;; ------------------------------------------------ .machine ppc .globl _main ;; レジスタ ;; ;; r4: char *argv[] ;; r5: 残りカードの枚数 ;; r6: スキャンする文字(スートか数字) ;; r7: スート役(フラッシュ)フラグ(役候補スートのASCIIコードが入る) ;; r8: ノーペアの数字用フラグ(13ビット使用) ;; r9: ワンペア、ツーペア用フラグ(13ビット使用) ;; r10: スリーカード用フラグ(13ビット使用) ;; r11: フォーカード用フラグ(13ビット使用) ;; _main: ;; レジスタの初期化 addi r4, r4, 4 ; argv[1] にポインタを進める lwz r4, 0(r4) ; argv[1] の文字列をレジスタにロード li r5, 5 ; 残りカード5枚 li r7, 0 li r8, 0 li r9, 0 li r10, 0 li r11, 0 _scan_card: ;; 一文字目(スート) lbz r6, 0(r4) bl _scan_suit ; サブルーチン addi r4, r4, 1 ;; 二文字目(数字) lbz r6, 0(r4) bl _scan_rank ; サブルーチン ;; 繰り返しの準備 subi r5, r5, 1 cmpli cr7, r5, 0 beq cr7, _show_hand ; 5枚チェックし終えたら役を表示する addi r4, r4, 1 b _scan_card ; 繰り返し ;; スートのスキャン _scan_suit: ;; 最初のカードならそのままフラグをセット cmpli cr7, r5, 5 beq cr7, _scan_first_suit ;; 二枚目以降 cmpli cr7, r7, 0 ; フラグがゼロならフラッシュの可能性もゼロ beqlr cr7 cmpl cr7, r7, r6 ; 前のスートと同じなら戻る beqlr cr7 li r7, 0 ; 前のスートと異なるならフラグをクリア blr ; サブルーチン終了 ;; 最初のカードのスートのスキャン _scan_first_suit: add r7, r0, r6 ; r0 は 0 とみなされるので、r7 = r6 blr ; サブルーチン終了 ;; ランクのスキャン _scan_rank: ;; ASCIIコードを 0-12 の整数にする cmpli cr7, r6, 65 ; 'A' beq cr7, _scan_rank_ace cmpli cr7, r6, 84 ; 'T' beq cr7, _scan_rank_ten cmpli cr7, r6, 74 ; 'J' beq cr7, _scan_rank_jack cmpli cr7, r6, 81 ; 'Q' beq cr7, _scan_rank_queen cmpli cr7, r6, 75 ; 'K' beq cr7, _scan_rank_king ;; 2-9 subi r6, r6, 49 b _scan_rank_body _scan_rank_ace: li r6, 0 b _scan_rank_body _scan_rank_ten: li r6, 9 b _scan_rank_body _scan_rank_jack: li r6, 10 b _scan_rank_body _scan_rank_queen: li r6, 11 b _scan_rank_body _scan_rank_king: li r6, 12 b _scan_rank_body ;; r15: ランクのビット表現 ;; r16: 論理演算結果 _scan_rank_body: li r0, 1 slw r15, r0, r6 ; 左シフト (1<<r6) ;; フォーカード:同ランクのカードが三枚あるかチェック and r16, r10, r15 cmpli cr7, r16, 0 bgt cr7, _switch_four_kind_flag ;; スリーカード:同ランクのカードが二枚あるかチェック and r16, r9, r15 cmpli cr7, r16, 0 bgt cr7, _switch_three_kind_flag ;; ワンペア:同ランクのカードが一枚あるかチェック and r16, r8, r15 cmpli cr7, r16, 0 bgt cr7, _switch_one_pair_flag ;; ノーペア or r8, r8, r15 ; ビットフラグを立てる blr ; サブルーチン終了 ;; ワンペア _switch_one_pair_flag: or r9, r9, r15 ; ビットフラグを立てる xor r8, r8, r15 ; ノーペアのフラグを下ろす blr ; サブルーチン終了 ;; スリーカード _switch_three_kind_flag: or r10, r10, r15 ; ビットフラグを立てる xor r9, r9, r15 ; ワンペアのフラグを下ろす blr ; サブルーチン終了 ;; フォーカード _switch_four_kind_flag: or r11, r11, r15 ; ビットフラグを立てる xor r8, r8, r15 ; スリーカードのフラグを下ろす blr ; サブルーチン終了 ;; 役の表示 _show_hand: ;; フラッシュ、ストレートフラッシュ、 ;; ロイヤルフラッシュのチェック cmpli cr7, r7, 0 bne cr7, _check_flushes ;; フォーカードのチェック andi. r0, r11, 8191 ; (1<<13)-1 cmpli cr7, r0, 0 bgt cr7, _show_four_kind ;; フルハウス、スリーカードのチェック andi. r0, r10, 8191 cmpli cr7, r0, 0 bgt cr7, _check_full_house_or_three_kind ;; ワンペア、ツーペアのチェック andi. r0, r9, 8191 cmpli cr7, r0, 0 bgt cr7, _check_one_or_two_pair ;; ストレートのチェック bl _check_straight cmpli cr7, r2, 0 bne cr7, _show_straight ;; ノーペア b _show_no_pair ;; フラッシュ、ストレートフラッシュ、ロイヤルフラッシュ _check_flushes: ;; ロイヤルフラッシュのチェック ;; ランク ATJQK のビットマスク li r0, 1|(1<<9)|(1<<10)|(1<<11)|(1<<12) and r2, r8, r0 cmpl cr7, r2, r0 beq cr7, _show_royal_flush ;; ストレートフラッシュのチェック bl _check_straight cmpli cr7, r2, 0 bne cr7, _show_straight_flush ;; フラッシュ b _show_flush ;; ストレートのチェック(サブルーチン) ;; ストレートなら r2 > 0 にして戻る _check_straight: ;; ビットマスク 11111 を左にずらしながら9回AND演算する li r0, (1<<5)-1 ; ビットマスク li r2, 0 ; 左シフト数 _find_straight: slw r15, r0, r2 ; 左シフト and r17, r8, r15 ; ノーペア用フラグを調べる cmpl cr7, r17, r15 beq cr7, _found_straight addi r2, r2, 1 ; 次のループの準備 cmpli cr7, r2, 9 ble cr7, _find_straight li r2, 0 ; 5つの連続した数字がなかった blr ; サブルーチン終了 _found_straight: li r2, 1 ; 5つの連続した数字を発見 blr ; サブルーチン終了 ;; フルハウスかスリーカード _check_full_house_or_three_kind: ;; ワンペアがあればフルハウス andi. r0, r9, 8191 cmpli cr7, r0, 0 bgt cr7, _show_full_house b _show_three_kind ;; ワンペアかツーペア _check_one_or_two_pair: li r0, 1 ; これをシフト li r2, 0 ; 左シフト数 li r16, 0 ; ペアの数 ;; ペア用フラグからペアの数をカウントする _find_pairs: slw r15, r0, r2 and r17, r9, r15 addi r2, r2, 1 cmpli cr7, r17, 0 bgt cr7, _found_pair cmpli cr7, r2, 13 ; 0-12 の 13 回チェック ble cr7, _find_pairs ;; ペアの数で分岐 cmpli cr7, r16, 1 beq cr7, _show_one_pair b _show_two_pair ;; 見つけたペアの数を増加 _found_pair: addi r16, r16, 1 b _find_pairs ; 戻る ;; ノーペア _show_no_pair: lis r4, hi16(no_pair) addi r4, r4, lo16(no_pair) li r5, 8 b _print_and_exit ;; ワンペア _show_one_pair: lis r4, hi16(one_pair) addi r4, r4, lo16(one_pair) li r5, 9 b _print_and_exit ;; ツーペア _show_two_pair: lis r4, hi16(two_pair) addi r4, r4, lo16(two_pair) li r5, 9 b _print_and_exit ;; スリーカード _show_three_kind: lis r4, hi16(three_kind) addi r4, r4, lo16(three_kind) li r5, 16 b _print_and_exit ;; ストレート _show_straight: lis r4, hi16(straight) addi r4, r4, lo16(straight) li r5, 9 b _print_and_exit ;; フラッシュ _show_flush: lis r4, hi16(flush) addi r4, r4, lo16(flush) li r5, 6 b _print_and_exit ;; フルハウス _show_full_house: lis r4, hi16(full_house) addi r4, r4, lo16(full_house) li r5, 11 b _print_and_exit ;; ストレートフラッシュ _show_straight_flush: lis r4, hi16(straight_flush) addi r4, r4, lo16(straight_flush) li r5, 15 b _print_and_exit ;; フォーカード _show_four_kind: lis r4, hi16(four_kind) addi r4, r4, lo16(four_kind) li r5, 15 b _print_and_exit ;; ロイヤルフラッシュ _show_royal_flush: lis r4, hi16(royal_flush) addi r4, r4, lo16(royal_flush) li r5, 12 b _print_and_exit ;; 文字列を出力して終了する ;; r4 に文字列のアドレスを、r5 に文字列の長さをセットしておく _print_and_exit: ;; sys_write() li r3, 1 ; 標準出力 li r0, 4 ; sys_write sc ; 呼び出し b _exit _exit: ;; sys_exit() li r3, 0 li r0, 1 sc ;; 定数 .data .align 2 no_pair: .asciz "No pair\n" .align 2 one_pair: .asciz "One pair\n" .align 2 two_pair: .asciz "Two pair\n" .align 2 three_kind: .asciz "Three of a kind\n" .align 2 straight: .asciz "Straight\n" .align 2 flush: .asciz "Flush\n" .align 2 full_house: .asciz "Full house\n" .align 2 four_kind: .asciz "Four of a kind\n" .align 2 straight_flush: .asciz "Straight flush\n" .align 2 royal_flush: .asciz "Royal flush\n" .align 2Rating0/0=0.00-0+
[ reply ]