Need help finding a probability error in a plinko simulator.

I'm doing an assignment for my intro class about a Plinko game, simulating possible outcomes. For those of you who have no idea what plinko is (like I didn't), here's a flash game version:

http://www.kongregate.com/games/StapleGun/plinko

The assignment parameters are to create a code that prompts the user to either quit, run a single chip simulator, or run a multiple chip simulator. If an invalid entry is ever entered, it is to return the user to the main menu. The program should repeat itself infinitely until the option to exit is chosen.

The plinko machine for our assignment has 12 rows of pegs, so 13 total slots including the entry slot and last slot, and 9 possible entry slots (0-8).

The single chip simulator starts with prompting the user for an entry slot. Then it simulates the chip falling through the machine, with a 50/50 chance to go either left or right for each peg it hits, with the condition that it doesn't exit the walls of the machine. When it reaches the bottom slot, the program records the slot and assigns a monetary reward value depending on which slot it ends up in. The simulation outputs the path of 13 slots the chip took to reach the bottom, then the winnings of the final slot.

The multiple chip simulator runs the same simulation, but before it does it prompts for a number of chips to drop total. It will simulate that number of chips all dropped sequentially into the same initial slot, then output only the total winnings and average winnings from that many chips.


Probability dictates that the chips should finish in slots that are closer to the initial slot more often than otherwise. So the average winnings for each slot for large numbers of chips should be different. My code is giving me very close values for average winnings regardless of the initial slot, which is an error, but I have no idea where it might be found.

Anyone have any insights?

Note that there are a few inefficient coding practices here that are mostly due to the fact that my instructors don't like people writing with more advanced tools than they've taught us, so please forgive any annoyances that might cause.

Code is split up over the next two comments since it and my intro are too long for a single submission, apparently.
Last edited on
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
#include <iostream>
#include <iomanip>
#include <ctime> //I had a recommendation I use srand(time(0)) at the beginning of the program to randomize the seed constantly
#include <cstdlib> //I'm not using RAND_MAX, but I'm just trying any fix

using namespace std;

