Home > Blog > C Card Game Poker Source Code: A Practical Guide to Building a Poker Engine in C

C Card Game Poker Source Code: A Practical Guide to Building a Poker Engine in C

Welcome to a comprehensive, practical, and SEO-friendly guide on building a compact yet capable poker engine in the C programming language. This article walks you through the core design decisions, data structures, and the essential algorithms required to model a Texas Hold’em style poker game. Along the way, you’ll find carefully crafted C source code snippets, explanations suitable for beginners and seasoned developers, and actionable steps to compile and test your own engine. If you’re a game developer, a systems programmer, or simply curious about how card games translate into efficient C code, this guide will provide a solid foundation.

Why focus on C for a poker engine? Because C gives you tight control over memory, cache locality, and performance—factors that matter in a turn-based card game where evaluations and simulations may be performed thousands or millions of times per minute. A well-structured C project can scale from a small educational prototype to a robust, portable poker framework that supports variants, AI opponents, and even multiplayer logic. In this article, you’ll learn how to map a real game’s rules into clean data models and deterministic algorithms, while keeping the code readable, maintainable, and accessible to search engines and readers alike.

Overview: what you’ll build in this guide

The core deliverable is a minimal but fully functional poker engine in C capable of evaluating the best 5-card hand from 7 cards (two hole cards plus five board cards) for two players. The engine includes:

  • A simple, portable card and deck representation, including shuffling.
  • A straightforward 5-card hand evaluator with clear tie-breaking rules.
  • A 7-card evaluator that brute-forces all 21 five-card combinations to find the best hand.
  • A tiny main program that demonstrates dealing, evaluating, and comparing two players.
  • Clear guidance on building, testing, and extending the engine for Hold’em-like games or variants.

The approach in this article keeps the code approachable, emphasizes correctness, and provides a natural stepping stone toward more advanced features such as a full-fledged Hold’em engine, AI opponents, or a networked multiplayer mode. If you are reading this for SEO, you’ll notice how the article uses structured headings, keyword-rich sections, and practical, repeatable code blocks that readers can copy and adapt.

Data models: representing cards, suits, and hands

At the heart of any card game is a compact representation of cards. In C, you typically store a rank and a suit. A rank from 2 through 14 (where 11=Jack, 12=Queen, 13=King, 14=Ace) and a suit from a small enum keep the memory footprint predictable. A well-designed model also makes it easy to print cards, compare them, and feed them into hand evaluators.

Key design goals for data modeling:

  • Small, predictable memory layout to improve cache efficiency
  • Clear separation of concerns between deck handling and hand evaluation
  • Simple APIs to create, shuffle, deal, and evaluate

The following code blocks illustrate a compact, pragmatic approach to modeling cards, suits, and 7-card hands. Use them as a starting point and adapt as needed for your project.

Core code: Card, Suit, Deck, and a working print utility

In this first code block, you’ll see a minimal yet complete setup for cards and a deck. The emphasis is on readability and portability across platforms (Windows, Linux, macOS). The code compiles with standard C89/C99 compilers and relies only on the standard library for randomness and I/O.

// card.h (inline in this post for brevity; split into separate headers in real projects)
#include <stdio.h>
#include <stdlib.h>

typedef enum { CLUBS = 0, DIAMONDS = 1, HEARTS = 2, SPADES = 3 } Suit;

typedef struct {
    unsigned rank; // 2 .. 14
    Suit suit;
} Card;

typedef struct {
    Card cards[52];
} Deck;

// Initialize a standard 52-card deck
static inline void init_deck(Deck* d) {
    int idx = 0;
    for (int s = 0; s < 4; ++s) {
        for (int r = 2; r <= 14; ++r) {
            d->cards[idx].rank = (unsigned)r;
            d->cards[idx].suit = (Suit)s;
            idx++;
        }
    }
}

// Simple Fisher-Yates shuffle
static inline void shuffle_deck(Deck* d, unsigned int seed) {
    srand(seed);
    for (int i = 51; i > 0; --i) {
        int j = rand() % (i + 1);
        Card tmp = d->cards[i];
        d->cards[i] = d->cards[j];
        d->cards[j] = tmp;
    }
}

