从同一类调用方法

7 投票
7 回答
26521 浏览
提问于 2025-04-16 11:58

我正在为一个简单的四连棋游戏写一个类,但在调用同一个类里的一个方法时遇到了问题。为了完整起见,这里是整个类的代码:

class Grid:
    grid = None
    # creates a new empty 10 x 10 grid
    def reset():
        Grid.grid = [[0] * 10 for i in range(10)]
    # places an X or O
    def place(player,x,y):
        Grid.grid[x][y] = player
    # returns the element in the grid
    def getAt(x,y):
        return Grid.grid[x][y]
    # checks for wins in a certain direction
    def checkLine(player,v,count,x,y):
        x = x+v[0]
        y = y+v[1]
        if x < 0 or x > 9:
            return
        if y < 0 or y > 9:
            return
        if Grid.grid[x][y] == p:
            count = count+1
            if count == 4:
                return True
            checkLine(player,v,count,x,y)
        return False
    # returns the number of the player that won
    def check():
        i = 'i'
        for x in range(0,10):
            for y in range(0,10):
                if Grid.grid[x][y] > 0:
                    p = Grid.grid[x][y]
                    f = checkLine(p,0,array(i,[1,0]),x,y)
                    if f:
                        return p
                    f = checkLine(p,0,array(i,[0,1]),x,y)
                    if f:
                        return p
                    f = checkLine(p,0,array(i,[1,1]),x,y)
                    if f:
                        return p
                    f = checkLine(p,0,array(i,[-1,0]),x,y)
                    if f:
                        return p
                    f = checkLine(p,0,array(i,[0,-1]),x,y)
                    if f:
                        return p
                    f = checkLine(p,0,array(i,[-1,-1]),x,y)
                    if f:
                        return p
                    f = checkLine(p,0,array(i,[1,-1]),x,y)
                    if f:
                        return p
                    f = checkLine(p,0,array(i,[-1,1]),x,y)
                    if f:
                        return p
        return 0
    reset = staticmethod(reset)
    place = staticmethod(place)
    getAt = staticmethod(getAt)
    check = staticmethod(check)
    checkLine = staticmethod(checkLine)

我想从check()方法里调用checkLine(),但是我遇到了一个错误,提示“NameError: global name 'checkLine' is not defined”。当我改为调用Grid.checkLine()时,又出现了“TypeError: 'module' object is not callable”的错误。

我该如何调用checkLine()呢?

编辑:

@beer_monk

class Grid(object):
    grid = None
    # creates a new empty 10 x 10 grid
    def reset(self):
        Grid.grid = [[0] * 10 for i in range(10)]
    # places an X or O
    def place(self,player,x,y):
        Grid.grid[x][y] = player
    # returns the element in the grid
    def getAt(self,x,y):
        return Grid.grid[x][y]
    # checks for wins in a certain direction
    def checkLine(self,player,v,count,x,y):
        x = x+v[0]
        y = y+v[1]
        if x < 0 or x > 9:
            return
        if y < 0 or y > 9:
            return
        if Grid.grid[x][y] == p:
            count = count+1
            if count == 4:
                return True
            checkLine(self,player,v,count,x,y)
        return False
    # returns the number of the player that won
    def check(self):
        i = 'i'
        for x in range(0,10):
            for y in range(0,10):
                if Grid.grid[x][y] > 0:
                    p = Grid.grid[x][y]
                    for vx in range(-1,2):
                        for vy in range(-1,2):
                            f = self.checkLine(p,0,array(i,[vx,vy]),x,y)
                            if f:
                                return p
        return 0
    reset = staticmethod(reset)
    place = staticmethod(place)
    getAt = staticmethod(getAt)
    check = staticmethod(check)
    checkLine = staticmethod(checkLine)

7 个回答

1

这是一个重新整理过的例子(希望能更好地展示类的使用!)

import itertools

try:
    rng = xrange   # Python 2.x
except NameError:
    rng = range    # Python 3.x

