Index Out Of Range When Artificially Limited - python

when I run this program, sometimes I receive an error.This error however is not possible as I am using an 8x8 grid and I limit the inputs so that they can only be numbers from 0-7, to obey the fact that list indexes start at 0.
The user must input coordinates (1-8),(A-H) and the program will check to see if those coordinates are correct, by systematically going through the CompShips list and repeatedly comparing those coordinates to ones given by the user. If the cords match, then a message will appear and a "Z" will change to an "X" on those coordinates, indicating a HIT. If the guess does not match, a "Z" will change to an "M" on those coordinates indicating a MISS.
CompShips=[[1,0],[1,1],[2,2],[2,3],[2,4],[3,0],[3,1],[3,2],[5,4],[5,5],[5,6],[5,7],[1,7],[2,7],[3,7],[4,7],[5,7]]
FRow1=["Z","Z","Z","Z","Z","Z","Z","Z",]
FRow2=["Z","Z","Z","Z","Z","Z","Z","Z",]
FRow3=["Z","Z","Z","Z","Z","Z","Z","Z",]
FRow4=["Z","Z","Z","Z","Z","Z","Z","Z",]
FRow5=["Z","Z","Z","Z","Z","Z","Z","Z",]
FRow6=["Z","Z","Z","Z","Z","Z","Z","Z",]
FRow7=["Z","Z","Z","Z","Z","Z","Z","Z",]
FRow8=["Z","Z","Z","Z","Z","Z","Z","Z",]
def PrintFireBoard():
print(Index)
print(FRow1)
print(FRow2)
print(FRow3)
print(FRow4)
print(FRow5)
print(FRow6)
print(FRow7)
print(FRow8)
FireBoard=[FRow1,FRow2,FRow3,FRow4,FRow5,FRow6,FRow7,FRow8]
while len(CompShips) !=0 or CompSuccess==17:
FireRow=input("Please Choose The Row That You Wish To Fire Upon (1-8) ")
FireIndex=input("Please Choose The Column That You Wish To Fire Upon (A-H) ")
#As Lists start at 0
FireRow=int(FireRow)-1
if FireIndex==("A"):
FireIndex=0
elif FireIndex==("B"):
FireIndex=1
elif FireIndex==("C"):
FireIndex=2
elif FireIndex==("D"):
FireIndex=3
elif FireIndex==("E"):
FireIndex=4
elif FireIndex==("F"):
FireIndex=5
elif FireIndex==("G"):
FireIndex=6
elif FireIndex==("H"):
FireIndex=7
Guess=[FireRow,FireIndex]
#Check To See If Correct
UserSuccess=0
for i in CompShips:
if Guess==i:
CompShips.remove(Guess)
UserSuccess=1
else:
pass
if UserSuccess==1:
print("HIT")
print(FireRow)
print(FireIndex)
FireBoard[[FireRow][FireIndex]]=("H")
PrintFireBoard()
else:
print("MISS")
print(FireRow)
print(FireIndex)
FireBoard[[FireRow][FireIndex]]=("M")
PrintFireBoard()
I receive the error:
IndexError: string index out of range

Looks like these two lines
FireBoard[[FireRow][FireIndex]]=("H")
FireBoard[[FireRow][FireIndex]]=("M")
should be
FireBoard[FireRow][FireIndex]="H"
FireBoard[FireRow][FireIndex]="M"
Explanation: In your old code, FireBoard[[FireRow][FireIndex]]=("H")
[FireRow][FireIndex] means, given a list [FireRow] (which contains just one element), get the FireIndex-th element. This is not what you're trying to do.
For example [3][0] returns 3, and [3][1] gives IndexError.
Take a look at How to define a two-dimensional array in Python
Also note that ("H") is the same as the string "H". There is no need to add parentheses.