int main()
{
	int selection = 0;
	int selected_slot = 0;
	int number_of_chips = 0;
	int path_step = 0;
	int seed = 0;
	int chip = 0;
	double current_slot = 0;
	double output_slot = 0;
	double winnings = 0;
	double total_winnings = 0;
	double average_winnings = 0;

	srand(time(0)); //constantly update the random generator seed

	cout << "Welcome to the plinko sumulator!" << endl << endl << endl;

	for (; 1 > 0;) //loop function infinitely
	{
		cout << "MENU: Please select one of the following options:" << endl << endl << "0 - Quit the program" << endl << "1 - Drop a single chip into one slot" << endl << "2 - Drop multiple chips into one slot" << endl << endl << "Enter your selection now: ";
		cin >> selection;

		while (selection < 0 || selection > 2) //if an invalid selection, loop the following
		{
			cout << endl << "INVALID SELECTION.  Please enter 0, 1 or 2" << endl << endl << endl << "MENU: Please select one of the following options:" << endl << endl << "0 - Quit the program" << endl << "1 - Drop a single chip into one slot" << endl << "2 - Drop multiple chips into one slot" << endl << endl << "Enter your selection now: ";
			cin >> selection;
		}

		if (selection == 0) //if 0 selected, close the program
		{
			cout << endl << endl << "GOODBYE!" << endl;
			system("pause");
			return 0;
		}

		if (selection == 1) //If 1 selected, run single chip drop simulator.
		{
			cout << endl << endl << "*** DROP SINGLE CHIP ***" << endl << endl << "Which slot do you want to drop the chip in (0-8)? " << endl;
			cin >> selected_slot;

			if (selected_slot < 0 || selected_slot > 8) //Invalid slot, start the program over
			{
				cout << endl << "INVALID SLOT." << endl << endl << endl << endl << endl;
			}

			else //Valid slot, run simulator
			{
				cout << endl << "*** DROPPING CHIP INTO SLOT " << selected_slot << " ***" << endl << endl << "PATH : [" << selected_slot; //The assignment's required output is left bracket, then each stop along the path separated by a space, then right bracket

				current_slot = selected_slot; //First slot is the selection
				for (path_step = 1; path_step <= 12; path_step++) //There are 12 rows of pegs before the end, so 13 total slots should be reported
				{
					seed = rand() % 2;

					if (seed == 1 && current_slot != 8 && current_slot != 0) //50/50 chance that seed is 1; if it is, and the slot is not already at the edges (8 or 0), add 0.5 to current slot (to obtain output slot, which current slot is set to at the end of the loop)
					{
						output_slot = current_slot + 0.5;
					}

					if (seed == 0 && current_slot != 0 && current_slot != 8) //Same as above but for seed = 0
					{
						output_slot = current_slot - 0.5;
					}

					if (current_slot == 0) //If the above don't apply because the slot is 0 or 8, then it must go up to 0.5 if 0, and down to 7.5 if 8.  Prevents it from falling out of the side.  This part is for 0
					{
						output_slot = current_slot + 0.5;
					}

					if (current_slot == 8) //Same as above for 8
					{
						output_slot = current_slot - 0.5;
					}

					if (floor(output_slot) == output_slot) //These two if functions exist to keep the output values for the current slot at the lowest possible decimal point (n or n.5)
					{
						cout << " " << fixed << setprecision(0) << output_slot;
					}

					if (floor(output_slot) != output_slot) //Same as above
					{
						cout << " " << fixed << setprecision(1) << output_slot;
					}

					current_slot = output_slot; //Set current_slot to value output_slot, and run the loop again.  This loop seems to function properly, but there must be some probability error here.

				}

				if (current_slot == 0 || current_slot == 8) //Next 5 if functions define the money gained from ending in each possible slot.  With the number of times the above loop runs and the safeguard to prevent it falling out the side, the end slot will always be an integer value between 0 and 8.
				{
					winnings = 100;
				}

				if (current_slot == 1 || current_slot == 7) //Same
				{
					winnings = 500;
				}

				if (current_slot == 2 || current_slot == 6) //Same
				{
					winnings = 1000;
				}

				if (current_slot == 3 || current_slot == 5) //Same
				{
					winnings = 0;
				}

				if (current_slot == 4) //Same
				{
					winnings = 10000;
				}

				cout << "]" << endl << endl << "WINNINGS: $" << fixed << setprecision(2) << winnings << endl << endl << endl << endl; //Required format for the output values of the simulation
			}
		} //run program from start again.  I haven't tested rigorously exactly, but this simulation seems to be a correct randomization of outputs within realistic probability; that is, beginning slot 0 is more likely to finish at 0-4 than 5-8. 


Code continued in next comment:
Last edited on
Code continued:

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
		
		if (selection == 2) //If 2 selected, run multiple chip drop simulator.  This is where I'm encountering the problem, though it seems to lie in the code created for the above simulation.
		{
			cout << endl << endl << "*** DROP MULTIPLE CHIPS ***" << endl << endl << "How many chips do you want to drop (>0)? " << endl;
			cin >> number_of_chips;

			if (number_of_chips <= 0) //Invalid number of chips entered, start program over
			{
				cout << endl << "INVALID NUMBER OF CHIPS." << endl << endl << endl << endl << endl;
			}

			else //Valid number, run simulator
			{
				cout << endl << "Which slot do you want to drop the chip in (0-8)?" << endl; //All chips are dropped into the same slot in this simulation
				cin >> selected_slot;

				if (selected_slot < 0 || selected_slot > 8) //Invalid slot entered, start program over
				{
					cout << endl << "INVALID SLOT." << endl << endl << endl << endl << endl;
				}

				else //Valid slot entered, run simulator
				{
					
					current_slot = selected_slot; //First slot is the selected one
					for (chip = 1; chip <= number_of_chips; chip++) //Run the loop the same number of times as chips were chosen
					{

						for (path_step = 1; path_step <= 12; path_step++) //Same code as in the single simulation to find the final output of a single chip, minus the path output in brackets
						{
							seed = rand() % 2;

							if (seed == 1 && current_slot != 8 && current_slot != 0)
							{
								output_slot = current_slot + 0.5;
							}

							if (seed == 0 && current_slot != 0 && current_slot != 8)
							{
								output_slot = current_slot - 0.5;
							}

							if (current_slot == 0)
							{
								output_slot = current_slot + 0.5;
							}

							if (current_slot == 8)
							{
								output_slot = current_slot - 0.5;
							}

							current_slot = output_slot;
						}

						if (current_slot == 0 || current_slot == 8) //Same winnings parameters as in simulation 1
						{
							winnings = 100;
						}

						if (current_slot == 1 || current_slot == 7)
						{
							winnings = 500;
						}

						if (current_slot == 2 || current_slot == 6)
						{
							winnings = 1000;
						}

						if (current_slot == 3 || current_slot == 5)
						{
							winnings = 0;
						}

						if (current_slot == 4)
						{
							winnings = 10000;
						}

						total_winnings = total_winnings + winnings; //Cumulative total winnings: first total winnnings is 0 + winnings of chip 1.  Next would be winnings of chip 1 + winnings of chip 2.  Etc, until the total winnings from n chips has been calculated.
					}

					average_winnings = total_winnings / number_of_chips; //Loop is over, total winnings have been found.  Average winnings are total winnings divided by number of chips.

					cout << endl << "Total Winnings on " << number_of_chips << " chips: " << fixed << setprecision(2) << total_winnings << endl << "Average winnings per chip: " << fixed << setprecision(2) << average_winnings << endl << endl << endl << endl;
				}
			}
		}

		total_winnings = 0; /*Reset total winnings to 0 to prevent leftover values from compromising the program's output.
							The issue I'm running into is that, according to other plinko simulators I've tried online, the average winnings should be following a bell curve from selected slot 0 to 8, that is, 0 and 8 have less average winnings than any other slot, 4 has the most.
							But my code, though it seems to generate a probable path through the plinko machine, always comes out with an average winnings value of around 1600 for large numbers of chips, regardless as to which slot was the initial slot.
							I have no idea where this discrepancy could be, I've been trying to figure it out for hours.*/
	}
}
Last edited on
Topic archived. No new replies allowed.