// Helper to print a single card
static inline const char* rank_name(unsigned r) {
    static const char* names[] = {"2","3","4","5","6","7","8","9","T","J","Q","K","A"};
    return names[r - 2];
}
static inline const char* suit_name(Suit s) {
    static const char* names[] = {"Clubs","Diamonds","Hearts","Spades"};
    return names[s];
}
static inline void print_card(const Card* c) {
    printf("%s of %s", rank_name(c->rank), suit_name(c->suit));
}

This snippet defines the basic data types and utilities. It’s intentionally straightforward so readers can immediately start experimenting with a deck and basic dealing. The real power comes when you wire these components into a hand evaluator, which we’ll cover next.

Core algorithm: five-card evaluator (simplified and educational)

The five-card evaluator is the core algorithm for scoring hands. In Hold’em, you evaluate the best 5-card hand from seven cards; a practical approach is to implement a robust five-card evaluator and use a 7-card evaluator that brute-forces all 21 possible 5-card combos. The following code block provides a compact, understandable 5-card evaluator. It’s not the ultra-fast tree with precomputed tables, but it is excellent for learning, testing, and small games. You can replace it later with a faster evaluator if you need higher throughput.

// hand_evaluator.h (embedded here for readability)
typedef struct {
    int rank_class; // 8..0 using our ranking scheme
    int tiebreakers[5];
} HandValue;

// Compare two hand values: return 1 if a > b, -1 if a < b, 0 if equal
static inline int hv_cmp(const HandValue* a, const HandValue* b) {
    if (a->rank_class != b->rank_class) return (a->rank_class > b->rank_class) ? 1 : -1;
    for (int i = 0; i < 5; ++i) {
        if (a->tiebreakers[i] != b->tiebreakers[i])
            return (a->tiebreakers[i] > b->tiebreakers[i]) ? 1 : -1;
    }
    return 0;
}

