Yahtzee oyunu oyna


18

Yahtzee oyununda, oyuncular sırayla 5 6 taraflı zarı her turda üç defaya kadar yuvarlarlar, muhtemelen rulolar arasında zar tasarrufu yaparlar ve daha sonra ruloları için kullanmak istedikleri kategoriyi seçerler. Bu, başka kategori kalmayana kadar devam eder (13 turdan sonra olur). Ardından, oyuncuların skorları hesaplanır ve en yüksek puana sahip oyuncu kazanır.

Kategoriler aşağıdaki gibidir ("zar toplamı" belirtilen zardaki pip sayısının toplanması anlamına gelir):

  • Üst Bölüm
    • Aslar : 1 pip gösteren zarların toplamı
    • İkili : 2 pip gösteren zarların toplamı
    • Üçlü : 3 pip gösteren zar toplamı
    • Dört ayak : 4 pip gösteren zar toplamı
    • Beşleme : 5 pip gösteren zarların toplamı
    • Sixes : 6 pip gösteren zarların toplamı
  • Alt Bölüm
    • Üçlü : Aynı değerde 3 zar, puan tüm zarların toplamıdır
    • Dörtlü : Aynı değerde 4 zar, puan tüm zarların toplamıdır
    • Full House : bir değeri olan 3 zar ve diğeri ile 2 zar, puan 25
    • Küçük Düz : 4 ardışık zar, puan 30
    • Büyük Düz : 5 ardışık zar, skor 40
    • Yahtzee : Aynı değere sahip 5 zarın hepsi, skor 50
    • Şans : herhangi bir zar kombinasyonu, puan tüm zarların toplamıdır

