Выбор элементов в массиве с помощью 2 координат и заполнение его - PullRequest
1 голос
/ 25 октября 2019

Я создаю игрового бота для линкора для сервера Discord. Я еще не реализовал часть Discord, и я все еще делаю логику игры.

Это код:

import numpy as np
import re

waters = np.zeros((10,10),'U2')

headers = ['A','B','C','D','E','F','G','H','I','J']

#PRINTS THE BOARD
for i,header in enumerate(headers):
    if i == 0:
        print('    ',end='')
    print(header + '  ',end='')
    if i == len(headers)-1: print()

for x,line in enumerate(waters):
    print('%2d'%(x),end='')
    for pos in line:
        if pos == '':
            print(' ##',end='')
        else:
            print(' '+pos,end='')
    print()

board_x_coord = {
    "A":0,
    "B":1,
    "C":2,
    "D":3,
    "E":4,
    "F":5,
    "G":6,
    "H":7,
    "I":8,
    "J":9
}

ship_type = [
    ["CV","Carrier",5],
    ["BB","Battleship",4],
    ["CA","Cruiser",3],
    ["SS","Submarine",3],
    ["DD","Destroyer",2],
]

def board_coord_to_npcoord(ship,coord):
    result = re.findall(r'([a-zA-Z0-9])',coord)
    try:
        if result[0] in headers:
            if int(result[1]) in range(0,9):
                if result[2] in headers:
                    if int(result[3]) in range(0,9):
                        x_crd_a = board_x_coord.get(result[0])
                        y_crd_a = int(result[1])
                        x_crd_b = board_x_coord.get(result[2])
                        y_crd_b = int(result[3])
                        print('X: %s , Y: %s , X: %s , Y: %s' %(x_crd_a,y_crd_a,x_crd_b,y_crd_b))
                        return True
        print('Error. Try again.')   
    except ValueError:
        print('Error. Try again.')
        return False

for ship in ship_type:
    while True:
        print('Coordinates for %s (%s): ' %(ship[1],ship[2]),end='')
        if board_coord_to_npcoord(ship[0],input()): break

Доска выглядит так:

   A  B  C  D  E  F  G  H  I  J
 0 ## ## ## ## ## ## ## ## ## ##
 1 ## ## ## ## ## ## ## ## ## ##
 2 ## ## ## ## ## ## ## ## ## ##
 3 ## ## ## ## ## ## ## ## ## ##
 4 ## ## ## ## ## ## ## ## ## ##
 5 ## ## ## ## ## ## ## ## ## ##
 6 ## ## ## ## ## ## ## ## ## ##
 7 ## ## ## ## ## ## ## ## ## ##
 8 ## ## ## ## ## ## ## ## ## ##
 9 ## ## ## ## ## ## ## ## ## ##

Скрипт запросит координаты. Ex. Перевозчик: A0E0, Линкор: A2A5

   A  B  C  D  E  F  G  H  I  J
 0 CV CV CV CV CV ## ## ## ## ##
 1 ## ## ## ## ## ## ## ## ## ##
 2 BB ## ## ## ## ## ## ## ## ##
 3 BB ## ## ## ## ## ## ## ## ##
 4 BB ## ## ## ## ## ## ## ## ##
 5 BB ## ## ## ## ## ## ## ## ##
 6 ## ## ## ## ## ## ## ## ## ##
 7 ## ## ## ## ## ## ## ## ## ##
 8 ## ## ## ## ## ## ## ## ## ##
 9 ## ## ## ## ## ## ## ## ## ##

Как заполнить выбранные элементы соответствующим типом корабля, а также как обнаружить столкновение?

Ответы [ 2 ]

1 голос
/ 25 октября 2019

Я сделал первый случай и несколько небольших изменений:

  • улучшенное регулярное выражение
  • используйте '##' в качестве значения по умолчанию для ячейки платы
  • изменена печатная платав функцию
import numpy as np
import re

waters = np.full((10,10), '##','U2')
headers = ['A','B','C','D','E','F','G','H','I','J']

#PRINTS THE BOARD
def printBoard():
    for i,header in enumerate(headers):
        if i == 0:
            print('    ',end='')
        print(header + '  ',end='')
        if i == len(headers)-1: print()

    for x,line in enumerate(waters):
        print('%2d'%(x),end='')
        [print(' '+pos,end='') for pos in line]
        print()

printBoard()

board_x_coord = {
    "A":0,
    "B":1,
    "C":2,
    "D":3,
    "E":4,
    "F":5,
    "G":6,
    "H":7,
    "I":8,
    "J":9
}