// Evaluate a 5-card hand
static HandValue evaluate_5card(const Card five[5]) {
    int counts[15] = {0};      // index by rank 2..14
    int suit_cnt[4] = {0};     // per-suit counts
    int ranks_seen[5];          // raw ranks for high-card tie-breakers
    int idx = 0;
    int present[15] = {0};       // 0/1 if rank is present

    for (int i = 0; i < 5; ++i) {
        Card c = five[i];
        counts[c.rank]++;
        suit_cnt[c.suit]++;
        present[c.rank] = 1;
        ranks_seen[idx++] = c.rank;
    }

    // Straight detection (including A-5 wheel)
    int straight_high = 0;
    // Check standard straights: 14..5
    for (int high = 14; high >= 5; --high) {
        int ok = 1;
        for (int r = high; r > high - 5; --r) {
            if (!present[r]) { ok = 0; break; }
        }
        if (ok) { straight_high = high; break; }
    }
    // Wheel: A-2-3-4-5 (high = 5)
    if (!straight_high && present[14] && present[5] && present[4] && present[3] && present[2]) {
        straight_high = 5;
    }

    // Flush check
    int is_flush = 0;
    for (int s = 0; s < 4; ++s) if (suit_cnt[s] == 5) is_flush = 1;

    // Collect rank groups
    int four = 0, three = 0;
    int four_rank = -1, three_rank = -1;
    int pairs[3]; int pcount = 0;
    for (int r = 2; r <= 14; ++r) {
        if (counts[r] == 4) { four = 1; four_rank = r; }
        else if (counts[r] == 3) { three = 1; three_rank = r; }
        else if (counts[r] == 2) { if (pcount < 3) pairs[pcount++] = r; }
    }

    // Evaluate categories
    HandValue hv;
    hv.rank_class = 0;
    for (int i = 0; i < 5; ++i) hv.tiebreakers[i] = 0;
    if (is_flush && straight_high) { // Straight Flush
        hv.rank_class = 8;
        hv.tiebreakers[0] = straight_high;
    } else if (four) { // Four of a Kind
        hv.rank_class = 7;
        hv.tiebreakers[0] = four_rank;
        // kicker
        int kicker = -1;
        for (int r = 14; r >= 2; --r) if (r != four_rank && counts[r] > 0) { kicker = r; break; }
        hv.tiebreakers[1] = kicker;
    } else if (three && pcount >= 1) { // Full House (three + pair)
        // If there is a second three, that works as pair too
        int pair_rank = (pcount ? pairs[0] : -1);
        if (three_rank != -1 && (pair_rank != -1 || (three_rank != -1 && counts[three_rank] == 3 && pcount >= 2))) {
            // Prefer actual pair rank if available; otherwise second triple acts as pair
            hv.rank_class = 6;
            hv.tiebreakers[0] = three_rank;
            hv.tiebreakers[1] = (pcount ? pair_rank : three_rank); // second trip becomes pair
        } else {
            // Fallback to three of a kind handled below
            hv.rank_class = 0;
        }
    } else if (is_flush) { // Flush
        hv.rank_class = 5;
        // Tiebreakers: sorted ranks of the flush
        int rlist[5], pos = 0;
        for (int r = 14; r >= 2; --r) {
            for (int t = 0; t < counts[r]; ++t) rlist[pos++] = r;
        }
        for (int i = 0; i < 5; ++i) hv.tiebreakers[i] = rlist[i];
    } else if (straight_high) { // Straight
        hv.rank_class = 4;
        hv.tiebreakers[0] = straight_high;
    } else if (three) { // Three of a Kind
        hv.rank_class = 3;
        hv.tiebreakers[0] = three_rank;
        // Kickers
        int kickers[2], k = 0;
        for (int r = 14; r >= 2; --r) {
            if (r != three_rank && counts[r] > 0) {
                kickers[k++] = r;
                if (k == 2) break;
            }
        }
        hv.tiebreakers[1] = kickers[0];
        hv.tiebreakers[2] = kickers[1];
    } else if (pcount >= 2) { // Two Pair
        // Sort pairs by rank descending
        int hi = pairs[0], lo = (pcount > 1 ? pairs[1] : -1);
        if (pcount > 1 && pairs[1] > hi) { hi = pairs[1]; lo = pairs[0]; }
        hv.rank_class = 2;
        hv.tiebreakers[0] = hi;
        hv.tiebreakers[1] = lo;
        // Kicker
        int kicker = -1;
        for (int r = 14; r >= 2; --r) {
            if (r != hi && r != lo && counts[r] > 0) { kicker = r; break; }
        }
        hv.tiebreakers[2] = kicker;
    } else if (pcount == 1) { // One Pair
        int pair_rank = pairs[0];
        hv.rank_class = 1;
        hv.tiebreakers[0] = pair_rank;
        int kickers[3], k = 0;
        for (int r = 14; r >= 2; --r) {
            if (r != pair_rank && counts[r] > 0) {
                kickers[k++] = r;
                if (k == 3) break;
            }
        }
        hv.tiebreakers[1] = kickers[0];
        hv.tiebreakers[2] = kickers[1];
        hv.tiebreakers[3] = kickers[2];
    } else { // High Card
        hv.rank_class = 0;
        int rlist[5], pos = 0;
        for (int r = 14; r >= 2; --r) {
            for (int t = 0; t < counts[r]; ++t) rlist[pos++] = r;
        }
        for (int i = 0; i < 5; ++i) hv.tiebreakers[i] = rlist[i];
    }
    return hv;
}

// Compare two HandValue for best hand
static int hv_better(const HandValue* a, const HandValue* b) {
    int c = hv_cmp(a, b);
    return c > 0;
}

The five-card evaluator above is intentionally didactic, making the tie-breaking rules explicit so readers can follow the logic. It supports all standard hand categories and produces a deterministic ranking that we can reuse in a 7-card evaluation stage. Note that performance should be considered for larger-scale games. For production-grade engines, exploring specialized hand-evaluator libraries or precomputed lookup tables (with proper licensing) can yield significantly faster results.

Bringing it together: evaluating 7 cards and running a tiny game loop

With the five-card evaluator in place, the next step is to extend to seven cards. The approach is straightforward: generate all 21 five-card combinations from seven cards, evaluate each with the 5-card evaluator, and keep the best result. This brute-force method is simple and correct, and it works well for learning purposes and small simulations. The following code demonstrates a minimal 7-card evaluator and a tiny main loop that compares two players' hands after dealing hole cards and a five-card board.

// seven_card_evaluator.c (integrated here for demonstration)

