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.

We start by creating our grid and giving it a name. We'll call it... hmm... let's see... how about "grid"?

In [ ]:

```
!pip install ipythonblocks
```

In [ ]:

```
from ipythonblocks import BlockGrid
grid = BlockGrid(8, 8, fill=(123, 234, 123))
grid
```

In [ ]:

```
grid[0, 0]
```

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.

If we assign an "RGB tuple" to a cell from the grid, that cell takes on that color.

In [ ]:

```
grid[0, 0] = (0, 0, 0)
grid[0, 2] = (255, 0, 0)
grid[0, 4] = (255, 255, 255)
grid[0, 6] = (0, 150, 150)
grid.show()
```

In [ ]:

```
from ipythonblocks import colors
```

In [ ]:

```
colors
```

In [ ]:

```
grid[1, 1] = colors['Teal']
grid[1, 2] = colors['Thistle']
grid[1, 3] = colors['Peru']
grid.show()
```

In [ ]:

```
row_number = 3
for column_number in [0, 1, 2, 3, 4, 5, 6]:
grid[row_number, column_number] = colors['Chocolate']
grid.show()
```

In [ ]:

```
grid.width
```

In [ ]:

```
row_number = 5
for column_number in range(grid.width):
grid[row_number, column_number] = colors['Violet']
grid.show()
```

How about columns? And how about painting three columns at once? Let's use *nested loops*.

In [ ]:

```
for column_number in [4, 5, 6]:
for row_number in range(grid.height):
grid[row_number, column_number] = colors['Crimson']
grid.show()
```

Our grid is looking cluttered. Let's define a *function* to start over by painting it all one color.

In [ ]:

```
def one_color(target_grid, color):
for row_number in range(target_grid.height):
for column_number in range(target_grid.width):
grid[row_number, column_number] = color
```

In [ ]:

```
one_color(grid, colors['LightGreen'])
grid.show()
```

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.

In [ ]:

```
import time
from IPython.display import clear_output
for color in [colors['Red'], colors['Green'], colors['Blue'], colors['White'], colors['Purple']]:
clear_output()
one_color(grid, color)
grid.show()
time.sleep(1)
```

*clear_output*? Not telling. Feel free to try it yourself.

In [ ]:

```
one_color(grid, colors['Black'])
for row_number in range(grid.height):
for column_number in range(grid.width):
if is_even(column_number):
grid[row_number, column_number] = colors['Yellow']
grid.show()
```

*is_even*; I just made that up. But we can fix that!

In [ ]:

```
def is_even(number):
if number % 2 == 0:
return True
else:
return False
```

In [ ]:

```
one_color(grid, colors['Black'])
for row_number in range(grid.height):
for column_number in range(grid.width):
if is_even(column_number + row_number):
grid[row_number, column_number] = colors['Yellow']
grid.show()
```

In [ ]:

```
base_color = [50, 50, 50]
for i in range(200):
clear_output()
for row_number in range(grid.height):
for column_number in range(grid.width):
grid[row_number, column_number] = (base_color[0], base_color[1]+row_number*20, base_color[2]+column_number*20)
grid.show()
base_color[0] += 1
base_color[1] += 1
base_color[2] += 1
time.sleep(0.02)
```

Now it's time to try out some ideas of your own! Here are some suggestions:

- Diagonal stripes
- Draw random stripes
- A flag
- Put a dark square in the middle of the grid, then make a randomly wandering path from there!

Use a bigger grid if you need one. Remember at the very beginning when we created the grid?

```
grid = BlockGrid(8, 8, fill=(123, 234, 123))
```

You can create it again with some different numbers.

Here are some more little pieces of code that might be fun elements to work into your projects!

Each time you execute this cell, you'll see a different, random shade.

In [ ]:

```
from random import randint
random_color = (randint(0, 255), randint(0, 255), randint(0, 255))
one_color(grid, random_color)
print(random_color)
grid.show()
```

Can you make the color depend on the distance from the upper-left corner? Can you draw an arc, for instance?

In [ ]:

```
for row_number in range(grid.height):
for column_number in range(grid.width):
distance_to_corner = (row_number**2 + column_number**2)**0.5
# now what can you do with that number?
grid.show()
```

There's a file called ascii8x8.py in this directory that we can use to do ASCII-style art with our blocks.

In [ ]:

```
from ascii8x8 import Font8x8
print(Font8x8['p'])
```

In [ ]:

```
from ascii8x8 import screen
screen('p', 0, 0)
```

What good does that do? Well, here's an example of applying it to the grid:

In [ ]:

```
for row_number in range(8):
for column_number in range(8):
if screen('p', row_number, column_number):
grid[row_number, column_number] = colors['Black']
grid.show()
```

So, perhaps you could...

- Flash your name across the grid, one letter at a time
- Print a letter upside-down
- Print a letter whose color changes with time
- Make a very wide grid and print a whole word in it