Kategori seçenekleri hakkında birkaç kural vardır:

  • Bir oyuncu atışıyla eşleşmeyen bir kategori seçerse, o kategori için 0 puan alır.
  • Bir oyuncu üst bölümde en az 63 puan alırsa, 35 bonus puanı alır.
  • Bir oyuncu bir Yahtzee atmışsa ancak Yahtzee kategorisi zaten alınmışsa (başka bir Yahtzee tarafından - bir bayan için 0 doldurmak sayılmaz), 100 puan bonus kazanır. Bu bonus her Yahtzee'ye birinciden sonra verilir.
    • Ayrıca, oynatıcı yine de bir kategori doldurmayı seçmelidir. Rulolarına karşılık gelen üst bölüm kategorisini seçmelidirler (örneğin, Sixes kategorisine 5 6'lı bir rulo yerleştirilmelidir). Karşılık gelen üst bölüm kategorisi daha önce kullanılmışsa, Yahtzee alt bölüm kategorisi için kullanılabilir (bu durumda Full House, Small Straight veya Large Straight seçildiğinde 0 yerine normal puan miktarı verilir). Alt bölüm kategorilerinin tümü alınırsa, Yahtzee 0 puanla kullanılmayan bir üst bölüm kategorisine uygulanabilir.

Meydan okuma

Bu mücadelede yarışmacılar Yahtzee'nin 1000 oyununu oynayacaklar. Her oyunun sonunda en yüksek puanı alan başvurulara 1 puan verilir. Tüm oyunlar bittikten sonra, en çok puana sahip olan başvuru kazanır. Beraberlik varsa beraberlik bozulana kadar sadece beraberinde gönderilen gönderilerle ek oyunlar oynanır.

kontrolör

Denetleyici kodunun tamamı bu GitHub deposunda bulunabilir . İşte oyuncuların etkileşime gireceği genel arayüzler:

public interface ScorecardInterface {

    // returns an array of unused categories
    Category[] getFreeCategories();

    // returns the current total score
    int getScore();

    // returns the current Yahtzee bonus
    int getYahtzeeBonus();

    // returns the current Upper Section bonus
    int getUpperBonus();

    // returns the current Upper Section total
    int getUpperScore();

}
public interface ControllerInterface {

    // returns the player's scorecard (cloned copy, so don't try any funny business)
    ScorecardInterface getScoreCard(Player p);

    // returns the current scores for all players, in no particular order
    // this allows players to compare themselves with the competition,
    //  without allowing them to know exactly who has what score (besides their own score),
    //  which (hopefully) eliminates any avenues for collusion or sabotage
    int[] getScores();

}
public enum Category {
    ACES,
    TWOS,
    THREES,
    FOURS,
    FIVES,
    SIXES,
    THREE_OF_A_KIND,
    FOUR_OF_A_KIND,
    FULL_HOUSE,
    SMALL_STRAIGHT,
    LARGE_STRAIGHT,
    YAHTZEE,
    CHANCE;

    // determines if the category is part of the upper section
    public boolean isUpper() {
        // implementation
    }

    // determines if the category is part of the lower section
    public boolean isLower() {
        // implementation
    }

    // determines if a given set of dice fits for the category
    public boolean matches(int[] dice) {
        // implementation
    }

    // calculates the score of a set of dice for the category
    public int getScore(int[] dice) {
        // implementation
    }

    // returns all categories that fit the given dice
    public static Category[] getMatchingCategories(int[] dice) {
        // implementation
    }
}
public class TurnChoice {

    // save the dice with the specified indexes (0-4 inclusive)
    public TurnChoice(int[] diceIndexes) {
        // implementation
    }

    // use the current dice for specified category
    public TurnChoice(Category categoryChosen) {
        // implementation
    }

}

public abstract class Player {

    protected ControllerInterface game;

    public Player(ControllerInterface game) {
        this.game = game;
    }

    public String getName() {
        return this.getClass().getSimpleName();
    }

    // to be implemented by players
    // dice is the current roll (an array of 5 integers in 1-6 inclusive)
    // stage is the current roll stage in the turn (0-2 inclusive)
    public abstract TurnChoice turn(int[] dice, int stage);

}

Ayrıca, içinde bazı yararlı yöntemler vardır Util.java. Denetleyici kodunu basitleştirmek için oradalar, ancak istedikleri takdirde oyuncular tarafından kullanılabilirler.

kurallar

  • Oyuncuların, Scorecard.getScorestüm oyuncuların mevcut puanlarını görmek için yöntemi kullanma dışında hiçbir şekilde etkileşime girmesine izin verilmez . Bu, diğer oyuncularla gizli anlaşma yapmayı veya sistemin ortak arayüzün parçası olmayan kısımlarını manipüle ederek diğer oyuncuları sabote etmeyi içerir.
  • Bir oyuncu yasadışı bir hamle yaparsa, turnuvada yarışmasına izin verilmez. Yasadışı hamlelere neden olan tüm sorunlar, turnuvanın yürütülmesinden önce çözülmelidir.
  • Turnuva yapıldıktan sonra ek başvurular yapılırsa, yeni sunumlarla yeni bir turnuva düzenlenecek ve kazanan sunum buna göre güncellenecektir. Bununla birlikte, yeni turnuvayı yönetirken hızlılık konusunda hiçbir garanti vermiyorum.
  • Gönderiler, denetleyici kodundaki gerçek oyun kurallarından sapmasına neden olan herhangi bir hatayı kullanamaz. Bana (bir yorumda ve / veya GitHub sorununda) hataları işaret edin ve bunları düzeltirim.
  • Java'nın yansıtma araçlarının kullanılması yasaktır.
  • JVM üzerinde çalışan veya Java veya JVM bayt koduna derlenebilen herhangi bir dil (Scala veya Jython gibi), Java ile arayüz oluşturmak için gereken ek kodları sağladığınız sürece kullanılabilir.

Son Yorumlar

Denetleyiciye eklememi istediğiniz herhangi bir yardımcı program varsa, yorumlarda sorun ve / veya GitHub'da bir sorun yaratın ve kuralın kırılmasına veya bilginin açığa çıkmasına izin vermediğini varsayarak ekleyeceğim. hangi oyuncular özel değildir. Kendiniz yazmak ve GitHub'da bir çekme isteği oluşturmak istiyorsanız, daha da iyi!


ACES? Yani ONES? Bunlar zar değil, kartlar.
mbomb007


Oynadığımda bunun denildiğini hatırlamıyorum, ama tamam.
mbomb007

Bir zar seti verilen belirli bir kategori için puan almak için bir yöntem var mı?
mbomb007

@ mbomb007 Hayır, ama kesinlikle bir tane yapabilirim :)
Mego

