简体   繁体   中英

How to make this with a for-loop?

Trying to make a batteship game and want to make the code more smooth...

#Board:
A = ["A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9"]
B = ["B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9"]
C = ["C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9"]
D = ["D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9"]
E = ["E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9"]
F = ["F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9"]
G = ["G0", "G1", "G2", "G3", "G4", "G5", "G6", "G7", "G8", "G9"]
H = ["H0", "H1", "H2", "H3", "H4", "H5", "H6", "H7", "H8", "H9"]
I = ["I0", "I1", "I2", "I3", "I4", "I5", "I6", "I7", "I8", "I9"]
J = ["J0", "J1", "J2", "J3", "J4", "J5", "J6", "J7", "J8", "J9"]
print("\n",A,"\n",B,"\n",C,"\n",D,"\n",E,"\n",F,"\n",G,"\n",H,"\n",I,"\n",J)

#Variables
A_set = set(A)
B_set = set(B)
C_set = set(C)
D_set = set(D)
E_set = set(E)
F_set = set(F)
G_set = set(G)
H_set = set(H)
I_set = set(I)
J_set = set(J)

When i check if the placed codinate are within the board I use this code:

def user_ship1():
    global nr1_user_ship
    nr1_user_ship = []
    print("Hide a ship within the board.")
    user_ship1 = input("")

    user_ship1 = user_ship1.capitalize()

    battlefield_check = set(user_ship1.split())

    within_battlefield0 = battlefield_check.intersection(A_set)
    within_battlefield1 = battlefield_check.intersection(B_set)
    within_battlefield2 = battlefield_check.intersection(C_set)
    within_battlefield3 = battlefield_check.intersection(D_set)
    within_battlefield4 = battlefield_check.intersection(E_set)
    within_battlefield5 = battlefield_check.intersection(F_set)
    within_battlefield6 = battlefield_check.intersection(G_set)
    within_battlefield7 = battlefield_check.intersection(H_set)
    within_battlefield8 = battlefield_check.intersection(I_set)
    within_battlefield9 = battlefield_check.intersection(J_set)

    if((within_battlefield0 == set()) and (within_battlefield1 == set()) and (within_battlefield2 == set()) and (within_battlefield3 == set()) and (within_battlefield4 == set()) and (within_battlefield5 == set()) and (within_battlefield6 == set()) and (within_battlefield7 == set()) and (within_battlefield8 == set()) and (within_battlefield9 == set())):
        print("Ship needs to be within the board.")
        exit()
    else:
        print("Great! Place another ship.")
    nr1_user_ship.append(user_ship1)

So how can I use this in a forloop instead and how do I change the code so I don't use the "global" variable

You can pack your sets in a list, and then take advantage of the built-in all function to minimize your if condition and avoid the 10 within_battlefieldx variables:

sets = [A_set, B_set, C_set, D_set, E_set, F_set, G_set, H_set, I_set, J_set]

if all(len(battlefield_check.intersection(s)) == 0 for s in sets):
    print("Ship needs to be within the board.")

You can actually avoid the 10 X_set variables as well by simply doing:

rows = [A, B, C, D, E, F, G, H, I, J]
sets = [set(row) for row in rows]

And you can then take one more step to eliminate the row variables by doing:

board = {'A': ["A0", "A1", "A2", ..., "A6", "A7", "A8", "A9"],
         'B': [...],
         ...}

And the above will change to:

sets = [set(row) for row in board.values()]

You can alternatively make the board a list of lists and use for row in board , but it seems you want to keep the rows indexed with letters so I used a dict instead.

In terms of refactoring the code and making it "more smooth", I would start by switching to a different data structure like a list or dictionary instead of opting for creating many variables with prefixes.

For the board for example, how about making the board a 2D array?

board = [ ["A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9"],
          ["B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9"],
          ["C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9"],
          ["D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9"],
          ["E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9"],
          ["F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9"],
          ["G0", "G1", "G2", "G3", "G4", "G5", "G6", "G7", "G8", "G9"],
          ["H0", "H1", "H2", "H3", "H4", "H5", "H6", "H7", "H8", "H9"],
          ["I0", "I1", "I2", "I3", "I4", "I5", "I6", "I7", "I8", "I9"],
          ["J0", "J1", "J2", "J3", "J4", "J5", "J6", "J7", "J8", "J9"] ]

print "\n".join(board)

As can be seen, each board item value is quite formulaic: "[row letter][column number 0 indexed]". So how about looping through each letter row and column and generating the board dynamically, like this?

board = [[None] * 10] * 10
for letterIdx, letter in enumerate(list("ABCDEFGHIJ")):
    for columnNum in range(10):
        board[letterIdx][columnNum] = letter + str(columnNum)

After refactoring this part, you can automatically generate the sets for each letter row like this for example:

boardSets = [None] * 10
for rowIdx, row in enumerate(board):
    boardSets[rowIdx] = set(row)

For the "within_battlefield" prefixed variables, you could put all of those in a list as well.

withinBattlefield = []
for rowSetIdx, rowSet in enumerate(boardSets):
    withinBattlefield[rowSetIdx] = battlefield_check.intersection(rowSet)

Now that everything is in a list, you could simply use a for loop and single conditional instead of the long if statement:

inBoard = true
for rowInBattlefield in withinBattlefield:
    if(rowInBattlefield == set()):
        inBoard = false

if(not inBoard):
    print("Ship needs to be within the board.")
    exit()
else:
    print("Great! Place another ship.")

This is just one example of how to refactor this code to be cleaner. Of course, this can be further refactored to be cleaner by adding variables for letters, board size, by putting some common functionality within functions, and so on.

I hope this answers your question and I wish you good luck on the battleship project!

Your code contains alot of boilerplate code, eg. code with repeated logic.

Imagine if you wanted to change the size of the board - that would take too much time with the code you are producing.

Replace your code with lists of lists like so:

board = [["A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9"],
         ["B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9"],
         ["C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9"],
         ["D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9"],
         ["E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9"],
         ["F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9"],
         ["G0", "G1", "G2", "G3", "G4", "G5", "G6", "G7", "G8", "G9"],
         ["H0", "H1", "H2", "H3", "H4", "H5", "H6", "H7", "H8", "H9"],
         ["I0", "I1", "I2", "I3", "I4", "I5", "I6", "I7", "I8", "I9"],
         ["J0", "J1", "J2", "J3", "J4", "J5", "J6", "J7", "J8", "J9"]]

print(board[0])
>>> ['A0', 'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9']
print(board[0][0])
>>> A0

This allows for more compact code:

print(any('B4' in sublist for sublist in board))
>>> True
print(any('BB' in sublist for sublist in board))
>>> False

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM