Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Bowling Calculator

0.00/5 (No votes)
14 Jan 2018 9  
An application to keep score of a bowling game with a hand-written looking score card

The Bowlers Name dialog

The Bowling Calculator dialog

The Bowlers score card

https://en.wikipedia.org/wiki/Automatic_scorer

An automatic scorer is the computerized scoring system introduced into bowling alleys in the 1970s. The use of automatic scorers took away the task of keeping score by hand. This also introduced new bowlers to the game that otherwise would not participate. Most modern systems not only tally the score of a game, but also keep track of handicaps and the scores of league players. Brunswick Bowling & Billiards and QubicaAMF Worldwide are leaders in the research and development of computer systems for bowling alleys for score keeping and other related business (i.e. finance bookkeeping, payrolls, account receivables, account payables).[1]

Automatic scoring equipment is considered as a cornerstone of the bowling center and is marketed as such by capital equipment manufacturers. Today's systems offer advanced graphics, advertising, and marketing features and can also support scoring non-traditional games such as no-tap.

Automatic scorers detect electronically a bowling pin with a wood core and an ionomer cladding. The pin has a fluorescent coating on the outer surface usually in the neck portion. The reason for this is so that electronically it can be detected if still standing or it has been knocked down. This is done with an ultraviolet light detecting system.[2]

Many bowlers didn't trust automatic scorers when they were introduced in the 1970s. Many continued to keep score using the traditional method on paper score sheets to verify the accuracy of the automatic scorers. Today, however, automatic scorers are found in most modern bowling centers. A 16-lane bowling center in Chicago installed the first Automatic Scorer in 1967 by Brunswick Corporation.[3]

In some installations, the automatic scoring is connected directly to the pinsetter circuitry with results sent electronically to the scorer. On string-based pin setting (used in five pin and some ten pin facilities) scores are determined by identifying which pin strings were tugged. Automatic scoring can also be directly connected to a Brunswick GS series pinsetter, which lowers the pin table after each ball.

The automatic scoring is directly connected to the foul detection unit so that foul line violations are automatically scored.

Scoring Code

/*
Deceptively simple looking iterative functions with variability at the 10th iteration.
In reality it is a paradox b/c it looks to the future and to the past at the same time
This is because on a strike or spare the future holds the final score
But when the pin is dropped in the future it has no knowledge of any pins it affects in the past

X = 10 + next 2 shots
/ = 10 + next shot
1 - 10 = face value
10th frame possible 3rd throw
*/

