Swapping two characters in a 2D array in python? - 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!
Related
How can I loop over random numbers to get coordinates for my class?
I need a loop over all of my clans, which are instances of a class. Each clan needs to be assigned a position, a x and a y coordinate. Preferably as two lists or as a single tuple (but no idea how I specify that). This is how it works for the 1st clan. Afterwards I always have to check, if the position is already assigned. If so, you have to search for a new position until it is free. I then coded my class like this: width = 20 height = 20 no_of_clans = 50 import random class clan: def __init__(self, index, position_list): self.index = index self.position_list = position_list def index(no_of_clans): return list(range(1, no_of_clans +1)) def position_list(self): for i in range(1, no_of_clans +1): positions = () if i ==1: #i can do it either like this positions = [(random.randint(0, width)), (random.randint(0, height))] positions.append(x,y) else: #or like this, I do not know, which one is better, both are running x = (random.randint(0, width)) y = (random.randint(0, height)) #check if x and y not already used #assert positions.append(x,y) return positions print(positions) how can I assign positions randomly when also using 0.5 steps? I always get an error message. I never get a list of my positions back, but I do not know what I did wrong. I know those are probably fairly basic questions but I am quite new to python an already searched for 5h today and I really do ot know where to start anymore. I would be really happy if someon could help me. Thank you so much in advance <3
I found the answer to my original question in this post: Coordinates of the edges of a honeycomb grid in python Will update if I am finished with the class-thing :)
Index Out Of Range When Artificially Limited
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()
Using a variable inside a string
I am facing a problem while trying to assign materials "on the go" to a set of cubes in Blender3D. I know it comes from the fact that the objects data names are being incremented when generated (Cube, Cube.001, cube.002...) but I don't know the way to have the name of the object being interactive with the loop. I'd really appreciate if someone could give me a tip !! Dark = bpy.data.materials['Dark'] Light= bpy.data.materials['Light'] for x in range(4): for y in range(4): for z in range(4): bpy.ops.mesh.primitive_add_cube(radius=.049, location=(x,y,z)) a = bpy.data.object['Cube'] if (x+y+z) % 2 == 0: a.data.materials.append(Dark) else: a.data.materials.append(Light)
Cannot set an array element with a sequence
I'm using the NumPy python library to run large-scale edits on a .csv file. I'm using this python code: import numpy as np def main(): try: e,a,ad,c,s,z,ca,fn,ln,p,p2,g,ssn,cn,com,dob,doh,em = np.loadtxt('c:\wamp\www\_quac\carryover_data\SI\Employees.csv',delimiter=',',unpack=True,dtype='str') x=0 dob = dob.split('/') for digit in dob: if len(digit) == 1: digit = str('0'+digit) dob = str(dob[2]+'-'+dob[0]+'-'+dob[1]) doh = doh.split('/') for digit in doh: if len(digit) == 1: digit = str('0'+digit) doh = str(doh[2]+'-'+doh[0]+'-'+doh[1]) for eID in e: saveLine=eID+','+a[x]+','+ad[x]+','+c[x]+','+s[x]+','+z[x]+','+ca[x]+','+fn[x]+','+ln[x]+','+p[x]+','+p2[x]+','+g[x]+','+ssn[x]+','+cn[x]+','+com[x]+','+dob[x]+','+doh[x]+','+em[x]+'\n' saveFile = open('fixedEmployees.csv','a') saveFile.write(saveLine) saveFile.close() x+=1 except Exception, e: print str(e) main() dob and doh contain a string, e.g. 4/26/2012 and I'm trying to convert these to mysql friendly DATE forms, e.g. 2012-04-26. The error that is printed when I run this script is cannot set an array element with a sequence It does not specify a line and so I don't know what this really means. I'm pretty new to python; I've checked other questions with this same error but I can't make sense of their code. Any help is very appreciated.
Try using zfill to reformat the date string so you can have a '0' before your '4'. (zfill pads a string on the left with zeros to fill the width.) doh = '4/26/2012' doh = doh.split('/') for i, s in enumerate(doh): doh[i] = s.zfill(2) doh = doh[2]+'-'+doh[0]+'-'+doh[1] # result: '2012-04-26' As for the cannot set an array element with a sequence it would be helpful to know where that is occurring. I'm guessing there is something wrong with structure of the array.
Ok, to solve it I had to do a couple things. After removing the try-except commands, I found out that the error was on line 5, the line with e,a,ad,c,s etc. I couldn't eliminate the problem until I simply copied the 2 columns I wanted to focus on only and made a new program for dealing with those. Then I had to create a .txt instead of a .csv because Excel auto-formats the dates and literally changes the values before I can even touch them. There is no way around that, I've learned. You can't turn the date-auto-format off. A serious problem with excel. So here's my solution for this NumPy script (it changes the first column and keeps the second the same): import numpy as np def main(): dob,doh=np.loadtxt('temp.csv', delimiter=',', unpack=True, dtype='str') x=0 for eachDate in dob: if any(c.isalpha() for c in eachDate): newDate=eachDate elif (eachDate == ''): newDate='' else: sp = eachDate.split('/') y=0 ndArray = ['','',''] for eachDig in sp: if len(eachDig) == 1: eachDig = str('0'+eachDig) if y == 0: ndArray[0] = eachDig elif y == 1: ndArray[1] = eachDig elif y == 2: ndArray[2] = eachDig newDate=str(ndArray[2]+'-'+ndArray[0]+'-'+ndArray[1]) y=0 y+=1 print eachDate+'--->'+newDate """creates a .txt file with the edited dates""" saveLine=str(newDate+','+doh[x]+'\n') saveFile=open('__newTemp.txt','a') saveFile.write(saveLine) saveFile.close() x+=1 main() I then used Data->Import from text with "TEXT" format option in Excel to get the column into my .csv. I realize this is probably bulky and noobish but it got the job done :3
python list Index out of range error
I am working on a python tetris game that my proffessor assigned for the final project of a concepts of programming class. I have got just about everything he wanted to work on it at this point but I am having a slight problem with one part of it. Whenever I start moving pieces left and right I keep getting "index out of range error". This only happens when it is up against a piece. Here are the culprits that are giving me grief. def clearRight(block=None): global board, activeBlock, stackedBlocks isClear = True if(block == None): block = activeBlock if(block != None): for square in block['squares']: row = square[1] col = square[0]+1 if(col >= 0 and stackedBlocks[row][col] !=None): isClear=False return isClear def clearLeft(block=None): global board, activeBlock, stackedBlocks isClear = True if(block == None): block = activeBlock if(block != None): for square in block['squares']: row = square[1] col = square[0]-1 if(col >= 0 and stackedBlocks[row][col] !=None): isClear=False return isClear I am not looking to get anyone to fix it for me, I'm only looking for tips on how to fix it myself. Thanks in advance for any help that is given.
There a typo that would cause that problem in the first method. When you're checking each cell in the block shifted one right, you don't check if they are off the grid. if (col >= 0 and ...) probably should be if (col < num_cols and ...) I also agree with CrazyDrummer, make a generic clear function Spoilers ... def clear(x_offset, block=None): if not block: block = activeBlock if not block: return True for x,y in block: x += x_offset if not (0 <= x < num_cols) or stackedBlocks[x, y]: return False return True
Look at what's different when you're getting the exception. Try printing out program state information to help you zero in. There's only one place where you access an array with variable indexes, so you can narrow your search radius a bit. Separate suggestion: Make a generic clear that takes determines what direction you want to clear from by the parameters. I highly recommend the book debugging rules!, it will aid you in searching out and properly fixing problems. :D