Ruby 2d array colors printing junk

时间:2022-11-27 20:48:37

I have a very specific error that I cannot seem to resolve. I have tried both the colorize plugin and the extended string class from

我有一个非常具体的错误,我似乎无法解决。我已尝试过colorize插件和扩展字符串类

Colorized Ruby output

彩色Ruby输出

Now what happens is when I want color some text it will work for one character. However, if that character is written over again or sometimes just the character next to it is written with a color, the 2d array becomes corrupted with the colorizing string text.

现在发生的事情是,当我想要颜色时,它会对一个角色起作用。但是,如果再次写入该字符,或者有时只是旁边的字符用颜色写入,则2d数组会因着色字符串文本而损坏。

Note that this problem occurs with the colorize gem in the above stack overflow link AND when I don't use it and just extend the string class myself.

请注意,上面的堆栈溢出链接中的colorize gem会出现此问题,当我不使用它时,我自己只扩展字符串类。

Provided is some sample code so that you can replicate it yourself. Note that you can NEVER use Ruby's pretty print to print the 2d array after coloring text as it will always look corrupted. If you do not wish to install the gem to test it yourself you can just extend the string class like one of the responses of the above link shows. It doesn't matter which version you choose, it doesn't effect the outcome in any way. I will also link that code at the bottom.

提供了一些示例代码,以便您可以自己复制它。请注意,在着色文本后,您永远不能使用Ruby的漂亮打印来打印2d数组,因为它总是看起来已损坏。如果您不希望安装gem来自己测试它,您可以像上面链接显示的响应之一那样扩展字符串类。您选择哪个版本并不重要,它不会以任何方式影响结果。我还会在底部链接该代码。

EDIT: One color per horizontal line is all that is allowed. Anything more than that causes corruption.

编辑:每条水平线一种颜色是允许的。除此之外的任何事情都会导致腐败。

This version works just fine.

这个版本工作得很好。

private def color(screen_object, i, j, k)

  #Creates 2d
  screen2 = Array.new(25) { Array.new(25, 0) }
  for i in 0...25 do
    if i == 0 || i == 24
      screen2[i] = '$-----------------------$'
    else
      screen2[i] = '|                       |'
    end
  end

  screen2[0][0] = '~'.colorize(:red)

  for i in 0..25
    puts "#{screen2[i]}"
  end

end

This version causes corruption when overwriting the same location with the same char and same color.

当使用相同的char和相同颜色覆盖相同位置时,此版本会导致损坏。

private def color(screen_object, i, j, k)
  #Creates 2d
  screen2 = Array.new(25) { Array.new(25, 0) }
  for i in 0...25 do
    if i == 0 || i == 24
      screen2[i] = '$-----------------------$'
    else
      screen2[i] = '|                       |'
    end
  end

  screen2[0][0] = '~'.colorize(:red)
  screen2[0][0] = '~'.colorize(:red)

  for i in 0..25
    puts "#{screen2[i]}"
  end
end

This version doesn't overwrite any chars, but having chars next to each other that are colorized causes corruption.

此版本不会覆盖任何字符,但是将颜色化的彼此相邻的字符导致损坏。

private def color(screen_object, i, j, k)
  #Creates 2d
  screen2 = Array.new(25) { Array.new(25, 0) }
  for i in 0...25 do
    if i == 0 || i == 24
      screen2[i] = '$-----------------------$'
    else
      screen2[i] = '|                       |'
    end
  end

  screen2[0][0] = '~'.colorize(:red)
  screen2[0][1] = '~'.colorize(:red)

  for i in 0..25
    puts "#{screen2[i]}"
  end
end

But sometimes writing chars right next to each other is fine. Chars that are next to each other vertically don't seem to be affected as much.

但有时候把对方写在一起很好。垂直相邻的字符似乎没有受到太大影响。

private def color(screen_object, i, j, k)
  #Creates 2d
  screen2 = Array.new(25) { Array.new(25, 0) }
  for i in 0...25 do
    if i == 0 || i == 24
      screen2[i] = '$-----------------------$'
    else
     screen2[i] = '|                       |'
    end
  end

  screen2[0][0] = '~'.colorize(:red)
  screen2[1][0] = '~'.colorize(:red)

  for i in 0..25
    puts "#{screen2[i]}"
  end
end

Finally, many chars can have a color as long as they aren't net to each other.

最后,只要它们不相互网络,许多字符就可以有颜色。

