std::array out of range error in simplified Blackjack game code

On LearnCPP, there's an exercise asking to play a simplified version of Blackjack. I was having trouble, so I looked at the Solutions while doing it. But when I run it now, it crashes with an "out of range" error. I don't know what's causing it, but I do know that an "out of range" error means that I somehow ended up trying to access an array or vector element that's out of bounds. I don't know how I could've done it, though.

Here's the code (warning: It's really long):
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
#include <iostream>
#include <array>
#include <ctime>
#include <cstdlib>
#include "keep_window_open.h"

enum CardRank
{
	CARD_2,
	CARD_3,
	CARD_4,
	CARD_5,
	CARD_6,
	CARD_7,
	CARD_8,
	CARD_9,
	CARD_10,
	CARD_JACK,
	CARD_QUEEN,
	CARD_KING,
	CARD_ACE,
	MAX_RANKS
};

enum CardSuit
{
	SUIT_CLUB,
	SUIT_DIAMOND,
	SUIT_HEART,
	SUIT_SPADE,
	MAX_SUITS
};

struct Card
{
	CardSuit suit;
	CardRank rank;
};

void printCard(const Card& card);
void swapCard(Card& card1, Card& card2);
void printDeck(const std::array<Card, 52>& deck);
void shuffleDeck(std::array<Card, 52>& deck);
int getRandomNumber(int min, int max);
int getCardValue(const Card& card);
bool playBlackJack(const std::array<Card, 52>& deck);
char getPlayerChoice();

int main()
{
	using namespace std;
	srand(static_cast<unsigned int>(time(0)));
	rand();

	array<Card, 52> deck;

	int card = 0;
	for (int suit = 0; suit < MAX_SUITS; ++suit)
	for (int rank = 0; suit < MAX_RANKS; ++rank)
	{
		deck[card].suit = static_cast<CardSuit>(suit);
		deck[card].rank = static_cast<CardRank>(rank);
		++card;
	}

	shuffleDeck(deck);
	if (playBlackJack(deck))
	{
		cout << "You win!\n";
	}
	else
	{
		cout << "You lose!\n";
	}

	keep_window_open();
	return 0;
}

void printCard(const Card& card)
{
	using namespace std;
	switch (card.rank)
	{
	case CardRank::CARD_2:
		cout << '2';
		break;
	case CardRank::CARD_3:
		cout << '3';
		break;
	case CardRank::CARD_4:
		cout << '4';
		break;
	case CardRank::CARD_5:
		cout << '5';
		break;
	case CardRank::CARD_6:
		cout << '6';
		break;
	case CardRank::CARD_7:
		cout << '7';
		break;
	case CardRank::CARD_8:
		cout << '8';
		break;
	case CardRank::CARD_9:
		cout << '9';
		break;
	case CardRank::CARD_10:
		cout << 'T';
		break;
	case CardRank::CARD_JACK:
		cout << 'J';
		break;
	case CardRank::CARD_KING:
		cout << 'K';
		break;
	case CardRank::CARD_QUEEN:
		cout << 'Q';
		break;
	case CardRank::CARD_ACE:
		cout << 'A';
		break;
	}

	switch (card.suit)
	{
	case CardSuit::SUIT_CLUB:
		cout << 'C';
		break;
	case CardSuit::SUIT_DIAMOND:
		cout << 'D';
		break;
	case CardSuit::SUIT_HEART:
		cout << 'H';
		break;
	case CardSuit::SUIT_SPADE:
		cout << 'S';
		break;
	}
}

void swapCard(Card& card1, Card& card2)
{
	Card temp = card1;
	card1 = card2;
	card2 = temp;
}

void printDeck(const std::array<Card, 52>& deck)
{
	using namespace std;
	for (const auto& card : deck)
	{
		printCard(card);
		cout << " ";
	}
	cout << "\n";
}

void shuffleDeck(std::array<Card, 52>& deck)
{
	for (int index = 0; index < 52; ++index)
	{
		int swapIndex = getRandomNumber(1, 52);
		swapCard(deck[index], deck[swapIndex]);
	}

}

int getRandomNumber(int min, int max)
{
	static const double fraction = 1.0 / (static_cast<double>(RAND_MAX) + 1.0);  
																				 
	return static_cast<int>(rand() * fraction * (max - min + 1) + min);
}

