Python 3 Patterns & Idioms / html / Projects.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    
    <title>Projects &mdash; Python 3 Patterns, Recipes and Idioms</title>
    <link rel="stylesheet" href="_static/default.css" type="text/css" />
    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
    <script type="text/javascript">
      var DOCUMENTATION_OPTIONS = {
          URL_ROOT:    '',
          VERSION:     '1.0',
          COLLAPSE_MODINDEX: false,
          FILE_SUFFIX: '.html'
      };
    </script>
    <script type="text/javascript" src="_static/jquery.js"></script>
    <script type="text/javascript" src="_static/doctools.js"></script>
    <link rel="shortcut icon" href="_static/favicon.ico"/>
    <link rel="index" title="Index" href="genindex.html" />
    <link rel="search" title="Search" href="search.html" />
    <link rel="top" title="Python 3 Patterns, Recipes and Idioms" href="index.html" />
    <link rel="prev" title="Pattern Refactoring" href="PatternRefactoring.html" />
  </head>
  <body>
    <div class="related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="genindex.html" title="General Index"
             accesskey="I">index</a></li>
        <li class="right" >
          <a href="PatternRefactoring.html" title="Pattern Refactoring"
             accesskey="P">previous</a> |</li>
        <li><a href="index.html">Python 3 Patterns, Recipes and Idioms</a> &raquo;</li>
      </ul>
    </div>
    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          <div class="body">
            
  
  <div class="section" id="projects">
<h1>Projects<a class="headerlink" href="#projects" title="Permalink to this headline"></a></h1>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">This chapter has not had any significant translation yet.</p>
</div>
<p>A number of more challenging projects for you to solve. [[Some of these may turn
into examples in the book, and so at some point might disappear from here]]</p>
<div class="section" id="rats-mazes">
<h2>Rats &amp; Mazes<a class="headerlink" href="#rats-mazes" title="Permalink to this headline"></a></h2>
<p>First, create a <em>Blackboard</em> (cite reference) which is an object on which anyone
may record information. This particular blackboard draws a maze, and is used as
information comes back about the structure of a maze from the rats that are
investigating it.</p>
<p>Now create the maze itself. Like a real maze, this object reveals very little
information about itself - given a coordinate, it will tell you whether there
are walls or spaces in the four directions immediately surrounding that
coordinate, but no more. For starters, read the maze in from a text file but
consider hunting on the internet for a maze-generating algorithm. In any event,
the result should be an object that, given a maze coordinate, will report walls
and spaces around that coordinate. Also, you must be able to ask it for an entry
point to the maze.</p>
<p>Finally, create the maze-investigating <strong>Rat</strong> class. Each rat can communicate
with both the blackboard to give the current information and the maze to request
new information based on the current position of the rat. However, each time a
rat reaches a decision point where the maze branches, it creates a new rat to go
down each of the branches. Each rat is driven by its own thread. When a rat
reaches a dead end, it terminates itself after reporting the results of its
final investigation to the blackboard.</p>
<p>The goal is to completely map the maze, but you must also determine whether the
end condition will be naturally found or whether the blackboard must be
responsible for the decision.</p>
<p>An example implementation by Jeremy Meyer:</p>
<div class="highlight-python"><pre># Projects/ratsAndMazes/Maze.py

class Maze(Canvas):
    lines = [] # a line is a char array
    width = -1
    height = -1
    main(self):
        if (args.length &lt; 1):
            print("Enter filename")
            System.exit(0)

        Maze m = Maze()
        m.load(args[0])
        Frame f = Frame()
        f.setSize(m.width*20, m.height*20)
        f.add(m)
        Rat r = Rat(m, 0, 0)
        f.setVisible(1)

    def __init__(self):
        lines = Vector()
        setBackground(Color.lightGray)

    def isEmptyXY(x, y):
        if (x &lt; 0) x += width
        if (y &lt; 0) y += height
        # Use mod arithmetic to bring rat in line:
        byte[] by =
            (byte[])(lines.elementAt(y%height))
        return by[x%width]==' '

    def setXY(x, y, byte newByte):
        if (x &lt; 0) x += width
        if (y &lt; 0) y += height
        byte[] by =
            (byte[])(lines.elementAt(y%height))
        by[x%width] = newByte
        repaint()

    def  load(String filename):
        String currentLine = null
        BufferedReader br = BufferedReader(
          FileReader(filename))
        for(currentLine = br.readLine()
            currentLine != null
            currentLine = br.readLine()) :
            lines.addElement(currentLine.getBytes())
            if(width &lt; 0 ||
               currentLine.getBytes().length &gt; width)
                width = currentLine.getBytes().length

        height = len(lines)
        br.close()

    def update(self, Graphics g): paint(g)
    def paint(Graphics g):
        canvasHeight = self.getBounds().height
        canvasWidth  = self.getBounds().width
        if (height &lt; 1 || width &lt; 1)
            return # nothing to do
        width =
            ((byte[])(lines.elementAt(0))).length
        for (int y = 0 y &lt; len(lines) y++):
            byte[] b
            b = (byte[])(lines.elementAt(y))
            for (int x = 0 x &lt; width x++):
                switch(b[x]):
                    case ' ': # empty part of maze
                        g.setColor(Color.lightGray)
                        g.fillRect(
                          x*(canvasWidth/width),
                          y*(canvasHeight/height),
                          canvasWidth/width,
                          canvasHeight/height)
                        break
                    case '*':     # a wall
                        g.setColor(Color.darkGray)
                        g.fillRect(
                          x*(canvasWidth/width),
                          y*(canvasHeight/height),
                          (canvasWidth/width)-1,
                          (canvasHeight/height)-1)
                        break
                    default:      # must be rat
                        g.setColor(Color.red)
                        g.fillOval(x*(canvasWidth/width),
                        y*(canvasHeight/height),
                        canvasWidth/width,
                        canvasHeight/height)
                        break::