static inline int best_of_seven(const Card seven[7], HandValue* out_best) {
    HandValue best;
    best.rank_class = -1;
    for (int i = 0; i < 7 - 4; ++i)
        for (int j = i + 1; j < 7 - 3; ++j)
            for (int k = j + 1; k < 7 - 2; ++k)
                for (int l = k + 1; l < 7 - 1; ++l)
                    for (int m = l + 1; m < 7; ++m) {
                        Card five[5] = { seven[i], seven[j], seven[k], seven[l], seven[m] };
                        HandValue hv = evaluate_5card(five);
                        if (best.rank_class == -1 || hv_better(&hv, &best)) {
                            best = hv;
                        }
                    }
    *out_best = best;
    return 0;
}

#include <time.h>
int main(void) {
    Deck deck;
    init_deck(&deck);
    shuffle_deck(&deck, (unsigned)time(NULL));

    // Two players: hole cards
    Card p1[2] = { deck.cards[0], deck.cards[1] };
    Card p2[2] = { deck.cards[2], deck.cards[3] };

    // Board: five community cards
    Card board[5] = { deck.cards[4], deck.cards[5], deck.cards[6], deck.cards[7], deck.cards[8] };

    // Gather seven cards for each player
    Card seven1[7] = { p1[0], p1[1], board[0], board[1], board[2], board[3], board[4] };
    Card seven2[7] = { p2[0], p2[1], board[0], board[1], board[2], board[3], board[4] };

    HandValue hv1, hv2;
    best_of_seven(seven1, &hv1);
    best_of_seven(seven2, &hv2);

    // Print basic results
    printf("Player 1 hand: ");
    print_card(&p1[0]); printf(", "); print_card(&p1[1]);
    printf("  Board: ");
    for (int i = 0; i < 5; ++i) { printf(" ["); print_card(&board[i]); printf("]"); }
    printf("\\n");

    printf("Player 2 hand: ");
    print_card(&p2[0]); printf(", "); print_card(&p2[1]);
    printf("\\n");

    // A simple textual winner
    int comp = hv_cmp(&hv1, &hv2);
    if (comp > 0) {
        printf("Player 1 wins with rank %d vs %d\\n", hv1.rank_class, hv2.rank_class);
    } else if (comp < 0) {
        printf("Player 2 wins with rank %d vs %d\\n", hv2.rank_class, hv1.rank_class);
    } else {
        printf("Push: both players have the same hand value (tie)\\n");
    }

    return 0;
}

Note on the example: This sample program focuses on clarity and a straightforward demonstration. In a real project, you may want to separate the evaluator into separate compilation units (headers and source files) and add robust error handling, input validation, and more comprehensive output formatting. The important takeaway is the end-to-end flow: deck creation, shuffling, dealing, seven-card evaluation, and winner determination.

Build and run: compiling the C poker engine

To build the example program, you’ll typically use a C compiler such as GCC compatible with your platform. A minimal Makefile is convenient, but you can also compile directly from the command line. Here is a practical command-line workflow that assumes you combined the code snippets into source files named deck.c, evaluator.c, seven_card_evaluator.c, and main.c (or integrated them as shown for a compact single-file example).

// Example build command (adjust for your filesystem)
gcc -std=c11 -O2 -Wall -Wextra -Wpedantic -o poker_engine deck.c evaluator.c seven_card_evaluator.c main.c

For a self-contained single-file demonstration, you can paste all code into one file, say poker_demo.c, and compile with:

gcc -std=c11 -O2 -Wall -Wextra -o poker_demo poker_demo.c

Tips for a smooth build and testing cycle:

  • Keep compiler warnings enabled to catch potential portability issues across platforms.
  • Use -O2 or -O3 for performance-tuning builds, but test with -O0 during development to ease debugging.
  • Leverage time-based seeding or a deterministic seed for reproducible tests when you’re debugging hand evaluation rules.
  • Consider adding a simple unit test harness (e.g., using a lightweight framework or your own test suite) to validate edge cases like straights, flushes, and full houses.

Optimization notes and practical extensions