int getCardValue(const Card& card)
{
	switch (card.rank)
	{
	case CardRank::CARD_2:
		return 2;
	case CardRank::CARD_3:
		return 3;
	case CardRank::CARD_4:
		return 4;
	case CardRank::CARD_5:
		return 5;
	case CardRank::CARD_6:
		return 6;
	case CardRank::CARD_7:
		return 7;
	case CardRank::CARD_8:
		return 8;
	case CardRank::CARD_9:
		return 9;
	case CardRank::CARD_10:
		return 10;
	case CardRank::CARD_JACK:
		return 10;
	case CardRank::CARD_QUEEN:
		return 10;
	case CardRank::CARD_KING:
		return 10;
	case CardRank::CARD_ACE:
		return 11;
	}
	return 0;
}

bool playBlackJack(const std::array<Card, 52>& deck)
{
	using namespace std;
	const Card *cardPtr = &deck[0];
	int totalPlayerPoints = 0;
	int totalDealerPoints = 0;

	totalDealerPoints += getCardValue(*cardPtr++);
	cout << "The dealer is showing " << totalDealerPoints << "\n";

	totalPlayerPoints += getCardValue(*cardPtr++);
	totalPlayerPoints += getCardValue(*cardPtr++);

	while (true)
	{
		cout << "You have " << totalPlayerPoints << "\n";
		char choice = getPlayerChoice();
		if (choice == 's')
		{
			break;
		}
		totalPlayerPoints = getCardValue(*cardPtr++);
		if (totalPlayerPoints > 21)
		{
			return false;
		}
	}

	while (totalDealerPoints < 17)
	{
		totalDealerPoints += getCardValue(*cardPtr++);
		cout << "The dealer now has " << totalDealerPoints << "\n";
	}

	if (totalDealerPoints > 21)
	{
		return true;
	}

	return (totalPlayerPoints > totalDealerPoints);
}

char getPlayerChoice()
{
	using namespace std;
	cout << "(h) to hit or (s) to stand: ";
	char choice;
	do
	{
		cin >> choice;
		cin.ignore(32767, '\n');
	} 
	while (choice != 'h' && choice != 's');
	return choice;
}


The specs do actually say to use a std::array here. And it's a really simplified version of the game, so we're only supposed to keep track of the total number of cards and points that the player and dealer have, rather than keeping tracking of each of the cards they're dealt with.

For reference, I'll also post the custom header I'm using and its corresponding .cpp file:

1
2
3
4
5
6
#ifndef KEEP_WINDOW_OPEN_H
#define KEEP_WINDOW_OPEN_H

void keep_window_open();

#endif 


1
2
3
4
5
6
7
8
9
10
11
12
13
// Function definition for keep_window_open() from the osman_headers.h header file.

#include <iostream>

void keep_window_open()
{
    using namespace std;
    cin.clear();
    cout << "Please enter a character to exit\n";
    char ch;
    cin >> ch;
	cin.ignore();
}
Did you run the program with your debugger? The debugger should be able to tell you exactly where it detects the problem and let you view the values of the variables at the time of the crash.

I know it's an out of range error because I checked it with the Debugger. I just don't know how to tell where it is on VS.
It appears that the problem is on line 61 and card has a value of 544.
Yeah, thanks. I just saw it. card[].rank and card[].suit are both out of bounds indices there. So how do I make sure that their values don't go higher than 52?
Look closely at your loop structure:
1
2
    for (int suit = 0; suit < MAX_SUITS; ++suit)
        for (int rank = 0; suit < MAX_RANKS; ++rank)

Why is the inner loop not checking that rank is < MAX_RANKS?
Ah. I missed that. Thanks.

By the way, when I added MAX_RANKS and MAX_SUITS to Watch on the Debugger, it told me that they're undefined. What's up with that?

Edit: I did it like this and now it seems to work. I just played it, but I'm not familiar enough with Blackjack to tell if it's fine, so would you play it and let me know? Here is the whole code (notice especially what I did with the code for initializing the deck):

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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
#include <iostream>
#include <array>
#include <ctime>
#include <cstdlib>
#include "keep_window_open.h"

enum CardRank
{
	CARD_2,
	CARD_3,
	CARD_4,
	CARD_5,
	CARD_6,
	CARD_7,
	CARD_8,
	CARD_9,
	CARD_10,
	CARD_JACK,
	CARD_QUEEN,
	CARD_KING,
	CARD_ACE,
	MAX_RANKS = 15
};

enum CardSuit
{
	SUIT_CLUB,
	SUIT_DIAMOND,
	SUIT_HEART,
	SUIT_SPADE,
	MAX_SUITS = 5
};

struct Card
{
	CardSuit suit;
	CardRank rank;
};