private def color(screen_object, i, j, k)
  #Creates 2d
   screen2 = Array.new(25) { Array.new(25, 0) }
  for i in 0...25 do
    if i == 0 || i == 24
      screen2[i] = '$-----------------------$'
    else
      screen2[i] = '|                       |'
    end
 end

  screen2[0][0] = '~'.colorize(:red)
 screen2[14][22] = '~'.colorize(:red)
  screen2[7][22] = '~'.colorize(:red)
  screen2[2][14] = '~'.colorize(:red)
  screen2[24][24] = '~'.colorize(:red)
  screen2[9][11] = '~'.colorize(:red)

  for i in 0..25
    puts "#{screen2[i]}"
  end
end

Here is the string extension if you don't wish to install gem. Credit goes to user Ivan Black from the other post.

如果您不想安装gem,这是字符串扩展名。从另一篇文章中获得用户Ivan Black的信用。

class String
def black;          "\e[30m#{self}\e[0m" end
def red;            "\e[31m#{self}\e[0m" end
def green;          "\e[32m#{self}\e[0m" end
def brown;          "\e[33m#{self}\e[0m" end
def blue;           "\e[34m#{self}\e[0m" end
def magenta;        "\e[35m#{self}\e[0m" end
def cyan;           "\e[36m#{self}\e[0m" end
def gray;           "\e[37m#{self}\e[0m" end

def bg_black;       "\e[40m#{self}\e[0m" end
def bg_red;         "\e[41m#{self}\e[0m" end
def bg_green;       "\e[42m#{self}\e[0m" end
def bg_brown;       "\e[43m#{self}\e[0m" end
def bg_blue;        "\e[44m#{self}\e[0m" end
def bg_magenta;     "\e[45m#{self}\e[0m" end
def bg_cyan;        "\e[46m#{self}\e[0m" end
def bg_gray;        "\e[47m#{self}\e[0m" end
def bold;           "\e[1m#{self}\e[22m" end
def italic;         "\e[3m#{self}\e[23m" end
def underline;      "\e[4m#{self}\e[24m" end
def blink;          "\e[5m#{self}\e[25m" end
def reverse_color;  "\e[7m#{self}\e[27m" end
end

1 个解决方案

#1


2  

The reason this is happening is because you're changing a single character into a string of more than one character. For instance, let's consider a simpler example (using the provided String class):

发生这种情况的原因是因为您将单个字符更改为多个字符的字符串。例如,让我们考虑一个更简单的例子(使用提供的String类):

string = "1"
puts [string.length, string[0], string.inspect, string]
puts '---'
string[0] = "1".red
puts [string.length, string[0], string.inspect, string]

The output of this is:

这个输出是:

1
1
"1"
1
---
10
  # nothing output, but string[0] = "\e"