# Projects/ratsAndMazes/Rat.py

class Rat:
    ratCount = 0
    prison = Maze()
    vertDir = 0
    horizDir = 0
    x = 0, y = 0
    myRatNo = 0
    def __init__(self, maze, xStart, yStart):
        myRatNo = ratCount++
        print ("Rat no." + myRatNo + " ready to scurry.")
        prison = maze
        x = xStart
        y = yStart
        prison.setXY(x,y, (byte)'R')

    def run(self): scurry().start()

    def scurry(self):
        # Try and maintain direction if possible.
        # Horizontal backward
        boolean ratCanMove = 1
        while(ratCanMove):
            ratCanMove = 0
            # South
            if (prison.isEmptyXY(x, y + 1)):
                vertDir = 1 horizDir = 0
                ratCanMove = 1

            # North
            if (prison.isEmptyXY(x, y - 1))
                if (ratCanMove)
                    Rat(prison, x, y-1)
                    # Rat can move already, so give
                    # this choice to the next rat.
                else:
                    vertDir = -1 horizDir = 0
                    ratCanMove = 1

            # West
            if (prison.isEmptyXY(x-1, y))
                if (ratCanMove)
                    Rat(prison, x-1, y)
                    # Rat can move already, so give
                    # this choice to the next rat.
                else:
                    vertDir = 0 horizDir = -1
                    ratCanMove = 1

            # East
            if (prison.isEmptyXY(x+1, y))
                if (ratCanMove)
                    Rat(prison, x+1, y)
                    # Rat can move already, so give
                    # this choice to the next rat.
                else:
                    vertDir = 0 horizDir = 1
                    ratCanMove = 1

            if (ratCanMove): # Move original rat.
                x += horizDir
                y += vertDir
                prison.setXY(x,y,(byte)'R')
                # If not then the rat will die.
            Thread.sleep(2000)

        print ("Rat no." + myRatNo +
          " can't move..dying..aarrgggh.")</pre>
</div>
<p>The maze initialization file:</p>
<div class="highlight-python"><pre># Projects/ratsAndMazes/Amaze.txt
   * **      *  * **      *
 ***    * *******    * ****
     ***          ***
 *****   **********   *****
 * * * * **  ** * * * **  *
   * * *  * **  * * *  * **
 *     **     *     **
   * **   * **  * **   * **
 *** *  *** ***** *  *** **
 *      *   * *      *   *
   * ** * *     * ** * *</pre>
</div>
<div class="section" id="other-maze-resources">
<h3>Other Maze Resources<a class="headerlink" href="#other-maze-resources" title="Permalink to this headline"></a></h3>
<p>A discussion of algorithms to create mazes as well as Java source code to
implement them:</p>
<p><a class="reference external" href="http://www.mazeworks.com/mazegen/mazegen.htm">http://www.mazeworks.com/mazegen/mazegen.htm</a></p>
<p>A discussion of algorithms for collision detection and other individual/group
moving behavior for autonomous physical objects:</p>
<p><a class="reference external" href="http://www.red3d.com/cwr/steer/">http://www.red3d.com/cwr/steer/</a></p>
</div>
</div>
</div>


          </div>
        </div>
      </div>
      <div class="sphinxsidebar">
        <div class="sphinxsidebarwrapper">
            <p class="logo"><a href="index.html">
              <img class="logo" src="_static/cover.png" alt="Logo"/>
            </a></p>
    <font color="Red">This book is in early development; you will find parts that are incorrect &amp; incomplete.</font>
    
            <h3><a href="index.html">Table Of Contents</a></h3>
            <ul>
<li><a class="reference external" href="">Projects</a><ul>
<li><a class="reference external" href="#rats-mazes">Rats &amp; Mazes</a><ul>
<li><a class="reference external" href="#other-maze-resources">Other Maze Resources</a></li>
</ul>
</li>
</ul>
</li>
</ul>


            <h4>Previous topic</h4>
            <p class="topless"><a href="PatternRefactoring.html" title="previous chapter">Pattern Refactoring</a></p>
            <h3>This Page</h3>
            <ul class="this-page-menu">
              <li><a href="_sources/Projects.txt">Show Source</a></li>
            </ul>
    
          <h3>Quick search</h3>
            <form class="search" action="search.html" method="get">
              <input type="text" name="q" size="18" /> <input type="submit" value="Go" />
              <input type="hidden" name="check_keywords" value="yes" />
              <input type="hidden" name="area" value="default" />
            </form>
    <h4><a href="http://www.mindviewinc.com/Books/Python3Patterns/Index.php">Project Homepage</a></h4>
    <h4><a href="http://www.bitbucket.org/BruceEckel/python-3-patterns-idioms/issues/">Corrections/Suggestions</a></h4>
    <h4><a href="http://www.mindviewinc.com/Consulting/Index.php">Consulting &amp; Training</a></h4><br><br>

        </div>
      </div>
      <div class="clearer"></div>
    </div>
    <div class="related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="genindex.html" title="General Index"
             accesskey="I">index</a></li>
        <li class="right" >
          <a href="PatternRefactoring.html" title="Pattern Refactoring"
             accesskey="P">previous</a> |</li>
        <li><a href="index.html">Python 3 Patterns, Recipes and Idioms</a> &raquo;</li>
      </ul>
    </div>
    <div class="footer">
      &copy; Copyright 2008, Creative Commons Attribution-Share Alike 3.0.
      Last updated on Feb 13, 2009.
      Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.5.
    </div>
  </body>
</html>
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.