Help with card game war

I am working on the card game war. I have setup three linked lists, one for each player's hand and one for the war cards. When a player hits war, I try to take off 5 cards (the original card that tied, three for war, then one to see who wins war). I add those cards to the linkedlist war and based on whomever wins with the fifth card, dump all the elements from the war linked list to that players linked list. For some reason, the code runs through and gets to a few "wars" and hits a segmentation fault. I don't know why it would run through wars more than once THEN hit a fault. Could someone please help?

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
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
#include<iostream>
#include <cstdlib>
#include <ctime>
#include <stdio.h>
using namespace std;
/*COM252 War midterm project
 * Rob Mancuso, Matthew Wimpelberg
*/

int funcCount = 0;

//Deck class to hold an array of cards
class Deck
{
public:
	int wDeck[52];
	int shuffledDeck[52];
	//Populate the deck with cards
	void fillDeck()
	{
		int i = 0;
		int cardnum = 2;
		//Start with card 2 and fill 4 of each up to 14 
		//We will handle printing J Q K A later from 11-14
		while (i<52)
		{
			for (int j = 1; j<5; j++)
			{
				wDeck[i] = cardnum;
				i++;
			}
			cardnum++;
		}
	}
	//Print method for debugging
	void printDeck()
	{
		for (int i = 0; i<52; i++)
		{
			switch (shuffledDeck[i])
			{
			case 11:
				cout << "J" << endl;
				break;
			case 12:
				cout << "Q" << endl;
				break;
			case 13:
				cout << "K" << endl;
				break;
			case 14:
				cout << "A" << endl;
				break;
			default: cout << shuffledDeck[i] << endl;
			}
		}
	}
	void shuffleDeck()
	{
		short int nums[52];
		short int x = 0, y = 0;
		srand(time(NULL));
		x = 0;
		while (x < 52)
		{
			y = 0;
                        //Generate a random number in the range of 0-52
			nums[x] = rand() % 52; 
                        //Check each number in the array to make sure the current random number isn't in it
			while (y < 52)
			{
				//If another number is equal to this one.
				if (nums[y] == nums[x] && x != y) //If another number is equal to this one.
				{
					--x; //Set x back one. 
					y = 0; //Reset y;
					break; //Try again.
				}
				else
				{
					++y; //Otherwise, check the next number.
				}
			}
			++x; //When we reach here, if --x happened, we need to start over.
		}
		x = 0; 
		//Fill the empty array of shuffled cards with the value of a random array element as the index of the ordered deck
		while (x < 52)
		{
			shuffledDeck[x] = wDeck[nums[x]];
			++x;
		}

	}
};

//Class to hold each players hand as a linked list
class Hand
{
public:
	int value;
};

class Link
{
public:
	Hand *pHand;
	Link *Next;
};

class LinkedList
{
private:
	Link *First;
	Link *Last;
public:
	LinkedList()
	{
		First = NULL;
	}
//Add a card to the beginning of the list
	void AddCard(int cValue)
	{
		Link *newLink = new Link;
		Hand *nHand = new Hand;
		newLink->pHand = nHand;
		nHand->value = cValue;
		newLink->Next = First; //makes next null
		First = newLink;
	}
//Add a card at the end or in this case the bottom of the pile so that it's not used by the player in the next hand after a winning one
	void AddCardEnd(int cValue)
	{
		//We setup two pointers to Link objects
		Link *lastItem = new Link;
		Link *newNode = new Link;
		Hand *nHand = new Hand;
		//This pointer called lastItem will start at the first element and go through the list
		lastItem = First;
		//Set the parameters of the hand
		newNode->pHand = nHand;
		nHand->value = 1;
		//If the first item is null then set it to the new Node
		if (First == NULL)
		{
			First = newNode;
			First->Next = NULL;
		}
		else
		{
			//Loop through the linked list to find the last element
			while (lastItem->Next != NULL)
			{
				lastItem = lastItem->Next;
			}
			//The item after the last item will be our new item
			lastItem->Next = newNode;
		}
	}


	void RemoveCard()
	{
		delete First->pHand;;
		First = First->Next;
	}

	//Remove the entire linked list
	void RemoveList(LinkedList LL)
	{
		Link *current = new Link;
		Link *temp = new Link;
		current = First;
		//Loop through the list for the last item
		while (current != NULL)
		{
			//Since we are going to remove the current link, we must store the next node in a temp variable to reuse
			temp = current->Next;
			//Remove the hand and the link, then move to the next item by setting current back to temp which held the node after the one we delet
			delete current->pHand;
			delete current;
			current = temp;
		}
		//Since you've reached the end, there is one more link and card that is null that must be deleted
		delete current->pHand;
		delete current;
	}

	int Display()
	{
        Link *current = First;
	while(current != NULL)
	{
	cout <<  current->pHand->value << "\n";
	current=current->Next;
	return current->pHand->value;
	}
	}
	
	int CountCards()
	{
        Link *current = First;
	int counter=0;
	while(current != NULL)
	{
	counter++;
	current=current->Next;
	}
	return counter;
	}
	int turn()
	{
		int val;
		Link *current = First;
		val = current->pHand->value;
		cout << val;
		//First = First->Next;
		return val;
	}
	//Deal out three cards from each player if there is a tie aka war
	int war()
	{
		int val1, val2, val3;
		val1 = turn();
		val2 = turn();
		val3 = turn();
		return turn();
	}
};

int main()
{
//Setup a deck object to hold the shuffled array and two linkedlist for a players hand
	Link *First= new Link;
	Link *Current=First;
	Deck nDeck;
	int z=0;
	LinkedList P1;
	LinkedList P2;
	int x;
	int counter = 0;
//Fill in the deck then shuffle it
	nDeck.fillDeck();
	nDeck.shuffleDeck();
	nDeck.printDeck();
        int p1count,p2count;
//Deal out the cards to each player from the shuffled deck
	for (int i = 0; i < 52; i++)
	{
		if (i % 2 == 0)
		{
			P1.AddCard(nDeck.shuffledDeck[i]);
		}
		else
		{
			P2.AddCard(nDeck.shuffledDeck[i]);
		}
	}
	cout << "-----Player1-----" << endl;
	cout << "-----Player2-----" << endl;
	cout << "-------------------------" << endl;
	int P1Card, P2Card, wCard1, wCard2;//holds the value of the turn
	int wCount = 0;
	do
	{
		cout <<"PLAYER ONE SCORE IS  " << p1count << "\n";

		cout <<"PLAYER TWO SCORE IS  " << p2count << "\n";
		//cin >> x;
		cout << "P1 card: ";
		P1Card = P1.turn();
		cout << endl << "P2 card : ";
		P2Card = P2.turn();
		cout << endl;
		//these ifs compare the value of the cards turned
		if (P1Card == 1 || P2Card==1)
		{
		P1.RemoveCard();P2.RemoveCard();
		continue;
		}
		if (P1Card > P2Card)
		{
			cout << "Player1 wins this round!";
			P1.RemoveCard();
			P1.AddCardEnd(P1Card);
			P1.AddCardEnd(P2Card);
			P2.RemoveCard();
			cout << "Player 1 now has ";
		}
		if (P2Card > P1Card)
		{
			cout << "Player2 wins this round!";
			P2.RemoveCard();
			P2.AddCardEnd(P2Card);
			P2.AddCardEnd(P1Card);
			P1.RemoveCard();
		}
		do
		{
		if (P1Card == P2Card)
		{
			cout << "WAR" << "\n";
			LinkedList war;

			war.AddCard(P1Card);
			P1.RemoveCard();
			war.AddCard(P1.turn());
			P1.RemoveCard();
			war.AddCard(P1.turn());
			P1.RemoveCard();
			war.AddCard(P1.turn());
			P1.RemoveCard();
			war.AddCard(P1.turn());
			P1.RemoveCard();

			war.AddCard(P2Card);
			P2.RemoveCard();
			war.AddCard(P2.turn());
			P2.RemoveCard();
			war.AddCard(P2.turn());
			P2.RemoveCard();
			war.AddCard(P2.turn());
			P2.RemoveCard();
			war.AddCard(P2.turn());
			P2.RemoveCard();
			wCard1=war.turn();
			war.RemoveCard();
			wCard2=war.turn();
			war.RemoveCard();
			if (wCard1==1 || wCard2==1)
			{
			P1.RemoveCard();P2.RemoveCard();
			break;
			}

			int addme=1;
			cout << "WCARD1 IS " << wCard1 << "\n";
			
			cout << "WCARD2 IS " << wCard2 << "\n";
				if (wCard1 > wCard2)
				{
				cout << "P1 wins war" << "\n";
					 while (addme!=0)
					
					{
						
						addme=war.Display();
						cout << "I ADDED " << addme << "\n";
						P1.AddCardEnd(addme);
						war.RemoveCard();	
					}
					
				}
				if (wCard1 < wCard2)
				{
				cout << "P2 wins war" << "\n";
					while (addme!=0)
					{
						addme=war.Display();
						cout << "I ADDED " << addme << "\n";
						P2.AddCardEnd(addme);
						war.RemoveCard();
					}	
				
				}
		}
		} while (wCard1 == wCard2);//repeats war while the cards turned last in both hands equal each other
	
                 p1count=P1.CountCards();
                 p2count = P2.CountCards();
	} while (p1count<52 & p2count<52);

	return 0;
}
I haven't read all of the code yet, or run the program even. But I noticed that your "RemoveCard()" function doesn't check to see if the players hand is empty.
Yes, I need to fix that. The segmentation fault comes when a player's hand isn't empty though.
The segfault is coming from Lines 294 or 295. The function "LinkedList::AddCardEnd()" has a few things wrong with it, you may want to consider starting from scratch on that one.
This is my new AddCardEnd()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    void AddCardEnd(int cValue)
        {
                //We setup two pointers to Link objects
                Link *lastItem = new Link;
                Link *newNode = new Link;
                Hand *nHand = new Hand;
                //This pointer called lastItem will start at the first element and go through the list
                lastItem = First;
                //Set the parameters of the hand
                newNode->pHand = nHand;
                //Loop through the linked list to find the last element
                while (lastItem->Next != NULL)
                {
                        lastItem = lastItem->Next;
                }
                //The item after the last item will be our new item
                lastItem->Next = newNode;
                newNode->Next=NULL;
        }
1
2
3
               Link *lastItem = new Link;    // lastItem points to a newly allocated link.
                // ...
                lastItem = First;    // lastItem points to the Link pointed to by First. 


What happens to the newly allocated Link that lastItem just pointed to? What happens on line 12 if lastItem is null?

Your LinkedList class has a member variable Last. Do you think that in a method that is intended to add a card to the end of the list, that variable might need to be updated? Assuming that variable is kept updated, why do you need to iterate through the entire list in AddCardEnd?
Last edited on
Topic archived. No new replies allowed.