Here is a much cleaner code!
CompShips=[[1,0],[1,1],[2,2],[2,3],
[2,4],[3,0],[3,1],[3,2],
[5,4],[5,5],[5,6],[5,7],
[1,7],[2,7],[3,7],[4,7],
[5,7]]
FRow=[["Z"]*8]*8 #1 More Pythonic
def PrintFireBoard():
#print(Index)
for i in range(0,8):
print(FRow[i])
FireBoard=FRow[:] #NOTE THIS ONE!!!
mydict = {}
for i,key in enumerate(["A","B","C","D","E","F","G","H"]): #2 More Pythonic
mydict[key] = i
while len(CompShips) !=0 or CompSuccess==17:
FireRow=input("Please Choose The Row That You Wish To Fire Upon (1-8) ")
FireIndex=input("Please Choose The Column That You Wish To Fire Upon (A-H) ")
FireRow=int(FireRow)-1
FireIndex = mydict[FireIndex]
Guess=[FireRow,FireIndex]
print(Guess)
UserSuccess=0
for i in CompShips:
if Guess==i:
CompShips.remove(Guess)
UserSuccess=1
else:
pass
if UserSuccess==1:
print("HIT")
print(FireRow,FireIndex)
FireBoard[FireRow][FireIndex]="H" #3 your problem here
PrintFireBoard()
else:
print("MISS")
print(FireRow,FireIndex)
FireBoard[FireRow][FireIndex]="M"
PrintFireBoard()
1) As explained in the comments that's just a more nicer way to create a list of lists!. Remember DRY principle! Do Not Repeat yourself!
2) Instead of having all that if else to convert the 'A' to 0. You can use a dictionary lookup instead!
3) Your problem seems to be here! correct this to FireBoard[FireRow][FireIndex]="H"
PS: NOTE THIS ONE!!!: I'm not just making FireBoard as an alias to FRow! I'm copying it into a FireBoard as a new list! There's a subtle difference read about it here. I'm doing this incase you don't want your original FRow list to be modified!

The indentation in your question was off. I think that all the code from
Guess=[FireRow,FireIndex]
until the end should be preceded by 4 spaces.
I've removed print(Index) since it was not defined.
To access FireBoard use:
FireBoard[FireRow][FireIndex]
Instead of
FireBoard[[FireRow][FireIndex]]
This should be working
CompShips=[[1,0],[1,1],[2,2],[2,3],[2,4],[3,0],[3,1],[3,2],[5,4],
[5,5],[5,6],[5,7],[1,7],[2,7],[3,7],[4,7],[5,7]]
FRow1=["Z","Z","Z","Z","Z","Z","Z","Z",]
FRow2=["Z","Z","Z","Z","Z","Z","Z","Z",]
FRow3=["Z","Z","Z","Z","Z","Z","Z","Z",]
FRow4=["Z","Z","Z","Z","Z","Z","Z","Z",]
FRow5=["Z","Z","Z","Z","Z","Z","Z","Z",]
FRow6=["Z","Z","Z","Z","Z","Z","Z","Z",]
FRow7=["Z","Z","Z","Z","Z","Z","Z","Z",]
FRow8=["Z","Z","Z","Z","Z","Z","Z","Z",]
def PrintFireBoard():
print(FRow1)
print(FRow2)
print(FRow3)
print(FRow4)
print(FRow5)
print(FRow6)
print(FRow7)
print(FRow8)
FireBoard=[FRow1,FRow2,FRow3,FRow4,FRow5,FRow6,FRow7,FRow8]
while len(CompShips) !=0 or CompSuccess==17:
FireRow=input("Please Choose The Row That You Wish To Fire Upon (1-8) ")
FireIndex=input("Please Choose The Column That You Wish To Fire Upon (A-H) ")
#As Lists start at 0
FireRow=int(FireRow)-1
if FireIndex==("A"):
FireIndex=0
elif FireIndex==("B"):
FireIndex=1
elif FireIndex==("C"):
FireIndex=2
elif FireIndex==("D"):
FireIndex=3
elif FireIndex==("E"):
FireIndex=4
elif FireIndex==("F"):
FireIndex=5
elif FireIndex==("G"):
FireIndex=6
elif FireIndex==("H"):
FireIndex=7
Guess=[FireRow,FireIndex]
#Check To See If Correct
UserSuccess=0
for i in CompShips:
if Guess==i:
CompShips.remove(Guess)
UserSuccess=1
else:
pass
if UserSuccess==1:
print("HIT")
print(FireRow)
print(FireIndex)
FireBoard[FireRow][FireIndex]=("H")
PrintFireBoard()
else:
print("MISS")
print(FireRow)
print(FireIndex)
FireBoard[FireRow][FireIndex]=("M")
PrintFireBoard()

