Changeset 17674 for docs

Show
Ignore:
Timestamp:
08/15/08 21:10:02 (6 years ago)
Author:
amachang
Message:

上級編と IE への対応方法を追加

Location:
docs/amachang/20080813-procamp2008
Files:
1 added
1 modified

Legend:

Unmodified
Added
Removed
  • docs/amachang/20080813-procamp2008/index.html

    r17619 r17674  
    14511451            </div> 
    14521452 
    1453  
     1453            <div> 
     1454                <h2>よりディープな JavaScript の世界へ</h2> 
     1455                <p> 
     1456                    テトリスがさっさと完成しちゃったっていう人に送る、よりディープな JavaScript の世界を紹介したいと思います。 
     1457                </p> 
     1458                <p> 
     1459                    完成したテトリスのコードを、より JavaScript 的に書き換えてみましょう! 
     1460                </p> 
     1461 
     1462                <div> 
     1463                    <h3>関数の名前は、関数という値が入った変数名</h3> 
     1464<pre><code>function hoge() { 
     1465    alert(1); 
     1466} 
     1467 
     1468hoge(); 
     1469</code></pre> 
     1470                    <p> 
     1471                        <a onclick="js(this)" href="javascript:void(0)">サンプル</a> 
     1472                    </p> 
     1473 
     1474                    <p> 
     1475                        この関数宣言は、実際には以下のようなことが行われています。 
     1476                    </p> 
     1477<pre><code>var hoge = function () { 
     1478    alert(1); 
     1479}; 
     1480 
     1481hoge(); 
     1482</code></pre> 
     1483                    <p> 
     1484                        実は、この書き方こそが本質的な JavaScript の関数の作りかたなのです。 
     1485                        今までの書き方は、これの簡易記法に過ぎません。 
     1486                    </p> 
     1487                    <p> 
     1488                        試しにさっきのコードを書き換えてみましょう! 
     1489                    </p> 
     1490 
     1491                    <p> 
     1492                        <a onclick="js(this)" href="javascript:void(0)">サンプル</a> 
     1493                    </p> 
     1494 
     1495<pre><code>&lt;!DOCTYPE html&gt; 
     1496&lt;html&gt; 
     1497    &lt;head&gt; 
     1498        &lt;meta charset=utf-8&gt; 
     1499        &lt;title&gt;Sample&lt;/title&gt; 
     1500        &lt;script type="text/javascript"&gt; 
     1501            var ctx; 
     1502            var blocks = [ 
     1503                [ 
     1504                    [1,1], 
     1505                    [0,1], 
     1506                    [0,1] 
     1507                ], 
     1508                [ 
     1509                    [1,1], 
     1510                    [1,0], 
     1511                    [1,0] 
     1512                ], 
     1513                [ 
     1514                    [1,1], 
     1515                    [1,1] 
     1516                ], 
     1517                [ 
     1518                    [1,0], 
     1519                    [1,1], 
     1520                    [1,0] 
     1521                ], 
     1522                [ 
     1523                    [1,0], 
     1524                    [1,1], 
     1525                    [0,1] 
     1526                ], 
     1527                [ 
     1528                    [0,1], 
     1529                    [1,1], 
     1530                    [1,0] 
     1531                ], 
     1532                [ 
     1533                    [1], 
     1534                    [1], 
     1535                    [1], 
     1536                    [1] 
     1537                ] 
     1538            ]; 
     1539 
     1540            var block = blocks[Math.floor(Math.random() * blocks.length)]; 
     1541            var posx = 0, posy = 0; 
     1542            var map, mapWidth = 10, mapHeight = 20; 
     1543 
     1544            <strong>var load = function() {</strong> 
     1545                var elmTarget = document.getElementById('target'); 
     1546                ctx = elmTarget.getContext('2d'); 
     1547 
     1548                map = []; 
     1549                for (var y = 0; y &lt; mapHeight; y++) { 
     1550                    map[y] = []; 
     1551                    for (var x = 0; x &lt; mapWidth; x++) { 
     1552                        map[y][x] = 0; 
     1553                    } 
     1554                } 
     1555                setInterval(paint, 200); 
     1556            <strong>};</strong> 
     1557 
     1558            <strong>var paintMatrix = function(matrix, offsetx, offsety, color) {</strong> 
     1559                ctx.fillStyle = color; 
     1560                for (var y = 0; y &lt; matrix.length; y ++) { 
     1561                    for (var x = 0; x &lt; matrix[y].length; x ++) { 
     1562                        if (matrix[y][x]) { 
     1563                            ctx.fillRect((x + offsetx) * 20, (y + offsety) * 20, 20, 20); 
     1564                        } 
     1565                    } 
     1566                } 
     1567            <strong>};</strong> 
     1568 
     1569            <strong>var check = function(map, block, offsetx, offsety) {</strong> 
     1570                if (offsetx &lt; 0 || offsety &lt; 0 || 
     1571                    mapHeight &lt; offsety + block.length || 
     1572                    mapWidth &lt; offsetx + block[0].length) { 
     1573                    return false; 
     1574                } 
     1575                for (var y = 0; y &lt; block.length; y ++) { 
     1576                    for (var x = 0; x &lt; block[y].length; x ++) { 
     1577                        if (block[y][x] &amp;&amp; map[y + offsety][x + offsetx]) {  
     1578                            return false; 
     1579                        } 
     1580                    } 
     1581                } 
     1582                return true; 
     1583            <strong>};</strong> 
     1584 
     1585            <strong>var mergeMatrix = function(map, block, offsetx, offsety) {</strong> 
     1586                for (var y = 0; y &lt; mapHeight; y ++) { 
     1587                    for (var x = 0; x &lt; mapWidth; x ++) { 
     1588                        if (block[y - offsety] &amp;&amp; block[y - offsety][x - offsetx]) { 
     1589                            map[y][x]++; 
     1590                        } 
     1591                    } 
     1592                } 
     1593            <strong>};</strong> 
     1594 
     1595            <strong>var clearRows = function(map) {</strong> 
     1596                for (var y = 0; y &lt; mapHeight; y ++) { 
     1597                    var full = true; 
     1598                    for (var x = 0; x &lt; mapWidth; x ++) { 
     1599                        if (!map[y][x]) { 
     1600                            full = false; 
     1601                        } 
     1602                    } 
     1603                    if (full) { 
     1604                        map.splice(y, 1); 
     1605                        var newRow = []; 
     1606                        for (var i = 0; i &lt; mapWidth; i ++) { 
     1607                            newRow[i] = 0; 
     1608                        } 
     1609                        map.unshift(newRow); 
     1610                    } 
     1611                } 
     1612            <strong>};</strong> 
     1613 
     1614            <strong>var paint = function() {</strong> 
     1615                ctx.clearRect(0, 0, 200, 400); 
     1616                paintMatrix(block, posx, posy, 'rgb(255, 0, 0)'); 
     1617                paintMatrix(map, 0, 0, 'rgb(128, 128, 128)'); 
     1618 
     1619                if (check(map, block, posx, posy + 1)) { 
     1620                    posy = posy + 1; 
     1621                } 
     1622                else { 
     1623                    mergeMatrix(map, block, posx, posy); 
     1624                    clearRows(map); 
     1625                    posx = 0; posy = 0; 
     1626                    block = blocks[Math.floor(Math.random() * blocks.length)]; 
     1627                } 
     1628            <strong>};</strong> 
     1629 
     1630            <strong>var rotate = function(block) {</strong> 
     1631                var rotated = []; 
     1632                for (var x = 0; x &lt; block[0].length; x ++) { 
     1633                    rotated[x] = []; 
     1634                    for (var y = 0; y &lt; block.length; y ++) { 
     1635                        rotated[x][block.length - y - 1] = block[y][x]; 
     1636                    } 
     1637                } 
     1638                return rotated; 
     1639            <strong>};</strong> 
     1640 
     1641            <strong>var key = function(keyCode) {</strong> 
     1642                switch (keyCode) { 
     1643                    case 38: 
     1644                        if (!check(map, rotate(block), posx, posy)) { 
     1645                            return; 
     1646                        } 
     1647                        block = rotate(block); 
     1648                        break; 
     1649                    case 39: 
     1650                        if (!check(map, block, posx + 1, posy)) { 
     1651                            return; 
     1652                        } 
     1653                        posx = posx + 1; 
     1654                        break; 
     1655                    case 37: 
     1656                        if (!check(map, block, posx - 1, posy)) { 
     1657                            return; 
     1658                        } 
     1659                        posx = posx - 1; 
     1660                        break; 
     1661                    case 40: 
     1662                        var y = posy; 
     1663                        while (check(map, block, posx, y)) { y++; } 
     1664                        posy = y - 1; 
     1665                        break; 
     1666                    default: 
     1667                        return; 
     1668                } 
     1669                ctx.clearRect(0, 0, 200, 400); 
     1670                paintMatrix(block, posx, posy, 'rgb(255, 0, 0)'); 
     1671                paintMatrix(map, 0, 0, 'rgb(128, 128, 128)'); 
     1672            <strong>};</strong> 
     1673 
     1674        &lt;/script&gt; 
     1675    &lt;/head&gt; 
     1676 
     1677    &lt;body onload="load()" onkeydown="key(event.keyCode)"&gt; 
     1678        &lt;canvas id="target" style="border: 5px solid gray" width="200" height="400"&gt;&lt;/canvas&gt; 
     1679    &lt;/body&gt; 
     1680&lt;/html&gt;</code></pre> 
     1681                    <p> 
     1682                        <a onclick="html(this)" href="javascript:void(0)">サンプル</a> 
     1683                    </p> 
     1684 
     1685                </div> 
     1686 
     1687                <div> 
     1688                    <h3>関数は、関数に渡せる</h3> 
     1689                    <p> 
     1690                        前の項で、関数は変数に代入可能な値というのが分かりました。 
     1691                    </p> 
     1692                    <p> 
     1693                        変数に代入可能な値は、関数にも渡すことができます。 
     1694                    </p> 
     1695                    <p> 
     1696                        実は、今までの例でも関数に関数を渡している箇所があります。 
     1697                        そうです。 paint 関数を定期的に呼び出すところですね。 
     1698                    </p> 
     1699                    <p> 
     1700                        以下のような例は setInterval という関数に hoge という関数を渡しているのですね。 
     1701                    </p> 
     1702<pre><code>var hoge = function() { 
     1703    alert(1); 
     1704}; 
     1705 
     1706// 3 秒に一回 hoge を呼び出す 
     1707setInterval(hoge, 3000); 
     1708</code></pre> 
     1709                    <p> 
     1710                        <a onclick="js(this)" href="javascript:void(0)">サンプル</a> 
     1711                    </p> 
     1712                    <p> 
     1713                        もちろん、変数に一回代入しなくても、直接関数を渡すことができます。 
     1714                    </p> 
     1715<pre><code>setInterval(function() { 
     1716    alert(1); 
     1717}, 3000); 
     1718</code></pre> 
     1719                    <p> 
     1720                        <a onclick="js(this)" href="javascript:void(0)">サンプル</a> 
     1721                    </p> 
     1722 
     1723                    <p> 
     1724                        では、テトリスのコードも直接関数を渡す形式に書き換えてみましょう! 
     1725                        (paint 関数の中身を直接 setInterval にぶち込みます) 
     1726                    </p> 
     1727<pre><code>&lt;!DOCTYPE html&gt; 
     1728&lt;html&gt; 
     1729    &lt;head&gt; 
     1730        &lt;meta charset=utf-8&gt; 
     1731        &lt;title&gt;Sample&lt;/title&gt; 
     1732        &lt;script type="text/javascript"&gt; 
     1733            var ctx; 
     1734            var blocks = [ 
     1735                [ 
     1736                    [1,1], 
     1737                    [0,1], 
     1738                    [0,1] 
     1739                ], 
     1740                [ 
     1741                    [1,1], 
     1742                    [1,0], 
     1743                    [1,0] 
     1744                ], 
     1745                [ 
     1746                    [1,1], 
     1747                    [1,1] 
     1748                ], 
     1749                [ 
     1750                    [1,0], 
     1751                    [1,1], 
     1752                    [1,0] 
     1753                ], 
     1754                [ 
     1755                    [1,0], 
     1756                    [1,1], 
     1757                    [0,1] 
     1758                ], 
     1759                [ 
     1760                    [0,1], 
     1761                    [1,1], 
     1762                    [1,0] 
     1763                ], 
     1764                [ 
     1765                    [1], 
     1766                    [1], 
     1767                    [1], 
     1768                    [1] 
     1769                ] 
     1770            ]; 
     1771 
     1772            var block = blocks[Math.floor(Math.random() * blocks.length)]; 
     1773            var posx = 0, posy = 0; 
     1774            var map, mapWidth = 10, mapHeight = 20; 
     1775 
     1776            var load = function() { 
     1777                var elmTarget = document.getElementById('target'); 
     1778                ctx = elmTarget.getContext('2d'); 
     1779 
     1780                map = []; 
     1781                for (var y = 0; y &lt; mapHeight; y++) { 
     1782                    map[y] = []; 
     1783                    for (var x = 0; x &lt; mapWidth; x++) { 
     1784                        map[y][x] = 0; 
     1785                    } 
     1786                } 
     1787 
     1788                <strong>setInterval(function() {</strong> 
     1789                    <strong>ctx.clearRect(0, 0, 200, 400);</strong> 
     1790                    <strong>paintMatrix(block, posx, posy, 'rgb(255, 0, 0)');</strong> 
     1791                    <strong>paintMatrix(map, 0, 0, 'rgb(128, 128, 128)');</strong> 
     1792 
     1793                    <strong>if (check(map, block, posx, posy + 1)) {</strong> 
     1794                        <strong>posy = posy + 1;</strong> 
     1795                    <strong>}</strong> 
     1796                    <strong>else {</strong> 
     1797                        <strong>mergeMatrix(map, block, posx, posy);</strong> 
     1798                        <strong>clearRows(map);</strong> 
     1799                        <strong>posx = 0; posy = 0;</strong> 
     1800                        <strong>block = blocks[Math.floor(Math.random() * blocks.length)];</strong> 
     1801                    <strong>}</strong> 
     1802                <strong>}, 200);</strong> 
     1803            }; 
     1804 
     1805            var paintMatrix = function(matrix, offsetx, offsety, color) { 
     1806                ctx.fillStyle = color; 
     1807                for (var y = 0; y &lt; matrix.length; y ++) { 
     1808                    for (var x = 0; x &lt; matrix[y].length; x ++) { 
     1809                        if (matrix[y][x]) { 
     1810                            ctx.fillRect((x + offsetx) * 20, (y + offsety) * 20, 20, 20); 
     1811                        } 
     1812                    } 
     1813                } 
     1814            }; 
     1815 
     1816            var check = function(map, block, offsetx, offsety) { 
     1817                if (offsetx &lt; 0 || offsety &lt; 0 || 
     1818                    mapHeight &lt; offsety + block.length || 
     1819                    mapWidth &lt; offsetx + block[0].length) { 
     1820                    return false; 
     1821                } 
     1822                for (var y = 0; y &lt; block.length; y ++) { 
     1823                    for (var x = 0; x &lt; block[y].length; x ++) { 
     1824                        if (block[y][x] &amp;&amp; map[y + offsety][x + offsetx]) {  
     1825                            return false; 
     1826                        } 
     1827                    } 
     1828                } 
     1829                return true; 
     1830            }; 
     1831 
     1832            var mergeMatrix = function(map, block, offsetx, offsety) { 
     1833                for (var y = 0; y &lt; mapHeight; y ++) { 
     1834                    for (var x = 0; x &lt; mapWidth; x ++) { 
     1835                        if (block[y - offsety] &amp;&amp; block[y - offsety][x - offsetx]) { 
     1836                            map[y][x]++; 
     1837                        } 
     1838                    } 
     1839                } 
     1840            }; 
     1841 
     1842            var clearRows = function(map) { 
     1843                for (var y = 0; y &lt; mapHeight; y ++) { 
     1844                    var full = true; 
     1845                    for (var x = 0; x &lt; mapWidth; x ++) { 
     1846                        if (!map[y][x]) { 
     1847                            full = false; 
     1848                        } 
     1849                    } 
     1850                    if (full) { 
     1851                        map.splice(y, 1); 
     1852                        var newRow = []; 
     1853                        for (var i = 0; i &lt; mapWidth; i ++) { 
     1854                            newRow[i] = 0; 
     1855                        } 
     1856                        map.unshift(newRow); 
     1857                    } 
     1858                } 
     1859            }; 
     1860 
     1861            var rotate = function(block) { 
     1862                var rotated = []; 
     1863                for (var x = 0; x &lt; block[0].length; x ++) { 
     1864                    rotated[x] = []; 
     1865                    for (var y = 0; y &lt; block.length; y ++) { 
     1866                        rotated[x][block.length - y - 1] = block[y][x]; 
     1867                    } 
     1868                } 
     1869                return rotated; 
     1870            }; 
     1871 
     1872            var key = function(keyCode) { 
     1873                switch (keyCode) { 
     1874                    case 38: 
     1875                        if (!check(map, rotate(block), posx, posy)) { 
     1876                            return; 
     1877                        } 
     1878                        block = rotate(block); 
     1879                        break; 
     1880                    case 39: 
     1881                        if (!check(map, block, posx + 1, posy)) { 
     1882                            return; 
     1883                        } 
     1884                        posx = posx + 1; 
     1885                        break; 
     1886                    case 37: 
     1887                        if (!check(map, block, posx - 1, posy)) { 
     1888                            return; 
     1889                        } 
     1890                        posx = posx - 1; 
     1891                        break; 
     1892                    case 40: 
     1893                        var y = posy; 
     1894                        while (check(map, block, posx, y)) { y++; } 
     1895                        posy = y - 1; 
     1896                        break; 
     1897                    default: 
     1898                        return; 
     1899                } 
     1900                ctx.clearRect(0, 0, 200, 400); 
     1901                paintMatrix(block, posx, posy, 'rgb(255, 0, 0)'); 
     1902                paintMatrix(map, 0, 0, 'rgb(128, 128, 128)'); 
     1903            }; 
     1904 
     1905        &lt;/script&gt; 
     1906    &lt;/head&gt; 
     1907 
     1908    &lt;body onload="load()" onkeydown="key(event.keyCode)"&gt; 
     1909        &lt;canvas id="target" style="border: 5px solid gray" width="200" height="400"&gt;&lt;/canvas&gt; 
     1910    &lt;/body&gt; 
     1911&lt;/html&gt;</code></pre> 
     1912                    <p> 
     1913                        <a onclick="html(this)" href="javascript:void(0)">サンプル</a> 
     1914                    </p> 
     1915                </div> 
     1916 
     1917                <div> 
     1918                    <h3>オブジェクトを作ってみよう</h3> 
     1919 
     1920                    <p> 
     1921                        今までに出てきた ctx などのような<strong>値の中にさらに値(関数も含む)を持つ値</strong>のことを 
     1922                        <strong>オブジェクト</strong>と言います。 
     1923                    </p> 
     1924 
     1925                    <p> 
     1926                        さっそく、オブジェクトを作ってみましょう。 
     1927                    </p> 
     1928<pre><code>var a = { 
     1929    hoge: 1, 
     1930    fuga: 2 
     1931}; 
     1932 
     1933alert(a.hoge); 
     1934alert(a.fuga); 
     1935</code></pre> 
     1936                    <p> 
     1937                        <a onclick="js(this)" href="javascript:void(0)">サンプル</a> 
     1938                    </p> 
     1939                    <p> 
     1940                        ここでの hoge や fuga のことをプロパティといいます。 
     1941                    </p> 
     1942 
     1943                    <p> 
     1944                        プロパティには、値を代入することもできます。 
     1945                    </p> 
     1946<pre><code>var a = { 
     1947    hoge: 1, 
     1948    fuga: 2 
     1949}; 
     1950 
     1951a.hoge = 3; 
     1952 
     1953alert(a.hoge); 
     1954</code></pre> 
     1955                    <p> 
     1956                        <a onclick="js(this)" href="javascript:void(0)">サンプル</a> 
     1957                    </p> 
     1958 
     1959                    <p> 
     1960                        存在しないプロパティに値を代入することもできます。 
     1961                    </p> 
     1962<pre><code>var a = { 
     1963    hoge: 1, 
     1964    fuga: 2 
     1965}; 
     1966 
     1967a.piyo = 3; 
     1968 
     1969alert(a.piyo); 
     1970</code></pre> 
     1971                    <p> 
     1972                        <a onclick="js(this)" href="javascript:void(0)">サンプル</a> 
     1973                    </p> 
     1974 
     1975                    <p> 
     1976                        関数をプロパティに持たせることもできます。 
     1977                        このときに this という特殊な変数なようなものを使うと、そのオブジェクト自体を関数内で扱うことが出来ます。 
     1978                    </p> 
     1979<pre><code>var a = { 
     1980    hoge: 1, 
     1981    fuga: 2, 
     1982    alertHoge: function() { 
     1983        alert(this.hoge); 
     1984    } 
     1985}; 
     1986 
     1987a.alertHoge(); 
     1988</code></pre> 
     1989                    <p> 
     1990                        <a onclick="js(this)" href="javascript:void(0)">サンプル</a> 
     1991                    </p> 
     1992 
     1993                    <p> 
     1994                        このように、<strong>値に対する様々な操作</strong>はオブジェクトにプロパティに入れた関数で行うと、 
     1995                        プログラム全体の見通しがよくなります。 
     1996                    </p> 
     1997 
     1998                </div> 
     1999 
     2000                <div> 
     2001                    <h3>同じ特性を持ったオブジェクトを作る</h3> 
     2002                    <p> 
     2003                        プログラムをやっていると、同じ特性を持ったオブジェクトを作りたいという時があります。 
     2004                        そのようなときは new という仕組みを使います。 
     2005                    </p> 
     2006 
     2007<pre><code>var Dog = function(name) { 
     2008    this.name = name; 
     2009    this.type = '犬'; 
     2010}; 
     2011 
     2012var pochi = new Dog('ポチ'); 
     2013var hachi = new Dog('ハチ'); 
     2014 
     2015alert(pochi.name); 
     2016alert(pochi.type); 
     2017 
     2018alert(hachi.name); 
     2019alert(hachi.type); 
     2020</code></pre> 
     2021                    <p> 
     2022                        <a onclick="js(this)" href="javascript:void(0)">サンプル</a> 
     2023                    </p> 
     2024 
     2025                    <p> 
     2026                        ちょっと変な感じがするかもしれませんが、関数には二つの使い方があるのです。 
     2027                    </p> 
     2028                    <ul> 
     2029                        <li>処理をまとめる(普通の関数として使う)</li> 
     2030                        <li>同じ特性を持ったオブジェクトを生成する</li> 
     2031                    </ul> 
     2032                    <p> 
     2033                        この 2 番目の使い方をする関数のことを<strong>コンストラクタ</strong>といいます。 
     2034                    </p> 
     2035                    <p> 
     2036                        このように関数と new を使ってオブジェクトを作った場合は、全員に共通のプロパティを持たせることができます。 
     2037                    </p> 
     2038                    <p> 
     2039                        以下の例をみてみましょう。 
     2040                    </p> 
     2041 
     2042<pre><code>var Dog = function(name) { 
     2043    this.name = name; 
     2044}; 
     2045 
     2046<strong>Dog.prototype.type = '犬';</strong> 
     2047<strong>Dog.prototype.bow = function() {</strong> 
     2048    <strong>alert(this.name + '「わんわん」');</strong> 
     2049<strong>};</strong> 
     2050 
     2051var pochi = new Dog('ポチ'); 
     2052var hachi = new Dog('ハチ'); 
     2053 
     2054pochi.bow(); 
     2055hachi.bow(); 
     2056</code></pre> 
     2057                    <p> 
     2058                        <a onclick="js(this)" href="javascript:void(0)">サンプル</a> 
     2059                    </p> 
     2060                    <p> 
     2061                        つまり pochi オブジェクトや hachi オブジェクトは 
     2062                        Dog.prototype オブジェクトが持っている全てのプロパティにアクセスすることができます。 
     2063                    </p> 
     2064                    <p> 
     2065                        このとき、 pochi オブジェクトや hachi オブジェクトは、 Dog.prototype オブジェクトを<strong>継承</strong>したオブジェクトといいます。 
     2066                    </p> 
     2067                </div> 
     2068 
     2069                <div> 
     2070                    <h3>配列が継承しているオブジェクト</h3> 
     2071                    <p> 
     2072                        このように、オブジェクトはオブジェクトを継承することで、共通のプロパティを作ることができます。 
     2073                    </p> 
     2074                    <p> 
     2075                        実は、配列も <strong>Array.prototype</strong> というオブジェクトを継承しています。 
     2076                    </p> 
     2077                    <p> 
     2078                        以下の例を見てみましょう。 
     2079                    </p> 
     2080 
     2081<pre><code>Array.prototype.first = function() { 
     2082    return this[0]; 
     2083}; 
     2084 
     2085var array = ['hoge', 'fuga', 'piyo']; 
     2086 
     2087alert(array.first()); 
     2088alert([10, 20, 30].first()); 
     2089</code></pre> 
     2090                    <p> 
     2091                        <a onclick="js(this)" href="javascript:void(0)">サンプル</a> 
     2092                    </p> 
     2093 
     2094                    <p> 
     2095                        Array.prototype のプロパティに関数を追加して、すべての配列に操作が加わったことが分かります。 
     2096                    </p> 
     2097                    <p> 
     2098                        では、さっきのテトリスの例も Array.prototype を拡張してみましょう。 
     2099                    </p> 
     2100 
     2101<pre><code>&lt;!DOCTYPE html&gt; 
     2102&lt;html&gt; 
     2103    &lt;head&gt; 
     2104        &lt;meta charset=utf-8&gt; 
     2105        &lt;title&gt;Sample&lt;/title&gt; 
     2106        &lt;script type="text/javascript"&gt; 
     2107 
     2108            <strong>Array.prototype.each = function(fn) {</strong> 
     2109                <strong>var result = [];</strong> 
     2110                <strong>for (var i = 0; i &lt; this.length; i ++) {</strong> 
     2111                    <strong>result[i] = fn(this[i], i);</strong> 
     2112                <strong>}</strong> 
     2113                <strong>return result;</strong> 
     2114            <strong>};</strong> 
     2115 
     2116            var ctx; 
     2117            var blocks = [ 
     2118                [ 
     2119                    [1,1], 
     2120                    [0,1], 
     2121                    [0,1] 
     2122                ], 
     2123                [ 
     2124                    [1,1], 
     2125                    [1,0], 
     2126                    [1,0] 
     2127                ], 
     2128                [ 
     2129                    [1,1], 
     2130                    [1,1] 
     2131                ], 
     2132                [ 
     2133                    [1,0], 
     2134                    [1,1], 
     2135                    [1,0] 
     2136                ], 
     2137                [ 
     2138                    [1,0], 
     2139                    [1,1], 
     2140                    [0,1] 
     2141                ], 
     2142                [ 
     2143                    [0,1], 
     2144                    [1,1], 
     2145                    [1,0] 
     2146                ], 
     2147                [ 
     2148                    [1], 
     2149                    [1], 
     2150                    [1], 
     2151                    [1] 
     2152                ] 
     2153            ]; 
     2154 
     2155            var block = blocks[Math.floor(Math.random() * blocks.length)]; 
     2156            var posx = 0, posy = 0; 
     2157            var mapWidth = 10, mapHeight = 20; 
     2158 
     2159            <strong>var map = new Array(mapHeight).each(function() {</strong> 
     2160                <strong>return new Array(mapWidth).each(function() { return 0; });</strong> 
     2161            <strong>});</strong> 
     2162 
     2163            var load = function() { 
     2164                var elmTarget = document.getElementById('target'); 
     2165                ctx = elmTarget.getContext('2d'); 
     2166 
     2167                setInterval(function() { 
     2168                    ctx.clearRect(0, 0, 200, 400); 
     2169                    paintMatrix(block, posx, posy, 'rgb(255, 0, 0)'); 
     2170                    paintMatrix(map, 0, 0, 'rgb(128, 128, 128)'); 
     2171 
     2172                    if (check(map, block, posx, posy + 1)) { 
     2173                        posy = posy + 1; 
     2174                    } 
     2175                    else { 
     2176                        mergeMatrix(map, block, posx, posy); 
     2177                        clearRows(map); 
     2178                        posx = 0; posy = 0; 
     2179                        block = blocks[Math.floor(Math.random() * blocks.length)]; 
     2180                    } 
     2181                }, 200); 
     2182            }; 
     2183 
     2184            var paintMatrix = function(matrix, offsetx, offsety, color) { 
     2185                ctx.fillStyle = color; 
     2186                 
     2187                <strong>matrix.each(function(row, y) {</strong> 
     2188                    <strong>row.each(function(val, x) {</strong> 
     2189                        <strong>if (val) {</strong> 
     2190                            <strong>ctx.fillRect((x + offsetx) * 20, (y + offsety) * 20, 20, 20);</strong> 
     2191                        <strong>}</strong> 
     2192                    <strong>});</strong> 
     2193                <strong>});</strong> 
     2194            }; 
     2195 
     2196            var check = function(map, block, offsetx, offsety) { 
     2197                if (offsetx &lt; 0 || offsety &lt; 0 || 
     2198                    mapHeight &lt; offsety + block.length || 
     2199                    mapWidth &lt; offsetx + block[0].length) { 
     2200                    return false; 
     2201                } 
     2202 
     2203                <strong>var ok = true;</strong> 
     2204                <strong>block.each(function(row, y) {</strong> 
     2205                    <strong>row.each(function(val, x) {</strong> 
     2206                        <strong>if (val &amp;&amp; map[y + offsety][x + offsetx]) {</strong> 
     2207                            <strong>ok = false;</strong> 
     2208                        <strong>}</strong> 
     2209                    <strong>});</strong> 
     2210                <strong>});</strong> 
     2211                <strong>return ok;</strong> 
     2212            }; 
     2213 
     2214            var mergeMatrix = function(map, block, offsetx, offsety) { 
     2215                <strong>map.each(function(row, y) {</strong> 
     2216                    <strong>row.each(function(val, x) {</strong> 
     2217                        <strong>if (block[y - offsety] &amp;&amp; block[y - offsety][x - offsetx]) {</strong> 
     2218                            <strong>row[x]++;</strong> 
     2219                        <strong>}</strong> 
     2220                    <strong>});</strong> 
     2221                <strong>});</strong> 
     2222            }; 
     2223 
     2224            var clearRows = function(map) { 
     2225                <strong>map.each(function(row, y) {</strong> 
     2226                    <strong>var full = true;</strong> 
     2227                    <strong>row.each(function(val, x) {</strong> 
     2228                        <strong>if (!val) {</strong> 
     2229                            <strong>full = false;</strong> 
     2230                        <strong>}</strong> 
     2231                    <strong>});</strong> 
     2232                    <strong>if (full) {</strong> 
     2233                        <strong>map.splice(y, 1);</strong> 
     2234                        <strong>map.unshift(new Array(mapWidth).each(function() { return 0 }));</strong> 
     2235                    <strong>}</strong> 
     2236                <strong>});</strong> 
     2237            }; 
     2238 
     2239            var rotate = function(block) { 
     2240                <strong>return new Array(block[0].length).each(function(_, y) {</strong> 
     2241                    <strong>return new Array(block.length).each(function(_, x) {</strong> 
     2242                        <strong>return block[block.length - x - 1][y];</strong> 
     2243                    <strong>});</strong> 
     2244                <strong>});</strong> 
     2245            }; 
     2246 
     2247            var key = function(keyCode) { 
     2248                switch (keyCode) { 
     2249                    case 38: 
     2250                        if (!check(map, rotate(block), posx, posy)) { 
     2251                            return; 
     2252                        } 
     2253                        block = rotate(block); 
     2254                        break; 
     2255                    case 39: 
     2256                        if (!check(map, block, posx + 1, posy)) { 
     2257                            return; 
     2258                        } 
     2259                        posx = posx + 1; 
     2260                        break; 
     2261                    case 37: 
     2262                        if (!check(map, block, posx - 1, posy)) { 
     2263                            return; 
     2264                        } 
     2265                        posx = posx - 1; 
     2266                        break; 
     2267                    case 40: 
     2268                        var y = posy; 
     2269                        while (check(map, block, posx, y)) { y++; } 
     2270                        posy = y - 1; 
     2271                        break; 
     2272                    default: 
     2273                        return; 
     2274                } 
     2275                ctx.clearRect(0, 0, 200, 400); 
     2276                paintMatrix(block, posx, posy, 'rgb(255, 0, 0)'); 
     2277                paintMatrix(map, 0, 0, 'rgb(128, 128, 128)'); 
     2278            }; 
     2279 
     2280        &lt;/script&gt; 
     2281    &lt;/head&gt; 
     2282 
     2283    &lt;body onload="load()" onkeydown="key(event.keyCode)"&gt; 
     2284        &lt;canvas id="target" style="border: 5px solid gray" width="200" height="400"&gt;&lt;/canvas&gt; 
     2285    &lt;/body&gt; 
     2286&lt;/html&gt;</code></pre> 
     2287                    <p> 
     2288                        <a onclick="html(this)" href="javascript:void(0)">サンプル</a> 
     2289                    </p> 
     2290                </div> 
     2291 
     2292                <div> 
     2293                    <h3>配列が継承しているオブジェクト</h3> 
     2294 
     2295<pre><code>&lt;!DOCTYPE html&gt; 
     2296&lt;html&gt; 
     2297    &lt;head&gt; 
     2298        &lt;meta charset=utf-8&gt; 
     2299        &lt;title&gt;Sample&lt;/title&gt; 
     2300        &lt;script type="text/javascript"&gt; 
     2301 
     2302            <strong>Array.prototype.each = function(fn) {</strong> 
     2303                <strong>var result = [];</strong> 
     2304                <strong>for (var i = 0; i &lt; this.length; i ++) {</strong> 
     2305                    <strong>result[i] = fn(this[i], i);</strong> 
     2306                <strong>}</strong> 
     2307                <strong>return result;</strong> 
     2308            <strong>};</strong> 
     2309 
     2310            var ctx; 
     2311            var blocks = [ 
     2312                [ 
     2313                    [1,1], 
     2314                    [0,1], 
     2315                    [0,1] 
     2316                ], 
     2317                [ 
     2318                    [1,1], 
     2319                    [1,0], 
     2320                    [1,0] 
     2321                ], 
     2322                [ 
     2323                    [1,1], 
     2324                    [1,1] 
     2325                ], 
     2326                [ 
     2327                    [1,0], 
     2328                    [1,1], 
     2329                    [1,0] 
     2330                ], 
     2331                [ 
     2332                    [1,0], 
     2333                    [1,1], 
     2334                    [0,1] 
     2335                ], 
     2336                [ 
     2337                    [0,1], 
     2338                    [1,1], 
     2339                    [1,0] 
     2340                ], 
     2341                [ 
     2342                    [1], 
     2343                    [1], 
     2344                    [1], 
     2345                    [1] 
     2346                ] 
     2347            ]; 
     2348 
     2349            var block = blocks[Math.floor(Math.random() * blocks.length)]; 
     2350            var posx = 0, posy = 0; 
     2351            var mapWidth = 10, mapHeight = 20; 
     2352 
     2353            <strong>var map = new Array(mapHeight).each(function() {</strong> 
     2354                <strong>return new Array(mapWidth).each(function() { return 0; });</strong> 
     2355            <strong>});</strong> 
     2356 
     2357            var load = function() { 
     2358                var elmTarget = document.getElementById('target'); 
     2359                ctx = elmTarget.getContext('2d'); 
     2360 
     2361                setInterval(function() { 
     2362                    ctx.clearRect(0, 0, 200, 400); 
     2363                    paintMatrix(block, posx, posy, 'rgb(255, 0, 0)'); 
     2364                    paintMatrix(map, 0, 0, 'rgb(128, 128, 128)'); 
     2365 
     2366                    if (check(map, block, posx, posy + 1)) { 
     2367                        posy = posy + 1; 
     2368                    } 
     2369                    else { 
     2370                        mergeMatrix(map, block, posx, posy); 
     2371                        clearRows(map); 
     2372                        posx = 0; posy = 0; 
     2373                        block = blocks[Math.floor(Math.random() * blocks.length)]; 
     2374                    } 
     2375                }, 200); 
     2376            }; 
     2377 
     2378            var paintMatrix = function(matrix, offsetx, offsety, color) { 
     2379                ctx.fillStyle = color; 
     2380                 
     2381                <strong>matrix.each(function(row, y) {</strong> 
     2382                    <strong>row.each(function(val, x) {</strong> 
     2383                        <strong>if (val) {</strong> 
     2384                            <strong>ctx.fillRect((x + offsetx) * 20, (y + offsety) * 20, 20, 20);</strong> 
     2385                        <strong>}</strong> 
     2386                    <strong>});</strong> 
     2387                <strong>});</strong> 
     2388            }; 
     2389 
     2390            var check = function(map, block, offsetx, offsety) { 
     2391                if (offsetx &lt; 0 || offsety &lt; 0 || 
     2392                    mapHeight &lt; offsety + block.length || 
     2393                    mapWidth &lt; offsetx + block[0].length) { 
     2394                    return false; 
     2395                } 
     2396 
     2397                <strong>var ok = true;</strong> 
     2398                <strong>block.each(function(row, y) {</strong> 
     2399                    <strong>row.each(function(val, x) {</strong> 
     2400                        <strong>if (val &amp;&amp; map[y + offsety][x + offsetx]) {</strong> 
     2401                            <strong>ok = false;</strong> 
     2402                        <strong>}</strong> 
     2403                    <strong>});</strong> 
     2404                <strong>});</strong> 
     2405                <strong>return ok;</strong> 
     2406            }; 
     2407 
     2408            var mergeMatrix = function(map, block, offsetx, offsety) { 
     2409                <strong>map.each(function(row, y) {</strong> 
     2410                    <strong>row.each(function(val, x) {</strong> 
     2411                        <strong>if (block[y - offsety] &amp;&amp; block[y - offsety][x - offsetx]) {</strong> 
     2412                            <strong>row[x]++;</strong> 
     2413                        <strong>}</strong> 
     2414                    <strong>});</strong> 
     2415                <strong>});</strong> 
     2416            }; 
     2417 
     2418            var clearRows = function(map) { 
     2419                <strong>map.each(function(row, y) {</strong> 
     2420                    <strong>var full = true;</strong> 
     2421                    <strong>row.each(function(val, x) {</strong> 
     2422                        <strong>if (!val) {</strong> 
     2423                            <strong>full = false;</strong> 
     2424                        <strong>}</strong> 
     2425                    <strong>});</strong> 
     2426                    <strong>if (full) {</strong> 
     2427                        <strong>map.splice(y, 1);</strong> 
     2428                        <strong>map.unshift(new Array(mapWidth).each(function() { return 0 }));</strong> 
     2429                    <strong>}</strong> 
     2430                <strong>});</strong> 
     2431            }; 
     2432 
     2433            var rotate = function(block) { 
     2434                <strong>return new Array(block[0].length).each(function(_, y) {</strong> 
     2435                    <strong>return new Array(block.length).each(function(_, x) {</strong> 
     2436                        <strong>return block[block.length - x - 1][y];</strong> 
     2437                    <strong>});</strong> 
     2438                <strong>});</strong> 
     2439            }; 
     2440 
     2441            var key = function(keyCode) { 
     2442                switch (keyCode) { 
     2443                    case 38: 
     2444                        if (!check(map, rotate(block), posx, posy)) { 
     2445                            return; 
     2446                        } 
     2447                        block = rotate(block); 
     2448                        break; 
     2449                    case 39: 
     2450                        if (!check(map, block, posx + 1, posy)) { 
     2451                            return; 
     2452                        } 
     2453                        posx = posx + 1; 
     2454                        break; 
     2455                    case 37: 
     2456                        if (!check(map, block, posx - 1, posy)) { 
     2457                            return; 
     2458                        } 
     2459                        posx = posx - 1; 
     2460                        break; 
     2461                    case 40: 
     2462                        var y = posy; 
     2463                        while (check(map, block, posx, y)) { y++; } 
     2464                        posy = y - 1; 
     2465                        break; 
     2466                    default: 
     2467                        return; 
     2468                } 
     2469                ctx.clearRect(0, 0, 200, 400); 
     2470                paintMatrix(block, posx, posy, 'rgb(255, 0, 0)'); 
     2471                paintMatrix(map, 0, 0, 'rgb(128, 128, 128)'); 
     2472            }; 
     2473 
     2474        &lt;/script&gt; 
     2475    &lt;/head&gt; 
     2476 
     2477    &lt;body onload="load()" onkeydown="key(event.keyCode)"&gt; 
     2478        &lt;canvas id="target" style="border: 5px solid gray" width="200" height="400"&gt;&lt;/canvas&gt; 
     2479    &lt;/body&gt; 
     2480&lt;/html&gt;</code></pre> 
     2481                    <p> 
     2482                        <a onclick="html(this)" href="javascript:void(0)">サンプル</a> 
     2483                    </p> 
     2484                </div> 
     2485 
     2486                <div> 
     2487                    <h3>オブジェクト指向</h3> 
     2488 
     2489                    <p> 
     2490                        今までに作ってきた、テトリスのプログラムを見ると 2 重配列の操作関数が沢山出てきます。 
     2491                    </p> 
     2492                    <ul> 
     2493                        <li>paintMatrix</li> 
     2494                        <li>check</li> 
     2495                        <li>mergeMatrix</li> 
     2496                        <li>clearRows</li> 
     2497                        <li>rotate</li> 
     2498                    </ul> 
     2499                    <p> 
     2500                        あるデータに対する操作関数が沢山ある場合は、 
     2501                        そのデータと操作関数をオブジェクトのプロパティにすると全体の見通しが良くなります。 
     2502                    </p> 
     2503                    <p> 
     2504                        このように、データと操作をオブジェクトというものにまとめて、 
     2505                        整理しながらプログラム書くことを<strong>オブジェクト指向</strong>と言います。 
     2506                    </p> 
     2507 
     2508                    <p> 
     2509                        では、 Matrix というコンストラクタを作って、二重配列への操作関数をまとめてみましょう。 
     2510                    </p> 
     2511<pre><code>&lt;!DOCTYPE html&gt; 
     2512&lt;html&gt; 
     2513    &lt;head&gt; 
     2514        &lt;meta charset=utf-8&gt; 
     2515        &lt;title&gt;Sample&lt;/title&gt; 
     2516        &lt;script type="text/javascript"&gt; 
     2517 
     2518            Array.prototype.each = function(fn) { 
     2519                var result = []; 
     2520                for (var i = 0; i &lt; this.length; i ++) { 
     2521                    result[i] = fn(this[i], i); 
     2522                } 
     2523                return result; 
     2524            }; 
     2525 
     2526            <strong>var Matrix = function(matrix) {</strong> 
     2527                <strong>this.matrix = matrix;</strong> 
     2528                <strong>this.height = matrix.length;</strong> 
     2529                <strong>this.width  = matrix[0].length;</strong> 
     2530            <strong>};</strong> 
     2531 
     2532            <strong>Matrix.prototype.each = function(fn) {</strong> 
     2533                <strong>return this.matrix.each(fn);</strong> 
     2534            <strong>};</strong> 
     2535 
     2536            <strong>Matrix.prototype.get = function(x, y) {</strong> 
     2537                <strong>return (this.matrix[y] &amp;&amp; this.matrix[y][x]) || 0;</strong> 
     2538            <strong>};</strong> 
     2539 
     2540            <strong>Matrix.prototype.paint = function(offsetx, offsety, color) {</strong> 
     2541                <strong>ctx.fillStyle = color;</strong> 
     2542                <strong>this.matrix.each(function(row, y) {</strong> 
     2543                    <strong>row.each(function(val, x) {</strong> 
     2544                        <strong>if (val) {</strong> 
     2545                            <strong>ctx.fillRect((x + offsetx) * 20, (y + offsety) * 20, 20, 20);</strong> 
     2546                        <strong>}</strong> 
     2547                    <strong>});</strong> 
     2548                <strong>});</strong> 
     2549            <strong>};</strong> 
     2550 
     2551            <strong>Matrix.prototype.check = function(block, offsetx, offsety) {</strong> 
     2552                <strong>if (offsetx &lt; 0 || offsety &lt; 0 ||</strong> 
     2553                    <strong>this.height &lt; offsety + block.height ||</strong> 
     2554                    <strong>this.width  &lt; offsetx + block.width) {</strong> 
     2555                    <strong>return false;</strong> 
     2556                <strong>}</strong> 
     2557 
     2558                <strong>var matrix = this.matrix;</strong> 
     2559                <strong>var ok = true;</strong> 
     2560                <strong>block.each(function(row, y) {</strong> 
     2561                    <strong>row.each(function(val, x) {</strong> 
     2562                        <strong>if (val &amp;&amp; matrix[y + offsety][x + offsetx]) {</strong> 
     2563                            <strong>ok = false;</strong> 
     2564                        <strong>}</strong> 
     2565                    <strong>});</strong> 
     2566                <strong>});</strong> 
     2567                <strong>return ok;</strong> 
     2568            <strong>};</strong> 
     2569 
     2570            <strong>Matrix.prototype.merge = function(block, offsetx, offsety) {</strong> 
     2571                <strong>this.matrix.each(function(row, y) {</strong> 
     2572                    <strong>row.each(function(val, x) {</strong> 
     2573                        <strong>row[x] += block.get(x - offsetx, y - offsety);</strong> 
     2574                    <strong>});</strong> 
     2575                <strong>});</strong> 
     2576            <strong>};</strong> 
     2577 
     2578            <strong>Matrix.prototype.clearRows = function() {</strong> 
     2579                <strong>var matrix = this.matrix;</strong> 
     2580                <strong>var width  = this.width;</strong> 
     2581                <strong>matrix.each(function(row, y) {</strong> 
     2582                    <strong>var full = true;</strong> 
     2583                    <strong>row.each(function(val, x) {</strong> 
     2584                        <strong>if (!val) {</strong> 
     2585                            <strong>full = false;</strong> 
     2586                        <strong>}</strong> 
     2587                    <strong>});</strong> 
     2588                    <strong>if (full) {</strong> 
     2589                        <strong>matrix.splice(y, 1);</strong> 
     2590                        <strong>matrix.unshift(new Array(width).each(function() { return 0 }));</strong> 
     2591                    <strong>}</strong> 
     2592                <strong>});</strong> 
     2593            <strong>};</strong> 
     2594 
     2595            <strong>Matrix.prototype.rotate = function() {</strong> 
     2596                <strong>var matrix = this.matrix;</strong> 
     2597                <strong>return new Matrix(new Array(matrix[0].length).each(function(_, y) {</strong> 
     2598                    <strong>return new Array(matrix.length).each(function(_, x) {</strong> 
     2599                        <strong>return matrix[matrix.length - x - 1][y];</strong> 
     2600                    <strong>});</strong> 
     2601                <strong>}));</strong> 
     2602            <strong>};</strong> 
     2603 
     2604 
     2605 
     2606            var ctx; 
     2607            var blocks = [ 
     2608                <strong>new Matrix(</strong>[ 
     2609                    [1,1], 
     2610                    [0,1], 
     2611                    [0,1] 
     2612                ])</strong>, 
     2613                <strong>new Matrix(</strong>[ 
     2614                    [1,1], 
     2615                    [1,0], 
     2616                    [1,0] 
     2617                ]<strong>)</strong>, 
     2618                <strong>new Matrix(</strong>[ 
     2619                    [1,1], 
     2620                    [1,1] 
     2621                ]<strong>)</strong>, 
     2622                <strong>new Matrix(</strong>[ 
     2623                    [1,0], 
     2624                    [1,1], 
     2625                    [1,0] 
     2626                ]<strong>)</strong>, 
     2627                <strong>new Matrix(</strong>[ 
     2628                    [1,0], 
     2629                    [1,1], 
     2630                    [0,1] 
     2631                ]<strong>)</strong>, 
     2632                <strong>new Matrix(</strong>[ 
     2633                    [0,1], 
     2634                    [1,1], 
     2635                    [1,0] 
     2636                ]<strong>)</strong>, 
     2637                <strong>new Matrix(</strong>[ 
     2638                    [1], 
     2639                    [1], 
     2640                    [1], 
     2641                    [1] 
     2642                ]<strong>)</strong> 
     2643            ]; 
     2644 
     2645            var block = blocks[Math.floor(Math.random() * blocks.length)]; 
     2646            var posx = 0, posy = 0; 
     2647 
     2648            var map = <strong>new Matrix(</strong>new Array(20).each(function() { 
     2649                return new Array(10).each(function() { return 0; }); 
     2650            })<strong>)</strong>; 
     2651 
     2652            var load = function() { 
     2653                var elmTarget = document.getElementById('target'); 
     2654                ctx = elmTarget.getContext('2d'); 
     2655 
     2656                setInterval(function() { 
     2657                    ctx.clearRect(0, 0, 200, 400); 
     2658                    <strong>block.paint(posx, posy, 'rgb(255, 0, 0)');</strong> 
     2659                    <strong>map.paint(0, 0, 'rgb(128, 128, 128)');</strong> 
     2660 
     2661                    if (<strong>map.check(block, posx, posy + 1)</strong>) { 
     2662                        posy = posy + 1; 
     2663                    } 
     2664                    else { 
     2665                        <strong>map.merge(block, posx, posy);</strong> 
     2666                        <strong>map.clearRows();</strong> 
     2667                        posx = 0; posy = 0; 
     2668                        block = blocks[Math.floor(Math.random() * blocks.length)]; 
     2669                    } 
     2670                }, 200); 
     2671            }; 
     2672 
     2673            var key = function(keyCode) { 
     2674                switch (keyCode) { 
     2675                    case 38: 
     2676                        if (!<strong>map.check(block.rotate(), posx, posy)</strong>) { 
     2677                            return; 
     2678                        } 
     2679                        block = <strong>block.rotate(block)</strong>; 
     2680                        break; 
     2681                    case 39: 
     2682                        if (!<strong>map.check(block, posx + 1, posy)</strong>) { 
     2683                            return; 
     2684                        } 
     2685                        posx = posx + 1; 
     2686                        break; 
     2687                    case 37: 
     2688                        if (!<strong>map.check(block, posx - 1, posy)</strong>) { 
     2689                            return; 
     2690                        } 
     2691                        posx = posx - 1; 
     2692                        break; 
     2693                    case 40: 
     2694                        var y = posy; 
     2695                        while (<strong>map.check(block, posx, y)</strong>) { y++; } 
     2696                        posy = y - 1; 
     2697                        break; 
     2698                    default: 
     2699                        return; 
     2700                } 
     2701                ctx.clearRect(0, 0, 200, 400); 
     2702                <strong>block.paint(posx, posy, 'rgb(255, 0, 0)')</strong>; 
     2703                <strong>map.paint(0, 0, 'rgb(128, 128, 128)')</strong>; 
     2704            }; 
     2705 
     2706        &lt;/script&gt; 
     2707    &lt;/head&gt; 
     2708 
     2709    &lt;body onload="load()" onkeydown="key(event.keyCode)"&gt; 
     2710        &lt;canvas id="target" style="border: 5px solid gray" width="200" height="400"&gt;&lt;/canvas&gt; 
     2711    &lt;/body&gt; 
     2712&lt;/html&gt;</code></pre> 
     2713                    <p> 
     2714                        <a onclick="html(this)" href="javascript:void(0)">サンプル</a> 
     2715                    </p> 
     2716                    <p> 
     2717                        ずいぶん、見通しが良くなりましたね! 
     2718                    </p> 
     2719                </div> 
     2720            </div> 
     2721 
     2722            <div> 
     2723                <h2>Internet Explorer で動かすために</h2> 
     2724                <p> 
     2725                    実は、ここまでのテトリスは Internet Explorer では動きません。 
     2726                    Internet Explorerでは、デフォルトでは canvas 要素が使えないのです。 
     2727                </p> 
     2728                <p> 
     2729                    でも、がっかりする必要はありません。 
     2730                    excanvas.js という JavaScript ファイルを html から読み込んでやれば、 
     2731                    Internet Explorer でも canvas を使うことができるようになります。 
     2732                </p> 
     2733 
     2734<pre><code>&lt;!DOCTYPE html&gt; 
     2735&lt;html&gt; 
     2736    &lt;head&gt; 
     2737        &lt;meta charset=utf-8&gt; 
     2738        &lt;title&gt;Sample&lt;/title&gt; 
     2739        <strong>&lt;script src="excanvas.js" type="text/javascript"&gt;&lt;/script&gt;</strong> 
     2740        &lt;script type="text/javascript"&gt; 
     2741 
     2742            Array.prototype.each = function(fn) { 
     2743                var result = []; 
     2744                for (var i = 0; i &lt; this.length; i ++) { 
     2745                    result[i] = fn(this[i], i); 
     2746                } 
     2747                return result; 
     2748            }; 
     2749 
     2750            var Matrix = function(matrix) { 
     2751                this.matrix = matrix; 
     2752                this.height = matrix.length; 
     2753                this.width  = matrix[0].length; 
     2754            }; 
     2755 
     2756            Matrix.prototype.each = function(fn) { 
     2757                return this.matrix.each(fn); 
     2758            }; 
     2759 
     2760            Matrix.prototype.get = function(x, y) { 
     2761                return (this.matrix[y] &amp;&amp; this.matrix[y][x]) || 0; 
     2762            }; 
     2763 
     2764            Matrix.prototype.paint = function(offsetx, offsety, color) { 
     2765                ctx.fillStyle = color; 
     2766                this.matrix.each(function(row, y) { 
     2767                    row.each(function(val, x) { 
     2768                        if (val) { 
     2769                            ctx.fillRect((x + offsetx) * 20, (y + offsety) * 20, 20, 20); 
     2770                        } 
     2771                    }); 
     2772                }); 
     2773            }; 
     2774 
     2775            Matrix.prototype.check = function(block, offsetx, offsety) { 
     2776                if (offsetx &lt; 0 || offsety &lt; 0 || 
     2777                    this.height &lt; offsety + block.height || 
     2778                    this.width  &lt; offsetx + block.width) { 
     2779                    return false; 
     2780                } 
     2781 
     2782                var matrix = this.matrix; 
     2783                var ok = true; 
     2784                block.each(function(row, y) { 
     2785                    row.each(function(val, x) { 
     2786                        if (val &amp;&amp; matrix[y + offsety][x + offsetx]) { 
     2787                            ok = false; 
     2788                        } 
     2789                    }); 
     2790                }); 
     2791                return ok; 
     2792            }; 
     2793 
     2794            Matrix.prototype.merge = function(block, offsetx, offsety) { 
     2795                this.matrix.each(function(row, y) { 
     2796                    row.each(function(val, x) { 
     2797                        row[x] += block.get(x - offsetx, y - offsety); 
     2798                    }); 
     2799                }); 
     2800            }; 
     2801 
     2802            Matrix.prototype.clearRows = function() { 
     2803                var matrix = this.matrix; 
     2804                var width  = this.width; 
     2805                matrix.each(function(row, y) { 
     2806                    var full = true; 
     2807                    row.each(function(val, x) { 
     2808                        if (!val) { 
     2809                            full = false; 
     2810                        } 
     2811                    }); 
     2812                    if (full) { 
     2813                        matrix.splice(y, 1); 
     2814                        matrix.unshift(new Array(width).each(function() { return 0 })); 
     2815                    } 
     2816                }); 
     2817            }; 
     2818 
     2819            Matrix.prototype.rotate = function() { 
     2820                var matrix = this.matrix; 
     2821                return new Matrix(new Array(matrix[0].length).each(function(_, y) { 
     2822                    return new Array(matrix.length).each(function(_, x) { 
     2823                        return matrix[matrix.length - x - 1][y]; 
     2824                    }); 
     2825                })); 
     2826            }; 
     2827 
     2828 
     2829 
     2830            var ctx; 
     2831            var blocks = [ 
     2832                new Matrix([ 
     2833                    [1,1], 
     2834                    [0,1], 
     2835                    [0,1] 
     2836                ]), 
     2837                new Matrix([ 
     2838                    [1,1], 
     2839                    [1,0], 
     2840                    [1,0] 
     2841                ]), 
     2842                new Matrix([ 
     2843                    [1,1], 
     2844                    [1,1] 
     2845                ]), 
     2846                new Matrix([ 
     2847                    [1,0], 
     2848                    [1,1], 
     2849                    [1,0] 
     2850                ]), 
     2851                new Matrix([ 
     2852                    [1,0], 
     2853                    [1,1], 
     2854                    [0,1] 
     2855                ]), 
     2856                new Matrix([ 
     2857                    [0,1], 
     2858                    [1,1], 
     2859                    [1,0] 
     2860                ]), 
     2861                new Matrix([ 
     2862                    [1], 
     2863                    [1], 
     2864                    [1], 
     2865                    [1] 
     2866                ]) 
     2867            ]; 
     2868 
     2869            var block = blocks[Math.floor(Math.random() * blocks.length)]; 
     2870            var posx = 0, posy = 0; 
     2871 
     2872            var map = new Matrix(new Array(20).each(function() { 
     2873                return new Array(10).each(function() { return 0; }); 
     2874            })); 
     2875 
     2876            var load = function() { 
     2877                var elmTarget = document.getElementById('target'); 
     2878                ctx = elmTarget.getContext('2d'); 
     2879 
     2880                setInterval(function() { 
     2881                    ctx.clearRect(0, 0, 200, 400); 
     2882                    block.paint(posx, posy, 'rgb(255, 0, 0)'); 
     2883                    map.paint(0, 0, 'rgb(128, 128, 128)'); 
     2884 
     2885                    if (map.check(block, posx, posy + 1)) { 
     2886                        posy = posy + 1; 
     2887                    } 
     2888                    else { 
     2889                        map.merge(block, posx, posy); 
     2890                        map.clearRows(); 
     2891                        posx = 0; posy = 0; 
     2892                        block = blocks[Math.floor(Math.random() * blocks.length)]; 
     2893                    } 
     2894                }, 200); 
     2895            }; 
     2896 
     2897            var key = function(keyCode) { 
     2898                switch (keyCode) { 
     2899                    case 38: 
     2900                        if (!map.check(block.rotate(), posx, posy)) { 
     2901                            return; 
     2902                        } 
     2903                        block = block.rotate(block); 
     2904                        break; 
     2905                    case 39: 
     2906                        if (!map.check(block, posx + 1, posy)) { 
     2907                            return; 
     2908                        } 
     2909                        posx = posx + 1; 
     2910                        break; 
     2911                    case 37: 
     2912                        if (!map.check(block, posx - 1, posy)) { 
     2913                            return; 
     2914                        } 
     2915                        posx = posx - 1; 
     2916                        break; 
     2917                    case 40: 
     2918                        var y = posy; 
     2919                        while (map.check(block, posx, y)) { y++; } 
     2920                        posy = y - 1; 
     2921                        break; 
     2922                    default: 
     2923                        return; 
     2924                } 
     2925                ctx.clearRect(0, 0, 200, 400); 
     2926                block.paint(posx, posy, 'rgb(255, 0, 0)'); 
     2927                map.paint(0, 0, 'rgb(128, 128, 128)'); 
     2928            }; 
     2929 
     2930        &lt;/script&gt; 
     2931    &lt;/head&gt; 
     2932 
     2933    &lt;body onload="load(); <strong>document.body.focus()</strong>" onkeydown="key(event.keyCode)"&gt; 
     2934        &lt;canvas id="target" style="border: 5px solid gray" width="200" height="400"&gt;&lt;/canvas&gt; 
     2935    &lt;/body&gt; 
     2936&lt;/html&gt;</code></pre> 
     2937                    <p> 
     2938                        <a onclick="html(this)" href="javascript:void(0)">サンプル</a> 
     2939                    </p> 
     2940 
     2941            </div> 
     2942            <p> 
     2943                やった!これで動くようになりました! 
     2944            </p> 
    14542945        </div> 
    1455  
    1456  
    14572946        <div id="footer"> 
    14582947            <p>This document is in the public domain.</p>