Yanıtlar:


4

DummyPlayer

package mego.yahtzee;
import java.util.Random;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class DummyPlayer extends Player {

    public DummyPlayer(ControllerInterface game) {
        super(game);
    }

    @Override
    public TurnChoice turn(int[] dice, int stage) {
        Category[] choices = game.getScoreCard(this).getFreeCategories();
        Category choice = choices[new Random().nextInt(choices.length)];
        if(IntStream.of(dice).allMatch(die -> die == dice[0])) {
            if(Stream.of(choices).filter(c -> c == Category.YAHTZEE).count() > 0) {
                choice = Category.YAHTZEE;
            } else if(Stream.of(choices).filter(c -> c == Util.intToUpperCategory(dice[0])).count() > 0) {
                choice = Util.intToUpperCategory(dice[0]);
            } else {
                choices = Stream.of(game.getScoreCard(this).getFreeCategories()).filter(c -> c.isLower()).toArray(Category[]::new);
                if(choices.length > 0) {
                    choice = choices[new Random().nextInt(choices.length)];
                } else {
                    choices = game.getScoreCard(this).getFreeCategories();
                    choice = choices[new Random().nextInt(choices.length)];
                }
            }
        }
        return new TurnChoice(choice);
    }

}

Bu oyuncu, Yahtzee kontrol cihazında bulunan araçların nasıl kullanılacağı konusunda temel bir taslak olarak hizmet etmek için burada. Mümkün olduğunca Yahtzee'yi seçer ve katı joker kurallarına uyurken rastgele seçimler yapar.


1

Aslar ve Sekizler

Son zamanlarda ne kadar meşgul olduğum sayesinde bu çok daha uzun sürdü.

package mego.yahtzee;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import static mego.yahtzee.Category.*;

public class AcesAndEights extends Player {
    private Category[] freeCategories, matchingCategories, usableCategories;

    public AcesAndEights(ControllerInterface game) {
        super(game);
    }

    @Override
    public TurnChoice turn(int[] dice, int stage) {
        List<Integer> holdIndices = new java.util.ArrayList<>();

        freeCategories = game.getScoreCard(this).getFreeCategories();

        matchingCategories = Category.getMatchingCategories(dice);
        Arrays.sort(matchingCategories);

        usableCategories = Arrays.stream(freeCategories)
                                 .filter(this::isMatchingCategory)
                                 .toArray(Category[]::new);
        Arrays.sort(usableCategories);

        if (isMatchingCategory(YAHTZEE))
            return doYahtzeeProcess(dice);

        if (isUsableCategory(FULL_HOUSE))
            return new TurnChoice(FULL_HOUSE);

        if (stage == 0 || stage == 1) {
            if (isMatchingCategory(THREE_OF_A_KIND)) {
                int num = 0;
                for (int i : dice) {
                    if (Util.count(Util.boxIntArray(dice), i) >= 3) {
                        num = i;
                        break;
                    }
                }
                for (int k = 0; k < 5; k++) {
                    if (dice[k] == num)
                        holdIndices.add(k);
                }
                return new TurnChoice(toIntArray(holdIndices.toArray(new Integer[0])));
            }

            if (isFreeCategory(LARGE_STRAIGHT) || isFreeCategory(SMALL_STRAIGHT)) {
                if (isUsableCategory(LARGE_STRAIGHT))
                    return new TurnChoice(LARGE_STRAIGHT);

                if (isMatchingCategory(SMALL_STRAIGHT)) {
                    if (!isFreeCategory(LARGE_STRAIGHT))
                        return new TurnChoice(SMALL_STRAIGHT);

                    int[] arr = Arrays.stream(Arrays.copyOf(dice, 5))
                                      .distinct()
                                      .sorted()
                                      .toArray();
                    List<Integer> l = Arrays.asList(Util.boxIntArray(dice));
                    if (Arrays.binarySearch(arr, 1) >= 0 && Arrays.binarySearch(arr, 2) >= 0) {
                        holdIndices.add(l.indexOf(1));
                        holdIndices.add(l.indexOf(2));
                        holdIndices.add(l.indexOf(3));
                        holdIndices.add(l.indexOf(4));
                    }
                    else if (Arrays.binarySearch(arr, 2) >= 0 && Arrays.binarySearch(arr, 3) >= 0) {
                        holdIndices.add(l.indexOf(2));
                        holdIndices.add(l.indexOf(3));
                        holdIndices.add(l.indexOf(4));
                        holdIndices.add(l.indexOf(5));
                    }
                    else {
                        holdIndices.add(l.indexOf(3));
                        holdIndices.add(l.indexOf(4));
                        holdIndices.add(l.indexOf(5));
                        holdIndices.add(l.indexOf(6));
                    }
                    return new TurnChoice(toIntArray(holdIndices.toArray(new Integer[0])));
                }
            }

            if (isFreeCategory(FULL_HOUSE)) {
                int o = 0, t = o;
                for (int k = 1; k <= 6; k++) {
                    if (Util.count(Util.boxIntArray(dice), k) == 2) {
                        if (o < 1)
                            o = k;
                        else
                            t = k;
                    }
                }

                if (o > 0 && t > 0) {
                    for (int k = 0; k < 5; k++) {
                        if (dice[k] == o || dice[k] == t)
                            holdIndices.add(k);
                    }
                    return new TurnChoice(toIntArray(holdIndices.toArray(new Integer[0])));
                }
            }
        }
        else {
            Arrays.sort(freeCategories, Comparator.comparingInt((Category c) -> c.getScore(dice))
                                                  .thenComparingInt(this::getPriority)
                                                  .reversed());
            return new TurnChoice(freeCategories[0]);
        }

        return new TurnChoice(new int[0]);
    }