Related

Problems with Dictionary Python3

I'm currently working on a guessing game assignment. The assignment uses a dictionary to store the course name which is the key and the course number which is the value. The user guesses the course number of the course name given. If the value matches the key then it should print "correct!" and vice versa.
I have gotten the program to display the keys one at a time with an input statement separating them. I've gotten the correct/incorrect counters working. I'm not able to get an if statement working which is supposed to check if the value matches the key. It prints incorrect every time regardless of if the answer is correct. I realize there's probably something wrong with the condition of the if statement because i'm not really sure how to extract one value at a time.
Here's what I have so far:
# Mainline
def main():
programming_courses={"Computer Concepts":"IT 1025",\
"Programming Logic":"IT 1050",\
"Java Programming":"IT 2670",\
"C++ Programming":"IT 2650",\
"Python Programming":"IT 2800"}
print ("Learn your programming courses!\n")
correct=0
incorrect=0
v=0
# Game Loop
for key in programming_courses.keys():
print(key)
answer = input("Enter the Course Number: ")
if answer != programming_courses.values():
print("Incorrect")
incorrect += 1
else:
print("Correct!")
correct += 1
# Display correct and incorrect answers
print ("You missed ",incorrect," courses.")
print ("You got ",correct," courses.\n")
# Entry Point
response=""
while (response!="n"):
main()
response=input("\n\nPlay again?(y/n)\n# ")
Your problem is here:
if answer != programming_courses.values():
programming_courses.values() is a list of all the values in the dictionary. If you don't understand what's happening in your program, it's really helpful to just print stuff out and see if it looks like what you expect.
What you want is the specific value for the key you're on right now, which you need to look up from the dictionary like so:
if answer != programming_courses[key]:
Also, iterating over a dict gives you the keys by default, so you can just say:
for key in programming_courses:
You don't need to use .keys() there.
Your problem is when you are checking your dict. Currently your code is comparing the answer to a list of all the values in the dict:
out[]:
dict_values(['IT 1025', 'IT 1050', 'IT 2670', 'IT 2650', 'IT 2800'])
If you change to the following it works, by taking the specific value from the dict with the given key:
for key in programming_courses.keys():
print(key)
answer = input("Enter the Course Number: ")
if answer != programming_courses[key]:
print("Incorrect")
incorrect += 1
else:
print("Correct!")
correct += 1
you could try this
if answer != programming_courses[key]:

How to set my input to an already existing variable in Python?

I'm relatively new to python, and I can't figure out how to do this. I need to take a number input from a user, then turn that into an already existing variable. So far, I've managed to take the input, but I don't think I can make it into a variable. I am trying to turn this said input (number) to be added onto the back of a string (the string is pos)
So, for example, If I entered the number 1, i would have pos1, 2 would be pos2, so on.
if win == 0:
displayboard()
newPlot = input("")
postochange = "pos"+newPlot
if postochange == "X" or "O":
print ("Sorry, but that space is taken!")
else:
if playerTurn == 1:
postochange = "X"
else:
postochange = "O"
I'll try to simplify this some more, I want to have the user give me a number, that I add to the text "pos" and that corresponds to a variable that I already have.
Can you instead use a dictionary of values e.g.:
pos_s = {'pos1':None,
'pos2':None}
pos_s['pos'+str(user_number)] = desired_value
then to get the value of the variable you would do this:
pos_s.get('pos'+str(user_number), None)
just complementing Mason Caiby's answer, if the final user can only enter a finite collection of values, I would validate the entry with a set.
Then you can associate/correspond to a variable that you already have.
# Python program to demonstrate differences
# between normal and frozen set
# Same as {"a", "b","c"}
normal_set = set(["a", "b","c"])
# Adding an element to normal set is fine
normal_set.add("d")
print("Normal Set")
print(normal_set)
# A frozen set
frozen_set = frozenset(["e", "f", "g"])
print("Frozen Set")
print(frozen_set)
# Uncommenting below line would cause error as
# we are trying to add element to a frozen set
# frozen_set.add("h")

