![](/img/trans.png)
[英]Is there any python module to plot 2d cartesian coordinate in text mode?
[英]Python - Printing an ASCII cartesian coordinate grid from a 2D array of position objects
非常抱歉,所有人,但这将是一个漫长的过程。 因此,作为我之前关于 STDIN 的查询的一个分支,不幸的是,似乎没有足够多的问题与我的具体问题相似,至少在 Python 中没有(也没有使用像 numpy 这样的东西,这比我的水平高出一点) . 我确实有很多我已经实现的代码,所以希望这会有所帮助(尽管它不是最干净的,而且正如我上面提到的,它相当长)。
就目前而言,我的问题是打印出表示 class 对象的二维数组的 ASCII 艺术,以便 ASCII 准确地在简单的 x,y 笛卡尔坐标网格的方向上描绘它们。
我有几个相互交互的类,第一个构造包含两个整数的 position 对象,表示笛卡尔坐标对的 x 和 y:
class Pos:
def __init__(self, x, y):
self.x = x
self.y = y
第二个 class 根据用户在我程序的不同部分提供的一些大小参数构造一个“正方形”网格,这里实现为一个填充了这些 position 对象的二维数组:
class Grid:
def __init__(self, size):
assert size > 0
self.size = size
self.grid = []
#1 Perhaps there is something wrong with my 2D implementation...
for x in range(size):
sub_grid = []
for y in range(size):
sub_grid.append(Pos(x, y))
self.grid.append(sub_grid)
在这个 class 中还有一个方法,它打印出网格的 ASCII 艺术作为用户的外部表示(这是一个混乱的位):
def print(self):
# This is the main ASCII-art.
size_check = self.size - 1
if self.size > 10:
print(' +' + ('-' * (((self.size * 2) + 1)) + '+'))
else:
print(' +' + ('-' * (((self.size * 2) + 1)) + '+'))
counter = 0
#2 ...or perhaps it's something wrong with this iterative condition.
for x in self.grid[::-1]:
if self.size > 10:
if size_check > 9:
print(self.size - 1 - counter, '|', end=' ')
else:
print('', self.size - 1 - counter, '|', end=' ')
else:
print(self.size - 1 - counter, '|', end=' ')
counter += 1
size_check -= 1
for y in x:
# This is only here to check if the coords are in the correct position in the art.
^^if y.x == 5 and y.y == 8:
print('O ', end='')^^
else:
print('. ', end='')
print('|')
if self.size > 10:
print(' +' + ('-' * (((self.size * 2) + 1)) + '+'))
print(' ', end='')
else:
print(' +' + ('-' * (((self.size * 2) + 1)) + '+'))
print(' ', end='')
# This is simply support for grid sizes greater than 10.
if self.size > 10:
for x in self.grid:
if x[0].x <= 9:
print('', '', end=' ')
elif x[0].x > 9 and x[0].x < (self.size - 1):
strng = str(x[0].x)
print(int(strng[0]), end=' ')
elif x[0].x == (self.size - 1):
strng = str(x[0].x)
print(int(strng[0]))
print(' ', end='')
for x in self.grid:
if x[0].x <= 9:
print(x[0].x, '', end='')
elif x[0].x > 9 and x[0].x < (self.size - 1):
strng = str(x[0].x)
print(int(strng[1]), end=' ')
elif x[0].x == (self.size - 1):
strng = str(x[0].x)
print(int(strng[1]), end=' ')
else:
for x in self.grid:
if x[0].x < (self.size - 1):
print(x[0].x, '', end='')
elif x[0].x == (self.size - 1):
print(x[0].x, end='')
print()
我知道这很多,但它成功打印出来的内容看起来像这样(给定大小 = 10):
+---------------------+
9 | . . . . . . . . . . |
8 | . . . . . . . . . . |
7 | . . . . . . . . . . |
6 | . . . . . . . . . . |
5 | . . . . . . . . . . |
4 | . . . . . . . . . . |
3 | . . . . . . . . . . |
2 | . . . . . . . . . . |
1 | . . . . . . . . . . |
0 | . . . . . . . . . . |
+---------------------+
0 1 2 3 4 5 6 7 8 9
现在这看起来很好,直到我尝试显示 position 对象应该位于的位置。 在上面的代码中,我用 ^^ 标记了一个条件语句,它在坐标 (5, 8) 处打印出一个“O”。 结果看起来像这样:
+---------------------+
9 | . . . . . . . . . . |
8 | . . . . . . . . . . |
7 | . . . . . . . . . . |
6 | . . . . . . . . . . |
5 | . . . . . . . . O . |
4 | . . . . . . . . . . |
3 | . . . . . . . . . . |
2 | . . . . . . . . . . |
1 | . . . . . . . . . . |
0 | . . . . . . . . . . |
+---------------------+
0 1 2 3 4 5 6 7 8 9
理想的 output 实际上应该是这样的:
+---------------------+
9 | . . . . . . . . . . |
8 | . . . . . O . . . . |
7 | . . . . . . . . . . |
6 | . . . . . . . . . . |
5 | . . . . . . . . . . |
4 | . . . . . . . . . . |
3 | . . . . . . . . . . |
2 | . . . . . . . . . . |
1 | . . . . . . . . . . |
0 | . . . . . . . . . . |
+---------------------+
0 1 2 3 4 5 6 7 8 9
正如您所看到的,ASCII 艺术以这样一种方式打印,从外部看起来好像 x 轴和 y 轴已经交换,即使在内部任何 position object 的坐标响应正确。 我在上面的代码中写了两条评论,我推测可能是什么问题。 我最好的猜测是我如何实现网格本身,或者我如何打印艺术作品; 但这就是我需要帮助弄清楚的。
一如既往,我们非常感谢您提供的任何帮助; 我再次道歉!
我建议使用字符串操作而不是直接打印来构建你的线条。 这将使代码更简单,并允许将模板字符串中的模式替换为典型的行内容。
例如:
# prepare the empty content
rows = 10
cols = 10
content = [["."]*cols for _ in range(rows)]
# assign values at coordinates as needed (based on your grid)
content[5][8] = "O"
grid = [(4,1,"H"),(6,3,"L"),(5,2,"E"),(4,6,"R"),(7,4,"L"),(6,6,"W"),(3,6,"L"),(2,6,"D"),(5,6,"O")]
for (y,x,c) in grid: content[y][x] = c
# build frame
width = len(str(max(rows,cols)-1))
contentLine = "# | values |"
dashes = "-".join("-"*width for _ in range(cols))
frameLine = contentLine.replace("values",dashes)
frameLine = frameLine.replace("#"," "*width)
frameLine = frameLine.replace("| ","+-").replace(" |","-+")
# print grid
print(frameLine)
for i,row in enumerate(reversed(content),1):
values = " ".join(f"{v:{width}s}" for v in row)
line = contentLine.replace("values",values)
line = line.replace("#",f"{rows-i:{width}d}")
print(line)
print(frameLine)
# x-axis numbers
numLine = contentLine.replace("|"," ")
numLine = numLine.replace("#"," "*width)
colNums = " ".join(f"{i:<{width}d}" for i in range(cols))
numLine = numLine.replace("values",colNums)
print(numLine)
output:
+---------------------+
9 | . . . . . . . . . . |
8 | . . . . . O . . . . |
7 | . . . . L . . . . . |
6 | . . . L . . W . . . |
5 | . . E . . . O . . . |
4 | . H . . . . R . . . |
3 | . . . . . . L . . . |
2 | . . . . . . D . . . |
1 | . . . . . . . . . . |
0 | . . . . . . . . . . |
+---------------------+
0 1 2 3 4 5 6 7 8 9
output 行=12,列=15:
+----------------------------------------------+
11 | . . . . . . . . . . . . . . . |
10 | . . . . . . . . . . . . . . . |
9 | . . . . . . . . . . . . . . . |
8 | . . . . . O . . . . . . . . . |
7 | . . . . L . . . . . . . . . . |
6 | . . . L . . W . . . . . . . . |
5 | . . E . . . O . . . . . . . . |
4 | . H . . . . R . . . . . . . . |
3 | . . . . . . L . . . . . . . . |
2 | . . . . . . D . . . . . . . . |
1 | . . . . . . . . . . . . . . . |
0 | . . . . . . . . . . . . . . . |
+----------------------------------------------+
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
1. Grid
结构
pub struct Grid {
cells: Vec<Vec<char>>,
num_rows: usize,
num_cols: usize,
}
Grid
结构表示字符网格。 它具有三个字段:
cells
:表示网格中单元格的二维字符向量。num_rows
:表示网格中行数的usize
。num_cols
:表示网格中列数的usize
。 2. Alignment
枚举
#[derive(Debug, PartialEq)]
enum Alignment {
Left,
Center,
Right,
}
Alignment
枚举表示打印网格时单元格值的可能对齐方式。 它具有三种变体:
Left
:将单元格值左对齐。Center
:将单元格值对齐到中心。Right
:将单元格值右对齐。 3. new
方法
fn new(num_rows: usize, num_cols: usize, empty_cell_char: char) -> Self {
let cells = vec![vec![empty_cell_char; num_cols]; num_rows];
Self {
cells,
num_rows,
num_cols,
}
}
}
new
方法是Grid
结构的构造方法。 它需要三个参数:
num_rows
:表示网格中行数的usize
。num_cols
:表示网格中列数的usize
。empty_cell_char
:表示要填充空单元格的char
的字符。 它创建一个具有给定行数和列数的新网Grid
object,并用给定字符填充单元格。
set_cell
方法
fn set_cell(&mut self, row: usize, col: usize, character: char) {
self.cells[row][col] = character;
}
}
set_cell
方法在网格的特定单元格中设置字符。 它需要三个参数:
row
:表示单元格行号的usize
。col
:表示单元格列号的usize
。character
:一个char
表示要在单元格中设置的字符。它在给定行和列的单元格中设置字符。
5. draw
方法
impl Grid {
fn draw(
&self,
cell_width: usize,
border_char: char,
row_separator_char: char,
col_separator_char: char,
x_axis_separator_char: char,
alignment: Alignment,
) {
let frame_top_bottom = (0..self.num_cols)
.map(|_| border_char.to_string().repeat(cell_width))
.collect::<Vec<_>>()
.join(&border_char.to_string());
let row_template = format!(
"{row_num}{row_separator}{row_values}{row_values_separator}",
row_num = "{row_num}",
row_separator = row_separator_char,
row_values = "{row_values}",
row_values_separator = row_separator_char
);
let row_num = row_template.replace(
"{row_num}",
format!("{:width$}", "", width = cell_width).as_str(),
);
let frame_top = row_num.replace("{row_values}", &frame_top_bottom);
println!("{}", frame_top);
for (row_num, row) in self.cells.iter().rev().enumerate() {
let row_num_str = format!("{:width$}", self.num_rows - row_num - 1, width = cell_width);
let row_values: Vec<String> = row
.iter()
.map(|cell| {
let aligned_string: String = match alignment {
Alignment::Left => format!("{:<width$}", cell, width = cell_width),
Alignment::Center => format!("{:^width$}", cell, width = cell_width),
Alignment::Right => format!("{:>width$}", cell, width = cell_width),
};
aligned_string
})
.collect();
println!(
"{}",
row_template
.replace(
"{row_num}",
format!("{:<width$}", row_num_str, width = cell_width).as_str()
)
.replace(
"{row_values}",
&row_values.join(&col_separator_char.to_string())
)
);
}
println!("{}", frame_top);
let col_nums: Vec<String> = (0..self.num_cols)
.map(|col| {
let aligned_string: String = match alignment {
Alignment::Left => format!("{:<width$}", col, width = cell_width),
Alignment::Center => format!("{:^width$}", col, width = cell_width),
Alignment::Right => format!("{:>width$}", col, width = cell_width),
};
aligned_string
})
.collect();
let x_axis = row_num.replace(
"{row_values}",
&col_nums.join(&x_axis_separator_char.to_string()),
);
println!("{}", x_axis);
}
}
draw
方法使用给定的参数将网格打印到控制台。 它需要六个参数:
cell_width
:表示打印网格时每个单元格宽度的usize
。
border_char
:一个char
表示用于网格边界的字符。
row_separator_char
:一个char
表示用作网格行之间分隔符的字符。
col_separator_char
:一个char
表示用作网格列之间分隔符的字符。
x_axis_separator_char
:一个char
,表示用作网格底部列号之间分隔符的字符。
alignment
:一个Alignment
值,表示打印网格时单元格值的 alignment。
draw
方法首先使用border_char
和cell_width
生成网格的顶部和底部边框。 然后它为网格的每一行创建一个模板,该模板由行号、行分隔符、该行的单元格值和行值分隔符组成。
然后它从下到上遍历网格的行,并使用模板和当前行号和单元格值为每一行生成一个字符串。 然后它将每一行打印到控制台。
最后,它使用alignment
和x_axis_separator_char
在网格底部生成列号,并将它们打印到控制台。
6. main
function
复制代码
fn main() {
let mut grid = Grid::new(3, 3, ' ');
grid.set_cell(0, 0, 'X');
grid.set_cell(1, 1, 'O');
grid.set_cell(2, 2, 'X');
grid.draw(
4,
'+',
'|',
' ',
' ',
Alignment::Right,
);
}
main
function新建一个3行3列的Grid
object,并使用set_cell
方法设置单元格中的字符。 然后它调用Grid
object 上的draw
方法将其打印到控制台,单元格宽度为 4,边框字符为'+'
,行分隔符为'|'
、列分隔符' '
、x 轴分隔符' '
和 alignment Alignment::Right
。
步 | 描述 |
---|---|
定义Grid 结构 |
Grid 结构表示具有三个字段的字符网格: cells ,表示网格中单元格的二维字符向量; num_rows ,表示网格中行数的usize ; 和num_cols ,一个表示网格中列数的usize 。 |
定义Alignment 枚举 |
Alignment 枚举表示打印网格时单元格值的可能对齐方式。 它具有三种变体: Left ,将单元格值左对齐; Center ,将单元格值与中心对齐; 和Right ,它将单元格值右对齐。 |
定义new 方法 |
new 方法是Grid 结构的构造函数。 它需要三个参数: num_rows ,一个表示网格中行数的usize ; num_cols ,表示网格中列数的usize ; 和empty_cell_char ,一个char 表示要填充空单元格的字符。 它创建一个具有给定行数和列数的新网Grid object,并用给定字符填充单元格。 |
定义set_cell 方法 |
set_cell 方法在网格的特定单元格中设置字符。 它需要三个参数: row ,一个usize 代表单元格的行号; col ,表示单元格列号的usize ; 和character ,一个char 表示要在单元格中设置的字符。 它在给定行和列的单元格中设置字符。 |
定义draw 方法 |
draw 方法使用给定的参数将网格打印到控制台。 它有六个参数: cell_width ,一个usize ,表示打印网格时每个单元格的宽度; border_char ,一个char 表示用于网格边界的字符; row_separator_char ,一个char 表示用作网格行之间分隔符的字符; col_separator_char ,一个char 表示用作网格列之间分隔符的字符; x_axis_separator_char ,一个char 表示用作网格底部列号之间分隔符的字符; 和alignment ,一个Alignment 值,表示打印网格时单元格值的 alignment。 它首先使用border_char 和cell_width 生成网格的顶部和底部边框。 然后它为网格的每一行创建一个模板,该模板由行号、行分隔符、该行的单元格值和行值分隔符组成。 然后它从下到上遍历网格的行,并使用模板和当前行号和单元格值为每一行生成一个字符串。 然后它将每一行打印到控制台。 最后,它使用alignment 和x_axis_separator_char 在网格底部生成列号,并将它们打印到控制台。 |
定义main function |
main function新建一个3行3列的Grid object,并使用set_cell 方法设置单元格中的字符。 然后它调用Grid object 上的draw 方法将其打印到控制台,单元格宽度为 4,边框字符为'+' ,行分隔符为 `' |
步 | 描述 |
---|---|
定义Grid 结构 |
Grid 结构表示具有三个字段的字符网格: cells ,表示网格中单元格的二维字符向量; num_rows ,表示网格中行数的usize ; 和num_cols ,一个表示网格中列数的usize 。 |
定义Alignment 枚举 |
Alignment 枚举表示打印网格时单元格值的 alignment。 它具有三个变体: Left 、 Center 和Right 。 |
定义new 方法 |
new 方法创建一个新的Grid object 具有给定的行数和列数,并用给定的字符填充单元格。 |
定义set_cell 方法 |
set_cell 方法在网格的特定单元格中设置字符。 |
定义draw 方法 |
draw 方法使用给定的参数将网格打印到控制台。 |
定义main function |
main function 创建一个Grid object 并在其单元格中设置字符。 然后它使用draw 方法将网格打印到控制台。 |
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.