三角形拼图 这怎么可能?

我看了半天没看出破绽,于是用Canvas + jQuery UI做了个网页拼图,拼了半天终于发现了其中的奥妙。

我讨厌剧透,所以贴出代码占位,以免想独立思考的同学意外看到答案。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>Missing Square?</title>
        <script type="text/javascript" src="jquery.js"></script>
        <script type="text/javascript" src="ui.core.js"></script>
        <script type="text/javascript" src="ui.draggable.js"></script>
        <script type="text/javascript" src="missingsquare.js"></script>
    </head>
    <body>
        <div style="float:left"><img src="missingsquare.jpg"/></div>
        <div style="float:left; margin: 10px"><canvas id="canvas-grid" width="150px" height="150px"></canvas></div>
    </body>
</html>

missingsquare.js
 
$(init);
 
var cellWidth = 18.5, cellHeight = 15;
 
function init() {
    drawGrid();
    drawTriangle1();
    drawTriangle2();
    drawPoly1();
    drawPoly2();
    
    $('#canvas-triangle1,#canvas-triangle2,#canvas-poly1,#canvas-poly2').draggable();
}
 
function drawGrid() {
    var cellCountX = 15, cellCountY = 15;
    var c = document.getElementById('canvas-grid');
    c.width = cellWidth * cellCountX + 1;
    c.height = cellHeight * cellCountY + 1;
    var ctx = c.getContext('2d');
    
    ctx.fillStyle = 'white';
    ctx.fillRect(0, 0, c.width, c.height);
    ctx.strokeStyle = 'rgb(127, 127, 127)';
    for (var i = 0; i <= cellCountX; i++) {
        ctx.moveTo(i * cellWidth, 0);
        ctx.lineTo(i * cellWidth, c.height);
        ctx.stroke();
    }
    
    for (var i = 0; i <= cellCountX; i++) {
        ctx.moveTo(0, i * cellHeight);
        ctx.lineTo(c.width, i * cellHeight);
        ctx.stroke();
    }
}
 
function drawTriangle1() {
    var canv = document.createElement('canvas');
    document.body.appendChild(canv);
    canv.id = 'canvas-triangle1';
    canv.width = cellWidth * 5;
    canv.height = cellHeight * 2;
    
    var ctx = canv.getContext('2d');
    ctx.strokeStyle = 'black';
    ctx.fillStyle = 'rgba(4, 145, 110, .5)';
    ctx.beginPath();
    ctx.moveTo(0, canv.height);
    ctx.lineTo(canv.width, canv.height);
    ctx.lineTo(canv.width, 0);
    ctx.fill();
    ctx.closePath();
    ctx.stroke();
}
 
function drawTriangle2() {
    var canv = document.createElement('canvas');
    document.body.appendChild(canv);
    canv.id = 'canvas-triangle2';
    canv.width = cellWidth * 8;
    canv.height = cellHeight * 3;
    
    var ctx = canv.getContext('2d');
    ctx.strokeStyle = 'black';
    ctx.fillStyle = 'rgba(194, 5, 3, .5)';
    ctx.beginPath();
    ctx.moveTo(0, canv.height);
    ctx.lineTo(canv.width, canv.height);
    ctx.lineTo(canv.width, 0);
    ctx.fill();
    ctx.closePath();
    ctx.stroke();
}
 
function drawPoly1() {
    var canv = document.createElement('canvas');
    canv.id = 'canvas-poly1';
    document.body.appendChild(canv);
    canv.width = cellWidth * 5;
    canv.height = cellHeight * 2;
    
    var ctx = canv.getContext('2d');
    ctx.strokeStyle = 'black';
    ctx.fillStyle = 'rgba(224, 152, 49, .5)';
    ctx.beginPath();
    ctx.moveTo(0, 0);
    ctx.lineTo(canv.width, 0);
    ctx.lineTo(canv.width, cellHeight * 1);
    ctx.lineTo(cellWidth * 2, cellHeight * 1);
    ctx.lineTo(cellWidth * 2, cellHeight * 2);
    ctx.lineTo(0, cellHeight * 2);
    ctx.fill();
    ctx.closePath();
    ctx.stroke();
}
 
function drawPoly2() {
    var canv = document.createElement('canvas');
    canv.id = 'canvas-poly2';
    document.body.appendChild(canv);
    canv.width = cellWidth * 5;
    canv.height = cellHeight * 2;
    
    var ctx = canv.getContext('2d');
    ctx.strokeStyle = 'black';
    ctx.fillStyle = 'rgba(115, 198, 71, .5)';
    ctx.beginPath();
    ctx.moveTo(cellWidth * 2, 0);
    ctx.lineTo(cellWidth * 5, 0);
    ctx.lineTo(cellWidth * 5, cellHeight * 2);
    ctx.lineTo(0, cellHeight * 2);
    ctx.lineTo(0, cellHeight * 1);
    ctx.lineTo(cellWidth * 2, cellHeight * 1);
    ctx.fill();
    ctx.closePath();
    ctx.stroke();
}

 

貌似三角形,并非三角形。

简单起见,假设格子是边长为1的正方形。红绿两三角形直角边比一个是3:8 一个是2:5 ,不相似,锐角也不等,所以接在一起两条斜边实际上是有夹角的,这样便围成了一个狭长的三角形。

下面我们来算算这个狭长三角形的面积。
我们先求狭长三角形的三边长,然后用海伦公式求面积。
(define (triangle-area a b c)
  (let ((s (/ (+ a b c) 2)))
    (sqrt (* s (- s a) (- s b) (- s c)))))

(define (hypo a b)
  (sqrt (+ (* a a) (* b b))))

(triangle-area (hypo 8 3) (hypo 5 2) (hypo 13 5))

;0.4999999999994106 实际上刚好等于0.5。我还在想为什么……

所以上下两个图形的面积差为2 * 0.5 = 1,这就解释了那个空格。

 

总结

这个quiz非常巧妙,故意用扁长的格子,使红绿三角形顶角差异更小,组合图形的“斜边”夹角更加难以察觉,看上去完全就像是一条直线。

人总觉得“眼见为实”,看起来觉得是直角三角形便毫不怀疑,结果陷入困境。

反思一下,解决类似矛盾时,怎么才能避免落入思考的陷阱,明察秋毫呢?

  1. 严密推理。任何想当然的因果关系都必须求证。
  2. 严格确定推理的每个条件都成立。若果结果是错的,要么是推理不正确,要么是条件不成立。在这里,“组合图形是三角形”就不成立,在此基础上去算面积便是错的。
  3. 如果实在是找不到破绽,那就遍历怀疑每一个条件、每一个推理,再小再显而易见的地方都不要放过。
  4. 直觉会欺骗你,但严密的逻辑推理不会。因此当脑子和眼睛意见不统一时,相信脑子。当然,请确认你的脑子很清醒,否则可能会很惨……
Advertisements
This entry was posted in Uncategorized. Bookmark the permalink.

3 Responses to 三角形拼图 这怎么可能?

  1. 唐珂 says:

    难道我初中的时候就和班上的同学讨论过了…难道我没给你看过么…
    我还专门打印出来研究,最后发现是个图形欺骗….
     

  2. Arrix says:

    @零点坐标 嗯,我记得以前看过,但是忘记了是怎么回事。这样也好,又有了一次发现的乐趣。我在想为什么面积差刚好是一格?是数字的巧合还是精巧的设计?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s