Created
November 4, 2015 00:58
-
-
Save DamnedFacts/b69a9eec96f6cecbe66a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "cells": [ | |
| { | |
| "metadata": {}, | |
| "cell_type": "markdown", | |
| "source": "# Racquetball Simulation" | |
| }, | |
| { | |
| "metadata": {}, | |
| "cell_type": "markdown", | |
| "source": "## Analysis and Specification\nRacquetball is played between two players using a racquet to hit a ball in a four-walled court\nOne player starts the game by putting the ball in motion – serving\nPlayers try to alternate hitting the ball to keep it in play, referred to as a rally\nThe rally ends when one player fails to hit a legal shot\n\n * Racquetball is played between two players using a racquet to hit a ball in a four-walled court\n * One player starts the game by putting the ball in motion – serving\n * Players try to alternate hitting the ball to keep it in play, referred to as a rally\n * The rally ends when one player fails to hit a legal shot\n - The player who misses the shot loses the rally\n - If the loser is the player who served, service passes to the other player\n - If the server wins the rally, a point is awarded\n - Players can only score points during their own service\n * The first player to reach 15 points wins the game\n\nIn our simulation, the ability level of the players will be represented by the probability that the player wins the rally when he or she serves." | |
| }, | |
| { | |
| "metadata": {}, | |
| "cell_type": "markdown", | |
| "source": "### Input: \nThe program prompts for and gets the service probabilities of players A and B. The program then prompts for and gets the number of games to be simulated" | |
| }, | |
| { | |
| "metadata": {}, | |
| "cell_type": "markdown", | |
| "source": "### Output:\nThe program will provide a series of **initial prompts**, to the user, such as the following:\n\n What is the probability player A wins a serve?\n What is the probability that player B wins a server?\n How many games to simulate?\n \nFinally, **when finished**, the program prints out a nice report, showing:\n 1. The number of games simulated\n 2. The number of wins \n 3. The winning percentage for each player\n \nSuch as:\n\n Games simulated: 500\n Wins for A: 268 (53.6%)\n Wins for B: 232 (46.4%)" | |
| }, | |
| { | |
| "metadata": { | |
| "collapsed": true, | |
| "trusted": true | |
| }, | |
| "cell_type": "code", | |
| "source": "# We need the 'random' function from the 'random' module.\nfrom random import random", | |
| "execution_count": 79, | |
| "outputs": [] | |
| }, | |
| { | |
| "metadata": { | |
| "collapsed": false, | |
| "trusted": true, | |
| "run_control": { | |
| "breakpoint": false | |
| } | |
| }, | |
| "cell_type": "code", | |
| "source": "# Here, we introduce you to writing classes\nclass Player:\n \"\"\"Player Class\n This class demonstrates the following aspects of object-oriented design, in Python:\n * An initializer method (__init__).\n * The concept of 'self' inside an object instance.\n * Attributes (instance variables and methods).\n * Using setter/getter functions OR accessing the attributes of an object directly\n \"\"\"\n def __init__(self, prob, name):\n self.probability = prob\n self.name = name\n self.wins = 0\n \n def get_prob(self):\n #print(\"Probability for player {} is {}\".format(self.name, self.probability))\n return self.probability\n \n def get_name(self):\n return self.name\n \n def set_prob(self, new_prob):\n self.probability = new_prob\n \n def set_name(self, new_name):\n self.name = new_name", | |
| "execution_count": 80, | |
| "outputs": [] | |
| }, | |
| { | |
| "metadata": { | |
| "collapsed": false, | |
| "trusted": true, | |
| "run_control": { | |
| "breakpoint": false | |
| } | |
| }, | |
| "cell_type": "code", | |
| "source": "# See, these objects are truly distinct.\nplayer_a = Player(0.7, \"Bob\")\nplayer_b = Player(0.45, \"Pete\")", | |
| "execution_count": 81, | |
| "outputs": [] | |
| }, | |
| { | |
| "metadata": { | |
| "collapsed": false, | |
| "trusted": true, | |
| "run_control": { | |
| "breakpoint": false | |
| } | |
| }, | |
| "cell_type": "code", | |
| "source": "# Look, we can call getters and setters to update the state inside one of our objects!\nplayer_a.get_prob()\nplayer_b.get_prob()\n\nplayer_b.set_prob(0.65)\n\nplayer_a.get_prob()\nplayer_b.get_prob()", | |
| "execution_count": 82, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": "0.65" | |
| }, | |
| "output_type": "execute_result", | |
| "metadata": {}, | |
| "execution_count": 82 | |
| } | |
| ] | |
| }, | |
| { | |
| "metadata": { | |
| "collapsed": true, | |
| "trusted": true | |
| }, | |
| "cell_type": "code", | |
| "source": "def printIntro():\n print(\"This program simulates racquet ball\")", | |
| "execution_count": 83, | |
| "outputs": [] | |
| }, | |
| { | |
| "metadata": { | |
| "collapsed": true, | |
| "trusted": true | |
| }, | |
| "cell_type": "code", | |
| "source": "def getInputs():\n # Instead of hardcoding our players' names, maybe we can ask for them here.\n a = eval(input(\"Player A prob:\"))\n b = eval(input(\"Player B prob:\"))\n n = eval(input(\"Number of games to play:\"))\n return a, b, n", | |
| "execution_count": 84, | |
| "outputs": [] | |
| }, | |
| { | |
| "metadata": { | |
| "collapsed": false, | |
| "trusted": true | |
| }, | |
| "cell_type": "code", | |
| "source": "def printSummary(playerA, playerB):\n # Print summary would do well by having customize output to make it clear who these players are, by name.\n n = playerA.wins + playerB.wins\n \n print(\"\\nGames simulated:\", n)\n print(\"Wins for {2}: {0} ({1:0.1%})\".format(playerA.wins, playerA.wins/n, playerA.get_name()))\n print(\"Wins for {2}: {0} ({1:0.1%})\".format(playerB.wins, playerB.wins/n, playerB.get_name()))", | |
| "execution_count": 85, | |
| "outputs": [] | |
| }, | |
| { | |
| "metadata": { | |
| "collapsed": true, | |
| "trusted": true | |
| }, | |
| "cell_type": "code", | |
| "source": "def gameOver(a, b):\n return a == 15 or b == 15", | |
| "execution_count": 86, | |
| "outputs": [] | |
| }, | |
| { | |
| "metadata": { | |
| "collapsed": true, | |
| "trusted": true | |
| }, | |
| "cell_type": "code", | |
| "source": "def simOneGame(player_a, player_b):\n serving = player_a.get_name()\n scoreA = 0\n scoreB = 0\n \n # We demonstrate getters more clearly, by retrieving a player's name and probability.\n # Their name is used to determine who is currently serving.\n while not gameOver(scoreA, scoreB):\n if serving == player_a.get_name():\n if random() < player_a.get_prob():\n scoreA += 1\n else:\n serving = player_b.get_name()\n else:\n if random() < player_b.get_prob():\n scoreB += 1\n else:\n serving = player_a.get_name()\n \n return scoreA, scoreB", | |
| "execution_count": 87, | |
| "outputs": [] | |
| }, | |
| { | |
| "metadata": { | |
| "collapsed": true, | |
| "trusted": true | |
| }, | |
| "cell_type": "code", | |
| "source": "def simNGames(n, player_a, player_b):\n # This is a minor change from how I did it in class, let's initialize our \n # player's win counts to zero.\n player_a.win = 0\n player_b.win = 0\n \n # loop n times\n for i in range(n):\n # simulate a game\n scoreA, scoreB = simOneGame(player_a, player_b)\n \n # if playerA wins\n if scoreA > scoreB:\n # Add one to winsA\n player_a.win += 1\n else:\n # Add one to winsB\n player_b.win += 1\n \n # No 'return' needed!\n \n # When our function finished, we don't need to return anything. The player objects we passed\n # in are now updated with new information about their respective wins. Since these player objects are being\n # passed around to various functions with different names and scopes, they do refer to the very same \n # player objects we instatiated in 'main', and therefore hold the new updated information on their wins.", | |
| "execution_count": 88, | |
| "outputs": [] | |
| }, | |
| { | |
| "metadata": { | |
| "collapsed": false, | |
| "trusted": true | |
| }, | |
| "cell_type": "code", | |
| "source": "def main():\n printIntro()\n probA, probB, n = getInputs()\n \n # Here, we create two players with 'hardcoded' names: Charlie and Amy.\n # These *instances* of class 'Player' are stored in 'player_a' and 'player_b', respectively.\n player_a = Player(probA, \"Charlie\")\n player_b = Player(probB, \"Amy\")\n \n # Too easy, we want this to be a fully fleshed-out object-oriented program.\n # winsA, winsB = simNGames(n, player_a.get_prob(), player_b.get_prob())\n \n # Now, instead of passing one int and two floats as an argument to this function,\n # we instead pass in the number of games we're playing and our two players (as objects!)\n simNGames(n, player_a, player_b)\n \n # Same here. Our player objects hold their own information about the number of wins they had\n printSummary(player_a, player_b)\n\nmain()", | |
| "execution_count": 89, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": "This program simulates racquet ball\nPlayer A prob:0.65\nPlayer B prob:0.8\nNumber of games to play:100\n\nGames simulated: 100\nWins for Charlie: 19 (19.0%)\nWins for Amy: 81 (81.0%)\n" | |
| } | |
| ] | |
| } | |
| ], | |
| "metadata": { | |
| "kernelspec": { | |
| "name": "python3", | |
| "display_name": "Python 3", | |
| "language": "python" | |
| }, | |
| "language_info": { | |
| "mimetype": "text/x-python", | |
| "version": "3.4.3", | |
| "file_extension": ".py", | |
| "codemirror_mode": { | |
| "name": "ipython", | |
| "version": 3 | |
| }, | |
| "nbconvert_exporter": "python", | |
| "name": "python", | |
| "pygments_lexer": "ipython3" | |
| } | |
| }, | |
| "nbformat": 4, | |
| "nbformat_minor": 0 | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment