首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python诅咒:文件中的addstr()打印行其余部分的空白

Python诅咒:文件中的addstr()打印行其余部分的空白
EN

Stack Overflow用户
提问于 2014-01-01 00:46:35
回答 2查看 2.5K关注 0票数 1

我正在用Python编写一个非常简单的农业游戏,使用诅咒。在这一点上,我已经成功地允许玩家(只是一个"@“角色)在窗口内移动。

我有几个文件与ascii艺术,我打印到窗口的东西,以填充世界,在其中的球员可以四处移动。例如,我有一个名为"house“的文件,其中包含:

代码语言:javascript
复制
 _ . ^ . _
/____.____\
|         |
| ## _ ## |
|_""_H_""_|

我有一个课程如下:

代码语言:javascript
复制
class Thing(object):    

    def __init__(self, Xstart, Ystart, looksLike, list, window):
        self.Xstart = Xstart
    self.Ystart = Ystart
    self.X = Xstart
    self.Y = Ystart

    self.looksLike = looksLike

    self.boundries = []
    self.find_boundries()

    list.append(self)

    self.draw(window)


def find_boundries(self):

    file = open(self.looksLike).readlines()
    for line in file:
        for char in line:
        if char == '\n':
            pass
        elif char == ' ':   # skip all whitespace
            self.X += 1
        else:
                self.boundries.append([self.X, self.Y])
            self.X += 1

        self.Y += 1
        self.X = self.Xstart

    self.X = self.Xstart    # reset x & y to starting coordinates
    self.Y = self.Ystart


def draw(self, window):

    #file = open(self.looksLike).readlines()

    #for line in file:
    #    window.addstr(self.Y, self.X, line)
    #    self.Y += 1

#self.Y = self.Ystart

    file = open(self.looksLike).read()

    for char in file:
        window.addch(self.Y, self.X, char)
    if char == '\n':
            self.Y += 1
    self.X = self.Xstart
    else:
    self.X += 1

self.X = self.Xstart    
self.Y = self.Ystart

因此,my Thing类的构造函数以一个文件名作为参数(looksLike),而its方法打开文件,读取文件,并将其内容打印到窗口。然后,我可以创建一个house对象,将我的" house“文件作为参数传递,我的ascii house将被打印到窗口。

问题是,一旦对象被打印到窗口,当我将播放机移到打印对象的右侧时,播放机就消失了。然而,在上面、下面和打印对象的左边,播放机仍停留在视图中。例如,

代码语言:javascript
复制
 _ . ^ . _
/____.____\
|         |
| ## _ ## |
|_""_H_""_|
                  @

在这个位置,"@“字符是可见的,但是如果我向上移动一个空格,它就消失了。如果我继续移动玩家向上,"@“将再次出现后,它移动到最上面的角色的房子。

我认为这个问题是由于addstr()和addch() (我都尝试过)在窗口结束之前打印空白的性质造成的,但是我一直找不到关于这方面的任何文档。

我已经考虑过为每个打印的对象创建一个新窗口,但是当有超过几个对象被打印到窗口时,这似乎会变得非常麻烦。另外,我希望定义打印到屏幕上的物体周围的边框,这些物体的形状不仅仅是方形或矩形。

是否有从文件到窗口的打印,没有尾随空格,也没有为每个打印对象创建一个新窗口?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-01-01 01:53:09

我假设这个问题是由于addstr()和addch() (我都尝试过)打印空白直到窗口结束的性质所致,

你为什么这么认为?

首先,您从未在您向我们展示的代码中实际调用addstr,所以不可能是这样。

至于addch,它绝对不应该这样做--正如您所看到的那样,例如,从右到左的绘制。或者通过运行这些琐碎的测试代码:

代码语言:javascript
复制
# usual curses setup
stdscr.addch(10, 10, 'a')
stdscr.addch(10, 9, 'b')

如果你没有在测试程序中看到a,你的终端就有问题了。但如果你是,那么你的假设是错误的,这与addch无关。

几乎可以肯定的是,问题是您实际上在房子文件中有空位。在诅咒中,如果你在另一个字符的上面画一个字符,它就会取代旧的字符,它不会试图合并它们或攻击它们或类似的东西。(这很好,因为大多数控制台没有任何方法来做任何这样的事情,…)

如果新字符是空格,它只是用空格替换旧字符。就像你看到的一样。

所以,修复方法是删除每一行末尾的所有空格,对吗?好吧,你可以这么做。或者你只需要rstrip()每一行。(您不需要\n;您可以通过完成对整个行的迭代来判断您已经到了一行的末尾,对吧?那么,您可以在您的file = open(…).readlines()代码中,或者在不麻烦readlines()的代码中,只在文件本身上循环;您不能使用不同的file = open(…).read()代码,但我不知道您为什么要在那里进行不同的操作。)

或者,由于您的find_boundries函数非常小心地跳过空格,所以您可能想在draw中做同样的事情,但忘记了吗?如果是这样的话,只需编写您打算跳过空格的代码。

但是,对于整个问题,有一个简单得多的解决方案:只需在房子后面而不是在它之前绘制@,这根本就不是一个问题。当然,这意味着如果玩家和房子在同一个地方,他会出现在房子的“外面”,而不是隐藏在“-but”里面--你已经有了防止这种情况发生的代码,所以如果它发生的话,它看起来应该不会有什么关系。

票数 1
EN

Stack Overflow用户

发布于 2014-01-01 01:33:39

幸运的是,我从来没有使用过诅咒,我不能看到你的玩家阶级。

尽管如此,这个片段可能会给您一些想法(按'x‘退出游戏)(使用WASD移动播放器)(需要启用ANSI的控制台:

代码语言:javascript
复制
#! /usr/bin/python3

class _GetchUnix:
    def __init__(self):
        import tty, sys

    def __call__(self):
        import sys, tty, termios
        fd = sys.stdin.fileno()
        old_settings = termios.tcgetattr(fd)
        try:
            tty.setraw(sys.stdin.fileno())
            ch = sys.stdin.read(1)
        finally:
            termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
        return ch

getch = _GetchUnix ()

house = ''' _ . ^ . _ 
/____.____\\
|         |
| ## _ ## |
|_""_H_""_|'''

class Screen:
    def __init__ (self, width, height, background):
        self.width = width
        self.height = height
        self.bg = '\x1b[{}m'.format (40 + background)
        self.clear = '\x1b[0m'
        self.objects = []

    def __iadd__ (self, obj):
        self.objects.append (obj)
        obj.screen = self
        return self

    def render (self):
        print ('\x1b[1;1H', end = '')
        for y in range (self.height):
            for x in range (self.width):
                print (self.bg + ' ' + self.clear, end = '')
            print ()
        for obj in self.objects: obj.render ()
        print ('\x1b[{};1H'.format (self.height) )

class Object:
    def __init__ (self, graphics, foreground, background, x, y):
        self.graphics = graphics.split ('\n')
        self.fg = '\x1b[{}m'.format (30 + foreground)
        self.bg = '\x1b[{}m'.format (40 + background)
        self.clear = '\x1b[0m'
        self.x = x
        self.y = y

    def render (self):
        for y, line in enumerate (self.graphics):
            print ('\x1b[{};{}H'.format (self.y + y, self.x), end = '')
            print (self.fg + self.bg + line + self.clear)

    def collide (self, x, y):
        if y < self.y: return False
        if x < self.x: return False
        if y > self.y + len (self.graphics) - 1: return False
        if x > self.x + len (self.graphics [y - self.y] ): return False
        return True

    def move (self, dx, dy):
        nx, ny = self.x + dx, self.y + dy
        if ny < 1: return
        if ny > self.screen.height: return
        if nx < 1: return
        if nx > self.screen.width: return
        for obj in self.screen.objects:
            if obj == self: continue
            if obj.collide (nx, ny): return
        self.x, self.y = nx, ny

house = Object (house, 0, 7, 6, 3)
player = Object ('@', 1, 3, 10, 10)
s = Screen (40, 20, 3)
s += house
s += player
while True:
    c = getch ()
    if c == 'x': break
    if c == 'w': player.move (0, -1)
    if c == 's': player.move (0, 1)
    if c == 'a': player.move (-1, 0)
    if c == 'd': player.move (1, 0)
    s.render ()

这里是一个屏幕截图:

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20864620

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档