Turning a list number, into another value that is returned [python]

I am currently working on this code:
def N_C(question,choice):
N_C_choice_count_max = len(choice)
N_C_choice_count_min = N_C_choice_count_max - N_C_choice_count_max
N_C_restart_input = True
N_C_choices = []
print(question)
for i in range (N_C_choice_count_min,N_C_choice_count_max):
print(N_C_choice_count_min+i+1,":",choice[i])
str(N_C_choices.append(N_C_choice_count_min+i+1))
while N_C_restart_input == True:
N_C_input = input(">")
if str(N_C_input) in str(N_C_choices):
break
else:
continue
return(N_C_input)
N_C("question",["choice1","choice2","asmanychoicesasyouwant"])
And it works fine as it is, but to select a choice you input the number of the choice, which makes sense, but I would like for it to instead return the number they choose, the actual choice that goes with that number.
I am thinking that maybe something with a dictionary could work, or even just using the choice list provided, but I cannot figure it out, and help is appreciated.
choice is a list containing all the answers and N_C_input is a number as a string, which is associated to choice.
return choice[int(N_C_input)-1]
Returns the actual choice.

Swapping two characters in a 2D array in python?

So, I'm brand new to programming, and this is frustrating me! What I want to do is be able to import a 4x8 text file, and turn the text into a 2D list so that I can swap two characters. For example, if the imported text file looks like this:
OOOOOOOO
OOOXOOOO
OOOOOOOO
OOOOOOOO
then I would like to be able to change the position of the X (the row/column location) when user input is entered, such that an O will get put in its place to preserve formatting. So, for exapmle, the program will prompt the user for their input and if the user enters "up," then the X will move one space up.
OOOXOOOO
OOOOOOOO
OOOOOOOO
OOOOOOOO
I want it to repeatedly prompt for a new move after each time one is made, and display the new grid each time (so you can see the X in its new position each time you enter a movement).
This is all I have so far. I know I need to first find the X, but I really don't know how to. I'm stuck here. Any help is appreciated.
#Global variables for the movements
UP = 8
DOWN = 2
RIGHT = 6
LEFT = 4
#Dimensions of grid
ROWS = 4
COLUMNS = 8
def start():
filename = input("Enter the name of the Start Positions file: ")
textFile = open(filename)
aMaze = [line.strip() for line in textFile]
for r in range(ROWS):
for c in range(COLUMNS):
print(aMaze[r][c], end="")
print()
def moveType():
while (True):
try:
move = input("ENTER YOUR MOVE: ")
except ValueError:
print("unimportant error message")
continue
if ((int(move)) in (DOWN, LEFT, RIGHT, UP)):
playerMove(move)
continue
else:
print("unimportant error message")
continue
return(move)
def playerMove(move):
move = (int(move))
if (move == DOWN):
#need help here
elif (move == UP):
#and here
elif (move == LEFT):
#don't know what i'm doing
elif (move == RIGHT):
#also here
start()
moveType()
This is a perfect opportunity to learn about abstraction. To solve your problem, think about the sub problems you could solve (with functions) that would make your final problem easier.
In your specific instance, wouldn't it be easier to write a program to find the Cartesian coordinates of where X is? With an (x,y) coordinate, you could then make a function to turn that coordinate (likely stored as a tuple) into a 2d array where that coordinate is an X an everything else is a zero.
Hint 1:
x =0
y =0
for row in numrows:
for col in numcols:
if array[row][col] == X
y = row
x = col
Hint 2:
for row in numrows:
for col in numcols:
if col is x and row is y:
place X
else:
place O
Note: if this were an application where you wanted to eek out every bit of performance, you certainly would not need to iterate through your array every time to find X. You could (and should) opt to store the location of X and then use two accesses into your array to flip X's and O's. But seeing as this is likely one of your first problems you are solving this is of course not a concern.
Hope this helps! Good luck starting to code!