    private TurnChoice doYahtzeeProcess(int[] dice) {
        if (isUsableCategory(YAHTZEE))
            return new TurnChoice(YAHTZEE);

        Category c = Util.intToUpperCategory(dice[0]);
        if (isUsableCategory(c))
            return new TurnChoice(c);

        Category[] arr = Arrays.stream(freeCategories)
                               .filter(x -> x.isLower())
                               .sorted(Comparator.comparing(this::getPriority)
                                                 .reversed())
                               .toArray(Category[]::new);
        if (arr.length > 0)
            return new TurnChoice(arr[0]);

        Arrays.sort(freeCategories, Comparator.comparingInt(this::getPriority));
        return new TurnChoice(freeCategories[0]);
    }

    private boolean isFreeCategory(Category c) {
        return Arrays.binarySearch(freeCategories, c) >= 0;
    }

    private boolean isMatchingCategory(Category c) {
        return Arrays.binarySearch(matchingCategories, c) >= 0;
    }

    private boolean isUsableCategory(Category c) {
        return Arrays.binarySearch(usableCategories, c) >= 0;
    }

    private int getPriority(Category c) {
        switch (c) {
            case YAHTZEE: return -3;        // 50 points
            case LARGE_STRAIGHT: return -1; // 40 points
            case SMALL_STRAIGHT: return -2; // 30 points
            case FULL_HOUSE: return 10;     // 25 points
            case FOUR_OF_A_KIND: return 9;  // sum
            case THREE_OF_A_KIND: return 8; // sum
            case SIXES: return 7;
            case FIVES: return 6;
            case FOURS: return 5;
            case THREES: return 4;
            case TWOS: return 3;
            case ACES: return 2;
            case CHANCE: return 1;          // sum
        }
        throw new RuntimeException();
    }

    private int[] toIntArray(Integer[] arr) {
        int[] a = new int[arr.length];
        for (int k = 0; k < a.length; k++)
            a[k] = arr[k];
        return a;
    }
}

Bot, zarda belirli kategorilerle eşleşebilecek desenler arar ve gerekli olanları tutar. Biri bulunursa hemen yüksek öncelikli bir eşleştirme kategorisi seçer; aksi takdirde en yüksek puanı veren bir kategori seçer. Maç başına ortalama 200 puan alır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.