1

I'm making a Yahtzee-like game with 5 dices using Flutter + Dart. I keep the dice values in a List<int>. What would be the best way to check if there is a full house, and what is the sum or relevant dices?

If I want only to determine if I have a full house, this solution would be good. But I have to calculate the sum afterwards, so I need to know how many of which numbers I have.

Making 30 ifs to cover each case is a solution, but probably not the best one. Does anyone have any better idea?

creativecreatorormaybenot
  • 114,516
  • 58
  • 291
  • 402
vtomic85
  • 590
  • 1
  • 11
  • 32
  • "*I have to calculate the sum afterwards*" - do you mean that you need to know the sume of the five dice, e.g. `1, 1, 1, 2, 2` `->` `7`? I found out that a full house always scores you `25` in a game of Yahtzee. – creativecreatorormaybenot Dec 08 '19 at 16:00
  • @creativecreatorormaybenot In my implementation I want it to be a "real" sum of all numbers – vtomic85 Dec 08 '19 at 16:11

2 Answers2

0

Here would be a simple Dart implementation using List/Iterable methods:

bool fullHouse(List<int> dice) {
  final counts = {1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0};

  dice.forEach((n) => counts[n]++);

  return counts.containsValue(3) && counts.containsValue(2);
}

int diceSum(List<int> dice) => dice.reduce((v, e) => v + e);

As you can see, I separated the sum and the full house check, but I can also adjust this if necessary.

Extension

If you are using a Dart 2.6 or later, you could also create a nice extension for this:

void main() {
  print([1, 1, 2, 1, 2].fullHouseScore);
}

extension YahtzeeDice on List<int> {
  int get fullHouseScore {
    if (isFullHouse) return diceSum;
    return 0;
  }

  bool get isFullHouse {
    final counts = {1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0};

    forEach((n) => counts[n]++);

    return counts.containsValue(3) && counts.containsValue(2);
  }

  int get diceSum => reduce((v, e) => v + e);
}

Testing

This would be a simple usage of the functions for testing:

int checkFullHouse(List<int> dice) {
  if (fullHouse(dice)) {
    final sum = diceSum(dice);
    print('Dice are a full house. Sum is $sum.');
    return sum;
  } else {
    print('Dice are not a full house.');
    return 0;
  }
}

void main() {
  const fullHouses = [
    [1, 1, 1, 2, 2],
    [1, 2, 1, 2, 1],
    [2, 1, 2, 1, 1],
    [6, 5, 6, 5, 5],
    [4, 4, 3, 3, 3],
    [3, 5, 3, 5, 3],
  ],
      other = [
    [1, 2, 3, 4, 5],
    [1, 1, 1, 1, 2],
    [5, 5, 5, 5, 5],
    [6, 5, 5, 4, 6],
    [4, 3, 2, 5, 6],
    [2, 4, 6, 3, 2],
  ];

  print('Testing dice that are full houses.');
  fullHouses.forEach(checkFullHouse);

  print('Testing dice that are not full houses.');
  other.forEach(checkFullHouse);
}
creativecreatorormaybenot
  • 114,516
  • 58
  • 291
  • 402
0

Why not just use the linked solution?

bool isFullHouse(List<int> diceResults) {
  String counterString = diceResults.map((i) => i.toString()).join();
  return RegExp('20*3|30*2').hasMatch(counterString);
}

int getDiceSum(List<int> diceResults) {
  int sum = 0;
  for (int i = 0; i < 6; i++) {
    sum += [0, 0, 2, 0, 3, 0][i] * (i + 1);
  }
  return sum;
}

// elsewhere
dice = [0, 0, 2, 0, 3, 0]; // example result
if (isFullHouse(dice)) {
  int score = getDiceSum(dice);
  // Do something with sum
}
Abion47
  • 22,211
  • 4
  • 65
  • 88
  • Why use `RegExp` when you can stick to lists? Also, nice seeing you here :) – creativecreatorormaybenot Dec 10 '19 at 19:37
  • @creativecreatorormaybenot What you lose in performance you gain in simplicity and conciseness. There are pre-established Regex patterns in the linked question for every possible thing in Yahtzee you can get a score for (besides simple stuff like 6's and chance). Lists and maps work just as well for a full house but would be a bit more involved for the other stuff like straights. It's just a case of "if it's not broke, don't fix it". (Plus, for a string this small and a method that is only getting called maybe a few times per second, the difference in performance is going to be negligible.) – Abion47 Dec 10 '19 at 23:15