#python #python-3.x #matrix #chess
#python #python-3.x #матрица #шахматы
Вопрос:
Я создаю шахматы на Python. Я изо всех сил пытаюсь переместить фигуру на доске, которая состоит из 8 списков, вот так:
[['___' for z in range(x)] for z in range(x)] # z is 8 in this instance
Довольно печатно это выглядит так:
a b c d e f g h
8 ['___', '___', '___', '___', '___', '___', '___', '___'] 8
7 ['___', '___', '___', '___', '___', '___', '___', '___'] 7
6 ['___', '___', '___', '___', '___', '___', '___', '___'] 6
5 ['___', '___', '___', '___', '___', '___', '___', '___'] 5
4 ['___', '___', '___', '___', '___', '___', '___', '___'] 4
3 ['___', '___', '___', '___', '___', '___', '___', '___'] 3
2 ['___', '___', '___', '___', '___', '___', '___', '___'] 2
1 ['___', '___', '___', '___', '___', '___', '___', '___'] 1
a b c d e f g h
Я размещаю фигуру на доске:
def create(self):
Config.board[self.y][self.x] = self.pieceid
Тогда это выглядит так:
a b c d e f g h
8 ['___', '___', '___', '___', '___', '___', '___', '___'] 8
7 ['___', '___', '___', '___', '___', '___', '___', '___'] 7
6 ['___', '___', '___', '___', '___', '___', '___', '___'] 6
5 ['___', '___', '___', '___', '___', '___', '___', '___'] 5
4 ['___', '___', '___', '___', '___', '___', '___', '___'] 4
3 ['___', '___', '___', '___', '___', '___', '___', '___'] 3
2 ['___', '___', '___', '___', '___', '___', '___', '___'] 2
1 ['___', '___', '___', '___', 'wN1', '___', '___', '___'] 1
a b c d e f g h
Теперь я проверяю возможные ходы коня (проверка еще не реализована):
def possible_moves(self):
pos_moves = []
# Up, Right (1 space, 2 spaces)
try:
if 1 <= self.x 2 <= len(Config.board) and 1 <= self.y - 1 <= len(Config.board):
if Config.board[self.x 2][self.y - 1] == '___':
pos_moves.append(f'{Config.tile_convert(self.x 2)}{Config.tile_convert(self.y - 1, True)}')
except IndexError: pass
#Up, Left
try:
if 1 <= self.x - 2 <= len(Config.board) and 1 <= self.y - 1 <= len(Config.board):
if Config.board[self.x - 2][self.y - 1] == '___':
pos_moves.append(f'{Config.tile_convert(self.x - 2)}{Config.tile_convert(self.y - 1, True)}')
except IndexError: pass
# Down, Right
try:
if 1 <= self.x 2 <= len(Config.board) and 1 <= self.y 1 <= len(Config.board):
if Config.board[self.x 2][self.y 1] == '___':
pos_moves.append(f'{Config.tile_convert(self.x 2)}{Config.tile_convert(self.y 1, True)}')
except IndexError: pass
#Down, Left
try:
if 1 <= self.x - 2 <= len(Config.board) and 1 <= self.y 1 <= len(Config.board):
if Config.board[self.x - 2][self.y 1] == '___':
pos_moves.append(f'{Config.tile_convert(self.x - 2)}{Config.tile_convert(self.y 1, True)}')
except IndexError: pass
# Right, Up
try:
if 1 <= self.x 1 <= len(Config.board) and 1 <= self.y - 2 <= len(Config.board):
if Config.board[self.x 1][self.y - 2] == '___':
pos_moves.append(f'{Config.tile_convert(self.x 1)}{Config.tile_convert(self.y - 2, True)}')
except IndexError: pass
# Right, Down
try:
if 1 <= self.x 1 <= len(Config.board) and 1 <= self.y 2 <= len(Config.board):
if Config.board[self.x 1][self.y 2] == '___':
pos_moves.append(f'{Config.tile_convert(self.x 1)}{Config.tile_convert(self.y 2, True)}')
except IndexError: pass
#Left, Up
try:
if 1 <= self.x - 1 <= len(Config.board) and 1 <= self.y - 2 <= len(Config.board):
print('Current: ', self.x, self.y)
print('New: ', self.x - 1, self.y - 2)
if Config.board[self.x - 1][self.y - 2] == '___':
pos_moves.append(f'{Config.tile_convert(self.x - 1)}{Config.tile_convert(self.y - 2, True)}')
except IndexError: pass
# Left, Down
try:
if 1 <= self.x - 1 <= len(Config.board) and 1 <= self.y 2 <= len(Config.board):
if Config.board[self.x - 1][self.y 2] == '___':
pos_moves.append(f'{Config.tile_convert(self.x - 1)}{Config.tile_convert(self.y 2, True)}')
except IndexError: pass
return pos_moves
И если перемещение находится в пределах этих возможных ходов, я перемещаю его:
def move(self, pos):
if pos in self.possible_moves():
Config.board[self.y][self.x] = '___'
self.x = Config.tile_convert(pos[0])
self.y = Config.tile_convert(pos[1], True)
Config.board[self.y][self.x] = self.pieceid
Тем не менее, по какой-то причине координаты выходят из строя, и фрагмент не может перемещаться, когда он должен быть в состоянии:
knight1.move('f3')
time.sleep(2)
knight1.move('g5')
time.sleep(2)
knight1.move('h7')
time.sleep(2)
print(knight1.possible_moves()) # f8 should be in here
knight1.move('f8') # fails
Печатая координаты, я пришел к выводу, что проблема в том, что они обновляются некорректно. Что не так с моей логикой?
Это мой tile_convert()
метод:
def tile_convert(cls, x, disp=False):
if not disp:
if isinstance(x, str):
return cls.letters.index(x)
else:
return cls.letters[x]
else:
return len(Config.board) - int(x)
Вот мой полный код, если вы хотите его запустить:
import time
class Config:
letters = tuple('abcdefghijklmnopqrstuvwxyz')
@classmethod
def new_board(cls, btype):
def size(x):
return [['___' for z in range(x)] for z in range(x)]
if 'custom' in btype.lower():
btype = int(btype.replace('custom', '').strip())
cls.board = size(btype)
elif btype.lower() == 'default':
cls.board = size(8)
elif btype.lower() == 'extended':
cls.board = size(10)
elif btype.lower() == 'small':
cls.board = size(5)
elif btype.lower() == 'max':
cls.board = size(25)
elif btype.lower() == 'min':
cls.board = size(1)
@classmethod
def print_board(cls):
def printl():
for x in range(len(cls.board)):
print(' '*6 f'{cls.letters[x]}', end='')
print('n')
printl()
for x in range(len(cls.board)):
print(f'{len(cls.board)-x} {cls.board[x]} {len(Config.board)-x}n')
printl()
print('n'*4)
@classmethod
def tile_convert(cls, x, disp=False):
if not disp:
if isinstance(x, str):
return cls.letters.index(x)
else:
return cls.letters[x]
else:
return len(Config.board) - int(x)
class ChessPiece:
def __init__(self, pos, color, num, piece):
self.x = int(Config.tile_convert(pos[0]))
self.y = len(Config.board) - int(pos[1])
self.color = color
self.pieceid = num
self.set_id()
self.create()
def __str__(self):
return self.__class__.__name__
def set_id(self):
if self.__class__.__name__ != "Knight":
self.pieceid = f'{piece[0]}{self.pieceid}'
else:
self.pieceid = f'N{self.pieceid}'
if self.color is not None:
if self.color.lower() in ('black', 'white', 'b', 'w'):
self.pieceid = self.color.lower()[0] self.pieceid
if self.color.lower() == 'b':
self.color = 'black'
elif self.color.lower() == 'w':
self.color = 'white'
else:
self.color = None
print("Invalid color input. Color not set.")
self.set_id()
else:
self.pieceid = '_' self.pieceid
def create(self):
Config.board[self.y][self.x] = self.pieceid
def move(self, pos):
if pos in self.possible_moves():
Config.board[self.y][self.x] = '___'
self.x = Config.tile_convert(pos[0])
self.y = Config.tile_convert(pos[1], True)
Config.board[self.y][self.x] = self.pieceid
Config.print_board()
else:
print(f'Unable to move to {pos}')
def get_info(self):
print(f'{self.__class__.__name__}:n')
print('ID: ', self.pieceid)
print('Position: ', Config.tile_convert(self.x), Config.tile_convert(self.y, True), sep='')
print('Color: ', self.color)
class Knight(ChessPiece):
def __init__(self, pos, color=None, num=''):
ChessPiece.__init__(self, pos, color, num, self.__class__.__name__)
def possible_moves(self):
pos_moves = []
# Up, Right (1 space, 2 spaces)
try:
if 1 <= self.x 2 <= len(Config.board) and 1 <= self.y - 1 <= len(Config.board):
if Config.board[self.x 2][self.y - 1] == '___':
pos_moves.append(f'{Config.tile_convert(self.x 2)}{Config.tile_convert(self.y - 1, True)}')
except IndexError: pass
#Up, Left
try:
if 1 <= self.x - 2 <= len(Config.board) and 1 <= self.y - 1 <= len(Config.board):
if Config.board[self.x - 2][self.y - 1] == '___':
pos_moves.append(f'{Config.tile_convert(self.x - 2)}{Config.tile_convert(self.y - 1, True)}')
except IndexError: pass
# Down, Right
try:
if 1 <= self.x 2 <= len(Config.board) and 1 <= self.y 1 <= len(Config.board):
if Config.board[self.x 2][self.y 1] == '___':
pos_moves.append(f'{Config.tile_convert(self.x 2)}{Config.tile_convert(self.y 1, True)}')
except IndexError: pass
#Down, Left
try:
if 1 <= self.x - 2 <= len(Config.board) and 1 <= self.y 1 <= len(Config.board):
if Config.board[self.x - 2][self.y 1] == '___':
pos_moves.append(f'{Config.tile_convert(self.x - 2)}{Config.tile_convert(self.y 1, True)}')
except IndexError: pass
# Right, Up
try:
if 1 <= self.x 1 <= len(Config.board) and 1 <= self.y - 2 <= len(Config.board):
if Config.board[self.x 1][self.y - 2] == '___':
pos_moves.append(f'{Config.tile_convert(self.x 1)}{Config.tile_convert(self.y - 2, True)}')
except IndexError: pass
# Right, Down
try:
if 1 <= self.x 1 <= len(Config.board) and 1 <= self.y 2 <= len(Config.board):
if Config.board[self.x 1][self.y 2] == '___':
pos_moves.append(f'{Config.tile_convert(self.x 1)}{Config.tile_convert(self.y 2, True)}')
except IndexError: pass
#Left, Up
try:
if 1 <= self.x - 1 <= len(Config.board) and 1 <= self.y - 2 <= len(Config.board):
print('Current: ', self.x, self.y)
print('New: ', self.x - 1, self.y - 2)
if Config.board[self.x - 1][self.y - 2] == '___':
pos_moves.append(f'{Config.tile_convert(self.x - 1)}{Config.tile_convert(self.y - 2, True)}')
except IndexError: pass
# Left, Down
try:
if 1 <= self.x - 1 <= len(Config.board) and 1 <= self.y 2 <= len(Config.board):
if Config.board[self.x - 1][self.y 2] == '___':
pos_moves.append(f'{Config.tile_convert(self.x - 1)}{Config.tile_convert(self.y 2, True)}')
except IndexError: pass
return pos_moves
Config.new_board('default')
Config.print_board()
knight1 = Knight('e1', color='w', num=1)
Config.print_board()
# knight1.get_info()
# print('nnnPossible Moves:', knight1.possible_moves())
knight1.move('f3')
time.sleep(2)
knight1.move('g5')
time.sleep(2)
knight1.move('h7')
time.sleep(2)
print(knight1.possible_moves())
knight1.move('f8')
Комментарии:
1. Почему вы используете
disp=True
при настройкеself.y
?2. Что означает этот параметр? Я не понимаю логику
tile_convert
.3. Преобразование с помощью
disp=True
преобразует отображаемое число y во внутреннее, поскольку внутренние числа возрастают, а отображаемые числа уменьшаются. В этом случае я загружаю отображаемое значение y. В любом случае, значения y, похоже, работают, а значения x, похоже, отключены4. Вам действительно нужно,
try/except IndexError
когда вы проверяете индекс с помощьюif
инструкций?5. Вот почему код прерывается без
try
, потому что вашиif
тесты неверны.
Ответ №1:
Ваши проверки индекса possible_moves
неверны, потому что индексы списка переходят от 0
к len(Config.board)-1
, а не от 1
к len(Config.board)
.
Вы можете значительно упростить код, используя цикл, чтобы попробовать все различные перемещения, и установить переменные, чтобы вам не приходилось постоянно повторять длинные выражения.
def possible_moves(self):
pos_moves = []
boardlen = len(Config.board)
for xoff, yoff in [(1, 2), (-1, 2), (1, -2), (-1, -2), (2, 1), (-2, 1), (2, -1), (-2, -1)]:
newx = self.x xoff
newy = self.y yoff
if 0 <= newx < boardlen and 0 <= newy < boardlen and Config.board[newy][newx] == '___':
pos_moves.append(f'{Config.tile_convert(newx)}{Config.tile_convert(newy, True)}')
return pos_moves