我是初学者C ++课程,我试图建立一个Yahtzee游戏,用户掷骰子,希望得到所有五个骰子相同的数字。我们需要尝试保持弹出最多的骰子(例如,我们滚动一个" 4 5 3 3 1",我想保持三个,以便它在整个游戏中保持不变)然后再次滚动继续努力让所有五个骰子都一样。以下是我到目前为止的情况:
#include <iostream>
using namespace std;
void choiceRoll(){
int num;
int dice1 = rand()%6+1;
int dice2 = rand()%6+1;
int dice3 = rand()%6+1;
int dice4 = rand()%6+1;
int dice5 = rand()%6+1;
cout << "Your roll is: " << dice1 << " " << dice2 << " " << dice3
<< " " << dice4 << " " << dice5 << endl;
}
int main() {
srand(time(NULL));
int dice1 = rand()%6+1;
int dice2 = rand()%6+1;
int dice3 = rand()%6+1;
int dice4 = rand()%6+1;
int dice5 = rand()%6+1;
int x;
int num;
char play;
cout << "Let's play some Yahtzee!" << endl;
choiceRoll();
while(x<1){
cout << "Which number do you want to hold?";
cin >> num;
if (num>=1 and num<=6)
choiceRoll();
else{
cout << "Thanks for playing!";
}
}
if (dice1=dice2=dice3=dice4=dice5){
cout << "YAHTZEE!!!!" << endl;
}
return 0;
}
任何人都可以帮助我能够允许用户输入保留一定数量并且能够继续滚动直到所有数字都相同吗?
答案 0 :(得分:4)
我受到了一些c ++ 17新鲜感的启发。这是:
#include <algorithm>
#include <array>
#include <cassert>
#include <iostream>
#include <iomanip>
#include <map>
#include <random>
#include <string>
#include <string_view>
using namespace std;
using Score = size_t;
namespace {
enum class face : Score { one=1, two, three, four, five, six, _hide=0 };
ostream& operator<<(ostream& os, face f) {
switch(f) {
case face::one: return os << "⚀";
case face::two: return os << "⚁";
case face::three: return os << "⚂";
case face::four: return os << "⚃";
case face::five: return os << "⚄";
case face::six: return os << "⚅";
case face::_hide: default: return os << ".";
}
}
face roll_one() {
static mt19937 e { random_device{}() };
static uniform_int_distribution<Score> dist(Score(face::one), Score(face::six));
return face{dist(e)};
}
}
template <size_t... I>
struct hand_impl {
static constexpr size_t N = sizeof...(I);
private:
static_assert(is_same_v<index_sequence<I...>, make_index_sequence<N> >, "this hack merely enables fold expressions");
using dice_t = array<face, N>;
using selection_t = array<bool, N>;
dice_t faces;
selection_t held = {};
public:
hand_impl() {
generate_n(faces.begin(), N, roll_one);
}
void hold_highest() {
held = matching(max({faces[I]...}));
}
void reroll() {
faces = {{ (held[I]? faces[I] : roll_one())... }};
}
enum class method { upper_box, _3_of_a_kind, _4_of_a_kind, full_house,
small_straight, large_straight, yahtzee, chance };
struct candidate_t {
dice_t faces;
selection_t key;
method how;
};
friend size_t score(candidate_t c) {
// fixed
switch(c.how) {
case method::full_house: return 25;
case method::small_straight: return 30;
case method::large_straight: return 40;
case method::yahtzee: return 50;
default: break;
}
// depending on face values
size_t all_values[] = { Score(c.faces[I])... };
switch(c.how) {
case method::upper_box: return ((c.key[I]? all_values[I] : 0) + ...);
case method::_3_of_a_kind:
case method::_4_of_a_kind:
case method::chance: return (all_values[I] + ...);
default: throw runtime_error("illegal move");
}
}
auto generate() const {
vector<candidate_t> result;
result.push_back({ faces, all(), method::chance });
// equal groups
for (face f : {face::one, face::two, face::three, face::four, face::five, face::six}) {
auto m = matching(f);
auto n = cardinality(m);
if (n) result.push_back({ faces, m, method::upper_box });
if (n==5) result.push_back({ faces, m, method::yahtzee });
if (n>=4) {
if (n>4) *find(begin(m), end(m), true) = false; // discard one
result.push_back({ faces, m, method::_4_of_a_kind });
}
if (n>=3) {
if (n>3) *find(begin(m), end(m), true) = false; // discard one
result.push_back({ faces, m, method::_3_of_a_kind });
// look at remaining two
dice_t other {{ (m[I]? face::_hide : faces[I])... }};
sort(begin(other), end(other));
// if they match, it's also a full house
if (other[0] == other[1])
result.push_back({ faces, m, method::full_house });
}
}
{
// straights (increasing series)
auto inorder = faces;
sort(begin(inorder), end(inorder), greater<>{}); // favour the higher values
auto decreasing_at = [&](size_t i) {
return Score(inorder[i]) == 1 + Score(inorder[(i+1) % N])? 'y':'n';
};
char const s[] = { decreasing_at(I)... };
if (auto where = string_view(s).find("yyyy"); where != string_view::npos)
result.push_back({ inorder, selection_t { (I>=where && I<where+4)... }, method::large_straight });
if (auto where = string_view(s).find("yyy"); where != string_view::npos)
result.push_back({ inorder, selection_t { (I>=where && I<where+3)... }, method::small_straight });
}
return result;
}
private:
static selection_t all() { return { (void(I), true)... }; }
selection_t matching(face f) const {
return { (faces[I] == f)... };
}
static size_t cardinality(selection_t s) {
return count(begin(s), end(s), true);
}
template <size_t Index>
static ostream& print_held(ostream& os, dice_t faces, selection_t held) {
return os << faces[Index] << (held[Index]? "\xCC\xB2":"");
}
template <size_t Index>
static ostream& print_key_dice(ostream& os, dice_t faces, selection_t key) {
return os << (key[Index]? faces[Index] : face::_hide);
}
friend ostream& operator<<(ostream& os, hand_impl h) {
return (print_held<I>(os, h.faces, h.held), ...);
}
friend ostream& operator<<(ostream& os, candidate_t const& c) {
struct R { ostream& os; ios::fmtflags kept; ~R() { os.flags(kept); } } keep { os, os.flags() };
os << "[" << left << setw(15) << c.how << "] ";
return (print_key_dice<I>(os, c.faces, c.key), ...);
}
friend ostream& operator<<(ostream& os, method m) {
switch(m) {
case method::upper_box: return os << "upper box";
case method::_3_of_a_kind: return os << "three of a kind";
case method::_4_of_a_kind: return os << "four of a kind";
case method::full_house: return os << "full house";
case method::small_straight: return os << "small straight";
case method::large_straight: return os << "large straight";
case method::yahtzee: return os << "yahtzee";
case method::chance: return os << "chance";
}
return os << "[no score]";
}
};
template <size_t... I> hand_impl<I...> make_hand_helper(index_sequence<I...>) { return {}; }
template <size_t N = 5> auto make_hand() { return make_hand_helper(make_index_sequence<N>{}); }
template <size_t N = 5> using hand = decltype(make_hand<N>());
using Yahtzee = hand<>;
int main() {
Yahtzee hand = make_hand();
auto rolls = 3;
do {
hand.hold_highest();
cout << hand << "\n";
multimap<Score, Yahtzee::candidate_t, greater<> > ranked;
for (auto c : hand.generate())
ranked.emplace(score(c), c);
for (auto&& [score, c] : ranked)
cout << setw(2) << score << " - " << c << "\n";
hand.reroll();
} while (--rolls);
}
打印
⚁⚄⚅̲⚃⚂ ¹
40 - [large straight ] ⚅⚄⚃⚂.
30 - [small straight ] ⚅⚄⚃..
20 - [chance ] ⚁⚄⚅⚃⚂
6 - [upper box ] ..⚅..
5 - [upper box ] .⚄...
4 - [upper box ] ...⚃.
3 - [upper box ] ....⚂
2 - [upper box ] ⚁....
⚃⚃⚅̲⚅̲⚁ ¹
22 - [chance ] ⚃⚃⚅⚅⚁
12 - [upper box ] ..⚅⚅.
8 - [upper box ] ⚃⚃...
2 - [upper box ] ....⚁
⚅̲⚅̲⚅̲⚅̲⚂ ¹
27 - [chance ] ⚅⚅⚅⚅⚂
27 - [four of a kind ] ⚅⚅⚅⚅.
27 - [three of a kind] .⚅⚅⚅.
25 - [full house ] .⚅⚅⚅.
24 - [upper box ] ⚅⚅⚅⚅.
3 - [upper box ] ....⚂
¹遗憾的是,浏览器并不都希望尊重U + 0332 COMBINING LOW LINE,这应该强调所持有的骰子,如下所示: