使用Canvas Logic获得三角形180度

时间:2017-02-23 01:45:09

标签: javascript css math canvas logic

我正在尝试创建一个小程序,其中三角形中的所有度数将加起来180度。到目前为止我所拥有的是,当我使用Math.Random方法时,我得到一个随机数,但有些数字的度数加起来不是180°。我已经尝试过使用if条件语句但到目前为止没有运气。

这是我的代码:

https://jsfiddle.net/14p880p9/

    var a = Math.round((Math.random() * 100) + 1);
    var b = Math.round((Math.random() * 100) + 1);
    var c = Math.round((Math.random() * 100) + 1);

    var d = a + b + c;



    ctx.beginPath();
    ctx.moveTo(50, 10);
    ctx.lineTo(50, 450);
    ctx.lineTo(650, 400);
    ctx.closePath();
    ctx.lineWidth = 10;
    ctx.strokeStyle = '#666666';
    ctx.stroke();
    ctx.fillStyle = "#FFCC00";
    ctx.fill();

    ctx.font = "30px Comic Sans MS";
    ctx.fillStyle = "black";
    ctx.fillText(a + "°",52,60);


    //width distance, and then altitude
    ctx.font = "30px Comic Sans MS";
    ctx.fillStyle = "black";
    ctx.fillText(b+ "°",60,420);



    //width distance, and then altitude
    ctx.font = "30px Comic Sans MS";
    ctx.fillStyle = "black";
    ctx.fillText(c + "°",570,400);

3 个答案:

答案 0 :(得分:3)

使用它,它可以生成任何组合,不像上面有限的选项,其中一个边必须是1-100。

createMarker

答案 1 :(得分:1)

您生成随机性的逻辑有点偏差。在你要求它在1-100之间产生3个随机数的那一刻。这种方法的缺点是数字与必须添加到180无关;

你应该更新这个逻辑,知道总数必须等于180.这样的事情:

var a = Math.round((Math.random() * 100) + 1); // generates a random number between 1-100
var b = Math.round((Math.random() * (179-a)) + 1); // generates a random number between 1-179 (minus a)
var c = 180 - a - b; // is the remaining value of 180 - a - b

var d = a + b + c;

<强> JSFIDDLE

答案 2 :(得分:1)

a)要么用棍子......

解决此问题的一种简单方法是将180视为一根棍子。你想把那根棍子分成3块。因此,您需要做的就是生成两个不等的舍入随机值,从1到179(切割点:one&amp; two)。你的随机值将是:

  • a:从零到最小值切割点
  • b:从最小值到最大值的切割点
  • c:从最大切割点到180

var Triangle = function() {
    this.getRandom = function() {
        // 1 - 179 random integer generator
        return Math.round(Math.random() * (179 - 1) + 1);
    }

    this.one = this.getRandom();
    this.two = this.getRandom();

    while (this.one == this.two) {
        // if equal, regenerate second - we don't want any segment to have 0 length
        this.two = this.getRandom();
    }

    return {
        'a': Math.min(this.one, this.two),
        'b': Math.max(this.one, this.two) - Math.min(this.one, this.two),
        'c': 180 - Math.max(this.one, this.two)
    }
}

// Now let's make a few tests... how about 180 tests?
for (var i = 0; i < 180; i++) {

    var t = new Triangle;

    var div = document.createElement('div');
    div.innerHTML = t.a + ' + ' + t.b + ' + ' + t.c + ' = ' +
        (t.a + t.b + t.c);

    document.getElementsByTagName('body')[0].appendChild(div);
}
div {
  width: 33.3333%;
  float: left;
  padding: .5rem 0;
  text-align: center;
}

b)......或数学

虽然上述方法很容易可视化,但确保每个细分值在1178之间的任何位置都有相同的机会(total - (parts - 1 )),从编程的角度来看,它并不是特别有效。

每次其中一个切割点与现有切割点重叠时,需要重新计算。在我们的情况下,这是非常罕见的,但鉴于totalparts的变量值,它发生的几率可能不同。
此外,我们完全可以避免重新生成任何价值,从而节省计算能力,最终节省地球,或者至少在很短的时间内推迟它的厄运。

如果我们从数学的角度来看这个,我们会注意到

  • 至少1部分将小于61 ((180 / (3 - 0)) + 1)
  • 至少2部分将小于91 ((180 / (3 - 1)) + 1)

因此,作为一般规则,至少n部分将小于(total / (parts - (n - 1)) + 1)。现在让我们重写我们的方法,在正确的可能值范围内生成最小量或随机数 我们还需要将total与之前所有值的总和之间的差值作为最后一个值添加 为了使其更有用,我还将totalparts视为变量,因此该方法可用于将任何total数字细分为任意数量的parts

var Segmentation = function (total, parts) {
    this.random = function (min, max) {
        return Math.round(Math.random() * (max - min) + min);
    }

    this.segments = [];
    for (var i = 0; i < parts - 1; i++) {
        this.segments.push(this.random(parts - i, total / parts + 1));
    }

    this.segments.push(total - this.segments.reduce((a, b) => a + b, 0));
    return this.segments;

}
// let's test it

var h1 = document.createElement('h2');
h1.innerHTML = 'Triangles';
document.getElementsByTagName('body')[0].appendChild(h1);

for (var i = 0; i < 21; i++) {

    var t = new Segmentation(180, 3),
        div = document.createElement('div');

    div.innerHTML = '';
    for (var j = 0; j < t.length; j++) {
        div.innerHTML += t[j] + (t.length - j > 1 ? ' + ' : ' = ');
    }
    div.innerHTML += t.reduce((a, b) => a + b, 0);

    document.getElementsByTagName('body')[0].appendChild(div);
}

var h1 = document.createElement('h2');
h1.innerHTML = '<hr />Rectangles';
document.getElementsByTagName('body')[0].appendChild(h1);

for (var i = 0; i < 21; i++) {

    var t = new Segmentation(360, 4),
        div = document.createElement('div');

    div.innerHTML = '';
    for (var j = 0; j < t.length; j++) {
        div.innerHTML += t[j] + (t.length - j > 1 ? ' + ' : ' = ');
    }
    div.innerHTML += t.reduce((a, b) => a + b, 0);

    document.getElementsByTagName('body')[0].appendChild(div);
}

var h1 = document.createElement('h2');
h1.innerHTML = '<hr />Random segments';
document.getElementsByTagName('body')[0].appendChild(h1);

for (var i = 0; i < 21; i++) {
    var total = Math.round(Math.random() * (2000 - 200) + 200),
        parts = Math.round(Math.random() * (8 - 3) + 3),
        t = new Segmentation(total, parts);

    var div = document.createElement('div');
    div.className = ('full');
    div.innerHTML = '';
    for (var j = 0; j < t.length; j++) {
        div.innerHTML += t[j] + (t.length - j > 1 ? ' + ' : ' = ');
    }
    div.innerHTML += t.reduce((a, b) => a + b, 0);

    document.getElementsByTagName('body')[0].appendChild(div);
}
div {
  width: 33.3333%;
  float: left;
  padding: .5rem 0;
  text-align: center;
}

div.full {
  width: 100%;
  text-align: initial;
}

使用此方法,数组中的第一个条目具有最小值的可能性,而最后一个条件具有最大值的最大值。

注意:在生产环境中使用此功能 ,建议不要清理输入值。

另一个注释:为了计算数组中所有现有值的总和,我使用了这个awesome answer的方法。