• System. out. println("Hello world")!

    После нескольких часов игры в казино с Ультимейт покер против диллера, мне стало интересно насколько это плюсовая игра. Некоторые говорят, что можно играть в плюс, некоторые что это слабоминусовая игра. Хочу проверить не на реальные деньги. Раньше учил программирование на Java. Хочу написать небольшую програмку, чтобы можно было использовать разные стратегии и понимать вообще как это будет действовать, максимально имитируя живую игру. Буду сюда постить код, идеи разные и результаты. Если не получится ничего, то хоть останутся записи для истории, может кому-то будет интересно в будущем!

    https://github.com/knighenko/UltimatePoker

    Сообщение отредактировал Goldenboat - 28.12.2024, 3:45
    Ответить Цитировать
    1/8
    + 1
  • Написал несколько классов.

    Класс Card представляет собой карту для игры в Холдем (или любую другую карточную игру можно). В этом классе  содержится информация о масти карты и её значении (ранге).

    package com.ultimate.objects;

    public class Card {
        // Масть карты (пики, черви, бубны, трефы)
        private String suit;
        // Ранг карты (2-10, J, Q, K, A)
        private int rank;

        public Card(String suit, int rank) {
            this.suit = suit;
            this.rank = rank;
        }

        public String getSuit() {
            return suit;
        }

        public void setSuit(String suit) {
            this.suit = suit;
        }

        public int getRank() {
            return rank;
        }

        public void setRank(int rank) {
            this.rank = rank;
        }

        @Override
        public String toString() {
            return rankToString(rank) + " of " + suit;
        }

        private String rankToString(int rank) {
            if (rank == 11) return "Jack";
            if (rank == 12) return "Queen";
            if (rank == 13) return "King";
            if (rank == 14) return "Ace";
            return String.valueOf(rank);
        }
    }
     

    Класс Player будет представлять игрока. Он будет содержать информацию о руках игрока , а также методы для взаимодействия с этими картами и позже добавлю поле количество чипов.

    package com.ultimate.objects;

    import java.util.ArrayList;
    import java.util.List;

    public class Player {
        private String name;
        List<Card> hand = new ArrayList<>();

        public Player(String name) {
            this.name = name;
        }

        public void addCard(Card card) {
            hand.add(card);
        }

        @Override
        public String toString() {
            return name + "'s hand: " + hand;
        }
    }
     

    Класс BestHand буду использовать для оценки и представления лучшей руки игрока. Этот класс будет содержать логику для оценки комбинаций карт (например, Пара, Стрит, Флеш и т. д.) и вычисления лучшей возможной руки, которую игрок может собрать, используя свои две карты и общие карты (комьюнити карты). Но еще нужно как-то придумать чтобы находить победителя, между двумя игроками, особенно когда старшая карта будет и определить киккер (в будущем может больше игроков будет), но поскольку это Ультимейт покер, то 2 игрока - Хедзап

    package com.ultimate.objects;

    import java.util.*;
    import java.util.stream.Collectors;

    public class BestHand {
        private List<Card> playerCards;
        private List<Card> communityCards;
        private List<Card> getAllCards;

        private List<Card> allCards;

        public BestHand(List<Card> playerCards, List<Card> communityCards) {
            allCards = new ArrayList<>(communityCards);
            allCards.addAll(playerCards); // Объединяем карты игрока и общие карты
        }

        // Проверка на флеш
        private static boolean isFlush(List<Card> cards) {
            return cards.stream()
                    .collect(Collectors.groupingBy(card -> card.getSuit()))
                    .values().stream()
                    .anyMatch(suitGroup -> suitGroup.size() >= 5);
        }

        // Проверка на стрит
        private static boolean isStraight(List<Card> cards) {
            List<Integer> ranks = cards.stream()
                    .map(card -> card.getRank())
                    .distinct()
                    .sorted()
                    .collect(Collectors.toList());

            for (int i = 0; i <= ranks.size() - 5; i++) {
                if (ranks.get(i + 4) - ranks.get(i) == 4) return true;
            }

            // Проверка на стрит с тузом (A, 2, 3, 4, 5)
            return ranks.containsAll(Arrays.asList(2, 3, 4, 5, 14));
        }

        // Проверка на стрит-флеш
        private static boolean isStraightFlush(List<Card> cards) {
            Map<String, List<Card>> suits = cards.stream()
                    .collect(Collectors.groupingBy(card -> card.getSuit()));

            for (List<Card> suitCards : suits.values()) {
                if (isStraight(suitCards)) return true;
            }
            return false;
        }

        // Проверка на каре
        private static boolean isFourOfAKind(List<Card> cards) {
            return hasOfAKind(cards, 4);
        }

        // Проверка на фул-хаус
        private static boolean isFullHouse(List<Card> cards) {
            return isThreeOfAKind(cards) && isPair(cards);
        }

        // Проверка на тройку
        private static boolean isThreeOfAKind(List<Card> cards) {
            return hasOfAKind(cards, 3);
        }

        // Проверка на две пары
        private static boolean isTwoPair(List<Card> cards) {
            return cards.stream()
                    .collect(Collectors.groupingBy(card -> card.getRank()))
                    .values().stream()
                    .filter(rankGroup -> rankGroup.size() == 2)
                    .count() >= 2;
        }

        // Проверка на пару
        private static boolean isPair(List<Card> cards) {
            return hasOfAKind(cards, 2);
        }

        // Проверка на конкретное количество одинаковых карт
        private static boolean hasOfAKind(List<Card> cards, int count) {
            return cards.stream()
                    .collect(Collectors.groupingBy(card -> card.getRank()))
                    .values().stream()
                    .anyMatch(rankGroup -> rankGroup.size() == count);
        }

        public String getCombination() {
            // Проверяем комбинации от самой сильной к самой слабой
            if (isStraightFlush(allCards)) return "Straight Flush";
            if (isFourOfAKind(allCards)) return "Four of a Kind";
            if (isFullHouse(allCards)) return "Full House";
            if (isFlush(allCards)) return "Flush";
            if (isStraight(allCards)) return "Straight";
            if (isThreeOfAKind(allCards)) return "Three of a Kind";
            if (isTwoPair(allCards)) return "Two Pair";
            if (isPair(allCards)) return "Pair";
            return "High Card";

        }
    }
     

    Вообще наверное лучше на GitHub ветку создам и там буду код выставлять.

    Сообщение отредактировал Goldenboat - 24.12.2024, 19:36
    Ответить Цитировать
    2/8
    + 0
  • Пока самое сложное это составить алгоритмы для проверки киккеров, когда комбинации игроков одинаковые. Особенно для фулхаусов трудновато было и стрит-флешей. Роял Флеш- это особый случай стритфлеша, я не стал его выделять пока, поскольку он выпадает очень редко (в живом покере только отчаянный лудоман будет за ним гонятся чтобы получить выплату 1к500 в Ультимейт покере на ставке Блайнд). Хотя я видел в Розвадове некоторых игроков, которые гонялись за стритфлешем и поймав его однажды, радовались как слоны на все казино! Как закончу с киккерами, перейду к созданию класса Колода, где буду реализовывать пресловутое ГСЧ (пока не знаю как).

    Ответить Цитировать
    3/8
    + 0
  • Создал класс Deck - Колода. ГСЧ использую стандартное из библиотеки Java, класс Random. Позже может быть по желанию, сделаю свой, например зависящий от температуры на Гавайских островах 🤩. Дальше буду реализовывать более расширено класс Player (Казино это тоже игрок будет, только оппонент наш с безмерным количеством денег, с которого мы всегда будем добирать в идеале 😆). Потом еще надо написать класс для обработки ставок и подсчета выигранных/проигранных денег

    package com.ultimate;

    import com.ultimate.objects.Card;

    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;

    public class Deck {
        private List<Card> cards;

        /**
         * Конструктор создаёт новую колоду карт и тасует её
         */
        public Deck() {
            cards = new ArrayList<>();
            initializeDeck();
            shuffle();
        }

        /**
         * Метод для инициализации колоды (добавления всех карт)
         */
        private void initializeDeck() {
            String[] suits = {"♥", "♦", "♣", "♠"};
            int[] ranks = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};

            for (String suit : suits) {
                for (int rank : ranks) {
                    cards.add(new Card(suit, rank));
                }
            }
        }

        /**
         * Метод для тасовки колоды
         */
        public void shuffle() {
            Collections.shuffle(cards);
        }

        /**
         * Метод для раздачи карты из колоды
         */
        public Card dealCard() {
            if (cards.isEmpty()) {
                System.out.println("The deck is empty. Cannot deal any more cards.");
                return null;
            }
            return cards.remove(cards.size() - 1);
        }

        /**
         * Метод для раздачи нескольких карт
         */
        public List<Card> dealMultipleCards(int count) {
            List<Card> dealtCards = new ArrayList<>();
            for (int i = 0; i < count; i++) {
                Card card = dealCard();
                if (card != null) {
                    dealtCards.add(card);
                } else {
                    break;
                }
            }
            return dealtCards;
        }

        /**
         * Метод для добавления карты в колоду
         */
        public void addCard(Card card) {
            cards.add(card);
        }

        /**
         * Метод для проверки, пуста ли колода
         */
        public boolean isEmpty() {
            return cards.isEmpty();
        }

        /**
         * Метод для удаления конкретной карты из колоды
         */
        public boolean removeCard(Card card) {
            return cards.remove(card);
        }

        /**
         * Метод для проверки, содержит ли колода конкретную карту
         */
        public boolean containsCard(Card card) {
            return cards.contains(card);
        }

        /**
         * Метод для получения количества оставшихся карт в колоде
         */
        public int remainingCards() {
            return cards.size();
        }

        /**
         * Метод для восполнения колоды и её тасовки
         */
        public void resetDeck() {
            cards.clear();
            initializeDeck();
            shuffle();
        }

        /**
         * Метод для отображения всех карт в колоде
         */
        public void displayDeck() {
            for (Card card : cards) {
                System.out.println(card);
            }
        }
        /**
         * Метод для "сжигания" (удаления) карты из колоды
         */
        public Card burnCard() {
            if (cards.isEmpty()) {
                System.out.println("The deck is empty. No card to burn.");
                return null;
            }
            return cards.remove(cards.size() - 1);
        }
    }
     

    Ответить Цитировать
    4/8
    + 1
  • Вроде бы реализовал алгоритмы префлоп раздач, кроме флопа и терна до вскрытия на ривере. Из 1м раздач в хедзапе дает следующий результат, думаю можно доверять ГСЧ.

    Ответить Цитировать
    5/8
    + 0
  • Пишу класс Game для реализаци процесса игры. Пока в тестовом варианте использую только ситуацию хедзап, и всего 2 ставки Анте и Блайнд. При ничьей никто не выиграл, если диллер-анте и Блайнд забирается, если игрок выиграл по то Анте и Блайнд удваивается. Запустил в цикле на 100, 1000 и 10000 раздач. Результаты выводил на график для наглядности. В итоге как и ожидалось, не выигрываем и не проигрываем на дистанции. Хорошо, что рейка нет, а так бы были в минус. Хорошо, что люди не компьютеры и не играют по ГТО, а то только Рейк бы месили и все. Завтра буду реализовывать пуш анте и ставку Play

    Ответить Цитировать
    6/8
    + 1
  •  

    Первые результаты. Если мы будем все время на любых картах ставить одинаковые ставки в размере х1 на Ante, Blind, Play, то после 10000 раздач получим такие результаты. Явно минусовая игра. Завтра попробую какую-нибудь стратегию из интернета реализовать, может график поменяется как-то....во что я очень слабо верю. Больше всего забирает денег - невыплата Blind, когда мы выигрываем (Blind выплачивается только со стрита и то 1 к1).

    Ответить Цитировать
    7/8
    + 0
  • Применив одну из стратегий из интернета (https://www.pokernews.com/casino/video-poker/ultimate-texas-holdem.htm)  (возможно где-то что-то не так написал в коде, но он открыт и если у кого будет желание, то можем ещё поработать), можно с уверенностью сказать что Ultimate Poker минусовая игра, намного больше чем 2-3%, если мы не учитываем игру по тейк-профит/стоплосс, а просто игру на дистанцию. Да, на кратком промежутке раздач (например 30-50 раздач) мы можем идти в плюс и будет складываться впечатление, что мы "бьем поляну", но уже на 1000 рук или даже 10000 рук  мы будем идти в минус. Использование тейкпрофит/стоплосс позволит минимизировать потери, но все равно не убережёт от банкротства (моделировал ситуацию из ежедневной игры по 300 раздач в день, 300 дней в год - можно так 3 года идти в плюс, а потом 2 года в минус). Итог- не рассматривать как источник дохода.

    Ответить Цитировать
    8/8
    + 0
1 человек читает эту тему (1 гость):
Зачем регистрироваться на GipsyTeam?
  • Вы сможете оставлять комментарии, оценивать посты, участвовать в дискуссиях и повышать свой уровень игры.
  • Если вы предпочитаете четырехцветную колоду и хотите отключить анимацию аватаров, эти возможности будут в настройках профиля.
  • Вам станут доступны закладки, бекинг и другие удобные инструменты сайта.
  • На каждой странице будет видно, где появились новые посты и комментарии.
  • Если вы зарегистрированы в покер-румах через GipsyTeam, вы получите статистику рейка, бонусные очки для покупок в магазине, эксклюзивные акции и расширенную поддержку.