void printCard(const Card& card);
void swapCard(Card& card1, Card& card2);
void printDeck(const std::array<Card, 52>& deck);
void shuffleDeck(std::array<Card, 52>& deck);
int getRandomNumber(int min, int max);
int getCardValue(const Card& card);
bool playBlackJack(const std::array<Card, 52>& deck);
char getPlayerChoice();

int main()
{
	using namespace std;
	srand(static_cast<unsigned int>(time(0)));
	rand();

	array<Card, 52> deck;

	int card = 0;
	for (int suit = 0; suit < MAX_SUITS; ++suit)
	for (int rank = 0; rank < MAX_RANKS; ++rank)
	{
		deck[card].suit = static_cast<CardSuit>(suit);
		deck[card].rank = static_cast<CardRank>(rank);
		++card;
		if (deck[card].suit <= 52 && deck[card].rank <= 52)
		{
			break;
		}
	}

	shuffleDeck(deck);
	bool won = playBlackJack(deck);

	if (won)
	{
		cout << "You win!\n";
	}
	else
	{
		cout << "You lose!\n";
	}

	keep_window_open();
	return 0;
}

void printCard(const Card& card)
{
	using namespace std;
	switch (card.rank)
	{
	case CardRank::CARD_2:
		cout << '2';
		break;
	case CardRank::CARD_3:
		cout << '3';
		break;
	case CardRank::CARD_4:
		cout << '4';
		break;
	case CardRank::CARD_5:
		cout << '5';
		break;
	case CardRank::CARD_6:
		cout << '6';
		break;
	case CardRank::CARD_7:
		cout << '7';
		break;
	case CardRank::CARD_8:
		cout << '8';
		break;
	case CardRank::CARD_9:
		cout << '9';
		break;
	case CardRank::CARD_10:
		cout << 'T';
		break;
	case CardRank::CARD_JACK:
		cout << 'J';
		break;
	case CardRank::CARD_KING:
		cout << 'K';
		break;
	case CardRank::CARD_QUEEN:
		cout << 'Q';
		break;
	case CardRank::CARD_ACE:
		cout << 'A';
		break;
	}

	switch (card.suit)
	{
	case CardSuit::SUIT_CLUB:
		cout << 'C';
		break;
	case CardSuit::SUIT_DIAMOND:
		cout << 'D';
		break;
	case CardSuit::SUIT_HEART:
		cout << 'H';
		break;
	case CardSuit::SUIT_SPADE:
		cout << 'S';
		break;
	}
}

void swapCard(Card& card1, Card& card2)
{
	Card temp = card1;
	card1 = card2;
	card2 = temp;
}

void printDeck(const std::array<Card, 52>& deck)
{
	using namespace std;
	for (const auto& card : deck)
	{
		printCard(card);
		cout << " ";
	}
	cout << "\n";
}

void shuffleDeck(std::array<Card, 52>& deck)
{
	for (int index = 0; index < 52; ++index)
	{
		int swapIndex = getRandomNumber(0, 52);
		swapCard(deck[index], deck[swapIndex]);
	}
}

int getRandomNumber(int min, int max)
{
	static const double fraction = 1.0 / (static_cast<double>(RAND_MAX) + 1.0);  
																				 
	return static_cast<int>(rand() * fraction * (max - min + 1) + min);
}

int getCardValue(const Card& card)
{
	switch (card.rank)
	{
	case CardRank::CARD_2:
		return 2;
	case CardRank::CARD_3:
		return 3;
	case CardRank::CARD_4:
		return 4;
	case CardRank::CARD_5:
		return 5;
	case CardRank::CARD_6:
		return 6;
	case CardRank::CARD_7:
		return 7;
	case CardRank::CARD_8:
		return 8;
	case CardRank::CARD_9:
		return 9;
	case CardRank::CARD_10:
		return 10;
	case CardRank::CARD_JACK:
		return 10;
	case CardRank::CARD_QUEEN:
		return 10;
	case CardRank::CARD_KING:
		return 10;
	case CardRank::CARD_ACE:
		return 11;
	}
	return 0;
}

