X-Git-Url: https://git.njae.me.uk/?a=blobdiff_plain;f=hangman%2F03-hangman-both.ipynb;h=54fbdb4a1c2fdc304e1039b026e9da95d35802ec;hb=9aab9a18ab1a0abfd9fd8b7a33bc0c833dea0560;hp=d9e565b688e142d8c9b8541c8603a873c5ac5429;hpb=5001e9431b2a52630f91d78f381c29aca25dd310;p=cas-master-teacher-training.git diff --git a/hangman/03-hangman-both.ipynb b/hangman/03-hangman-both.ipynb index d9e565b..54fbdb4 100644 --- a/hangman/03-hangman-both.ipynb +++ b/hangman/03-hangman-both.ipynb @@ -1,1186 +1,1028 @@ { - "metadata": { - "name": "", - "signature": "sha256:5e9f030b42097ebbcce2654cdb1d9370fde38b61bdbfa85a0cc700e76d5a8a71" - }, - "nbformat": 3, - "nbformat_minor": 0, - "worksheets": [ + "cells": [ { - "cells": [ - { - "cell_type": "code", - "collapsed": false, - "input": [ - "import re\n", - "import random\n", - "import string\n", - "import collections" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 71 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "WORDS = [w.strip() for w in open('/usr/share/dict/british-english').readlines() \n", - " if re.match(r'^[a-z]*$', w.strip())]" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 72 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "STARTING_LIVES = 10" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 73 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "class Game:\n", - " def __init__(self, target, player=None, lives=STARTING_LIVES):\n", - " self.lives = lives\n", - " self.player = player\n", - " self.target = target\n", - " self.discovered = list('_' * len(target))\n", - " self.wrong_letters = []\n", - " self.game_finished = False\n", - " self.game_won = False\n", - " self.game_lost = False\n", - " \n", - " def find_all(self, letter):\n", - " return [p for p, l in enumerate(self.target) if l == letter]\n", - " \n", - " def update_discovered_word(self, guessed_letter):\n", - " locations = self.find_all(guessed_letter)\n", - " for location in locations:\n", - " self.discovered[location] = guessed_letter\n", - " return self.discovered\n", - " \n", - " def do_turn(self):\n", - " if self.player:\n", - " guess = self.player.guess(self.discovered, self.wrong_letters, self.lives)\n", - " else:\n", - " guess = self.ask_for_guess()\n", - " if guess in self.target:\n", - " self.update_discovered_word(guess)\n", - " else:\n", - " self.lives -= 1\n", - " if guess not in self.wrong_letters:\n", - " self.wrong_letters += [guess]\n", - " if self.lives == 0:\n", - " self.game_finished = True\n", - " self.game_lost = True\n", - " if '_' not in self.discovered:\n", - " self.game_finished = True\n", - " self.game_won = True\n", - " \n", - " def ask_for_guess(self):\n", - " print('Word:', ' '.join(self.discovered), \n", - " ' : Lives =', self.lives, \n", - " ', wrong guesses:', ' '.join(sorted(self.wrong_letters)))\n", - " guess = input('Enter letter: ').strip().lower()[0]\n", - " return guess\n", - " \n", - " def play_game(self):\n", - " self.do_turn()\n", - " while not self.game_finished:\n", - " self.do_turn()\n", - " if not self.player:\n", - " self.report_on_game()\n", - " return self.game_won\n", - " \n", - " def report_on_game(self):\n", - " if self.game_won:\n", - " print('You won! The word was', self.target)\n", - " else:\n", - " print('You lost. The word was', self.target)\n", - " return self.game_won" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 74 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "g = Game(random.choice(WORDS))" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 75 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "g.target" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 76, - "text": [ - "'strife'" - ] - } - ], - "prompt_number": 76 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "g.discovered" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 77, - "text": [ - "['_', '_', '_', '_', '_', '_']" - ] - } - ], - "prompt_number": 77 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "g.do_turn()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Word: _ _ _ _ _ _ : Lives = 10 , wrong guesses: \n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "stream": "stdout", - "text": [ - "Enter letter: e\n" - ] - } - ], - "prompt_number": 78 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "g.lives" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 79, - "text": [ - "10" - ] - } - ], - "prompt_number": 79 - }, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Putting both halves together\n", + "We now have systems that can do both halves of the Hangman game. Now it's time to put them together so that we can get a machine to play itself. At the moment, let's concentrate on just the plumbing: let's get the two halves working together. In the next step, we'll think about different strategies and compare their effectiveness.\n", + "\n", + "The word of this section is \"encapsulation.\" \n", + "\n", + "First, a change in terminology. We'll call a `player` the thing that makes the guesses (the guesser player from before). We'll call a `game` the thing that handles receiving guesses, updating `discovered` words, updating lives and all of that. That's what was the setting player from before, but without the bit about picking a random word. We'll have the `game` accept the `target` as a parameter, so that we can test everything more easily (if we know what word the `player` is trying to guess, we can predict what it should do).\n", + "\n", + "Back to encapsulation.\n", + "\n", + "We want to bundle all the state information for a `game` into one 'thing' so that we don't need to worry about global variables. We will also want to bundle up everything to do with a `player` into one 'thing' so we can tell the game about it. For the `player`, the thing will include both any state it needs and the definition of that `player`'s guessing strategy. We're also going to have a bunch of related players, all doing much the same thing but with different strategies.\n", + "\n", + "In this case, objects seem like a natural fit.\n", + "\n", + "(Insert Neil's aikido instructor story here.)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Object-orientation in Python\n", + "There are a few things to remember about object orientation in Python.\n", + "\n", + "1. It's an ugly kludge that was bolted on long after the language was defined.\n", + "\n", + "2. `self` needs to be passed in to all object methods as the first parameter, though it doesn't appear when you call the method.\n", + "\n", + "3. Use `self.whatever` to refer to the instance variable `whatever`\n", + "\n", + "4. Use `self.however(arg1, arg2)` when one method calls another in the same object.\n", + "\n", + "Apart from that, it's pretty straightforward." + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import re\n", + "import random\n", + "import string\n", + "import collections" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "WORDS = [w.strip() for w in open('/usr/share/dict/british-english').readlines() \n", + " if re.match(r'^[a-z]*$', w.strip())]" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "STARTING_LIVES = 10" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This is pretty much the same code as for the `setter` part, just with plenty of `self` statements scatter around. A few things to note:\n", + "\n", + "* `initialise()` is now named `__init__()` (note the double underscores fore and aft).\n", + "* `player` and `lives` are parameters to the `game`, but with default values.\n", + "* I've added two new flags, `game_won` and `game_lost`.\n", + "* `do_turn` asks the player for a guess, if there is a player.\n", + "* The `guess()` method of the `player` is passed the `lives`, in case the guess should change depending on the progress of the game (the `player` can always ignore it).\n", + "* After a guess has been processed, `do_turn` has a few more statements to set the relevant flags to represent the state of the game.\n", + "* `report_on_game()` has been added for when the game is being played against a human." + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "class Game:\n", + " def __init__(self, target, player=None, lives=STARTING_LIVES):\n", + " self.lives = lives\n", + " self.player = player\n", + " self.target = target\n", + " self.discovered = list('_' * len(target))\n", + " self.wrong_letters = []\n", + " self.game_finished = False\n", + " self.game_won = False\n", + " self.game_lost = False\n", + " \n", + " def find_all(self, letter):\n", + " return [p for p, l in enumerate(self.target) if l == letter]\n", + " \n", + " def update_discovered_word(self, guessed_letter):\n", + " locations = self.find_all(guessed_letter)\n", + " for location in locations:\n", + " self.discovered[location] = guessed_letter\n", + " return self.discovered\n", + " \n", + " def do_turn(self):\n", + " if self.player:\n", + " guess = self.player.guess(self.discovered, self.wrong_letters, self.lives)\n", + " else:\n", + " guess = self.ask_for_guess()\n", + " if guess in self.target:\n", + " self.update_discovered_word(guess)\n", + " else:\n", + " self.lives -= 1\n", + " if guess not in self.wrong_letters:\n", + " self.wrong_letters += [guess]\n", + " if self.lives == 0:\n", + " self.game_finished = True\n", + " self.game_lost = True\n", + " if '_' not in self.discovered:\n", + " self.game_finished = True\n", + " self.game_won = True\n", + " \n", + " def ask_for_guess(self):\n", + " print('Word:', ' '.join(self.discovered), \n", + " ' : Lives =', self.lives, \n", + " ', wrong guesses:', ' '.join(sorted(self.wrong_letters)))\n", + " guess = input('Enter letter: ').strip().lower()[0]\n", + " return guess\n", + " \n", + " def play_game(self):\n", + " self.do_turn()\n", + " while not self.game_finished:\n", + " self.do_turn()\n", + " if not self.player:\n", + " self.report_on_game()\n", + " return self.game_won\n", + " \n", + " def report_on_game(self):\n", + " if self.game_won:\n", + " print('You won! The word was', self.target)\n", + " else:\n", + " print('You lost. The word was', self.target)\n", + " return self.game_won" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's test it!" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "g = Game(random.choice(WORDS))" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "g.wrong_letters" - ], - "language": "python", + "data": { + "text/plain": [ + "'distension'" + ] + }, + "execution_count": 48, "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 80, - "text": [ - "[]" - ] - } - ], - "prompt_number": 80 - }, + "output_type": "execute_result" + } + ], + "source": [ + "g.target" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "g.do_turn()" - ], - "language": "python", + "data": { + "text/plain": [ + "['_', '_', '_', '_', '_', '_', '_', '_', '_', '_']" + ] + }, + "execution_count": 49, "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Word: _ _ _ _ _ e : Lives = 10 , wrong guesses: \n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "stream": "stdout", - "text": [ - "Enter letter: d\n" - ] - } - ], - "prompt_number": 81 - }, + "output_type": "execute_result" + } + ], + "source": [ + "g.discovered" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "g.lives" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 82, - "text": [ - "9" - ] - } - ], - "prompt_number": 82 - }, + "name": "stdout", + "output_type": "stream", + "text": [ + "Word: _ _ _ _ _ _ _ _ _ _ : Lives = 10 , wrong guesses: \n", + "Enter letter: e\n" + ] + } + ], + "source": [ + "g.do_turn()" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "g.discovered" - ], - "language": "python", + "data": { + "text/plain": [ + "10" + ] + }, + "execution_count": 51, "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 83, - "text": [ - "['_', '_', '_', '_', '_', 'e']" - ] - } - ], - "prompt_number": 83 - }, + "output_type": "execute_result" + } + ], + "source": [ + "g.lives" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "g.wrong_letters" - ], - "language": "python", + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 52, "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 84, - "text": [ - "['d']" - ] - } - ], - "prompt_number": 84 - }, + "output_type": "execute_result" + } + ], + "source": [ + "g.wrong_letters" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "g = Game(random.choice(WORDS))\n", - "g.play_game()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Word: _ _ _ _ _ _ _ : Lives = 10 , wrong guesses: \n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "stream": "stdout", - "text": [ - "Enter letter: d\n" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Word: _ _ _ _ _ _ d : Lives = 10 , wrong guesses: \n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "stream": "stdout", - "text": [ - "Enter letter: e\n" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Word: _ e _ _ _ e d : Lives = 10 , wrong guesses: \n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "stream": "stdout", - "text": [ - "Enter letter: f\n" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Word: _ e _ _ _ e d : Lives = 9 , wrong guesses: f\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "stream": "stdout", - "text": [ - "Enter letter: e\n" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Word: _ e _ _ _ e d : Lives = 9 , wrong guesses: f\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "stream": "stdout", - "text": [ - "Enter letter: s\n" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Word: _ e _ _ _ e d : Lives = 8 , wrong guesses: f s\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "stream": "stdout", - "text": [ - "Enter letter: t\n" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Word: _ e _ _ _ e d : Lives = 7 , wrong guesses: f s t\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "stream": "stdout", - "text": [ - "Enter letter: n\n" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Word: _ e _ _ _ e d : Lives = 6 , wrong guesses: f n s t\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "stream": "stdout", - "text": [ - "Enter letter: m\n" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Word: _ e _ _ _ e d : Lives = 5 , wrong guesses: f m n s t\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "stream": "stdout", - "text": [ - "Enter letter: h\n" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Word: _ e _ _ _ e d : Lives = 4 , wrong guesses: f h m n s t\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "stream": "stdout", - "text": [ - "Enter letter: o\n" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Word: _ e _ _ _ e d : Lives = 3 , wrong guesses: f h m n o s t\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "stream": "stdout", - "text": [ - "Enter letter: i\n" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Word: _ e _ i _ e d : Lives = 3 , wrong guesses: f h m n o s t\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "stream": "stdout", - "text": [ - "Enter letter: r\n" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Word: r e _ i r e d : Lives = 3 , wrong guesses: f h m n o s t\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "stream": "stdout", - "text": [ - "Enter letter: w\n" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "You won! The word was rewired\n" - ] - }, - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 85, - "text": [ - "True" - ] - } - ], - "prompt_number": 85 - }, + "name": "stdout", + "output_type": "stream", + "text": [ + "Word: _ _ _ _ e _ _ _ _ _ : Lives = 10 , wrong guesses: \n", + "Enter letter: q\n" + ] + } + ], + "source": [ + "g.do_turn()" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "g = Game(random.choice(WORDS))\n", - "g.play_game()" - ], - "language": "python", + "data": { + "text/plain": [ + "9" + ] + }, + "execution_count": 54, "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Word: _ _ _ _ _ : Lives = 10 , wrong guesses: \n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "stream": "stdout", - "text": [ - "Enter letter: e\n" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Word: _ _ _ _ _ : Lives = 9 , wrong guesses: e\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "stream": "stdout", - "text": [ - "Enter letter: s\n" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Word: _ _ _ _ s : Lives = 9 , wrong guesses: e\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "stream": "stdout", - "text": [ - "Enter letter: t\n" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Word: _ _ _ _ s : Lives = 8 , wrong guesses: e t\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "stream": "stdout", - "text": [ - "Enter letter: o\n" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Word: _ _ _ _ s : Lives = 7 , wrong guesses: e o t\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "stream": "stdout", - "text": [ - "Enter letter: i\n" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Word: _ _ _ _ s : Lives = 6 , wrong guesses: e i o t\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "stream": "stdout", - "text": [ - "Enter letter: u\n" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Word: _ _ _ _ s : Lives = 5 , wrong guesses: e i o t u\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "stream": "stdout", - "text": [ - "Enter letter: a\n" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Word: _ _ _ _ s : Lives = 4 , wrong guesses: a e i o t u\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "stream": "stdout", - "text": [ - "Enter letter: y\n" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Word: _ y _ _ s : Lives = 4 , wrong guesses: a e i o t u\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "stream": "stdout", - "text": [ - "Enter letter: w\n" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Word: _ y _ _ s : Lives = 3 , wrong guesses: a e i o t u w\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "stream": "stdout", - "text": [ - "Enter letter: h\n" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Word: h y _ _ s : Lives = 3 , wrong guesses: a e i o t u w\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "stream": "stdout", - "text": [ - "Enter letter: m\n" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Word: h y m _ s : Lives = 3 , wrong guesses: a e i o t u w\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "stream": "stdout", - "text": [ - "Enter letter: n\n" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "You won! The word was hymns\n" - ] - }, - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 86, - "text": [ - "True" - ] - } - ], - "prompt_number": 86 - }, + "output_type": "execute_result" + } + ], + "source": [ + "g.lives" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "g.target" - ], - "language": "python", + "data": { + "text/plain": [ + "['_', '_', '_', '_', 'e', '_', '_', '_', '_', '_']" + ] + }, + "execution_count": 55, "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 108, - "text": [ - "'six'" - ] - } - ], - "prompt_number": 108 - }, + "output_type": "execute_result" + } + ], + "source": [ + "g.discovered" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "class PlayerAlphabetical:\n", - " def guess(self, discovered, missed, lives):\n", - " guessed_letters = [l.lower() for l in discovered + missed if l in string.ascii_letters]\n", - " return [l for l in string.ascii_lowercase if l not in guessed_letters][0]" - ], - "language": "python", + "data": { + "text/plain": [ + "['q']" + ] + }, + "execution_count": 56, "metadata": {}, - "outputs": [], - "prompt_number": 109 - }, + "output_type": "execute_result" + } + ], + "source": [ + "g.wrong_letters" + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "g = Game(random.choice(WORDS), player=PlayerAlphabetical())" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 110 + "name": "stdout", + "output_type": "stream", + "text": [ + "Word: _ _ _ _ _ _ _ _ : Lives = 10 , wrong guesses: \n", + "Enter letter: e\n", + "Word: e _ e _ _ _ _ e : Lives = 10 , wrong guesses: \n", + "Enter letter: x\n", + "Word: e _ e _ _ _ _ e : Lives = 9 , wrong guesses: x\n", + "Enter letter: s\n", + "Word: e _ e _ _ _ _ e : Lives = 8 , wrong guesses: s x\n", + "Enter letter: l\n", + "Word: e _ e _ _ _ _ e : Lives = 7 , wrong guesses: l s x\n", + "Enter letter: t\n", + "Word: e _ e _ _ _ _ e : Lives = 6 , wrong guesses: l s t x\n", + "Enter letter: m\n", + "Word: e _ e _ _ _ _ e : Lives = 5 , wrong guesses: l m s t x\n", + "Enter letter: h\n", + "Word: e _ e _ _ _ _ e : Lives = 4 , wrong guesses: h l m s t x\n", + "Enter letter: i\n", + "Word: e _ e _ _ _ _ e : Lives = 3 , wrong guesses: h i l m s t x\n", + "Enter letter: a\n", + "Word: e _ e _ _ _ _ e : Lives = 2 , wrong guesses: a h i l m s t x\n", + "Enter letter: o\n", + "Word: e _ e _ _ o _ e : Lives = 2 , wrong guesses: a h i l m s t x\n", + "Enter letter: n\n", + "Word: e _ e _ _ o n e : Lives = 2 , wrong guesses: a h i l m s t x\n", + "Enter letter: r\n", + "Word: e _ e r _ o n e : Lives = 2 , wrong guesses: a h i l m s t x\n", + "Enter letter: v\n", + "Word: e v e r _ o n e : Lives = 2 , wrong guesses: a h i l m s t x\n", + "Enter letter: y\n", + "You won! The word was everyone\n" + ] }, { - "cell_type": "code", - "collapsed": false, - "input": [ - "g.play_game()" - ], - "language": "python", + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 57, "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 111, - "text": [ - "False" - ] - } - ], - "prompt_number": 111 - }, + "output_type": "execute_result" + } + ], + "source": [ + "g = Game(random.choice(WORDS))\n", + "g.play_game()" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "g.discovered" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 112, - "text": [ - "['l', 'e', 'g', 'a', 'l', 'l', '_']" - ] - } - ], - "prompt_number": 112 + "name": "stdout", + "output_type": "stream", + "text": [ + "Word: _ _ _ _ _ _ _ _ _ : Lives = 10 , wrong guesses: \n", + "Enter letter: q\n", + "Word: _ _ _ _ _ _ _ _ _ : Lives = 9 , wrong guesses: q\n", + "Enter letter: z\n", + "Word: _ _ _ _ _ _ _ _ _ : Lives = 8 , wrong guesses: q z\n", + "Enter letter: x\n", + "Word: _ _ _ _ _ _ _ _ _ : Lives = 7 , wrong guesses: q x z\n", + "Enter letter: e\n", + "Word: _ _ _ _ _ _ _ _ _ : Lives = 6 , wrong guesses: e q x z\n", + "Enter letter: a\n", + "Word: _ _ a _ _ _ _ _ _ : Lives = 6 , wrong guesses: e q x z\n", + "Enter letter: v\n", + "Word: _ _ a _ _ _ _ _ _ : Lives = 5 , wrong guesses: e q v x z\n", + "Enter letter: b\n", + "Word: _ _ a _ _ _ _ _ _ : Lives = 4 , wrong guesses: b e q v x z\n", + "Enter letter: k\n", + "Word: _ _ a _ k _ k _ _ : Lives = 4 , wrong guesses: b e q v x z\n", + "Enter letter: l\n", + "Word: _ _ a _ k _ k _ _ : Lives = 3 , wrong guesses: b e l q v x z\n", + "Enter letter: j\n", + "Word: _ _ a _ k _ k _ _ : Lives = 2 , wrong guesses: b e j l q v x z\n", + "Enter letter: p\n", + "Word: _ _ a _ k _ k _ _ : Lives = 1 , wrong guesses: b e j l p q v x z\n", + "Enter letter: d\n", + "You lost. The word was sharkskin\n" + ] }, { - "cell_type": "code", - "collapsed": false, - "input": [ - "g.target" - ], - "language": "python", + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 58, "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 113, - "text": [ - "'legally'" - ] - } - ], - "prompt_number": 113 - }, + "output_type": "execute_result" + } + ], + "source": [ + "g = Game(random.choice(WORDS))\n", + "g.play_game()" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "g = Game(random.choice(WORDS), player=PlayerAlphabetical())\n", - "g.play_game()\n", - "print('Target:', g.target, '; Discovered:', g.discovered, '; Lives remaining:', g.lives)" - ], - "language": "python", + "data": { + "text/plain": [ + "'sharkskin'" + ] + }, + "execution_count": 59, "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Target: cavalry ; Discovered: ['c', 'a', '_', 'a', 'l', '_', '_'] ; Lives remaining: 0\n" - ] - } - ], - "prompt_number": 114 - }, + "output_type": "execute_result" + } + ], + "source": [ + "g.target" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Player objects\n", + "Let's work ourselves gently into this.\n", + "\n", + "In the first instance, the only thing a `player` needs is to respond to the `guess` method. Let's make objects with just this method. Let's even make it simpler than the player from the `guesser` stage, and have it just guess letters in alphabetical order." + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "class PlayerAlphabetical:\n", + " def guess(self, discovered, missed, lives):\n", + " return [l for l in string.ascii_lowercase if l not in discovered + missed][0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "That wasn't too hard, was it?\n", + "\n", + "Let's use it to play a game." + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "g = Game(random.choice(WORDS), player=PlayerAlphabetical())" + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "LETTER_COUNTS = collections.Counter(l.lower() for l in open('sherlock-holmes.txt').read() if l in string.ascii_letters)\n", - "LETTERS_IN_ORDER = [p[0] for p in LETTER_COUNTS.most_common()]\n", - "\n", - "class PlayerFreqOrdered:\n", - " def guess(self, discovered, missed, lives):\n", - " guessed_letters = [l.lower() for l in discovered + missed if l in string.ascii_letters]\n", - " return [l for l in LETTERS_IN_ORDER if l not in guessed_letters][0]" - ], - "language": "python", + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 70, "metadata": {}, - "outputs": [], - "prompt_number": 115 - }, + "output_type": "execute_result" + } + ], + "source": [ + "g.play_game()" + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "g = Game(random.choice(WORDS), player=PlayerFreqOrdered())\n", - "g.play_game()\n", - "print('Target:', g.target, '; Discovered:', g.discovered, '; Lives remaining:', g.lives)" - ], - "language": "python", + "data": { + "text/plain": [ + "['c', 'e', '_', '_', 'i', 'f', 'i', 'c', 'a', '_', 'e', '_']" + ] + }, + "execution_count": 71, "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Target: deathblow ; Discovered: ['d', 'e', 'a', 't', 'h', '_', 'l', 'o', 'w'] ; Lives remaining: 0\n" - ] - } - ], - "prompt_number": 116 - }, + "output_type": "execute_result" + } + ], + "source": [ + "g.discovered" + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "g = Game(random.choice(WORDS), player=PlayerFreqOrdered())\n", - "g.play_game()\n", - "print('Target:', g.target, '; Discovered:', g.discovered, '; Lives remaining:', g.lives)" - ], - "language": "python", + "data": { + "text/plain": [ + "'certificates'" + ] + }, + "execution_count": 72, "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Target: littered ; Discovered: ['l', 'i', 't', 't', 'e', 'r', 'e', 'd'] ; Lives remaining: 5\n" - ] - } - ], - "prompt_number": 117 - }, + "output_type": "execute_result" + } + ], + "source": [ + "g.target" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Bored with looking at all the state of the game with different cells. Let's have a `print()` statement that tells us what we need." + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "g = Game(random.choice(WORDS), player=PlayerFreqOrdered())\n", - "g.play_game()\n", - "print('Target:', g.target, '; Discovered:', g.discovered, '; Lives remaining:', g.lives)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Target: licenced ; Discovered: ['l', 'i', 'c', 'e', 'n', 'c', 'e', 'd'] ; Lives remaining: 1\n" - ] - } - ], - "prompt_number": 118 - }, + "name": "stdout", + "output_type": "stream", + "text": [ + "Target: turnoffs ; Discovered: ['_', '_', '_', '_', '_', 'f', 'f', '_'] ; Lives remaining: 0\n" + ] + } + ], + "source": [ + "g = Game(random.choice(WORDS), player=PlayerAlphabetical())\n", + "g.play_game()\n", + "print('Target:', g.target, '; Discovered:', g.discovered, '; Lives remaining:', g.lives)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Another player\n", + "Let's reimplement our player that does letters in frequency order. Again, this is essentially code reused from earlier." + ] + }, + { + "cell_type": "code", + "execution_count": 76, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "LETTER_COUNTS = collections.Counter(l.lower() for l in open('../sherlock-holmes.txt').read() if l in string.ascii_letters)\n", + "LETTERS_IN_ORDER = [p[0] for p in LETTER_COUNTS.most_common()]\n", + "\n", + "class PlayerFreqOrdered:\n", + " def guess(self, discovered, missed, lives):\n", + " return [l for l in LETTERS_IN_ORDER if l not in discovered + missed][0]" + ] + }, + { + "cell_type": "code", + "execution_count": 77, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "class PlayerFixedOrder:\n", - " def __init__(self, ordered_letters):\n", - " self.ordered_letters = ordered_letters\n", - " \n", - " def guess(self, discovered, missed, lives):\n", - " guessed_letters = [l.lower() for l in discovered + missed if l in string.ascii_letters]\n", - " return [l for l in self.ordered_letters if l not in guessed_letters][0]" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 119 - }, + "name": "stdout", + "output_type": "stream", + "text": [ + "Target: cartons ; Discovered: ['c', 'a', 'r', 't', 'o', 'n', 's'] ; Lives remaining: 2\n" + ] + } + ], + "source": [ + "g = Game(random.choice(WORDS), player=PlayerFreqOrdered())\n", + "g.play_game()\n", + "print('Target:', g.target, '; Discovered:', g.discovered, '; Lives remaining:', g.lives)" + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "class PlayerAlphabetical(PlayerFixedOrder):\n", - " def __init__(self):\n", - " super().__init__(string.ascii_lowercase)\n", - "\n", - "class PlayerFreqOrdered(PlayerFixedOrder):\n", - " def __init__(self):\n", - " super().__init__(LETTERS_IN_ORDER)\n" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 120 - }, + "name": "stdout", + "output_type": "stream", + "text": [ + "Target: douching ; Discovered: ['d', 'o', 'u', 'c', 'h', 'i', 'n', '_'] ; Lives remaining: 0\n" + ] + } + ], + "source": [ + "g = Game(random.choice(WORDS), player=PlayerFreqOrdered())\n", + "g.play_game()\n", + "print('Target:', g.target, '; Discovered:', g.discovered, '; Lives remaining:', g.lives)" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "g = Game(random.choice(WORDS), player=PlayerFreqOrdered())\n", - "g.play_game()\n", - "print('Target:', g.target, '; Discovered:', g.discovered, '; Lives remaining:', g.lives)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Target: unworthier ; Discovered: ['u', 'n', 'w', 'o', 'r', 't', 'h', 'i', 'e', 'r'] ; Lives remaining: 5\n" - ] - } - ], - "prompt_number": 121 - }, + "name": "stdout", + "output_type": "stream", + "text": [ + "Target: minimisation ; Discovered: ['m', 'i', 'n', 'i', 'm', 'i', 's', 'a', 't', 'i', 'o', 'n'] ; Lives remaining: 4\n" + ] + } + ], + "source": [ + "g = Game(random.choice(WORDS), player=PlayerFreqOrdered())\n", + "g.play_game()\n", + "print('Target:', g.target, '; Discovered:', g.discovered, '; Lives remaining:', g.lives)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Player subclasses and inheritance\n", + "Time to DRY the code a little. Both of these players (`PlayerAlphabetical` and `PlayerFreqOrdered`) are essentially the same. The only difference is the set of letters used in the middle of the `guess` method. \n", + "\n", + "Let's create a generic \"letters in a fixed order\" class that has that implementation of `guess` and is passed in a set of letters in order. The two players we already have are subclasses of that, where we have pre-packaged letter orders.\n", + "\n", + "Here's the generic player. Note that the ordered letters are passed in as a parameter to the `__init__()` method, and `guess()` uses that letter sequence." + ] + }, + { + "cell_type": "code", + "execution_count": 85, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "class PlayerFixedOrder:\n", + " def __init__(self, ordered_letters):\n", + " self.ordered_letters = ordered_letters\n", + " \n", + " def guess(self, discovered, missed, lives):\n", + " return [l for l in self.ordered_letters if l not in discovered + missed][0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can now specify the subclasses, using the fixed order. The initialisation of the subclasses now takes no additional parameter, but we pass the hardcoded order to the superclass's `__init__()`." + ] + }, + { + "cell_type": "code", + "execution_count": 86, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "class PlayerAlphabetical(PlayerFixedOrder):\n", + " def __init__(self):\n", + " super().__init__(string.ascii_lowercase)\n", + "\n", + "class PlayerFreqOrdered(PlayerFixedOrder):\n", + " def __init__(self):\n", + " super().__init__(LETTERS_IN_ORDER)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Does it work?" + ] + }, + { + "cell_type": "code", + "execution_count": 87, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "g = Game(random.choice(WORDS), player=PlayerFreqOrdered())\n", - "g.play_game()\n", - "print('Target:', g.target, '; Discovered:', g.discovered, '; Lives remaining:', g.lives)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Target: kneel ; Discovered: ['_', 'n', 'e', 'e', 'l'] ; Lives remaining: 0\n" - ] - } - ], - "prompt_number": 122 - }, + "name": "stdout", + "output_type": "stream", + "text": [ + "Target: yogi ; Discovered: ['_', 'o', '_', 'i'] ; Lives remaining: 0\n" + ] + } + ], + "source": [ + "g = Game(random.choice(WORDS), player=PlayerFreqOrdered())\n", + "g.play_game()\n", + "print('Target:', g.target, '; Discovered:', g.discovered, '; Lives remaining:', g.lives)" + ] + }, + { + "cell_type": "code", + "execution_count": 88, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "g = Game(random.choice(WORDS), player=PlayerAlphabetical())\n", - "g.play_game()\n", - "print('Target:', g.target, '; Discovered:', g.discovered, '; Lives remaining:', g.lives)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Target: provisoes ; Discovered: ['_', '_', '_', '_', 'i', '_', '_', 'e', '_'] ; Lives remaining: 0\n" - ] - } - ], - "prompt_number": 123 - }, + "name": "stdout", + "output_type": "stream", + "text": [ + "Target: slimmest ; Discovered: ['s', 'l', 'i', 'm', 'm', 'e', 's', 't'] ; Lives remaining: 3\n" + ] + } + ], + "source": [ + "g = Game(random.choice(WORDS), player=PlayerFreqOrdered())\n", + "g.play_game()\n", + "print('Target:', g.target, '; Discovered:', g.discovered, '; Lives remaining:', g.lives)" + ] + }, + { + "cell_type": "code", + "execution_count": 89, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "g = Game(random.choice(WORDS), player=PlayerFixedOrder(list(reversed(string.ascii_lowercase))))\n", - "g.play_game()\n", - "print('Target:', g.target, '; Discovered:', g.discovered, '; Lives remaining:', g.lives)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Target: invincible ; Discovered: ['_', '_', 'v', '_', '_', '_', '_', '_', '_', '_'] ; Lives remaining: 0\n" - ] - } - ], - "prompt_number": 124 - }, + "name": "stdout", + "output_type": "stream", + "text": [ + "Target: diseases ; Discovered: ['d', 'i', '_', 'e', 'a', '_', 'e', '_'] ; Lives remaining: 0\n" + ] + } + ], + "source": [ + "g = Game(random.choice(WORDS), player=PlayerAlphabetical())\n", + "g.play_game()\n", + "print('Target:', g.target, '; Discovered:', g.discovered, '; Lives remaining:', g.lives)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Can we use the generic version directly?" + ] + }, + { + "cell_type": "code", + "execution_count": 90, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "g = Game(random.choice(WORDS), player=PlayerFixedOrder(list(reversed(string.ascii_lowercase))))\n", - "g.play_game()\n", - "print('Target:', g.target, '; Discovered:', g.discovered, '; Lives remaining:', g.lives)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Target: clogging ; Discovered: ['_', '_', '_', '_', '_', '_', '_', '_'] ; Lives remaining: 0\n" - ] - } - ], - "prompt_number": 125 - }, + "name": "stdout", + "output_type": "stream", + "text": [ + "Target: pardon ; Discovered: ['p', '_', 'r', '_', 'o', 'n'] ; Lives remaining: 0\n" + ] + } + ], + "source": [ + "g = Game(random.choice(WORDS), player=PlayerFixedOrder(list(reversed(string.ascii_lowercase))))\n", + "g.play_game()\n", + "print('Target:', g.target, '; Discovered:', g.discovered, '; Lives remaining:', g.lives)" + ] + }, + { + "cell_type": "code", + "execution_count": 91, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "wins = 0\n", - "for _ in range(1000):\n", - " g = Game(random.choice(WORDS), player=PlayerAlphabetical())\n", - " g.play_game()\n", - " if g.game_won:\n", - " wins += 1\n", - "print(wins)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "44\n" - ] - } - ], - "prompt_number": 126 - }, + "name": "stdout", + "output_type": "stream", + "text": [ + "Target: grouchier ; Discovered: ['_', 'r', 'o', 'u', '_', '_', '_', '_', 'r'] ; Lives remaining: 0\n" + ] + } + ], + "source": [ + "g = Game(random.choice(WORDS), player=PlayerFixedOrder(list(reversed(string.ascii_lowercase))))\n", + "g.play_game()\n", + "print('Target:', g.target, '; Discovered:', g.discovered, '; Lives remaining:', g.lives)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Mass gaming\n", + "Now we can get machines playing each other, we get get them playing *lots* of games and just tell us the summaries. \n", + "\n", + "Which of these three methods (alphabetical, frequency ordered, reverse alphabetical) is the best? Let's get each player to play 1000 random games and see which gets the most wins." + ] + }, + { + "cell_type": "code", + "execution_count": 92, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "wins = 0\n", - "for _ in range(1000):\n", - " g = Game(random.choice(WORDS), player=PlayerFreqOrdered())\n", - " g.play_game()\n", - " if g.game_won:\n", - " wins += 1\n", - "print(wins)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "320\n" - ] - } - ], - "prompt_number": 127 - }, + "name": "stdout", + "output_type": "stream", + "text": [ + "49\n" + ] + } + ], + "source": [ + "wins = 0\n", + "for _ in range(1000):\n", + " g = Game(random.choice(WORDS), player=PlayerAlphabetical())\n", + " g.play_game()\n", + " if g.game_won:\n", + " wins += 1\n", + "print(wins)" + ] + }, + { + "cell_type": "code", + "execution_count": 96, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "wins = 0\n", - "for _ in range(1000):\n", - " g = Game(random.choice(WORDS), player=PlayerFixedOrder(list(reversed(string.ascii_lowercase))))\n", - " g.play_game()\n", - " if g.game_won:\n", - " wins += 1\n", - "print(wins)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "7\n" - ] - } - ], - "prompt_number": 128 - }, + "name": "stdout", + "output_type": "stream", + "text": [ + "309\n" + ] + } + ], + "source": [ + "wins = 0\n", + "for _ in range(1000):\n", + " g = Game(random.choice(WORDS), player=PlayerFreqOrdered())\n", + " g.play_game()\n", + " if g.game_won:\n", + " wins += 1\n", + "print(wins)" + ] + }, + { + "cell_type": "code", + "execution_count": 94, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 128 + "name": "stdout", + "output_type": "stream", + "text": [ + "6\n" + ] } ], - "metadata": {} + "source": [ + "wins = 0\n", + "for _ in range(1000):\n", + " g = Game(random.choice(WORDS), player=PlayerFixedOrder(list(reversed(string.ascii_lowercase))))\n", + " g.play_game()\n", + " if g.game_won:\n", + " wins += 1\n", + "print(wins)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Frequency ordered is much better than the others, but still only wins about 30% of the time. I'm sure we can do better.\n", + "\n", + "That's the next part..." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [] } - ] -} \ No newline at end of file + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.2+" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +}