将游戏转换为面向对象的版本
Transforming a game to an object-oriented version
我编写了一个简单的控制台游戏,允许我将我的玩家移动到一个有墙壁和空白区域的小关卡中。仅使用几个简单的函数即可完成。
我对Python比较陌生,但我接下来想学习OOP,如果我想使这个游戏面向对象,我该如何从这里继续?
我理解类并且反对相当,但如果我不理解所有答案,请耐心等待。
这是当前游戏:
LEVEL = [
'xxxxxx',
'x x',
'x i x',
'x x',
'x x',
'xxxxxx'
]
def get_block(x, y):
"""Gets a block at the given coordinates."""
try:
return LEVEL[y][x]
except IndexError:
return None
def set_block(x, y, block):
"""Sets a block at the given coordinates."""
try:
LEVEL[y] = LEVEL[y][:x] + block + LEVEL[y][x + 1:]
except IndexError:
pass
def get_player_position():
"""Gets player's position."""
for y, row in enumerate(LEVEL):
for x, column in enumerate(row):
if column == 'i':
return x, y
def set_player_position(x, y):
"""Sets player's position."""
block = get_block(x, y)
if block == ' ':
px, py = get_player_position()
set_block(px, py, ' ')
set_block(x, y, 'i')
def main():
"""Entry point for the program."""
cmd = ''
while cmd.lower() not in ('quit', 'q'):
print('\n' * 30)
for row in LEVEL:
print(row)
cmd = input('Command: ').lower()
px, py = get_player_position()
if cmd == 'w':
set_player_position(px, py - 1)
elif cmd == 's':
set_player_position(px, py + 1)
elif cmd == 'a':
set_player_position(px - 1, py)
elif cmd == 'd':
set_player_position(px + 1, py)
print('Bye.')
if __name__ == '__main__':
main()
你的问题很开放,所以很难给出一个包罗万象的答案——所以我所做的是在你现有的代码中确定一个数据结构并将其转换为 class.
用于对全局数据数据结构进行操作的函数现在都是 class 实例的所有 public 方法,这是唯一允许更改其中保存的数据的方法名为 _field
.
的私有属性
做这类事情是编写面向对象软件必不可少的第一步。
希望这个例子对您有所启发。
class PlayingField(object):
# Class constants
PLAYER = 'i'
EMPTY = ' '
EDGE = 'x'
DEFAULT_SIZE = 6
def __init__(self, size=DEFAULT_SIZE):
X, EMPTY = self.EDGE, self.EMPTY
self._size = size
# build playing field
self._field = [size*X] + (size-2)*[X + (size-2)*EMPTY + X] + [size*X]
self._set_block(2, 2, self.PLAYER) # Initialize player's position.
def display(self):
print(30*'\n')
for row in self._field:
print(row)
def get_player_position(self):
"""Gets player's position."""
for y, row in enumerate(self._field):
for x, column in enumerate(row):
if column == self.PLAYER:
return x, y
else:
raise ValueError("Couldn't determine player's location on field")
def set_player_position(self, x, y):
"""Sets player's position."""
block = self._get_block(x, y)
if block == self.EMPTY:
px, py = self.get_player_position()
self._set_block(px, py, self.EMPTY)
self._set_block(x, y, self.PLAYER)
# Private methods
def _get_block(self, x, y):
"""Gets a block at the given coordinates."""
try:
return self._field[y][x]
except IndexError:
return None
def _set_block(self, x, y, block):
"""Sets a block at the given coordinates."""
try:
self._field[y] = self._field[y][:x] + block + self._field[y][x + 1:]
except IndexError:
pass
def main():
"""Entry point for the program."""
field = PlayingField()
cmd = ''
while cmd.lower() not in ('quit', 'q'):
field.display()
cmd = input('Command: ').lower()
px, py = field.get_player_position()
if cmd == 'w':
field.set_player_position(px, py - 1)
elif cmd == 's':
field.set_player_position(px, py + 1)
elif cmd == 'a':
field.set_player_position(px - 1, py)
elif cmd == 'd':
field.set_player_position(px + 1, py)
print('Bye.')
if __name__ == '__main__':
main()
我编写了一个简单的控制台游戏,允许我将我的玩家移动到一个有墙壁和空白区域的小关卡中。仅使用几个简单的函数即可完成。
我对Python比较陌生,但我接下来想学习OOP,如果我想使这个游戏面向对象,我该如何从这里继续?
我理解类并且反对相当,但如果我不理解所有答案,请耐心等待。
这是当前游戏:
LEVEL = [
'xxxxxx',
'x x',
'x i x',
'x x',
'x x',
'xxxxxx'
]
def get_block(x, y):
"""Gets a block at the given coordinates."""
try:
return LEVEL[y][x]
except IndexError:
return None
def set_block(x, y, block):
"""Sets a block at the given coordinates."""
try:
LEVEL[y] = LEVEL[y][:x] + block + LEVEL[y][x + 1:]
except IndexError:
pass
def get_player_position():
"""Gets player's position."""
for y, row in enumerate(LEVEL):
for x, column in enumerate(row):
if column == 'i':
return x, y
def set_player_position(x, y):
"""Sets player's position."""
block = get_block(x, y)
if block == ' ':
px, py = get_player_position()
set_block(px, py, ' ')
set_block(x, y, 'i')
def main():
"""Entry point for the program."""
cmd = ''
while cmd.lower() not in ('quit', 'q'):
print('\n' * 30)
for row in LEVEL:
print(row)
cmd = input('Command: ').lower()
px, py = get_player_position()
if cmd == 'w':
set_player_position(px, py - 1)
elif cmd == 's':
set_player_position(px, py + 1)
elif cmd == 'a':
set_player_position(px - 1, py)
elif cmd == 'd':
set_player_position(px + 1, py)
print('Bye.')
if __name__ == '__main__':
main()
你的问题很开放,所以很难给出一个包罗万象的答案——所以我所做的是在你现有的代码中确定一个数据结构并将其转换为 class.
用于对全局数据数据结构进行操作的函数现在都是 class 实例的所有 public 方法,这是唯一允许更改其中保存的数据的方法名为 _field
.
做这类事情是编写面向对象软件必不可少的第一步。
希望这个例子对您有所启发。
class PlayingField(object):
# Class constants
PLAYER = 'i'
EMPTY = ' '
EDGE = 'x'
DEFAULT_SIZE = 6
def __init__(self, size=DEFAULT_SIZE):
X, EMPTY = self.EDGE, self.EMPTY
self._size = size
# build playing field
self._field = [size*X] + (size-2)*[X + (size-2)*EMPTY + X] + [size*X]
self._set_block(2, 2, self.PLAYER) # Initialize player's position.
def display(self):
print(30*'\n')
for row in self._field:
print(row)
def get_player_position(self):
"""Gets player's position."""
for y, row in enumerate(self._field):
for x, column in enumerate(row):
if column == self.PLAYER:
return x, y
else:
raise ValueError("Couldn't determine player's location on field")
def set_player_position(self, x, y):
"""Sets player's position."""
block = self._get_block(x, y)
if block == self.EMPTY:
px, py = self.get_player_position()
self._set_block(px, py, self.EMPTY)
self._set_block(x, y, self.PLAYER)
# Private methods
def _get_block(self, x, y):
"""Gets a block at the given coordinates."""
try:
return self._field[y][x]
except IndexError:
return None
def _set_block(self, x, y, block):
"""Sets a block at the given coordinates."""
try:
self._field[y] = self._field[y][:x] + block + self._field[y][x + 1:]
except IndexError:
pass
def main():
"""Entry point for the program."""
field = PlayingField()
cmd = ''
while cmd.lower() not in ('quit', 'q'):
field.display()
cmd = input('Command: ').lower()
px, py = field.get_player_position()
if cmd == 'w':
field.set_player_position(px, py - 1)
elif cmd == 's':
field.set_player_position(px, py + 1)
elif cmd == 'a':
field.set_player_position(px - 1, py)
elif cmd == 'd':
field.set_player_position(px + 1, py)
print('Bye.')
if __name__ == '__main__':
main()