code optimization for memory game - python

I made this memory card matching game for class and feel like I wrote more code than I had to. Is there any way to optimize this? The assignment was just to get a working program but I feel like I need to learn a little bit of optimization.
import random
class Card(object):
""" A card object with value but not suit"""
def __init__(self, value):
"""Creates a card with the given value and suit."""
self.value = value
self.face = 0
def showFace(self):
'''flips the card over'''
self.face = 1
def __str__(self):
"""Returns the string representation of a card."""
return str(self.value)
class Deck(object):
""" A deck containing cards."""
def __init__(self, rows, columns):
"""Creates a full deck of cards."""
self._cards = []
self._rows = rows
self._columns = columns
for value in range(1,(int((self._rows*self._columns)/2))+1):
c = Card(value)
self._cards.append(c)
self._cards.append(c)
def shuffle(self):
"""Shuffles the cards."""
random.shuffle(self._cards)
def deal(self):
"""Removes and returns the top card or None
if the deck is empty."""
if len(self) == 0:
return None
else:
return self._cards.pop(0)
def __len__(self):
"""Returns the number of cards left in the deck."""
return len(self._cards)
def __str__(self):
"""Returns the string representation of a deck."""
self.result = ''
for c in self._cards:
self.result = self.result + str(c) + '\n'
return self.result
class Game(Deck,Card):
'''Runs the memory game'''
def __init__(self, rows, columns):
'''gets rows and columns for the game'''
self._rows = rows
self._columns = columns
def play(self):
'''starts the game'''
self._deck = Deck(self._rows, self._columns)
self._deck.shuffle()
Game.populateBoard(self)
matches = 0
#While the game is not finished
while True:
while True: #The First Card
try:
coor1 = input("Enter coordinates for first card ")
coor1 = coor1.split(' ') # Removes spaces
coor1 = [x for x in coor1 if x != ' '] # puts in list
coor1 = [int(x)-1 for x in coor1 if x == x] # converts
except IndexError:
print('***Invalid coordinates! Try again.***')
except ValueError:
print('***Invalid coordinates! Try again.***')
else:
try: #Check if coordinates are valid
if 0 > coor1[0] or coor1[0] > self._rows\
or 0 > coor1[1] or coor1[1] > self._columns:
print('***Invalid coordinates! Try again.***')
else:
guess1 = self._gameboard[coor1[0]][coor1[1]]
break
except IndexError:
print('***Invalid coordinates! Try again.***')
while True: # The Second Card
try:
coor2 = input("Enter coordinates for second card ")
coor2 = coor2.split(' ') # Removes Spaces
coor2 = [x for x in coor2 if x != ' '] # puts in list
coor2 = [int(x)-1 for x in coor2 if x == x]# converts
except IndexError:
print('***Invalid coordinates! Try again.***')
except ValueError:
print('***Invalid coordinates! Try again.***')
else:
try: #Check if coordinates are valid
if 0 > coor2[0] or coor2[0] > self._rows\
or 0 > coor2[1] or coor2[1] > self._columns:
print('***Invalid coordinates! Try again.***')
else:
guess2 = self._gameboard[coor2[0]][coor2[1]]
break
except IndexError:
print('***Invalid coordinates! Try again.***')
if guess1 == guess2\
and coor2[0]-coor1[0] == 0\
and coor2[1]-coor1[1] == 0:#User enters same input for 1 and 2
print("***That's the same card! Try again.***")
elif guess1 == guess2:
guess1.showFace()
Game.showBoard(self)
matches += 1
if matches == ((self._rows * self._columns)/2):
break
else:
Game.showBoard(self)
print('Not an identical pair. Found',guess1,'at ('+
str(coor1[0]+1)+','+ str(coor1[1]+1)+') and', guess2,
'at ('+str(coor2[0]+1)+','+str(coor2[1]+1)+')')
def populateBoard(self):
'''populates the game board'''
self._gameboard = []
for row in range(self._rows):
self._gameboard.append([0] * self._columns)
for row in range(len(self._gameboard)):
for column in range(len(self._gameboard[row])):
self._gameboard[row][column] = self._deck.deal()
Game.showBoard(self)
def showBoard(self):
'''shows the board'''
for row in self._gameboard:
for card in row:
if card.face == 0:
print('*', end =" ")
else:
print(card, end= " ")
print()
def main():
while True:
# Force user to enter valid value for number of rows
while True:
rows = input("Enter number of rows ")
if rows.isdigit() and ( 1 <= int(rows) <= 9):
rows = int(rows)
break
else:
print (" ***Number of rows must be between 1 and 9! Try again.***")
# Adding *** and indenting error message makes it easier for the user to see
# Force user to enter valid value for number of columns
while True:
columns = input("Enter number of columns ")
if columns.isdigit() and ( 1 <= int(columns) <= 9):
columns = int(columns)
break
else:
print (" ***Number of columns must be between 1 and 9! Try again.***")
if rows * columns % 2 == 0:
break
else:
print (" ***The value of rows X columns must be even. Try again.***")
game = Game(rows, columns)
game.play()
if __name__ == "__main__":
main()