bool playBlackJack(const std::array<Card, 52>& deck)
{
	using namespace std;
	const Card *cardPtr = &deck[0];
	int totalPlayerPoints = 0;
	int totalDealerPoints = 0;

	totalDealerPoints += getCardValue(*cardPtr++);
	cout << "The dealer is showing " << totalDealerPoints << "\n";

	totalPlayerPoints += getCardValue(*cardPtr++);
	totalPlayerPoints += getCardValue(*cardPtr++);

	while (true)
	{
		cout << "You have " << totalPlayerPoints << "\n";
		char choice = getPlayerChoice();
		if (choice == 's')
		{
			break;
		}
		totalPlayerPoints = getCardValue(*cardPtr++);
		if (totalPlayerPoints > 21)
		{
			return false;
		}
	}

	while (totalDealerPoints < 17)
	{
		totalDealerPoints += getCardValue(*cardPtr++);
		cout << "The dealer now has " << totalDealerPoints << "\n";
	}

	if (totalDealerPoints > 21)
	{
		return true;
	}

	return (totalPlayerPoints > totalDealerPoints);
}

char getPlayerChoice()
{
	using namespace std;
	cout << "(h) to hit or (s) to stand: ";
	char choice;
	do
	{
		cin >> choice;
		cin.ignore(32767, '\n');
	} 
	while (choice != 'h' && choice != 's');
	return choice;
}


Edit: Never mind; the program ran fine only once for me and then it keeps crashing after that.
Last edited on
The first thing I notice is that your deck doesn't seem to be properly initialized.

I inserted this right after your "initialization" routine. It would be nice if your printCard() function played better with the iostreams.

1
2
3
4
5
6
7
8
    int i = 1;
    for(auto& itr : deck)
    {
        std::cout << i++ << " ";
        printCard(itr);
        std::cout << std::endl;
    }
    return(0);

And I got this output
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
1 2C
2 3C
3 4C
4 5C
5 6C
6 7C
7 8C
8 9C
9 TC
10 JC
11 QC
12 KC
13 AC
14 C
15 C
16 2D
17 3D
18 4D
19 5D
20 6D
21 7D
22 8D
23 9D
24 TD
25 JD
26 2H
27 3H
28 4H
29 5H
30 6H
31 7H
32 2S
33 3S
34 4S
35 5S
36 6S
37 2
38 3
39 4
40 5
41 6
42 7
43 2D
44 
45 2
46 2H
47 2
48 
49 
50 2
51 2S
52 2
Any ideas on how to fix that? And by the way, when I try to run the code now, sometimes it runs fine and at other times it just crashes.

I've got MAX_SUITS and MAX_RANKS set to their actual values manually in their respective enums. MAX_SUITS is set to 5 and MAX_RANKS is set to 13.
I've got MAX_SUITS and MAX_RANKS set to their actual values manually in their respective enums. MAX_SUITS is set to 5 and MAX_RANKS is set to 13.

Surely you can see these numbers are inconsistent. A deck of cards has 13 ranks and 4 suits, so, logically speaking these numbers should be 5 and 14 or 4 and 13, but I'd guess the latter.

Of course, it wouldn't be an issue if you didn't define them manually (which, as you can see, introduces the possibility of human error.)
Last edited on
now why is this still crashing at times?
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
#include <iostream>
#include <array>
#include <ctime>
#include <cstdlib>
#include "keep_window_open.h"

enum CardRank
{
	CARD_2,
	CARD_3,
	CARD_4,
	CARD_5,
	CARD_6,
	CARD_7,
	CARD_8,
	CARD_9,
	CARD_10,
	CARD_JACK,
	CARD_QUEEN,
	CARD_KING,
	CARD_ACE,
	MAX_RANKS
};

enum CardSuit
{
	SUIT_CLUB,
	SUIT_DIAMOND,
	SUIT_HEART,
	SUIT_SPADE,
	MAX_SUITS
};

struct Card
{
	CardSuit suit;
	CardRank rank;
};

void printCard(const Card& card);
void swapCard(Card& card1, Card& card2);
void printDeck(const std::array<Card, 52>& deck);
void shuffleDeck(std::array<Card, 52>& deck);
int getRandomNumber(int min, int max);
int getCardValue(const Card& card);
bool playBlackJack(const std::array<Card, 52>& deck);
char getPlayerChoice();

int main()
{
	using namespace std;
	srand(static_cast<unsigned int>(time(nullptr)));
	rand();

	array<Card, 52> deck;

	int card = 0;
	for (int suit = 0; suit < MAX_SUITS; ++suit)
	{
		for (int rank = 0; rank < MAX_RANKS; ++rank)
		{
			deck[card].suit = static_cast<CardSuit>(suit);
			deck[card].rank = static_cast<CardRank>(rank);
			++card;
			if (deck[card].rank <= MAX_RANKS || deck[card].suit <= MAX_SUITS)
			{
				break;
			}
		}
	}

	shuffleDeck(deck);
	bool won = playBlackJack(deck);

	if (won)
	{
		cout << "You win!\n";
	}
	else
	{
		cout << "You lose!\n";
	}

	keep_window_open();
	return 0;
}