As you evolve this engine from a teaching example to a production-ready tool, you’ll likely revisit several aspects for performance and feature richness. Here are practical directions and considerations:

  • Hand evaluation speed: The brute-force 7-card evaluator is robust for small games but can be slow in a real-time AI or Monte Carlo simulator. Consider implementing a fast 7-card evaluator (lookup tables, bitboard tricks, or a widely used open-source evaluator with proper licensing).
  • Memory layout and cache locality: A compact representation of cards and preallocated buffers can reduce cache misses during hand evaluation and simulations.
  • Extensibility for variants: You can add support for Omaha, Five-Card Draw, or other poker variants by adjusting deck usage (e.g., Omaha with four hole cards and board cards).
  • Game loop separation: Separate the engine logic (rules and evaluation) from the UI or network layer. This makes the engine testable and portable to different frontends (CLI, GUI, or multiplayer servers).
  • AI and opponents: Introduce a simple AI with move ordering decisions (fold, call, raise) based on hand strength, pot odds, and risk tolerance. As your AI grows, you’ll want to diversify heuristics and implement learning components or Monte Carlo simulations.

Tuning for readability, maintainability, and SEO

Beyond correctness and performance, you also want your codebase to be understandable and discoverable. Here are some practices that help both readers and search engines when you publish a blog post or a repository.

  • Document the algorithms: Use clear comments to explain the ranking scheme, tie-breakers, and all edge cases (e.g., wheel straights). A readable narrative helps readers and search engines understand the article’s structure.
  • Structure the code with headers and separation: Put public interfaces in header files (.h) and implementation details in source files (.c). This separation improves navigation in code readers and in search results when content is crawled.
  • Provide build instructions and a quick-start guide: A concise “How to build” section makes your article more approachable and increases user engagement, which is favorable for SEO.
  • Offer additional resources: Include references to established open-source evaluators and licensing considerations, so readers can explore more advanced techniques while respecting licenses.

Additional resources and next steps

If you want to take the project further, here are practical next steps:

  1. Experiment with Hold’em-style simulations: Implement a turn-based betting mechanism and reveal community cards in stages (flop, turn, river) before evaluating hands.
  2. Integrate a simple UI: Create a text-based interface that lets a user interact with the engine, view hands, and print boards in a friendly format.
  3. Explore open-source evaluations: Look for C-based poker evaluators with permissive licenses to replace the educational evaluator with a high-performance solution. Respect licensing terms when incorporating external code.
  4. Write unit tests: Introduce a small test suite that asserts correct hand types for known examples (e.g., a royal flush, a full house, etc.).
  5. Publish and share: Consider hosting on GitHub or a similar platform to showcase your architecture, code quality, and the engine’s design decisions to other developers and recruiters.

Frequently asked questions (FAQ)

Q: Is this engine suitable for a production game?
A: It’s a solid educational foundation. For production, you’ll want a faster evaluator, robust game loop, network multiplayer, and thorough testing. Always check licenses for any third-party evaluators you use.
Q: Can I use this for other card games?
A: Yes. The data structures (cards, deck, and combinatorial evaluation) are adaptable to games like Rummy or Blackjack with appropriate rules and scoring.
Q: How hard is it to extend to AI opponents?
A: Start with a rule-based heuristic and a simple evaluation of hand strength versus pot odds. Over time you can add Monte Carlo simulations or reinforcement learning strategies.

Summary and call to action

This article presented a practical, step-by-step approach to building a C-based poker engine, focusing on readable data models, a clear hand evaluation workflow, and a simple but functional game loop. The code blocks serve as a starting point that you can customize for your project’s needs. By combining solid programming discipline with careful attention to the user experience, you can turn a small, approachable example into a versatile engine for games, simulations, and AI experiments.

Ready to start coding? Copy the core ideas into your editor, compile, and run the demo. Tweak constants, refine the evaluator, and watch your engine come to life. If you’d like, you can extend the blog with additional variants, performance benchmarks, and a richer testing harness to help readers turn this into a scalable project.

Get involved: next steps and reader engagement

If you found this guide useful, consider sharing your own enhancements, benchmarking results, or alternative evaluation strategies in the comments or your own repository. Open collaboration makes learning faster, and a well-documented project can become a valuable resource for aspiring game developers and engineers exploring C-based game logic. Happy coding, and may your poker engine be fast, correct, and easy to extend.


Teen Patti Master — Every Card, Every Win, Every Adventure

🎮 A New Challenge Every Round

In Teen Patti Master, no two games are the same. Experience unpredictable matches with new opponents and fresh strategies.

🏆 Climb the Ranks

Earn your place on the global leaderboard. Teen Patti Master lets you prove your skills and rise to the top.

💰 Real Rewards for Every Hand

Play for more than just chips — Teen Patti Master gives you the chance to win real money for every clever move.