Here is a couple of places the code can be simplified
def populateBoard(self):
'''populates the game board'''
self._gameboard = [self._deck.deal() for row in self._rows
for column in self._columns]
self.showBoard()
and
def showBoard(self):
'''shows the board'''
for row in self._gameboard:
print(*(card if card.face else '*' for card in row))

coor1[0] is computed many times over. Consider assigning the result to a local variable and then using this local variable.

Related

Python memory matching game loop/logic issue

I am making a basic game of memory matching. The idea is that by user input a board can be created with cards. Those cards all have a match somewhere on the board. Basically the input is the dimensions of the board and then coordinates to identify possible matches. However everytime I enter input even if valid the code seems to defer to invalid input. However when I enter two identical coordinates the part of my code will execute for that case. I am not sure what is going on here.
import random
class Card():
"""Card object """
def __init__(self, val):
self.val = val
self.face = False
def isFaceUp(self):
"""check to see if the cards face up"""
return self.face
def getVal(self):
return self.val
def makeFaceUp(self):
self.face = True
def __str__(self):
return ", ".join(("Value: ", str(self.val), "Face: ", str(self.face)))
class Deck():
def __init__(self, pairs):
self._pairs = pairs
self._cards = []
for cards in range(self._pairs):
card1 = Card(cards + 1)
self._cards.append(card1)
card2 = Card(cards+1)
self._cards.append(card2)
def deal(self):
if len(self) ==0:
return None
else:
return self._cards.pop(0)
def shuffle(self):
random.shuffle(self._cards)
def __len__(self):
return len(self._cards)
class Game():
def __init__(self, rows, columns):
self._deck = Deck((rows*columns)//2)
self._rows = rows
self._columns = columns
self._board = []
for row in range(self._rows):
self._board.append([0] * self._columns)
self.populateBoard()
def populateBoard(self):
"""Puts all cards in the board random"""
self._deck.shuffle()
for columns in range(self._columns):
for rows in range(self._rows):
self._board[rows][columns] = self._deck.deal()
def revealBoard(self):
"""checks the values on the board making sure theres pairs"""
for rows in range(self._rows):
for columns in range(self._columns):
print(str(self._board[rows][columns].getVal()) + \
" ", end="")
print("")
def displayGame(self):
"""Displays the game in a 2d list"""
for rows in range(self._rows):
for columns in range(self._columns):
if self._board[rows][columns].isFaceUp() == False:
print("*", end = "")
else:
print(str(self._board[rows][columns].getVal() + \
" ", end = ""))
print("")
def play(self):
"""Allows the game to play setting the cards into a double list """
while not self.isGameOver():
self.displayGame()
c1 = input("Enter coordinates, (row, column) of card: ")
c2 = input("Enter the coordinates of match: ")
newC1 = list(map(int, c1.split()))
newCard1 = self._board[(newC1[0])-1][(newC1[1])-1] #Get value here???
newC2 = list(map(int, c2.split()))
newCard2 = self._board[(newC2[0])-1][(newC2[1])-1]
try:
if newCard1 != newCard2:
print("Not a pair", "Found: ",newCard1, "at", "(" + newC1, ", ", newC2, ")")
elif newC1 == newC2:
print("Identical Coordinate Entery")
elif newCard1.getVal() == newCard2.getVal():
self._board[newC1[0]-1][newC1[1]-1].makeFaceUp()
self._board[newC2[0]-1][newC2[1]-1].makeFaceUp()
print("pair found")
except:
print("invalid input")
print("Game Over")
self.displayGame
def isGameOver(self):
"""Test to determine if all the cards are facing up and revelied the game will be over"""
for rows in range(self._rows):
if not all(card.isFaceUp() for card in self._board[rows]):
return False
return True
def main():
while True:
# Force user to enter valid value for number of rows
while True:
rows = input("Enter number of rows ")
if rows.isdigit() and ( 1 <= int(rows) <= 9):
rows = int(rows)
break
else:
print (" ***Number of rows must be between 1 and 9! Try again.***")
# Adding *** and indenting error message makes it easier for the user to see
# Force user to enter valid value for number of columns
while True:
columns = input("Enter number of columns ")
if columns.isdigit() and ( 1 <= int(columns) <= 9):
columns = int(columns)
break
else:
print (" ***Number of columns must be between 1 and 9! Try again.***")
if rows * columns % 2 == 0:
break
else:
print (" ***The value of rows X columns must be even. Try again.***")
game = Game(rows, columns)
game.play()
if __name__ == "__main__":
main()
Any help is appreciated and if anyone would need to see other parts of my code simply ask I'd be happy to put them in there if it will help finding this error.
Edit: Went ahead and added the whole code for testing.
Okay, so from what I could deduce, the error is your very broad error handling in Game.play(). It checks for any error, but when you remove that statement, you could see that you were trying to add a list to a string. To fix that, add in:
newC1 = "(" + ", ".join (list (map (str, newC1))) + ")"
Do the same for newC2. This just changes the lists into strings that look like coordinates.

TicTacToe Python with board size selection

Desperately trying to create a code for a python TicTacToe game.
Im quite new to Python so am stuck with a feature that I want to add.
The idea is that the player can select whether he wants to play with 2, 3 players or against the computer.
He then selects whether he would like to be X or O (or Y for 3 players)
He then selects any boardsize up to 9x9.
So far so good, the two player, NbyN and X or O selection works and I have split the code into three seperate files (two classes) for ease.
I am lost with trying to figure out how to create the computer algorithm and to extend the game to 3 players.
Has anyone got any idea how I could do this?
Below is the code:
Player File:
class Player:
def __init__(self, player_name, shape):
self.player_name = player_name
self.shape = shape
def get_player_loc_input(self, rows, columns):
player_input = input('Enter in location for your move: ') # player input is with respect to field index location/values
converted_input = int(player_input)
if 1 <= converted_input <= (rows * columns): # bound checking
converted_input -= 1 # adjust from n+1 to n
transformed_value = (rows-(converted_input//columns)-1, converted_input%columns) # (row,col) tuple obj
return transformed_value
else:
raise ValueError('Input is not an index on the playing field. Try again\n')#
TicTac File:
class TicTac:
def __init__(self, rows, columns):
#self.playing_field = [ [7,8,9], [4,5,6], [1,2,3] ] #init the playing field to their respective nums on the numpad: 3x3
self.winner_found = False
self.is_full = False
self.possible_moves_left = columns * rows
self.rows = rows
def DefineBoard():
field = []
value = (rows * columns)
for row in range(rows):
field.append([])
for col in range(columns):
field[row].insert(0, value)
value = value - 1
return field
self.playing_field = DefineBoard()
#value = (rows * columns)
#def decrement(x): return (x-1)
#self.playing_field = [ [ decrement(value) for i in range(columns) ] for i in range(rows)]
def DrawBoard(self): #prints playing field based on size input
print('-------------')
for list in self.playing_field:
print('| ', end='')
for item in list:
print(str(item) + ' | ', end='')
print('\n-------------')
def Instructions(self):
print('\n-------------------------------------')
print('When entering in the location please enter the number of the index you want to replace with your shape.')
print('\nPrinting Initial Playing Field...')
self.DrawBoard()
print('\nLet the game begin!')
print('-------------------------------------')
def PlayerMove(self, index, shape):
row, col = index[0], index[1]
field_value = self.playing_field[row][col]
#if the value is of type int we can replace it
if isinstance(field_value, int):
self.playing_field[row][col] = shape #overwrite the value
self.possible_moves_left -= 1 #reduce the moves left
#check possible moves after its been updated
if self.possible_moves_left == 0:
self.is_full = True
raise EnvironmentError('All index posistions filled.\nGame Over. Nobody won.')
#else its the Player's shape (string)
else:
raise ValueError('Invalid Index. Position already filled. Try again.\n')
def ConsecutiveSymbols(self):
def check_list(passed_list):
#fast & quick check to tell if the "row" is incomplete
if isinstance(passed_list[0], str):
player_shape = passed_list[0] # set to first val
#compare the values to each other
for val in passed_list:
if isinstance(val, int) or player_shape != val:
return False #we found an inconsistency
return True #everything matched up
def Diagonal(orientation):
DiagonalList = []
counter = 0 if orientation is 'LtR' else self.rows-1
for row in self.playing_field:
DiagonalList.append(row[counter])
counter = counter+1 if orientation is 'LtR' else counter-1
return DiagonalList
# check rows for match
for row_list in self.playing_field:
if check_list(row_list):
return True
#check cols for match
transposed_playing_field = [list(a) for a in zip(*self.playing_field)] #convert our tuples from zip to a list format
for col_list in transposed_playing_field:
if check_list(col_list):
return True
#check diagonals for match
if check_list(Diagonal('LtR')): #LtR \ gets replaced each time we check
return True
if check_list(Diagonal('RtL')): # RtL / gets replaced each time we check
return True
return False #if we got here then no matches were found
Main File:
try:
from .TicTac import TicTac
from .Player import Player
except Exception:
from TicTac import TicTac
from Player import Player
winners=[]
def GameBegins():
Game=input("Would you like to play with 2, 3 players or against the CPU?").upper()
if Game=="2":
selection=input("Player 1: Would you like to play as X or O?").upper()
if selection == "X":
Players = {'Player_1': Player('Player_1', "X"), 'Player_2': Player('Player_2', "O")}
elif selection == "O":
Players = {'Player_1': Player('Player_1', "O"), 'Player_2': Player('Player_2', "X")}
else:
print("Please enter either X or O")
return False
if Game=="3":
selection=input("Player 1: Would you like to play as X, O or Y?").upper()
if selection == "X":
selection2=input("Player 2: Would you like to play as O or Y?").upper()
if selection2=="O":
Players = {'Player_1': Player('Player_1', "X"),"Player_2":Player("Player_2","O"),"Player_3":Player("Player_3","Y")}
elif selection2=="Y":
Players = {'Player_1': Player('Player_1', "X"),"Player_2":Player("Player_2","Y"),"Player_3":Player("Player_3","O")}
else:
print("Please enter either O or Y")
return False
elif selection == "O":
selection2=input("Player 2: Would you like to play as X or Y?").upper()
if selection2=="X":
Players = {'Player_1': Player('Player_1', "O"),"Player_2":Player("Player_2","X"),"Player_3":Player("Player_3","Y")}
elif selection2=="Y":
Players = {'Player_1': Player('Player_1', "O"),"Player_2":Player("Player_2","Y"),"Player_3":Player("Player_3","X")}
else:
print("Please enter either X or Y")
return False
elif selection=="Y":
selection2=input("Player 2: Would you like to play as X or O?").upper()
if selection2=="X":
Players = {'Player_1': Player('Player_1', "Y"),"Player_2":Player("Player_2","X"),"Player_3":Player("Player_3","O")}
elif selection2=="O":
Players = {'Player_1': Player('Player_1', "Y"),"Player_2":Player("Player_2","O"),"Player_3":Player("Player_3","X")}
else:
print("Please enter either X or O")
return False
if Game=="CPU":
CPU()
x=input("enter boardsize: ")
if x >="2":
rows, columns = int(x),int(x) #Players input becomes board size
else:
print("Please enter a boardsize of 3 or more")
GameBegins()
global game
game = TicTac(rows, columns)
game.Instructions()
player_id = 'Player_1' # index to swap between players, Player_1 starts
while (game.winner_found == False and game.is_full == False):
print('\nIt\'s ' + Players[player_id].player_name + ' Turn')
# loop until user inputs correct index value
while True:
try:
index = Players[player_id].get_player_loc_input(rows,columns)
shape = Players[player_id].shape
game.PlayerMove(index, shape)
except ValueError as msg:
print(msg)
continue
except EnvironmentError as msg:
print(msg)
break
game.winner_found = game.ConsecutiveSymbols() # check if a player has won
game.DrawBoard()
if game.winner_found:
print(Players[player_id].player_name + ' has won!') # print player who won
winners.append(str(Players[player_id].player_name))
player_id = 'Player_2' if player_id is 'Player_1' else 'Player_1' # switch between the 2 players
Replay() # Game has ended. Play Again?
def Replay():
PlayerDecision = input('\nDo you want to play again? (Y/N) ')
PlayerDecision = PlayerDecision.upper() #force to uppercase for consistency
if PlayerDecision == 'Y':
GameBegins()
elif PlayerDecision == 'N':
file=open("winners.txt","w")
for w in winners:
file.write(str(winners))
file.close()
exit(0)
else:
print('Incorrect input.')
Replay()
def main():
while True:
GameBegins()
if __name__ == '__main__':
main()
Would really appreciate some suggestions, thanks in advance!

Python input statement

I have created a battleship like game, and have it all completed except for one detail.
I have the following input statement:
x, y = input("Enter two numbers here: ").split()
with the 2 numbers being entered corresponding to the players chosen coordinates. I also need to be able to handle the entry of 'q' or 'h' for the quit or help options. However, since i am taking two variables from this statement when only a q or h is entered i get the error that the statement needs 2 elements to unpack, which makes sense. Any pointers on how to get around this?
import random, math
class oceanTreasure:
def __init__(self):
self.board = self.board()
self.found = 0
self.left = 3
self.sonarsLeft = 20
self.chests= []
self.chest()
def board(self):
board = []
for x in range(16): # the main list is a list of 60 lists
board.append([])
for y in range(61): # each list in the main list has 15 single-character strings.
board[x].append('~')
return board
def chest(self):
chest1 = [random.randint(0,60), random.randint(0,15)]
chest2 = [random.randint(0,60), random.randint(0,15)]
chest3 = [random.randint(0,60), random.randint(0,15)]
self.chests = [chest1, chest2, chest3]
def getChestsLeft(self):
return self.found
def getChests(self):
return self.chests
def getTreasuresLeft(self):
return self.left
def getSonarsLeft(self):
return self.sonarsLeft
def dropSonar(self,x,y):
ySonar = ['a','b','c','d','e','f','g']
whichAxis, axis = self.checkDistance(x,y)
if whichAxis == True:
sonar = axis
if whichAxis == 'xaxis':
sonar = axis
elif whichAxis == 'yaxis':
sonar = ySonar[axis-1]
elif whichAxis == None:
sonar = axis
self.board[int(y)][int(x)] = sonar
self.sonarsLeft -=1
return axis
def checkDistance(self,x,y):
closest = self.chests[0]
distance = 100
for chest in self.chests:
temp = math.sqrt(math.pow((chest[0]-int(x)),2) + math.pow((chest[1]-int(y)),2))
if temp < distance:
closest = chest
distance = temp
xaxis =math.fabs((closest[0] - int(x)))
yaxis = math.fabs((closest[1]-int(y)))
if yaxis == 0 and xaxis == 0:
self.chests.remove(closest)
self.found +=1
self.left -=1
return True, 'X'
elif xaxis <= 9 and yaxis <=5 :
if yaxis == 0 :
return 'xaxis',int(math.fabs(xaxis))
if xaxis == 0 :
return 'yaxis',int(math.fabs(yaxis))
if min(xaxis//2,yaxis) ==(xaxis//2) :
return 'xaxis', int(math.fabs(xaxis))
elif min(xaxis//2,yaxis) == (yaxis) or xaxis == 0 :
return 'yaxis', int(math.fabs(yaxis))
else: return None,0
def drawBoard(self):
firstLine = ' '
for i in range(1,7):
firstLine += (' '*9) + str(i)
print(firstLine)
secondLine = ' '
secondLine += ('0123456789' *6)
print(secondLine)
print()
i = 0
for i in range(0,16):
boardRow = ''
for x in range(0,61):
boardRow += str(self.board[i][x])
if i < 10:
print(str(i) +' ' + str(boardRow) + str(i))
if i >= 10:
print(str(i) +' ' + str(boardRow) + str(i))
print()
print(secondLine)
print(firstLine)
device = 'devices'
if self.sonarsLeft ==1:
device = 'device'
print('You have %s sonar %s availabe. You have found %s treasures and have %s left' %(self.sonarsLeft, device, self.found, self.left))
ocean = oceanTreasure()
ocean.drawBoard()
gameOver = False
instructionsList = ['This is a treasure hunting game.' , 'You begin the game with 20 sonar devices available (each device has a range of 9 units in the x axis and 5 in the y axis).','When you place a device, if an "O" is displayed that means there are no chests in range.', 'If a number from 1-9 is displayed, the closest chest is within n units away on the X axis.', 'If a letter from a-e is displayed, the closest chest is n units away on the Y axis (a =1, b =2 and so on...).', 'The game ends when you run out of sonar devices, all the treasure is found or you enter "q" to quit.', 'Thanks for playing and happy hunting!']
while ocean.getTreasuresLeft() != 0 and ocean.getSonarsLeft() >0 and gameOver == False:
response = False
coordinate = False
while response == False:
inputString = input("Enter two numbers seperated by a space (X Y): ")
if inputString == 'q':
gameOver = True
response = True
elif inputString == 'h':
for instruction in instructionsList:
print(instruction)
response = True
else:
try:
x,y = inputString.split()
assert int(x) <=60 and int(y) <=15
response = True
coordinate = True
except AssertionError:
print('Please enter a valid move')
if gameOver == True:
break
#whichAxis, axis =ocean.checkDistance(x,y)
#print(axis)
if coordinate == True:
axis = ocean.dropSonar(x,y)
ocean.drawBoard()
if axis == 'X':
print('Congratulations, you have found a treasure!')
if ocean.getTreasuresLeft() == 0:
print('Congratulations, you found all the treasure')
elif ocean.getSonarsLeft() == 0:
print('Sorry, you ran out of sonar devices, the remaining chests were: %s ' % str(ocean.getChests()))
How about separating the tests to be a little clearer:
input_string = input("Enter two numbers here: ")
if input_string == 'q':
do_quit()
elif input_string == 'h':
do_help()
else:
x,y = input_string.split()
That way you can test for your special cases, and process the x and y if they are not found.
may be this, for example:
a = input("text")
b = a.split()
if len(b) == 1:
if b[0] == 'q':
return
elif b[0] == 'h':
print 'it is help ... '
elif len(b) == 2:
# process for two inputted numbers
You can just separate the input:
# get the input
ipt = input("Enter two numbers here: ")
# check if your option is entered
if ipt == 'q' or ipt == 'h':
# do something
else:
x,y = ipt.split()

ValueError: too many values to unpack (expected 2), listcomp

Been trying to learn python and therefore using a pre-made minesweeper and the exercise was to make a class of some functions. But i seem to fet the error:
line 66, in <listcomp>
values = [grid[r][c] for r,c in self.getneighbors(grid, rowno, colno)]
ValueError: too many values to unpack (expected 2)
And i have no idea how to fix it, tried .items but i have no idea what to do. Hopefully i can get some help/tips. Thank you!
import string
import random
gridsize = int(input('SIZE:'))
numberofmines = int(input('MINES:'))
def setupgrid(gridsize,start,numberofmines):
grid = [['0' for i in range(gridsize)] for i in range(gridsize)]
mines = generatemines(grid,start,numberofmines)
p = omringande(grid)
p.getnumbers(grid)
return (grid,mines)
def showgrid(grid):
gridsize = len(grid)
horizontal = ' '+4*gridsize*'-'+'-'
# Print top column letters
toplabel = ' :) '
for i in string.ascii_lowercase[:gridsize]:
toplabel = toplabel+i+' '
print (toplabel,'\n',horizontal)
# Print left row numbers
for idx,i in enumerate(grid):
row = '{0:2} |'.format(idx+1)
for j in i:
row = row+' '+j+' |'
print (row+'\n'+horizontal)
print ('')
def getrandomcell(grid):
gridsize = len(grid)
a = random.randint(0,gridsize-1)
b = random.randint(0,gridsize-1)
return (a,b)
class omringande(object):
def __init__(self,grid):
self.grid = grid
def getneighbors(self,grid,rowno,colno):
gridsize = len(grid)
row = grid[rowno]
column = grid[rowno][colno]
neighbors = []
for i in range(-1,2):
for j in range(-1,2):
if i == 0 and j == 0: continue
elif -1<rowno+i<gridsize and -1<colno+j<gridsize:
neighbors.append((rowno+i,colno+j))
return (row,column)
def getnumbers(self,grid):
gridsize = len(grid)
for rowno,row in enumerate(grid):
for colno,col in enumerate(row):
if col!='X':
# Gets the values of the neighbors
values = [grid[r][c] for r,c in self.getneighbors(grid, rowno, colno)]
# Counts how many are mines
grid[rowno][colno] = str(values.count('X'))
# Generate mines
def generatemines(grid,start,numberofmines):
gridsize = len(grid)
mines = []
for i in range(numberofmines):
cell = getrandomcell(grid)
while cell==(start[0],start[1]) or cell in mines:
cell = getrandomcell(grid)
mines.append(cell)
for i,j in mines: grid[i][j] = 'X'
return mines
def showcells(grid,currgrid,rowno,colno):
# Exit function if the cell was already shown
if currgrid[rowno][colno]!=' ':
return
# Show current cell
currgrid[rowno][colno] = grid[rowno][colno]
# Get the neighbors if the cell is empty
if grid[rowno][colno] == '0':
for r,c in omringande.getneighbors(grid,rowno,colno):
# Repeat function for each neighbor that doesn't have a flag
if currgrid[r][c] != 'F':
showcells(grid,currgrid,r,c)
def playagain():
choice = input('Play again? (y/n): ')
return choice.lower() == 'y'
def playgame():
currgrid = [[' ' for i in range(gridsize)] for i in range(gridsize)]
showgrid(currgrid)
grid = []
flags = []
helpmessage = "Type the column followed by the row (eg. a5).\nTo put or remove a flag, add 'f' to the cell (eg. a5f)\n"
print (helpmessage)
while True:
while True:
lastcell = str(input('Enter the cell ({} mines left): '.format(numberofmines-len(flags))))
print ('\n\n')
flag = False
try:
if lastcell[2] == 'f': flag = True
except IndexError: pass
try:
if lastcell == 'help':
print (helpmessage)
else:
lastcell = (int(lastcell[1])-1,string.ascii_lowercase.index(lastcell[0]))
break
except (IndexError,ValueError):
showgrid(currgrid)
print ("Invalid cell.",helpmessage)
if len(grid)==0:
grid,mines = setupgrid(gridsize,lastcell,numberofmines)
rowno,colno = lastcell
if flag:
# Add a flag if the cell is empty
if currgrid[rowno][colno]==' ':
currgrid[rowno][colno] = 'F'
flags.append((rowno,colno))
# Remove the flag if there is one
elif currgrid[rowno][colno]=='F':
currgrid[rowno][colno] = ' '
flags.remove((rowno,colno))
else: print ('Cannot put a flag there')
else:
# If there is a flag there, show a message
if (rowno,colno) in flags:
print ('There is a flag there')
else:
if grid[rowno][colno] == 'X':
print ('Game Over\n')
showgrid(grid)
if playagain(): playgame()
else: exit()
else:
showcells(grid,currgrid,rowno,colno)
showgrid(currgrid)
if set(flags)==set(mines):
print ('You Win')
if playagain(): playgame()
else: exit()
playgame()
I keep getting the error when the player is supposed to make their move. Tried using (mentioned in other forums) the ".items" but without success.

Chess in Python: list indices must be integers, not str

I wrote early version of chess in python. I have a problem with this:
File "C:/Users/Goldsmitd/PycharmProjects/CHESS/chess_ver0.04.py", line 39, in move
self.board[destination_x][destination_y] = 1
TypeError: list indices must be integers, not str
my code:
class Chess_Board:
def __init__(self):
self.board = self.create_board()
def create_board(self):
board_x=[]
for x in range(8):
board_y =[]
for y in range(8):
if (x==7 and y==4):
board_y.append('K')
elif (x== 7 and y == 3):
board_y.append('Q')
else:
board_y.append('.')
board_x.append(board_y)
return board_x
class WHITE_KING(Chess_Board):
def __init__(self):
Chess_Board.__init__(self)
self.symbol = 'K'
self.position_x = 7
self.position_y = 4
def move (self):
print ('give x and y cordinates fo white king')
destination_x = input()
destination_y = input()
self.board[destination_x][destination_y] = 'K'
I don't know what does not work
The value recieved from input() has a 'string' type (even if it looks like number), so you should convert it to integer.
self.board[int(destination_x)][int(destination_y)] = 'K'
The code above will fail if you enter something else than digits, so it is better to add an additional check before:
def move (self):
destination_x = None
destination_y = None
while not (destination_x and destination_y):
print ('give x and y cordinates fo white king')
try:
destination_x = int(input())
destination_y = int(input())
except ValueError as e:
pass
self.board[destination_x][destination_y] = 'K'

Categories