Use iterating variable to check value of dict key? - python

here is my code
tiles = [" a ", " b ", " c ", " d ", " e ", " f ", " g ", " h ", " i "]
check = {'0': False, '1': False, '2': False, '3': False, '4': False, '5': False,
'6': False, '7': False, '8': False}
tile = input("Player 1: What tile?")
for index, z in enumerate(tiles):
if int(tile) == index and ********:
tiles[index] = str("xxxxx")
What I want to be able to do, is on line 8, check if tile is the same as index, and also check the value of the key(this part is the ********)
Basically I want to use the iterating variable index to request and check the value of the key that is the same as index. This might look like
if int(tile) == index and check[?index?] == False:
Please help and I am more than wiling to explain further as I am not very good at explaining these kind of things.

Try:
if int(tile) == index and not check[str(index)]:
There are chances that tile is already an integer (if you entered one). Keys of check are strings.

Related

Validate a record in a dict list, if found, update, if not, insert (Python)

I have a minor problem because of my understanding of how this works. I have a function to play the dice game, then send the results in a list to another function where valid the dice results, the list takes the name of the player and the values ​​of the dice, it looks like this:
['John', 1, 2, 3, 3, 3]
Then I'm trying to save the record in a dict, to later save it in a new list, where all the information of the players will be, it will look like this:
[
{
'Name': 'luis',
'Dice': (1, 2, 3, 3, 3),
'Bet': 500
}, {
'Name': 'andrew',
'Dice': (2, 2, 2, 1, 2),
'Bet': 500
}
]
But I don't know how to do the following:
If the list is empty, without player dictionaries, save the first one based on a previous validation.
Whose validation is that it checks if the "key" Name already has the "value" of the player's name, if so, it does not insert a new one, like the first point, but it updates the value of the "key" dice to the new values ​​of the dice you receive.
Here is my full code:
import os
import random as r
from colorama import *
os.system('cls')
player_data = []
def validate_values(list_values):
dice_player_values = list_values[1], list_values[2], list_values[3], list_values[4], list_values[5]
player = {
"Name": list_values[0],
"Dice": dice_player_values,
"Bet": 500
}
if(1 not in list_values):
print(Fore.RED + Style.BRIGHT + list_values[0] + ", next, don't have enough look." + Style.RESET_ALL)
os.system('pause')
play_dice()
else:
# player_data.append(player)
# next((item for item in player_data if item["name"] == list_values[0]), None)
for dato in player_data:
if(dato["Name"] != list_values[0]):
player_data.append(player)
continue
else:
dato["Name"]["Dice"] = dice_player_values
contar_unos = list_values.count(1)
print("It find's: ", str(contar_unos) , ", one.")
print(player_data)
os.system('pause')
play_dice()
def play_dice():
os.system('cls')
dice_values = []
dice_values.clear()
print(Fore.GREEN + "What's your name? : " + Style.RESET_ALL)
player_name = input().lower()
dice_values.append(player_name)
dice_one = r.randint(1,3)
dice_values.append(dice_one)
dice_two = r.randint(1,3)
dice_values.append(dice_two)
dice_three = r.randint(1,3)
dice_values.append(dice_three)
dice_four = r.randint(1,6)
dice_values.append(dice_four)
dice_five = r.randint(1,6)
dice_values.append(dice_five)
print(dice_values)
os.system('pause')
validate_values(dice_values)
return dice_values
dice = play_dice()
I think your error is where you are checking if there's already a player with a certain name in the list:
for dato in player_data:
if(dato["Name"] != list_values[0]):
player_data.append(player)
continue
This is only checking if the current item in the list has a person with that specific name. You need to check them all at once before you do anything. So you could do something like this:
newPlayer = false
for dato in player_data:
if dato['Name'] == list_values[0]:
dato['Dice'] = dice_player_values
newPlayer = true
break
if newPlayer == true:
player_data.append(player)

Python: I have a list of dictionaries but when I try to call a specific Key and Value it is throwing a error