ship_type = [
    ["CV","Carrier",5],
    ["BB","Battleship",4],
    ["CA","Cruiser",3],
    ["SS","Submarine",3],
    ["DD","Destroyer",2],
]

def board_coord_to_npcoord(ship,coord):
    try:
        result = re.findall(r'([A-J])(\d)([A-J])(\d)',coord)[0]
        x_crd_a = board_x_coord.get(result[0])
        y_crd_a = int(result[1])
        x_crd_b = board_x_coord.get(result[2])
        y_crd_b = int(result[3])
        vertical = ship[2] == abs(x_crd_b - x_crd_a + 1) and y_crd_a == y_crd_b
        horizontal = ship[2] == abs(y_crd_b - y_crd_a + 1) and x_crd_a == x_crd_b
        valid = vertical or horizontal
        if valid == False:
            print('Invalid length')
            return False
        if vertical:
            waters[y_crd_a][x_crd_a:x_crd_b + 1] = ship[0] 
            print(waters[y_crd_a][x_crd_a:x_crd_b])
            printBoard()
        print('X: %s , Y: %s , X: %s , Y: %s' %(x_crd_a,y_crd_a,x_crd_b,y_crd_b))
        return True
    except ValueError:
        print('Error. Try again.')
        return False

for ship in ship_type:
    while True:
        print('Coordinates for %s (%s): ' %(ship[1],ship[2]),end='')
        if board_coord_to_npcoord(ship,input()): break
0 голосов
/ 27 октября 2019

Я изменил входы. Теперь он принимает 1 координату (X, Y) и ориентацию (H, V). Если H, он будет заполняться слева направо, начиная с заданной координаты, а также то же самое для V, но на этот раз он снизу.

И также не имеет значения, если есть 'Re пробел во входе Ex. A 0 H он будет действителен до тех пор, пока шаблон соответствует.

import re
import numpy as np

class PlaceToBoardError(Exception):
    pass

waters = np.full((10, 10), 'WW','U2')
headers = ['A','B','C','D','E','F','G','H','I','J']

ship_type = [
    ["CV","Carrier",5],
    ["BB","Battleship",4],
    ["CA","Cruiser",3],
    ["SS","Submarine",3],
    ["DD","Destroyer",2],
]

board_x_coord = {
    "a":0,
    "b":1,
    "c":2,
    "d":3,
    "e":4,
    "f":5,
    "g":6,
    "h":7,
    "i":8,
    "j":9
}

def printBoard():
    for i,header in enumerate(headers):
        if i == 0:
            print('    ',end='')
        print(header + '  ',end='')
        if i == len(headers)-1: print()

    for x,line in enumerate(waters):
        print('%2d'%(x),end='')
        [print(' '+pos,end='') for pos in line]
        print()

def collision_detect(selected_waters):
    if any(water != 'WW' for water in selected_waters): 
            return True
    return False

def place_to_board(ship,coord):
    try:
        pattern = r'(?i)\s*([a-j])\s*(\d)\s*([hv])'
        result = re.match(pattern,coord)
        if result == None: 
            raise PlaceToBoardError('Invalid coordinates. Please try again.')
        x_coord = board_x_coord.get(result[0][0].lower())
        y_coord = int(result[0][1])
        orientation = result[0][2].lower()

        if orientation == 'h':
            selected_waters = waters[y_coord,x_coord:ship[2]+x_coord]
            if collision_detect(selected_waters): 
                raise PlaceToBoardError('A ship is already placed in those waters. Please try again.')
            if len(selected_waters) == ship[2]:
                waters[y_coord,x_coord:ship[2]+x_coord] = ship[0]
            else:
                raise PlaceToBoardError('Not enough space. Please try again.')
        elif orientation == 'v':
            selected_waters = waters[y_coord:ship[2]+y_coord:,x_coord]
            if collision_detect(selected_waters): 
                raise PlaceToBoardError('A ship is already placed in those waters. Please try again.')
            if len(selected_waters) == ship[2]:
                waters[y_coord:ship[2]+y_coord:,x_coord] = ship[0]
            else:
                raise PlaceToBoardError('Not enough space. Please try again.')
        return True
    except PlaceToBoardError as ptbe:
        print(ptbe)
        return False
printBoard()
for ship in ship_type:
    while True:
        print('Coordinates for %s (%s): ' %(ship[1],ship[2]),end='')
        if place_to_board(ship,input()): 
            printBoard()
            break
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...