⚡ Real-Time, No Delay

Fast-paced gameplay and quick matchmaking ensure you’re always in the action. Teen Patti Master never keeps you waiting.
Download Now

Latest Blog

Unlocking the Secrets of Teen Patti: A Comprehensive Guide to the Classic Blackjack Game

Teen Patti, often referred to as Indian Poker, has surged in popularity both in India and around the world. Combining elements of bluffing, strategy, ...
read more >

The Ultimate Guide to Teen Patti: Master the Game and Boost Your Skills

Teen Patti, often referred to as Indian Poker, is a popular card game that has captivated players for generations. It combines strategy, psychology, a...
read more >

The Ultimate Guide to Teen Patti: Strategies, Variations, and Fun

Teen Patti, also known as Indian Poker, is a thrilling card game that has captured the hearts of millions worldwide. Whether played at family gatherin...
read more >

Best Poker Game Sites 2025: Top Online Poker Rooms for Real Money, Bonuses, and Fair Play

In the crowded world of online poker, players chase the same essential rewards: smooth software, fair play, real money potential, and strong bonuses t...
read more >

The Ultimate Guide to Teen Patti Unity: Strategies, Tips, and Tricks for Success

Teen Patti, also known as Indian Poker, has gained immense popularity across the globe, especially in India, where it encapsulates social bonding and ...
read more >

Ultimate Guide to Teen Patti: Rules, Strategies, and Variants

Teen Patti, also known as Indian Poker, is a thrilling card game that has captured the hearts of players across India and beyond. With a blend of skil...
read more >

FAQs - Teen Patti Master

(Q.1) What is Teen Patti Master?
Ans: Teen Patti Master is a fun online card game based on the traditional Indian game called Teen Patti. You can play it with friends and other players all over the world.
(Q.2) How do I download Teen Patti Master?
Ans: Go to the app store on your phone, search for “Teen Patti Master,” click on the app, and then press “Install.”
(Q.3) Is Teen Patti Master free to play?
Ans: Yes, it’s free to download and play. But, if you want extra chips or other features, you can buy them inside the app.
(Q.4) Can I play Teen Patti Master with my friends?
Ans: Yes! The game has a multiplayer feature that lets you play with your friends in real time.
(Q.5) What is Teen Patti Speed?
Ans: Teen Patti Speed is a faster version of Teen Patti Master. It’s great for players who like quicker games.
(Q.6) How is Rummy Master different from Teen Patti Master?
Ans: Rummy Master is based on the card game Rummy, and Teen Patti Master is based on Teen Patti. Both need strategy and skill but have different rules.
(Q.7) Is Rummy Master available for all devices?
Ans: Yes, you can download Rummy Master on many different devices, like smartphones and tablets.
(Q.8) How do I start playing Slots Meta?
Ans: Download the Slots Meta app, create an account, and you can start playing different slot games.
(Q.9) Are there any strategies for winning in Slots Meta?
Ans: Slots mostly depend on luck, but knowing the game, like paylines and bonus features, and managing your money wisely can help.
(Q.10) Are these games purely based on luck?
Ans: Teen Patti and Slots rely a lot on luck, but Rummy Master needs more skill and strategy.
(Q.11) Is it safe to make in-app purchases in these games?
Ans: Yes, buying things inside these games is safe. They use secure payment systems to protect your financial information.
(Q.12) How often is Teen Patti Master App Updated?
Ans: Teen Patti Master Updates on regular basis so that the players don’t encounter any sort of issues with the game and you will always find the latest version of Teen Patti Master APK on our website.
(Q.13) Is there customer support available for Teen Patti Master and related games?
Ans: Yes, there’s customer support in the apps if you have any questions or problems.
(Q.14) Do I need an internet connection to play these games?
Ans: Yes, an internet connection is needed because these games are played online with other players.
(Q.15) How often are new features or games added?
Ans: New features and games are added regularly to keep everything exciting and fun.

Disclaimer: This game involves an element of financial risk and may be addictive. Please play responsibly and at your won risk.This game is strictly for users 18+.

Warning: www.cogviagra.com provides direct download links for Teen Patti Master and other apps, owned by Taurus.Cash. We don't own the Teen patti Master app or its copyrights; this site is for Teen Patti Master APK download only.

Teen Patti Master Game App Download Button