def readParksFile(fileName="national_parks(1).csv"):
nationalParks = open(fileName)
headers = nationalParks.readline()
keys = headers.split(",")
numKeys = len(keys)
parksList = []
values = nationalParks.readlines()
rowsList = []
parksDictionary = {}
for row in values:
rowsList.append(row.split(","))
for item in rowsList:
parksDictionary = {}
for i in range(numKeys):
parksDictionary[keys[i]] = item[i]
parksList.append(parksDictionary)
for i in range(len(parksList)):
return(parksList[i])
nationalParks.close()
I created a list of dictionaries using the code above
def printParksInState(parksList):
state = getStateAbbr()
for parksDictionary in parksList:
if state in parksDictionary["State"]:
print(parksDictionary["Name"] + " (" + parksDictionary["Code"] + ")")
print("\t" + "Location:" + parksDictionary["State"])
print("\t" + "Area:" + parksDictionary["Acres"] + " acres")
print("\t" + "Date Established:" + tasks.convertDate(parksDictionary["Date"]))
else:
print("There are no national parks in " + state + " or it is not a valid state")
I have functions that uses the list of dictionaries to print information
def main():
print("National Parks")
parksList = tasks.readParksFile()
menuDict = interface.getMenuDict()
choice = ("")
while choice != "Q":
print(interface.displayMenu(menuDict))
choice = interface.getUserChoice(menuDict)
if choice == "A":
interface.printAllParks(parksList)
elif choice == "B":
interface.printParksInState(parksList)
elif choice == "C":
interface.printLargestPark(parksList)
elif choice == "D":
interface.printParksForSearch(parksList)
else:
print("This is not an option")
In my main function I call the other functions that uses the list of dictionaries
Error
However no matter what function I call it throws the error that string indices must be integers and I am not sure what this error is or how to fix it. Please help!
The error is telling you that parksDictionary isn't a dict, it's a str.
The bug is in readParksFile, which is only returning a single item:
for i in range(len(parksList)):
return(parksList[i])
It should instead just do:
nationalParks.close()
return parksList
As soon as you return, the function is done, so you can only return one thing, and you should close() the file before then.

How to select the nearby key in python dictionary?

Please consider the below Python code:
def allot():
dict2 = {'1': 1, '2': 1, '3': 0, '4': , '5': 1}
allotted_id = None
for k in dict2:
usr_id = 3
if (str(usr_id) != k):
continue;
if ((str(usr_id) == k) and (dict2[str(usr_id)] == 1)):
print("\n user Requested Id : ", usr_id)
print("\n user Requested Id is available ! ")
allotted_id = k
break;
else:
print("\n user Requested Id : ", usr_id)
print("\n user Requested Id is not available ! ")
usr_id = usr_id + 1
if (dict2[str(usr_id)] == 1):
allotted_id = usr_id
break;
print('So allotted dict2 Id', allotted_id)
allot()
In the "dict2", if values == 1 then it is active or if values == 0 then it is inactive. Here, match the usr_id with key id in dict2.
Case 1: dict2 = {'1': 1, '2': 1, '3': 1, '4': 1, '5': 1}. Now usr_id==3 and dict2 key '3'==1. so allotted id=3.
Case 2: dict2 = {'1': 1, '2': 1, '3': 0, '4': 1, '5': 1}. Now usr_id==3 and dict2 key '3'==0 . Then next active id is allotted.So allotted id=4.
Case 3: dict2 = {'1': 1, '2': 1, '3': 0, '4': 0, '5': 1}. Now usr_id==3 and dict2 key '3' & '4'==0 . So the next nearest active id to the usr_id want allocate (is nothing but key id '2').How to do it?
Guide me for my case 3 scenario. Thanks in advance.
Assuming you want no efficiency changes to the code, you're overwriting the usr_id in the for k in dict2 loop.
def allot():
dict2 = {'1': 1, '2': 1, '3': 0, '4': , '5': 1}
allotted_id = None
usr_id = 3 # Move this out of the loop
for k in dict2:
if (str(usr_id) != k):
continue;
if ((str(usr_id) == k) and (dict2[str(usr_id)] == 1)):
print("\n user Requested Id : ", usr_id)
print("\n user Requested Id is available ! ")
allotted_id = k
break;
else:
print("\n user Requested Id : ", usr_id)
print("\n user Requested Id is not available ! ")
usr_id = usr_id + 1
if (dict2[str(usr_id)] == 1):
allotted_id = usr_id
break;
print('So allotted dict2 Id', allotted_id)
allot()
You can write this code to do more checks and utilise the dictionary structure a bit more...
def allot():
# Variables to Enter
dict2 = {1: 1, 2: 1, 3: 0, 4: 0, 5: 1}
usr_id = 3
# Boolean Variables
allotted_id = None
upper_exhausted = False
lower_exhausted = False
# Need to calculate the min and max to know when to stop searching
max_id = max(dict2.keys())
min_id = min(dict2.keys())
# Check the initial ID
if dict2[usr_id] == 0:
print("ID {} inactive. Continuing search.".format(usr_id))
else:
allotted_id = usr_id
# Run two searches - one increasing through the dictionary
# and one decreasing through the dictionary
upper_usr_id = usr_id + 1
lower_usr_id = usr_id - 1
# Run loop whilst the max and min dict key haven't been reached
# AND there's no allotted ID.
while not allotted_id:
if not upper_exhausted:
if dict2[upper_usr_id] == 0:
print("ID {} inactive. Continuing search.".format(upper_usr_id))
if upper_usr_id < max_id:
upper_usr_id += 1
else:
upper_exhausted = True # Maximum has been reached
else:
allotted_id = upper_usr_id
if not lower_exhausted:
if dict2[lower_usr_id] == 0:
print("ID {} inactive. Continuing search.".format(lower_usr_id))
if lower_usr_id > min_id:
lower_usr_id -= 1
else:
lower_exhausted = True # Minimum has been reached
else:
allotted_id = lower_usr_id
# Exhausted all values - No Data value
if upper_exhausted and lower_exhausted:
allotted_id = -999
if allotted_id == -999:
print("Couldn't allot an ID")
else:
print("Allotted ID is: {}".format(allotted_id))
allot()
I would use numpy:
user_ids = np.array(range(5))
valid_user = np.array([1, 1, 0, 0, 1])
anchor_id = 2
dist_from_anchor = np.abs(user_ids - anchor_id)
dist_from_anchor[valid_user == 0] = len(user_ids) +1 #will not be the min
print(np.argmin(dist_from_anchor))
I used the minimum user_id as 0 (just a cs thing...) but you can easily change it to be 1...
I suggest a different approach (Dont know how flexible you are with your approach)-
Store your data like this
dict2 = {"1": {1, 2, 5}, "0": {3, 4}} # 1 for available Ids and 0 for allocated
Now for any incoming user id
if usr_id in dict2["1"]:
allotted_id = usr_id
elif usr_id in dict2["0"]:
# either return the first available Or
# traverse and return the next higher user id available
else:
# exception

