{ "metadata": { "name": "" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "IPython Blocks\n", "==============\n", "\n", "Welcome to the IPython Blocks! This is a grid of colored blocks we can use to practice all sorts of programming concepts. There's a tutorial on IPython Blocks at http://nbviewer.ipython.org/urls/raw.github.com/jiffyclub/ipythonblocks/master/demos/ipythonblocks_demo.ipynb, but you don't need to read that now; just follow along here.\n", "\n", "We start by creating our grid and giving it a name. We'll call it... hmm... let's see... how about \"grid\"?" ] }, { "cell_type": "code", "collapsed": false, "input": [ "!pip install ipythonblocks" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "code", "collapsed": false, "input": [ "from ipythonblocks import BlockGrid\n", "grid = BlockGrid(8, 8, fill=(123, 234, 123))\n", "grid" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can refer to each cell in the grid by its coordinates from the upper-left corner. The first index is the number of steps down, the second is the number of steps to the right." ] }, { "cell_type": "code", "collapsed": false, "input": [ "grid[0, 0]" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "In programming, colors are often referred to by an \"RGB tuple\". That's a series of three numbers, representing how much red, how much green, and how much blue, respectively. For the grid, those numbers go on a scale from 0 to 255. So pure red is (255, 0, 0), black is (0, 0, 0), white is (255, 255, 255), and so on.\n", "\n", "If we assign an \"RGB tuple\" to a cell from the grid, that cell takes on that color." ] }, { "cell_type": "code", "collapsed": false, "input": [ "grid[0, 0] = (0, 0, 0)\n", "grid[0, 2] = (255, 0, 0)\n", "grid[0, 4] = (255, 255, 255)\n", "grid[0, 6] = (0, 150, 150)\n", "grid.show()" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's not spend all day typing those tedious RGB tuples! This looks like a perfect place for a dictionary. Lucky us, we can get a dictionary with all sorts of colors defined from the ipythonblocks module, the same place we got the BlockGrid." ] }, { "cell_type": "code", "collapsed": false, "input": [ "from ipythonblocks import colors" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "code", "collapsed": false, "input": [ "colors" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "Wow, looks like somebody used to work at a paint store! OK, let's use some of those in the next row down." ] }, { "cell_type": "code", "collapsed": false, "input": [ "grid[1, 1] = colors['Teal']\n", "grid[1, 2] = colors['Thistle']\n", "grid[1, 3] = colors['Peru']\n", "grid.show()" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now suppose we want to color a bunch of blocks. Let's use a loop so we don't have to write a line for every single one." ] }, { "cell_type": "code", "collapsed": false, "input": [ "row_number = 3\n", "for column_number in [0, 1, 2, 3, 4, 5, 6]:\n", " grid[row_number, column_number] = colors['Chocolate']\n", "grid.show()" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "The grid defines a \"height\" and a \"width\", these will be handy to work on cells all the way across it." ] }, { "cell_type": "code", "collapsed": false, "input": [ "grid.width" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "code", "collapsed": false, "input": [ "row_number = 5\n", "for column_number in range(grid.width):\n", " grid[row_number, column_number] = colors['Violet']\n", "grid.show()" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "How about columns? And how about painting three columns at once? Let's use *nested loops*." ] }, { "cell_type": "code", "collapsed": false, "input": [ "for column_number in [4, 5, 6]:\n", " for row_number in range(grid.height):\n", " grid[row_number, column_number] = colors['Crimson']\n", "grid.show()" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "Our grid is looking cluttered. Let's define a *function* to start over by painting it all one color." ] }, { "cell_type": "code", "collapsed": false, "input": [ "def one_color(target_grid, color):\n", " for row_number in range(target_grid.height):\n", " for column_number in range(target_grid.width):\n", " grid[row_number, column_number] = color\n" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "code", "collapsed": false, "input": [ "one_color(grid, colors['LightGreen'])\n", "grid.show()" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "Animation\n", "---------\n", "\n", "A couple of tricks will let our grid change over time. We'll need *sleep* from the *time* module, plus the *clear_output* function from IPython. " ] }, { "cell_type": "code", "collapsed": false, "input": [ "import time\n", "from IPython.display import clear_output\n", "for color in [colors['Red'], colors['Green'], colors['Blue'], colors['White'], colors['Purple']]:\n", " clear_output()\n", " one_color(grid, color)\n", " grid.show()\n", " time.sleep(1)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "What if we used grid.show() like before, instead of *clear_output*? Not telling. Feel free to try it yourself." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "OK, how about a checkerboard? We could paint the whole grid black, then paint red onto every second square." ] }, { "cell_type": "code", "collapsed": false, "input": [ "one_color(grid, colors['Black'])\n", "for row_number in range(grid.height):\n", " for column_number in range(grid.width):\n", " if is_even(column_number):\n", " grid[row_number, column_number] = colors['Yellow']\n", "grid.show()" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "Icky, an error message! Because there's no such thing as a function *is_even*; I just made that up. But we can fix that!" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def is_even(number):\n", " if number % 2 == 0:\n", " return True\n", " else:\n", " return False" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now go back up and re-run the earlier cell. And we get... hmm, good for bumblebees, bad for checkers. Let's make a modified version." ] }, { "cell_type": "code", "collapsed": false, "input": [ "one_color(grid, colors['Black'])\n", "for row_number in range(grid.height):\n", " for column_number in range(grid.width):\n", " if is_even(column_number + row_number):\n", " grid[row_number, column_number] = colors['Yellow']\n", "grid.show()" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "How crazy can we get, using just what we've already learned? Let's make a diagonal color gradient, then pour some bleach on it." ] }, { "cell_type": "code", "collapsed": false, "input": [ "base_color = [50, 50, 50]\n", "for i in range(200):\n", " clear_output()\n", " for row_number in range(grid.height):\n", " for column_number in range(grid.width):\n", " grid[row_number, column_number] = (base_color[0], base_color[1]+row_number*20, base_color[2]+column_number*20)\n", " grid.show()\n", " base_color[0] += 1\n", " base_color[1] += 1\n", " base_color[2] += 1\n", " time.sleep(0.02)\n", " " ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now it's time to try out some ideas of your own! Here are some suggestions:\n", "\n", "* Diagonal stripes\n", "* Draw random stripes\n", "* A flag\n", "* Put a dark square in the middle of the grid, then make a randomly wandering path from there!\n", "\n", "Use a bigger grid if you need one. Remember at the very beginning when we created the grid?\n", "\n", " grid = BlockGrid(8, 8, fill=(123, 234, 123))\n", "\n", "You can create it again with some different numbers.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Code snippets\n", "=============\n", "\n", "Here are some more little pieces of code that might be fun elements to work into your projects!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Random numbers\n", "--------------\n", "\n", "Each time you execute this cell, you'll see a different, random shade." ] }, { "cell_type": "code", "collapsed": false, "input": [ "from random import randint\n", "random_color = (randint(0, 255), randint(0, 255), randint(0, 255))\n", "one_color(grid, random_color)\n", "print(random_color)\n", "grid.show()" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pythagorean theorem\n", "-------------------\n", "\n", "Can you make the color depend on the distance from the upper-left corner? Can you draw an arc, for instance?" ] }, { "cell_type": "code", "collapsed": false, "input": [ "for row_number in range(grid.height):\n", " for column_number in range(grid.width):\n", " distance_to_corner = (row_number**2 + column_number**2)**0.5\n", " # now what can you do with that number?\n", "grid.show()" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "ASCII Art\n", "---------\n", "\n", "There's a file called ascii8x8.py in this directory that we can use to do ASCII-style art with our blocks. " ] }, { "cell_type": "code", "collapsed": false, "input": [ "from ascii8x8 import Font8x8\n", "print(Font8x8['p'])" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "It's hard to tell, but that's a list of strings, and if those strings are stacked, they form a rough inversed \"p\". But we've also provided a function that, using that same data, and given the (row_number, column_number) of a place in the grid, tells us whether that spot should be on (True) or off (False)." ] }, { "cell_type": "code", "collapsed": false, "input": [ "from ascii8x8 import screen\n", "screen('p', 0, 0)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "What good does that do? Well, here's an example of applying it to the grid:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "for row_number in range(8):\n", " for column_number in range(8):\n", " if screen('p', row_number, column_number):\n", " grid[row_number, column_number] = colors['Black']\n", "grid.show()" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ "So, perhaps you could...\n", "\n", "* Flash your name across the grid, one letter at a time\n", "* Print a letter upside-down \n", "* Print a letter whose color changes with time\n", "* Make a very wide grid and print a whole word in it\n" ] } ], "metadata": {} } ] }