\e[31m1\e[0m
1 # (this line is red)

While running this, it's easier to see, the length of the string changes from 1 to 10, so string[0] changes accordingly, from the digit "1" to the character "\e". So now, if we were to change the first character again by re-running just the last couple lines of that script:

运行它时,更容易看到,字符串的长度从1变为10,因此字符串[0]相应地改变,从数字“1”变为字符“\ e”。所以现在,如果我们通过重新运行该脚本的最后几行来再次更改第一个字符:

puts '---'
string[0] = "1".red
puts [string.length, string[0], string.inspect, string]

the output for this section is:

此部分的输出是:

---
19

\e[31m1\e[0m[31m1\e[0m
1[31m1 # (first character is red, but then we have the random string)

This string is now 'corrupted' because we have replaced only the character "\e" with the string "\e[31m1\e[0m" and then we still have the rest of the original string "[31m1\e[0m" at the end of it.

此字符串现在已“损坏”,因为我们只用字符串“\ e [31m1 \ e [0m”替换了字符“\ e”,然后我们仍然拥有原始字符串的其余部分“[31m1 \ e [0m”在它结束时。

You can add more than one color per line, you just have to make sure you're accounting for the new length of the string, after you do so, for instance:

您可以为每行添加多种颜色,只需确保在执行此操作后考虑字符串的新长度,例如:

string = "12"
string[0] = "1".red
string[-1] = "2".blue
puts string
# outputs "12" with the "1" red and the "2" blue.

This one works because we're making sure not to step on the color codes' toes, by targeting the first character of the string and then targeting the last character, which wasn't affected by adding the color escapes around the first one. If you want the second character in a string, you have to check the length of the colorized string:

这个是有效的,因为我们确保不要踩到颜色代码的脚趾,通过定位字符串的第一个字符然后定位最后一个字符,这不受在第一个字符周围添加颜色转义的影响。如果您想要字符串中的第二个字符,则必须检查着色字符串的长度:

string = "123"
string[0] = "1".red
string["1".red.length] = "2".blue
puts string
# '123' with '1' being red, '2' being blue and '3' being unaffected.

Re-reading your example, you might just be confused by the fact that you think your array, screen2 is an array of arrays, and while it starts out that way, it doesn't end that way:

重新阅读你的例子,你可能只是因为你认为你的数组,screen2是一个数组数组这一事实而感到困惑,并且当它以这种方式开始时,它不会以这种方式结束:

screen2 = Array.new(25) { Array.new(25, 0) }
# at this point, screen2 is an array of arrays, with values of 0
for i in 0...25 do
  # this conditional changes the elements in the outer array to be strings
  # not arrays!
  if i == 0 || i == 24
    screen2[i] = '$-----------------------$'
  else
    screen2[i] = '|                       |'
  end
end
# here, screen2 is an array of strings, not an array of arrays. This
# allows my above explanation to become relevant.

Hope this all makes sense and helps

希望这一切都有意义和有帮助

#1


2  

The reason this is happening is because you're changing a single character into a string of more than one character. For instance, let's consider a simpler example (using the provided String class):

发生这种情况的原因是因为您将单个字符更改为多个字符的字符串。例如,让我们考虑一个更简单的例子(使用提供的String类):

string = "1"
puts [string.length, string[0], string.inspect, string]
puts '---'
string[0] = "1".red
puts [string.length, string[0], string.inspect, string]

The output of this is:

这个输出是:

1
1
"1"
1
---
10
  # nothing output, but string[0] = "\e"
\e[31m1\e[0m
1 # (this line is red)

While running this, it's easier to see, the length of the string changes from 1 to 10, so string[0] changes accordingly, from the digit "1" to the character "\e". So now, if we were to change the first character again by re-running just the last couple lines of that script:

运行它时,更容易看到,字符串的长度从1变为10,因此字符串[0]相应地改变,从数字“1”变为字符“\ e”。所以现在,如果我们通过重新运行该脚本的最后几行来再次更改第一个字符:

puts '---'
string[0] = "1".red
puts [string.length, string[0], string.inspect, string]

the output for this section is:

此部分的输出是:

---
19

\e[31m1\e[0m[31m1\e[0m
1[31m1 # (first character is red, but then we have the random string)

This string is now 'corrupted' because we have replaced only the character "\e" with the string "\e[31m1\e[0m" and then we still have the rest of the original string "[31m1\e[0m" at the end of it.

此字符串现在已“损坏”,因为我们只用字符串“\ e [31m1 \ e [0m”替换了字符“\ e”,然后我们仍然拥有原始字符串的其余部分“[31m1 \ e [0m”在它结束时。

You can add more than one color per line, you just have to make sure you're accounting for the new length of the string, after you do so, for instance:

您可以为每行添加多种颜色,只需确保在执行此操作后考虑字符串的新长度,例如:

string = "12"
string[0] = "1".red
string[-1] = "2".blue
puts string
# outputs "12" with the "1" red and the "2" blue.

This one works because we're making sure not to step on the color codes' toes, by targeting the first character of the string and then targeting the last character, which wasn't affected by adding the color escapes around the first one. If you want the second character in a string, you have to check the length of the colorized string:

这个是有效的,因为我们确保不要踩到颜色代码的脚趾,通过定位字符串的第一个字符然后定位最后一个字符,这不受在第一个字符周围添加颜色转义的影响。如果您想要字符串中的第二个字符,则必须检查着色字符串的长度:

string = "123"
string[0] = "1".red
string["1".red.length] = "2".blue
puts string
# '123' with '1' being red, '2' being blue and '3' being unaffected.

Re-reading your example, you might just be confused by the fact that you think your array, screen2 is an array of arrays, and while it starts out that way, it doesn't end that way:

重新阅读你的例子,你可能只是因为你认为你的数组,screen2是一个数组数组这一事实而感到困惑,并且当它以这种方式开始时,它不会以这种方式结束:

screen2 = Array.new(25) { Array.new(25, 0) }
# at this point, screen2 is an array of arrays, with values of 0
for i in 0...25 do
  # this conditional changes the elements in the outer array to be strings
  # not arrays!
  if i == 0 || i == 24
    screen2[i] = '$-----------------------$'
  else
    screen2[i] = '|                       |'
  end
end
# here, screen2 is an array of strings, not an array of arrays. This
# allows my above explanation to become relevant.

Hope this all makes sense and helps

希望这一切都有意义和有帮助