Easier way to check for four in row/column/diagonal in connect four game?

I am making a connect four game with X's and O's. The code for checking for four in a row/column/diagonal works but I have a lot of if statements in my code. The game fully works right now but I'm wondering if there is an easier solution to the checking. Below, I have included all my code for context.
I have tried using coordinates. It seems kind of inefficient though. The function for checking is called check.
namex = input("Player X, enter your name. ") #asks for player 1 name
nameo = input("Player O, enter your name. ") #asks for player 2 name
game = [[".", ".", ".", ".", ".", "."], #gameboard
[".", ".", ".", ".", ".", "."],
[".", ".", ".", ".", ".", "."],
[".", ".", ".", ".", ".", "."],
[".", ".", ".", ".", ".", "."],
[".", ".", ".", ".", ".", "."],
[".", ".", ".", ".", ".", "."]]
loop = True
def output(matrix):
str1 = ""
str2 = ""
str3 = ""
str4 = ""
str5 = ""
str6 = ""
print("0 1 2 3 4 5 6 ") #print labels for columns in gameboard
for a in matrix:
row = 0
for b in a: #"a" is a column and "b" is a ./x/o
row += 1
if row == 1:
str1 += b
str1 += " "
if row == 2:
str2 += b
str2 += " "
if row == 3:
str3 += b
str3 += " "
if row == 4:
str4 += b
str4 += " "
if row == 5:
str5 += b
str5 += " "
if row == 6:
str6 += b
str6 += " "
print(str1) #print string for row 1
print(str2) #print string for row 2
print(str3) #print string for row 3
print(str4) #print string for row 4
print(str5) #print string for row 5
print(str6) #print string for row 6
def check(matrix): #function to check for four in row/column/diagonal to win
positionx = []
positiono = []
x = 0
for a in matrix:
y = 5
for b in a:
if b == "X":
positionx.append([x, y])
if b == "O":
positiono.append([x, y])
y -= 1
x += 1
for c1 in positionx:
'''check four in row/column/diagonal for x'''
for c2 in positionx:
for c3 in positionx:
for c4 in positionx:
if c4[0]-c3[0] == 1:#check for four in row
if c3[0]-c2[0] == 1:
if c2[0]-c1[0] == 1:
return "xwin"
if c4[1]-c3[1] == 1: #check for four in column
if c3[1]-c2[1] == 1:
if c2[1]-c1[1] == 1:
return "xwin"
if c4[0]-c3[0] == 1: #check four in diagonal
if c4[1]-c3[1] == 1:
if c3[0]-c2[0] == 1:
if c3[1]-c2[1] == 1:
if c2[0]-c1[0] == 1:
if c2[1]-c1[1] == 1:
return "xwin"
for d1 in positiono:
'''check four in row/column/diagonal for o'''
for d2 in positiono:
for d3 in positiono:
for d4 in positiono:
if d4[0]-d3[0] == 1: #check for four in row
if d3[0]-d2[0] == 1:
if d2[0]-d1[0] == 1:
return "owin"
if d4[1]-d3[1] == 1: #check for four in column
if d3[1]-d2[1] == 1:
if d2[1]-d1[1] == 1:
return "owin"
if d4[0]-d3[0] == 1: #check four in diagonal
if d4[1]-d3[1] == 1:
if d3[0]-d2[0] == 1:
if d3[1]-d2[1] == 1:
if d2[0]-d1[0] == 1:
if d2[1]-d1[1] == 1:
return "owin"
while loop == True:
xinput = input(namex + ", you're X. What column do you want to play in? Please enter a number 0-6 ")
xcolumn = int(xinput)
xrow = 5
occupied1 = False
while occupied1 == False:
if game[xcolumn][xrow] == ".": #if there is a "." change to "X"
game[xcolumn][xrow] = "X"
output(game)
occupied1 = True
xrow -= 1
if check(game) == "xwin":
loop = False
print(namex + " wins!")
break
if check(game) == "owin":
loop = False
print(nameo + " wins!")
break
oinput = input(nameo + ", you're O. What column do you want to play in? Please enter number 0-6 ")
ocolumn = int(oinput)
orow = 5
occupied2 = False
while occupied2 == False:
if game[ocolumn][orow] == ".": #if there is a "." change to "O"
game[ocolumn][orow] = "O"
output(game)
occupied2 = True
orow -= 1
if check(game) == "xwin":
loop = False
print(namex + " wins!")
break
if check(game) == "owin":
loop = False
print(nameo + " wins!")
break
I'm also open to any other suggestions to make my code for this game better. Thanks!
I had some spare time, so I rewrote your program. It's much more efficient now. Read the comments to understand how it works
cols = [[] for x in range(6)]
# I opted to have a matrix of COLUMNS rather than rows because you can easily
# append items to the end of the list to simulate a real tile being placed there
# it's more intuitive and saves us time, as you'll see
def checkWin(cols):
for i in range(6): # Each column
for j in range(6): # Each row
try: #check if the element at these coordinates exists yet
cols[i][j]
except IndexError:
break
# go back to next i - impossible that there's anything with a higher
# j because if a list is n items long, and we go to j (which is one
# higher than n and doesn't exist) then there can't be an element at
# index j + someNumber.
ret = False
try: #vertical: j is the index in each column, so this goes up the column
if cols[i][j] == cols[i][j+1] == cols[i][j+2] == cols[i][j+3] is not None:
ret = True
except IndexError: #one of the elements of the comparison doesn't exist
pass #We can't be sure that none of the other trials will return True
try: #horizontal
if cols[i][j] == cols[i+1][j] == cols[i+2][j] == cols[i+3][j] is not None:
ret = True
except IndexError:
pass
try: #diagonal
if cols[i][j] == cols[i+1][j+1] == cols[i+2][j+2] == cols[i+3][j+3] is not None:
ret = True
except IndexError:
pass
try: #other diagonal
if cols[i][j] == cols[i-1][j+1] == cols[i-2][j+2] == cols[i-3][j+3] is not None:
ret = True
except IndexError:
pass
if ret:
return cols[i][j]
return None # We've gone through every single possible element and there are NO matches
def printBoard(cols):
# Pretty intuitive function IMO - we swap i and j to go through rows.
returnstr = '\n1 2 3 4 5 6\n'
for i in range(6):
for j in range(6):
try:
cols[j][5-i]
except IndexError:
returnstr += '_ '
continue
returnstr += cols[j][5-i]+' '
returnstr += '\n'
print(returnstr)
playerX = input('Player X, input your name: ')
playerO = input('Player O, input your name: ')
if playerX == playerO:
print("Cannot have the same name!")
exit()
count = 0
while not checkWin(cols):
printBoard(cols)
i = input('{}, input your column (1-6): '.format(playerO if count else playerX))
try:
target = cols[int(i)-1]
if len(target) == 6:
print("Column {} is already full! Please pick another.".format(i))
continue
target.append('O' if count else 'X')
except ValueError:
print("'{}' is not a number! Try again.".format(i))
continue
except IndexError:
print("{} is not a valid column number! Please pick another.".format(i))
continue
count = (count+1) % 2
printBoard(cols)
if checkWin(cols) == 'X':
print('{} (Player X), you win!'.format(playerX))
else:
print('{} (Player O), you win!'.format(playerO))
A good start would be to write a generalized function that checks for a diagonal at an arbitrary location:
def diagonal(grid, x, y, piece):
'''
Return True if grid contains a four-in-a-row diagonal starting at coordinates
(x, y) and traveling downwards and to the right. Otherwise return False.
'''
for i in range(x, x+4):
# if this square does not contain the desired piece, return False
if grid[x+i][y+i] != piece
return False
# if we got all the way through the loop, this must be a diagonal
return True
Then you would call this function for every possible starting coordinate of a four square diagonal, for each player X and O.
To improve this function, you could add a way to check for diagonals that travel the other direction (up and to the right).