void printCard(const Card& card)
{
	using namespace std;
	switch (card.rank)
	{
	case CardRank::CARD_2:
		cout << '2';
		break;
	case CardRank::CARD_3:
		cout << '3';
		break;
	case CardRank::CARD_4:
		cout << '4';
		break;
	case CardRank::CARD_5:
		cout << '5';
		break;
	case CardRank::CARD_6:
		cout << '6';
		break;
	case CardRank::CARD_7:
		cout << '7';
		break;
	case CardRank::CARD_8:
		cout << '8';
		break;
	case CardRank::CARD_9:
		cout << '9';
		break;
	case CardRank::CARD_10:
		cout << 'T';
		break;
	case CardRank::CARD_JACK:
		cout << 'J';
		break;
	case CardRank::CARD_KING:
		cout << 'K';
		break;
	case CardRank::CARD_QUEEN:
		cout << 'Q';
		break;
	case CardRank::CARD_ACE:
		cout << 'A';
		break;
	case CardRank::MAX_RANKS:
		break;
	}

	switch (card.suit)
	{
	case CardSuit::SUIT_CLUB:
		cout << 'C';
		break;
	case CardSuit::SUIT_DIAMOND:
		cout << 'D';
		break;
	case CardSuit::SUIT_HEART:
		cout << 'H';
		break;
	case CardSuit::SUIT_SPADE:
		cout << 'S';
		break;
	case CardSuit::MAX_SUITS:
		break;
	}
}

void swapCard(Card& card1, Card& card2)
{
	Card temp = card1;
	card1 = card2;
	card2 = temp;
}

void printDeck(const std::array<Card, 52>& deck)
{
	using namespace std;
	for (const auto& card : deck)
	{
		printCard(card);
		cout << " ";
	}
	cout << "\n";
}

void shuffleDeck(std::array<Card, 52>& deck)
{
	for (int index = 0; index < 52; ++index)
	{
		int swapIndex = getRandomNumber(0, 52);
		swapCard(deck[index], deck[swapIndex]);
	}
}

int getRandomNumber(int min, int max)
{
	static const double fraction = 1.0 / (static_cast<double>(RAND_MAX) + 1.0);  
																				 
	return static_cast<int>(rand() * fraction * (max - min + 1) + min);
}

int getCardValue(const Card& card)
{
	switch (card.rank)
	{
	case CardRank::CARD_2:
		return 2;
	case CardRank::CARD_3:
		return 3;
	case CardRank::CARD_4:
		return 4;
	case CardRank::CARD_5:
		return 5;
	case CardRank::CARD_6:
		return 6;
	case CardRank::CARD_7:
		return 7;
	case CardRank::CARD_8:
		return 8;
	case CardRank::CARD_9:
		return 9;
	case CardRank::CARD_10:
		return 10;
	case CardRank::CARD_JACK:
		return 10;
	case CardRank::CARD_QUEEN:
		return 10;
	case CardRank::CARD_KING:
		return 10;
	case CardRank::CARD_ACE:
		return 11;
	}
	return 0;
}

bool playBlackJack(const std::array<Card, 52>& deck)
{
	using namespace std;
	const Card *cardPtr = &deck[0];
	int totalPlayerPoints = 0;
	int totalDealerPoints = 0;

	totalDealerPoints += getCardValue(*cardPtr++);
	cout << "The dealer is showing " << totalDealerPoints << "\n";

	totalPlayerPoints += getCardValue(*cardPtr++);
	totalPlayerPoints += getCardValue(*cardPtr++);

	while (true)
	{
		cout << "You have " << totalPlayerPoints << "\n";
		char choice = getPlayerChoice();
		if (choice == 's')
		{
			break;
		}
		totalPlayerPoints = getCardValue(*cardPtr++);
		if (totalPlayerPoints > 21)
		{
			return false;
		}
	}

	while (totalDealerPoints < 17)
	{
		totalDealerPoints += getCardValue(*cardPtr++);
		cout << "The dealer now has " << totalDealerPoints << "\n";
	}

	if (totalDealerPoints > 21)
	{
		return true;
	}

	return (totalPlayerPoints > totalDealerPoints);
}