Nested Loop 'If'' Statement Won't Print Value of Tuple

Current assignment is building a basic text adventure. I'm having trouble with the following code. The current assignment uses only functions, and that is the way the rules of the assignment state it must be done.
def make_selections(response):
repeat = True
while repeat == True:
selection = raw_input('-> ')
for i, v in enumerate(response):
i +=1 # adds 1 to the index to make list indices correlate to a regular 1,2,3 style list
if selection == i:
print v[1]
else:
print "There's an error man, what are you doing?!?!?"
firstResponse = 'You chose option one.'
secondResponse = 'You chose option two.'
thirdResponse = 'You chose option three.'
responses = [(0, firstResponse), (1, secondResponse),( 0, thirdResponse)]
make_selections(responses)
My intention in that code is to make it so if the user selects a 1, it will return firstResponse, if the user selects 2 it will return secondResponse, etc.
I am basically just bug testing the code to make sure it produces the appropriate response, hence the "Error man..." string, but for some reason it just loops through the error message without printing the appropriate response string. Why is this?
I know that this code is enumerating the list of tuples and I can call them properly, as I can change the code to the following and get the expected output:
for i, v in enumerate(response):
i += 1 # adds 1 to the index to make list indices correlate to a regular 1,2,3 style list
print i, v
Also, two quick asides before anyone asks:
I know there is currently no way to get out of this while loop. I'm just making sure each part of my code works before I move on to the next part. Which brings me to the point of the tuples.
When I get the code working, a 0 will produce the response message and loop again, asking the user to make a different selection, whereas a 1 will produce the appropriate response, break out of the loop, and move on to the next 'room' in the story... this way I can have as many 'rooms' for as long of a story as I want, the player does not have to 'die' each time they make an incorrect selection, and each 'room' can have any arbitrary amount of options and possible responses to choose from and I don't need to keep writing separate loops for each room.
There are a few problems here.
First, there's no good reason to iterate through all the numbers just to see if one of them matches selection; you already know that will be true if 1 <= selection <= len(response), and you can then just do response[selection-1] to get the v. (If you know anything about dicts, you might be able to see an even more convenient way to write this whole thing… but if not, don't worry about it.)
But if you really want to do this exhaustive search, you shouldn't print out There is an error man after any mismatch, because then you're always going to print it at least twice. Instead, you want to only print it if all of them failed to match. You can do this by keeping track of a "matched" flag, or by using a break and an else: clause on your for loop, whichever seems simpler, but you have to do something. See break and continue Statements, and else Clauses on Loops in the tutorial for more details.
But the biggest problem is that raw_input returns a string, and there's no way a string is ever going to be equal to a number. For example, try '1' == 1 in your interactive interpreter, and it'll say False. So, what you need to do is convert the user's input into a number so you can compare it. You can do that like this:
try:
selection = int(selection)
except ValueError:
print "That's not a number!"
continue
Seems like this is a job for dictionaries in python. Not sure if your assignment allows this, but here's my code:
def make_selections(response):
selection = raw_input('-> ')
print response.get(selection, err_msg)
resp_dict = {
'1':'You chose option one.',
'2':'You chose option two.',
'3':'You chose option three.'
}
err_msg = 'Sorry, you must pick one of these choices: %s'%sorted(resp_dict.keys())
make_selections(resp_dict)
The problem is that you are comparing a string to an integer. Selection is raw input, so it comes in as a str. Convert it to an int and it will evaluate as you expect.
You can check the type of a variable by using type(var). For example, print type(selection) after you take the input will return type 'str'.
def make_selections(response):
repeat = True
while repeat == True:
selection = raw_input('-> ')
for i, v in enumerate(response):
i +=1 # adds 1 to the index to make list indices correlate to a regular 1,2,3 style list
if int(selection) == i:
print v[1]
else:
print "There's an error man, what are you doing?!?!?"

Categories