C++ :: Aufgabe #312

1 Lösung Lösung öffentlich

Kniffel (Yahtzee, Pasch)

Fortgeschrittener - C++ von JKooP - 06.11.2020 um 15:24 Uhr
Schreibe eine Klasse/Modul mit der/dem es möglich ist das Spiel Kniffel in abgespeckter Form abzubilden.
Zur Vereinfachung soll statt 3 nur 1 Mal gewürfelt werden.
Als Ergebnis sollen alle möglichen Gewinnstufen eines Wurfs sowohl des oberen als auch des unteren Blocks mit der erreichten Punktzahl ausgegeben werden.

Beispielwurf: 2-2-2-4-4

Oberer Block:
Zweier: 2+2+2 = 6 (nur Summe der 2er zählen)
Vierer: 4+4 = 8 (nur Summe der 4er zählen)

Unterer Block:
Dreierpasch: 2+2+2 und 4+6 = 16 (Summe aller Augen)
Full House: Dreierpasch + Zweierpasch -> Sonderwertung = 25
Chance: 2+2+2+4+6 = 16 (Summe aller Augen)

Als Erweiterung kann auch das dreimalige Würfeln implementiert werden.
Da die Interaktion mit der Konsole nicht allzu bedienerfreundlich ist, sollte
man vielleicht auf eine grafischen Benutzeroberfläche ausweichen.

Viel Spaß

Lösungen:

vote_ok
von JKooP (18090 Punkte) - 05.06.2021 um 19:23 Uhr
C++ 17
Quellcode ausblenden C-Code
#include <iostream>
#include <vector>
#include <ctime>
#include <algorithm>
#include <map>
#include <numeric>
#include <tuple>
#include <string>
#include <sstream>
using namespace std;

enum class Spec_Points {
	aces = 1, twos, threes, fours, fives, sixes,
	chance, two_of_a_kind, three_of_a_kind, four_of_a_kind,
	full_house = 25, small_straight = 30, large_straight = 40, yahtzee = 50
};

vector<int>v_dice;
const vector<string>v_small_straight{ "1234", "2345", "3456" };
const vector<string>v_large_straight{ "12345", "23456" };

const map<string, Spec_Points>types {
	{"aces", Spec_Points::aces}, {"twos", Spec_Points::twos}, {"threes", Spec_Points::threes},
	{"fours", Spec_Points::fours}, {"fives", Spec_Points::fives}, {"sixes", Spec_Points::sixes},
	{"chance", Spec_Points::chance}, {"two of a kind", Spec_Points::two_of_a_kind},
	{"three of a kind", Spec_Points::three_of_a_kind}, {"four of a kind", Spec_Points::four_of_a_kind},
	{"full house", Spec_Points::full_house}, {"small straight", Spec_Points::small_straight},
	{"large straight", Spec_Points::large_straight}, {"yahtzee", Spec_Points::yahtzee} };

void roll_sort_dice() {
	srand((int)time(0));
	for (size_t i = 0; i < 5; i++)
		v_dice.push_back(rand() % 6 + 1);
	sort(v_dice.begin(), v_dice.end());
}

void print_dice() {
	cout << "dice:\n" << "\n";
	for (const auto& i : v_dice)
		cout << i << " ";
	cout << "\n\n";
}

vector<int> get_grouped_dice() {
	vector<int>v(6);
	for (const auto& i : v_dice)
		v[i-1]++;
	return v;
}

string map_get_key(const map<string, Spec_Points>& m, const int& compare) {
	for (const auto& v : m)
		if ((int)v.second == compare)
			return v.first;
	return "";
}

void print_upper_section() {
	auto k{ 1 };
	cout << "upper section:\n" << "\n";
	for (const auto& i : get_grouped_dice()) {
		if (i > 0)
			cout << i << "x " << map_get_key(types, k) << " => " << i * k << "\n";
		k++;
	}
}

bool is_x_of_a_kind(const int& compare) {
	for (const auto& i : get_grouped_dice())
		if (i == compare)
			return true;
	return false;
}

bool is_straight(const vector<string>& compare) {
	ostringstream s;

	if (!v_dice.empty())
		copy(v_dice.begin(), v_dice.end() - 1, ostream_iterator<int>(s));

	for (const auto& i : compare)
		if (s.str().find(i) != string::npos)
			return true;
	return false;
}

void print_lower_section() {
	auto sum{ accumulate(v_dice.begin(), v_dice.end(), 0) };

	const vector<tuple<string, bool, int>>v_low {
		{map_get_key(types, (int)Spec_Points::three_of_a_kind), is_x_of_a_kind(3), sum },
		{map_get_key(types, (int)Spec_Points::four_of_a_kind), is_x_of_a_kind(4), sum },
		{map_get_key(types, (int)Spec_Points::full_house), is_x_of_a_kind(2) && is_x_of_a_kind(3), (int)Spec_Points::full_house },
		{map_get_key(types, (int)Spec_Points::small_straight), is_straight(v_small_straight), (int)Spec_Points::small_straight },
		{map_get_key(types, (int)Spec_Points::large_straight), is_straight(v_large_straight), (int)Spec_Points::large_straight },
		{map_get_key(types, (int)Spec_Points::yahtzee), is_x_of_a_kind(5), (int)Spec_Points::yahtzee },
		{map_get_key(types, (int)Spec_Points::chance), true, sum }
	};

	cout << "\nlower section:\n" << "\n";
	for (const auto& i : v_low)
		if (get<1>(i))
			cout << "1x " << get<0>(i) << " => " << get<2>(i) << "\n";
}

int main()
{
	roll_sort_dice();
	print_dice();
	print_upper_section();
	print_lower_section();
}