char getPlayerChoice()
{
	using namespace std;
	cout << "(h) to hit or (s) to stand: ";
	char choice;
	do
	{
		cin >> choice;
		cin.ignore(32767, '\n');
	} 
	while (choice != 'h' && choice != 's');
	return choice;
}
And by the way, when I try to run the code now, sometimes it runs fine and at other times it just crashes.


Then run the program with your debugger. The debugger will be able to tell you exactly where it detects the problem and you should be able to view the variables at the time of the crash. I would start by getting your deck initialized properly, then perhaps some of the problems will be solved.

Notice how I placed a return(0) statement directly after my code to print the deck? This is because until the deck is initialized properly there is no sense of running the rest of the program.

Also why are you now using 15 for MAX_RANKS and 5 for MAX_SUIT?
One problem I found was swapCard (deck[index], deck[swapIndex]);
where value of swapIndex was 52.
@Jlb: Please look at the latest code I posted. It doesn't have the MAX values set like that.

Should I put the code for initializing the deck in a separate function and just it have it return the deck after it's done?

@Thomas: Does it have to be less than 52? And should I explicitly make it less than 52 or what?
Did you print out the array after you initialized it?

Do all the values look correct?

Don't worry about the rest of the program until you are sure your initialization routine is working properly!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
	using namespace std;
        // Comment out the srand() statement until you get your basic logic fixed. It is easier to debug if you always have the same sequence of cards.
	// srand(static_cast<unsigned int>(time(nullptr)));

        // This  following line is not needed, just get rid if it.
	rand();

	array<Card, 52> deck;

	int card = 0;
	for (int suit = 0; suit < MAX_SUITS; ++suit)
	{
		for (int rank = 0; rank < MAX_RANKS; ++rank)
		{
			deck[card].suit = static_cast<CardSuit>(suit);
			deck[card].rank = static_cast<CardRank>(rank);
			++card;
// Please explain the following  in English. 
			if (deck[card].rank <= MAX_RANKS || deck[card].suit <= MAX_SUITS)
			{
				break;
			}
		}
	}


That if statement doesn't make much sense to me, please explain.

Should I put the code for initializing the deck in a separate function and just it have it return the deck after it's done?

That's a design issue, I'll leave that decision to you.
@Thomas: Does it have to be less than 52? And should I explicitly make it less than 52 or what?


Your max index in the array cards is 51, no wonder that it crashes.
Alright, guys; I fixed it. The call to the Random Number Generator, the min-max arguments, were out of whack (I changed them to 0 and 51, and now it works), and I also counted the enum items in CardRank and CardSuit and set the Max values to the correct numbers. I don't get an out of bounds error anymore. Just to be safe, I've also decided to use std::array::at() instead of operator[] to access the array indices in initDeck().

@Jlb (about the if-statement you're talking about): I've taken it out now since I don't seem to need it anymore, but it was supposed to make sure that the array index doesn't go out of bounds. The break statement will stop the loop once the value in deck[card].suit is less than or equal to MAX_SUITS and/or the value in deck[card].rank is less than or equal to MAX_RANKS. Although it might've made more sense to check if they're equal to the max values, not less than or equal. I was just scared of the chances of getting a range error increasing if I put deck[card].suit == MAX_SUITS and deck[card].rank ==MAX_RANKS

This will probably get to long if I post the code here, so I'll post it again in another post later (if you want me to).
Last edited on
I've taken it out now since I don't seem to need it anymore, but it was supposed to make sure that the array index doesn't go out of bounds.

That's good, it shouldn't have been needed. But you shouldn't have been checking the "cards" you should have been checking that the index didn't go out of range. And in either case, if the test failed you should have informed the user and halted the program. If your initialization failed there is no way you should continue.

Now with the changes does the array print what appears to be valid information after the initialization, and after the shuffle?

Last edited on
I'll try calling the printCard() and printDeck() functions in main(). But about ending the program if a range error is thrown, that would be done using a try-catch block, right? Where should I have put the block, though? In main(), or in initDeck()?

here's the initDeck() code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
std::array<Card, 52> initDeck()
{
	using namespace std;
	array<Card, 52> deck;
	int card = 0;
	for (int suit = 0; suit < MAX_SUITS; ++suit)
	{
		for (int rank = 0; rank < MAX_RANKS; ++rank)
		{
			deck.at(card).suit = static_cast<CardSuit>(suit);
			deck.at(card).rank = static_cast<CardRank>(rank);
			++card;
		}
	}
	return deck;
}


Yeah, the print functions check out now, too. I should mark this as "solved" now.
Last edited on
Topic archived. No new replies allowed.