BOOL CBCDlg::UpdateScore(int nP1, int nP2, int nP3, unsigned int & MyCurrentFrame, unsigned int & MyFrameScore, unsigned int & MyRunningTotal, unsigned int & MyTotalScore)
{
	CString cs;
	unsigned int iFrame = MyCurrentFrame;
	{
		unsigned int nFramePins = 10;
		unsigned int nShots = iFrame != 9 ? 2 : 3;

		for (unsigned int iShot = 0; iShot < nShots; ++iShot)
		{
			unsigned int nPins1 = 0;
			if (iShot == 0)
				nPins1 = nP1;
			else if (iShot == 1)
				nPins1 = nP2;
			else if (iShot == 2)
				nPins1 = nP3;

			// Update the pins in the scoring array
			unsigned int iPos = iFrame * 2;
			m_arrPoints[iPos + iShot] = nPins1;

			// Update the remaining number of pins
			nFramePins -= nPins1;

			// Update the remaining number of throws
			if (nFramePins == 0)
			{
				if (iFrame != 9)
					nShots--;
				nFramePins = 10;
			}
			else
			{
				if (iFrame == 9 && iShot == 1 && m_arrPoints[iPos] != 10)
					nShots--;
			}
		}

		// Tally the score and update the score card
		unsigned int iCurrentFrame = 0;
		unsigned int iTotalScore = 0;
		unsigned int iFrameScore = 0;

		unsigned int arrFrameScore[10];
		memset(&arrFrameScore[0], 0, 10 * sizeof(unsigned int));

		while (iCurrentFrame <= iFrame)
		{
			unsigned int iPos = iCurrentFrame * 2;
			unsigned int nPins = m_arrPoints[iPos];
			CString csTemp;

			if (iCurrentFrame != 9)
			{
				// Strike is 10 + sum of next 2 rolls
				if (nPins == 10)
				{
					// Next roll starts in next frame
					unsigned int nPins2 = m_arrPoints[iPos + 2];
					if (nPins2 == 10)
					{
						// Next roll starts in next frame if the next frame is not the last frame
						if ((iCurrentFrame + 1) != 9)
						{
							unsigned int nPins3 = m_arrPoints[iPos + 4];
							iFrameScore = 20 + nPins3;
						}
						else // Next roll starts in the middle shot of the last frame
						{
							unsigned int nPins3 = m_arrPoints[iPos + 3];
							iFrameScore = 20 + nPins3;
						}
					}
					else
					{
						// Next roll is the second shot of the next frame
						unsigned int nPins3 = m_arrPoints[iPos + 3];
						iFrameScore = 10 + nPins2 + nPins3;
					}
					csTemp.Format(_T("%3s"), _T("X"));
					cs += csTemp;
				}
				else
				{
					// Next roll is the next shot
					unsigned int nPins2 = m_arrPoints[iPos + 1];
					if ((nPins + nPins2) == 10)
					{
						// Next roll is the first shot of the next frame
						unsigned int nPins3 = m_arrPoints[iPos + 2];

						// Spare is 10 + sum of next roll
						iFrameScore = 10 + nPins3;

						if (nPins)
							csTemp.Format(_T("%2d%s"), nPins, _T("/"));
						else
							csTemp = _T(" -/");

						cs += csTemp;
					}
					else
					{
						// Open is sum of pins
						iFrameScore = nPins + nPins2;

						if (m_iCurrentThrow == 1 && iCurrentFrame == iFrame)
						{
							if (nPins)
								csTemp.Format(_T(" %d "), nPins);
							else
								csTemp = _T(" - ");
						}
						else
						{
							if (nPins && nPins2)
								csTemp.Format(_T(" %d%d"), nPins, nPins2);
							else if (nPins && !nPins2)
								csTemp.Format(_T(" %d-"), nPins);
							else if (!nPins && nPins2)
								csTemp.Format(_T(" -%d"), nPins2);
							else
								csTemp = _T(" --");
						}
						cs += csTemp;
					}
				}
				cs += _T(" ");
			}
			else
			{
				// Score is sum of pins'
				unsigned int nPins1 = m_arrPoints[iPos];
				unsigned int nPins2 = m_arrPoints[iPos + 1];
				unsigned int nPins3 = m_arrPoints[iPos + 2];
				iFrameScore = nPins1 + nPins2 + nPins3;

				// Generate the score card text
				if (m_iCurrentThrow == 1)
				{
					if (nPins1 == 10) // 1 strike
						csTemp = _T("X  ");
					else
					{
						if (nPins1)
							csTemp.Format(_T("%d  "), nPins1); // Pins
						else
							csTemp = _T("-  ");
					}
				}
				else if (m_iCurrentThrow == 2)
				{
					if (nPins1 == 10 && nPins2 == 10) // 2 strikes
						csTemp = _T("XX ");
					else if (nPins1 == 10 && nPins2 < 10) // 1 strike and pins
					{
						if (nPins2)
							csTemp.Format(_T("X%d "), nPins2);
						else
							csTemp = _T("X- ");
					}
					else if (nPins1 + nPins2 == 10) // 1 spare
					{
						if (nPins1)
							csTemp.Format(_T("%d/ "), nPins1);
						else
							csTemp = _T("-/ ");
					}
					else
					{
						if (nPins1 && nPins2)
							csTemp.Format(_T("%d%d "), nPins1, nPins2); // pins
						else if (nPins1 && !nPins2)
							csTemp.Format(_T("%d -"), nPins1); // pins
						else if (!nPins1 && nPins2)
							csTemp.Format(_T("- %d"), nPins2); // pins
						else
							csTemp = _T("- -");
					}
				}
				else
				{
					if (nPins1 == 10 && nPins2 == 10 && nPins3 == 10) // 3 strikes
						csTemp = _T("XXX");
					else if (nPins1 == 10 && nPins2 == 10 && nPins3 < 10) // 2 strikes and pins
					{
						if (nPins3)
							csTemp.Format(_T("XX%d"), nPins3);
						else
							csTemp = _T("XX-");
					}
					else if (nPins1 == 10 && (nPins2 + nPins3) == 10) // 1 strike and a spare
					{
						if (nPins2)
							csTemp.Format(_T("X%d/"), nPins2);
						else
							csTemp = _T("X-/");
					}
					else if ((nPins1 + nPins2) == 10 && nPins3 == 10) // 1 spare and a strike
					{
						if (nPins1)
							csTemp.Format(_T("%d/X"), nPins1);
						else
							csTemp = _T("-/X");
					}
					else if ((nPins1 + nPins2) == 10 && nPins3 < 10) // 1 spare and pins
					{
						if (nPins1 && nPins3)
							csTemp.Format(_T("%d/%d"), nPins1, nPins3);
						else if (nPins1 && !nPins3)
							csTemp.Format(_T("%d/-"), nPins1);
						else if (!nPins1 && nPins3)
							csTemp.Format(_T("-/%d"), nPins3);
						else
							csTemp = _T("-/-");
					}
					else
					{
						if (nPins1 && nPins2)
							csTemp.Format(_T("%d%d"), nPins1, nPins2);
						else if (nPins1 && !nPins2)
							csTemp.Format(_T("%d-"), nPins1);
						else if (!nPins1 && nPins2)
							csTemp.Format(_T("-%d"), nPins2);
						else
							csTemp = _T("--");
					}
				}

				// Append the score
				cs += csTemp;
			}

			// Update the frame and total score
			arrFrameScore[iCurrentFrame] = iFrameScore;
			iTotalScore += iFrameScore;

			++iCurrentFrame;
		}


		// Put the pins on the score card
		Text(cs, 1, 2);

		// Get the frame scores
		cs.Empty();
		for (iCurrentFrame = 0; iCurrentFrame <= iFrame; ++iCurrentFrame)
		{
			CString csTemp;
			csTemp.Format(_T("%3d"), arrFrameScore[iCurrentFrame]);
			cs += csTemp;
			if (iCurrentFrame != 9)
				cs += _T(" ");
		}

		// Put the frame score on the score card
		Text(cs, 1, 3);

		// Get the running total
		cs.Empty();
		unsigned int iRunningTotal = 0;
		for (iCurrentFrame = 0; iCurrentFrame <= iFrame; ++iCurrentFrame)
		{
			iRunningTotal += arrFrameScore[iCurrentFrame];
			CString csTemp;
			csTemp.Format(_T("%3d"), iRunningTotal);
			cs += csTemp;
			if (iCurrentFrame != 9)
				cs += _T(" ");
		}

		// Put the running total on the score card
		Text(cs, 1, 4);

		// Set the outparameters
		MyFrameScore = arrFrameScore[MyCurrentFrame];
		MyRunningTotal = iRunningTotal;
		MyTotalScore = iTotalScore;

		CString csTotalScore;
		csTotalScore.Format(_T("Score: %d"), MyTotalScore);
		Text(csTotalScore, 1, 5);
	}

	return 0;
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here