class Turn(object):
    def __init__(self, players):
        self.players = itertools.cycle(players)
        self.next()

    def __call__(self):
        return self.now

    def next(self):
        self.now = self.players.next()

class Grid(object):
    EMPTY = ' '
    WIDTH = 10
    HEIGHT = 10
    WINLENGTH = 4

    def __init__(self, debug=False):
        self.debug = debug
        self.grid = [Grid.EMPTY*Grid.WIDTH for i in rng(Grid.HEIGHT)]
        self.player = Turn(['X','O'])

    def set(self, x, y):
        if self.grid[y][x]==Grid.EMPTY:
            t = self.grid[y]
            self.grid[y] = t[:x] + self.player() + t[x+1:]
            self.player.next()
        else:
            raise ValueError('({0},{1}) is already taken'.format(x,y))

    def get(self, x, y):
        return self.grid[y][x]

    def __str__(self):
        corner = '+'
        hor = '='
        ver = '|'
        res = [corner + hor*Grid.WIDTH + corner]
        for row in self.grid[::-1]:
            res.append(ver + row + ver)
        res.append(corner + hor*Grid.WIDTH + corner)
        return '\n'.join(res)

    def _check(self, s):
        if self.debug: print("Check '{0}'".format(s))
        # Exercise left to you!
        # See if a winning string exists in s
        # If so, return winning player char; else False
        return False

    def _checkVert(self):
        if self.debug: print("Check verticals")
        for x in rng(Grid.WIDTH):
            winner = self._check([self.get(x,y) for y in rng(Grid.HEIGHT)])
            if winner:
                return winner
        return False

    def _checkHoriz(self):
        if self.debug: print("Check horizontals")
        for y in rng(Grid.HEIGHT):
            winner = self._check([self.get(x,y) for x in rng(Grid.WIDTH)])
            if winner:
                return winner
        return False

    def _checkUpdiag(self):
        if self.debug: print("Check up-diagonals")
        for y in rng(Grid.HEIGHT-Grid.WINLENGTH+1):
            winner = self._check([self.get(d,y+d) for d in rng(min(Grid.HEIGHT-y, Grid.WIDTH))])
            if winner:
                return winner
        for x in rng(1, Grid.WIDTH-Grid.WINLENGTH+1):
            winner = self._check([self.get(x+d,d) for d in rng(min(Grid.WIDTH-x, Grid.HEIGHT))])
            if winner:
                return winner
        return False

    def _checkDowndiag(self):
        if self.debug: print("Check down-diagonals")
        for y in rng(Grid.WINLENGTH-1, Grid.HEIGHT):
            winner = self._check([self.get(d,y-d) for d in rng(min(y+1, Grid.WIDTH))])
            if winner:
                return winner
        for x in rng(1, Grid.WIDTH-Grid.WINLENGTH+1):
            winner = self._check([self.get(x+d,d) for d in rng(min(Grid.WIDTH-x, Grid.HEIGHT))])
            if winner:
                return winner
        return False

    def isWin(self):
        "Return winning player or False"
        return self._checkVert() or self._checkHoriz() or self._checkUpdiag() or self._checkDowndiag()

def test():
    g = Grid()
    for o in rng(Grid.WIDTH-1):
        g.set(0,o)
        g.set(Grid.WIDTH-1-o,0)
        g.set(Grid.WIDTH-1,Grid.HEIGHT-1-o)
        g.set(o,Grid.HEIGHT-1)
    print(g)
    return g

g = test()
print g.isWin()
3

语法:

class_Name.function_Name(self)

示例:

Turn.checkHoriz(self)
13

去掉这个类吧。直接用普通的函数和模块级别的变量来处理grid。这个类对你没有任何帮助。

另外,如果你真的想在类里面调用checkline,你可以用Grid.checkline来调用。例如:

class Foo:
    @staticmethod
    def test():
        print('Hi')
    @staticmethod
    def test2():
        Foo.test()

Foo.test2()       

打印输出

Hi

撰写回答