【问题标题】:Porting a ruby method to javascript将 ruby​​ 方法移植到 javascript
【发布时间】:2013-07-04 21:54:42
【问题描述】:

我正在尝试将一些 ruby​​ 代码移植到 javascript,但我正在为某一行苦苦挣扎

Ruby 代码如下: 它会从俄罗斯方块游戏中删除所有完整的行:

  # removes all filled rows and replaces them with empty ones, dropping all rows
  # above them down each time a row is removed and increasing the score.  
  def remove_filled
    (2..(@grid.size-1)).each{|num| row = @grid.slice(num);
      # see if this row is full (has no nil)
      if @grid[num].all?
        # remove from canvas blocks in full row
        (0..(num_columns-1)).each{|index|
          @grid[num][index].remove;
          @grid[num][index] = nil
        }
        # move down all rows above and move their blocks on the canvas
        ((@grid.size - num + 1)..(@grid.size)).each{|num2|
          @grid[@grid.size - num2].each{|rect| rect && rect.move(0, block_size)};

          # I can't port this line
          @grid[@grid.size-num2+1] = Array.new(@grid[@grid.size - num2])
        }
        # insert new blank row at top
        @grid[0] = Array.new(num_columns);
        # adjust score for full flow
        @score += 10;
      end
    }
    self
  end

其中@grid是一个二维数组,初始化如下:

@grid = Array.new(num_rows) {Array.new(num_columns)}

到目前为止我所做的javascript如下

我已经在评论中指出这是我无法解决的问题

removeFilled() {
            for (var i = 2; i < this.grid.length; i++) {
                var row = this.grid.slice(i);

                var allFull = true;

                for (var g = 0; g < this.grid[i].length; g++ ) {
                    if (this.grid[i][g] == undefined) {
                        allFull = false;
                        break;
                    }
                }

                if (allFull) {
                    for (var j = 0; j < this.numColumns; j++) {
                        this.grid[i][j].remove();
                        this.grid[i][j] = undefined;
                    }

                    for (var k = this.grid.length - i + 1; k <= this.grid.length; k++) {

                        var rects = this.grid[this.grid.length - k];

                        for(var l = 0; l < rects.length; l++) {
                            var rect  = rects[l];
                            if (rect) {
                                rect.move(0, this.blockSize);
                            }
                        }

                        // ***this is the line I can't port
                        this.grid[this.grid.length - k + 1] = new Array(this.grid[this.grid.length - k]);
                    }

                    this.grid[0] =  new Array(this.numColumns);
                    this.score += 10;
                }
            }
        }

任何想法如何移植有问题的线路?

【问题讨论】:

  • 好吧,为什么不能移植它? (你可能想看看Array.slice。)
  • 所以开始:grid[grid.length - k + 1] = grid[grid.length - k]。好的,我们正在取得进展。那么 ruby​​ 中的Array.new(arr) 有什么作用呢?
  • this.grid[this.grid.length - k + 1] 存在还是正在创建?如果它正在被创建,那么this.grid.length 将增加一,因此this.grid[this.grid.length - k] 实际上就是它自己!除非这是您的意图,否则您应该将其设置为变量并使用它:var currentGridLenght = this.grid.length;
  • 是的,它存在。它是二维网格中的一行。无论等号右侧的代码正在做什么(在 Ruby 代码中),都需要对其进行初始化。
  • 它将网格数组中的项目设置为与之前的项目相同(从而将其向下移动)。类似于 row[3] = row[2] 的副本。似乎不完全合乎逻辑,但我不熟悉 Ruby。在 javascript 中,我会在数组的顶部添加一个项目 .unshift().pop() 最后一个(因此将它们向下移动)。

标签: javascript ruby arrays


【解决方案1】:

如果我理解正确,您希望将数组放在给定位置并将其复制到一个位置。

你可以这样做:

  this.grid[this.grid.length - k + 1] =  this.grid[this.grid.length - k].slice(0);

【讨论】:

    【解决方案2】:

    TL;DR @raam86 给出了正确答案。不同之处在于,在 ruby​​ 中 Array.new old_arr 将创建数组的副本。在 JS 中,您可以通过 old_arr.slice() 实现相同的目标

    据我了解,您的 sn-p 可以变成这样:

    function falsy(val) {
      return undefined === val || null === val || false === val;
    }
    
    function all(arr) {
      return arr.reduce(function (a, b) { return a && !falsy(b); }, true);
    }
    
    // removes all filled rows and replaces them with empty ones, dropping all rows
    // above them down each time a row is removed and increasing the score.
    function removeFilled() {
      var i, j, k, rects,
          _grid       = this.grid,
          _numColumns = this.numColumns,
          _blockSize  = this.blockSize;
    
      for (i = 2; i < _grid.length; i++) {
        // see if this row is full (has no nil)
        if (all(_grid[i])) {
          // remove from canvas blocks in full row
          for (j = 0; j < _numColumns; j++) {
            _grid[i][j].remove();
            _grid[i][j] = undefined;
          }
    
          // move down all rows above and move their blocks on the canvas
          for (j = _grid.length - i + 1; j < _grid.length; j++) {
            rects = _grid[_grid.length - j];
            for (k = 0; k < rects.length; k++) {
              if (!falsy(rects[k])) {
                rects[k].move(0, _blockSize);
              }
            }
    
            _grid[_grid.length - j + 1] = _grid[_grid.length - j].slice();
          }
    
          _grid[0] = new Array(_numColumns);
          this.score += 10;
        }
      }
    
      return this;
    }
    

    PS 你真的应该检查你正在使用的逻辑并考虑重构它。例如,在一个地方你使用num_columns 在另一个地方你传递行的元素数量。你迭代数组改变它,我建议你考虑操作数组的副本,在这种情况下你的代码会变得不那么复杂。

    【讨论】:

    • 谢谢 - 我同意。一旦我有了一个工作副本,我就会对它进行大量重构。我可能会在很多方面使用下划线 js。
    • 我建议您考虑lodash 而不是下划线。或者甚至与Sugar.js 一起去获得更多的红宝石:D
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-25
    • 2014-01-15
    • 1970-01-01
    • 1970-01-01
    • 2014-09-11
    • 1970-01-01
    相关资源
    最近更新 更多