How to implement a for loop

I have my for loop set up, but im missing one condition and just don't know where to put it! Let's say the user already picked "a1" and picks it again. I don't want that value to be used but instead tell him it's already been picked and let him pick again. I tried making it but the way I had it, it told him that he already picked it, but didn't let him go again.
def inputCoordinate():
coordinate = False
while not coordinate :
user = (input("Enter your move: "))
if user in List:
if user == "a1":
value = "O"
gameboard[0] = value
playedmoves.append("a1")
elif user == "a2":
value = "O"
gameboard[3] = value
playedmoves.append("a2")
elif user == "a3":
value = "O"
gameboard [6] = value
playedmoves.append("a3")
elif user == "b1":
value = "O"
gameboard[1] = value
playedmoves.append("b1")
elif user =="b2":
value = "O"
gameboard[4] = value
playedmoves.append("b2")
elif user == "b3":
value = "O"
gameboard[7] = value
playedmoves.append("b3")
elif user =="c1":
value = "O"
gameboard[2]=value
playedmoves.append("c1")
elif user == "c2":
value = "O"
gameboard[5] = value
playedmoves.append("c2")
elif user == ("c3"):
value = "O"
gameboard[8] = value
playedmoves.append("c3")
else:
print("invalid Coordinates")
continue
return value
playedmoves =("a1","b2")
List = ("a1", "a2", "a3", "b1", "b2", "b3", "c1", "c2", "c3")
So you want to force the user to repeatedly enter a move until they enter a valid one. That means that you need to wrap the input statement in a loop, something like this:
while some_condition_is_not_met:
user = input("Enter your move: ")
if not valid_move(user):
print "bad move, please re-enter"
You could make the while loop depend on a variable that gets set when the user enters a valid move:
good_move = False
while not good_move:
user = input("Enter your move: ")
if valid_move(user):
good_move = True
else:
print "bad move, please re-enter"
Just test against playedmoves right where you are testing if the move is valid:
if user in List and user not in playedmoves:
You really want to use a mapping here to translate position to index:
pos_to_index = {"a1": 0, "a2": 3, "a3": 6, "b1": 1, "b2": 4, "b3": 7, "c1": 2, "c2": 5, "c3": 8}
def inputCoordinate():
while True:
user = (input("Enter your move: "))
index = pos_to_index.get(user)
if index is not None and gameboard[index] not in ('O', 'X'):
gameboard[index] = 'O'
else:
print("invalid Coordinates")
continue
return 'O'
Here we use the gameboard to see if a move is still available; if there is a naught or cross there already, the move is obviously not a valid one. The pos_to_index mapping gets rid of the 9 if statements in one go.
Isn't using a Dictionary in this case waaaay simplier?
playedmoves = []
moves = {"a1":0, "a2":3, "a3":6, "b1":2, "b2":4, "b3":7, "c1":2, "c2":5, "c3":8}
if user in moves and not in playedmoves:
gameboard[moves[user]] = "0"
playedmoves.append(user)
else:
print("Invalid coordinates.")
Suggest to rewrite like this:
mapping = {"a1": 0, "a2": 3, ... }
List = mapping.keys()
playedmoves =("a1","b2")
def inputCoordinate():
coordinate = False
while not coordinate :
user = (input("Enter your move: "))
value = "0" # <---
if user in List:
gameboard[mapping[user]] = value
playedmoves.append(user)
else:
print("invalid Coordinates")
continue
return value

Categories

Resources