-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDeck.cpp
More file actions
135 lines (110 loc) · 3.07 KB
/
Deck.cpp
File metadata and controls
135 lines (110 loc) · 3.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include <vector>
#include <random>
#include <algorithm>
#include <stdexcept>
#include <iostream>
#include "node.h"
#include "Deck.h"
// ---------- Helper functions (only used inside this file) ----------
// remove and return top card (updates head pointer)
static Card popFront(Node<Card>*& head) {
if (head == nullptr) {
throw std::runtime_error("Cannot deal from an empty deck");
}
Node<Card>* temp = head;
Card value = temp->data;
head = head->next;
if (head != nullptr) {
head->prev = nullptr;
}
delete temp;
return value;
}
// count nodes in the list
static int listSize(Node<Card>* cur) {
int count = 0;
while (cur != nullptr) {
count++;
cur = cur->next;
}
return count;
}
// Constructor: start with an empty linked list
Deck::Deck() : head(nullptr) {}
// Destructor: automatically clears nodes when Deck is destroyed
Deck::~Deck() {
clear(); // automatic cleanup to prevent memory leaks
}
bool Deck::empty() const {
return head == nullptr;
}
int Deck::size() const {
return listSize(head);
}
void Deck::clear() {
deleteList(head); // deletes all nodes
head = nullptr; // prevents dangling pointer
}
// Build a standard 52-card deck:
// suits: Clubs, Diamonds, Hearts, Spades
// ranks: 1..13 (A..K)
void Deck::buildStandard52() {
clear(); // start fresh avoid accidentally appending another deck
Card::Suit suits[] = {
Card::Suit::Clubs,
Card::Suit::Diamonds,
Card::Suit::Hearts,
Card::Suit::Spades
};
for (Card::Suit s : suits) {
for (int r = 1; r <= 13; r++) {
insertAtEnd(head, Card(r, s));
}
}
}
// Shuffle approach
void Deck::shuffle() {
if (size() <= 1)
return; // nothing to shuffle for 0 or 1 card
// Step 1: move cards to a vector
std::vector<Card> temp;
while (!empty()) {
temp.push_back(popFront(head)); // remove from top and store in vector
}
// Step 2: shuffle the vector
std::random_device rd;
std::mt19937 rng(rd());
std::shuffle(temp.begin(), temp.end(), rng);
// Step 3: rebuild the linked list
for (const Card& c : temp) {
insertAtEnd(head, c);
}
}
Card Deck::dealOne() {
return popFront(head);
}
// Cut the deck at k:
// Move the first k cards to the bottom.
// Example: [A B C D E], cut(2) -> [C D E A B]
void Deck::cut(int k) {
int n = size();
if (n <= 1) return;
// normalize k to [0, n)
k %= n;
if (k < 0) k += n;
if (k == 0) return;
// Move k cards from top to bottom
for (int i = 0; i < k; i++) {
Card c = popFront(head);
insertAtEnd(head, c);
}
}
void Deck::printTopN(int n) const {
const Node<Card>* cur = head;
for (int i = 0; cur != nullptr && i < n; i++) {
std::cout << cur->data;
if (cur->next != nullptr && i < n - 1) std::cout << " ";
cur = cur->next;
}
std::cout << std::endl;
}