how to read an array from txt.file? Python, curses - python

I am using curses in python, and I am trying to create a game where you print out characters in the terminal window. the field is then supposed to be saved in a text file if you press 's' and if you press 'o' the saved playing field is supposed to be uploaded. I manage to store all characters in an array, but i don't know how to upload the file back/print it on the terminal window.
So the problem is that i don't know how to 'reload' the characters i have stored.
The saved txt.file looks like this:
[' ', ' ', 'f', 'i', ' '....]
[' ', 'f', ' ', ' ', ' '....]
[...
[...
etc
My program.....
import curses
def main(scr):
"""
Draw a border around the screen, move around using the cursor and leave a mark
of the latest pressed character on the keyboard.
Quit using 'q'.
"""
# Clear the screen of any output
scr.clear()
# Get screen dimensions
y1, x1 = scr.getmaxyx()
y1 -= 1
x1 -= 1
y0, x0 = 0, 0 #min
# Get center position
yc, xc = (y1-y0)//2, (x1-x0)//2
# Draw a border
scr.border()
# Move cursor to center
scr.move(yc, xc)
# Refresh to draw out
scr.refresh()
#Make a copy of the playing field
array = [[' ' for _ in range(x1-1)] for _ in range(y1-1)]
# Main loop
x = xc
y = yc
ch = 'j'
while True:
key = scr.getkey()
if key == 'q':
break
elif key == 'KEY_UP' and (y-1) > y0:
y -= 1
elif key == 'KEY_DOWN' and (y+1) < y1:
y += 1
elif key == 'KEY_LEFT' and (x-1) > x0:
x -= 1
elif key == 'KEY_RIGHT' and (x+1) < x1:
x += 1
elif key == 's':
text_file = open("border.txt", "w")
for char in array:
text_file.write("%s\n" % char)
text_file.close()
elif key == 'o':
scr.clear()
saved_file = open("border.txt", "r")
scr.addstr... # this is the part that don't work.
scr.refresh()
else:
if key != 'KEY_UP' and key != 'KEY_DOWN' and key != 'KEY_LEFT' and key != 'KEY_RIGHT':
ch = key
#place the key in the array
posY = y
posX = x
if y >= y0 and x >= x0 and y <= (y1) and x <= (x1):
array[int(posY-1)][int(posX-1)] = ch
# Draw out the char at cursor positino
scr.addstr(ch)
# Move cursor to new position
if y < y1 and y > y0 and x > x0 and x < x1:
scr.move(y, x)
# Redraw all items on the screen
scr.refresh()

You can try to store your data with the python pickle module. It is intended for serialization of data structures like this. Later on you can reload your structure with pickle again

Related

If a certain letter is included in a string then its coordinate will increase or decrease

The program should ask what its first coordinates are. Then movement is asked and its answer should be with
r,R,l,L,u,U,d,D.
Coordinate are input with a comma (x,y), and then again if 'u','d','l','r' are input then the x or y axis will increase or decrease.
'u' and 'd' for the y-axis; 'r' and 'l' for the x-axis.
def program_for_grid(x,y,where):
if where == 'r' or where == 'R':
# move x upp +
for r in range(len(where)):
r == 'r' or r == 'R'
x + 1
elif where == 'l' or where == 'L':
# move x down -
for l in range(len(where)):
l == 'l' or l == 'L'
x - 1
elif where == 'u' or where == 'U':
# move y up +
for u in range(len(where)):
u == 'u' or u == 'U'
y + 1
elif where == 'd' or where == 'D':
# move y down -
for d in range(len(where)):
d == 'd' or d == 'D'
y - 1
x_axis,y_axis = input('Initial position: ').split(',')
int_x_axix = int(x_axis)
int_y_axix = int(x_axis)
movement = input('Movement: ')
grid = program_for_grid(int_x_axix,int_y_axix,movement)
print(grid)
Something like this?
def delta(movement):
"""
Parse the string for movement instructions and
return resulting relative coordinates
"""
x = 0
y = 0
for letter in movement.lower():
if letter == "d": y -= 1
elif letter == "u": y += 1
elif letter == "l": x -= 1
elif letter == "r": x += 1
else:
print("warning: skipping undefined", letter)
return x, y
x_axis,y_axis = input('Initial position: ').split(',')
int_x_axix = int(x_axis)
int_y_axix = int(y_axis)
while True:
movement = input('Movement: ')
xdelta, ydelta = delta(movement)
int_x_axix += xdelta
int_y_axix += ydelta
print(f"resulting position: ({int_x_axix},{int_y_axix})")

List append MemoryError

So I have this piece of code I'm trying to make generate level layouts for a grid of rooms. The first time through the mainloop it runs perfectly it runs and does exactly what it should but the second time through it pauses just after the first print error and gives me the attached error and I cant figure out what's wrong with it.
(the y/n prompt is only to slow down the program so I can see what's happening)
userInput = ""
roomChance = 0.5
world = [[0,0,0], \
[0,1,0], \
[0,0,0]]
possibleWorld = []
newX = []
def check_neighbours(xy):
possibleWorld.clear()
yLoops = 0
for y in xy:
print(" y:", y)
xLoops = 0
for x in y:
print(" x:", x)
#Check left cell
if(xLoops-1 >= 0):
if(y[xLoops-1] == 1):
possibleWorld.append([xLoops, yLoops])
print("x-1:", y[xLoops-1])
#Check right cell
if(xLoops+1 < len(y)):
if(y[xLoops+1] == 1):
possibleWorld.append([xLoops, yLoops])
print("x+1:", y[xLoops+1])
#Check above cell
if(yLoops-1 >= 0):
if(xy[yLoops-1][xLoops] == 1):
possibleWorld.append([xLoops, yLoops])
print("y-1:", xy[yLoops-1][xLoops])
#Check above cell
if(yLoops+1 < len(xy)):
if(xy[yLoops+1][xLoops] == 1):
possibleWorld.append([xLoops, yLoops])
print("y+1:", xy[yLoops+1][xLoops])
print("\n")
xLoops += 1
yLoops += 1
def assign_neighbours(possible, world, chance):
for i in possible:
if(random.random() < chance):
world[i[1]][i[0]] = 1
possible.clear()
def border_expand(world):
for x in world[0]:
if(x == 1):
for i in world[0]:
newX.append(0)
world.insert(0, newX)
newX.clear
break
def print_world(world):
for y in world:
print(y)
# ==================== Mainloop ====================
while(True):
userInput = input(print("Generate Level? Y/N?"))
check_neighbours(world)
print(possibleWorld)
assign_neighbours(possibleWorld, world, roomChance)
print_world(world)
border_expand(world)
print("\n")
print_world(world)
File "C:\Users\Potato\Desktop\Level gen_query.py", line 96, in <module>
border_expand(world)
File "C:\Users\Potato\Desktop\Level gen_query.py", line 67, in border_expand
newX.append(0)
MemoryError```
You're not calling newX.clear, so it is continually growing. When you run world.insert(0, newX) you are inserting a reference to newX into world[0], even if you did call newX.clear() you would not get the behaviour you want as the first element in world would be empty.
You need to create a new list on every call to border_expand so that it is a new list every time
def border_expand(world):
newX = []
for x in world[0]:
if(x == 1):
for i in world[0]:
newX.append(0)
world.insert(0, newX)
break

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()

Python Tkinter - How to make certain code use less memory

I am programming an Othello game in a GUI. I have begun working on the animations that flip certain tiles, which is here. My computer(s) will start choking when the when the amount of tiles on the board becomes larger. I do not know what to do to simplify this code or use less memory. (I can use an automove key I have enabled to finish the game at light speed, without the animations. That works fine.) Here is the definition I am using to flip the tiles.
def animateFlips(self, i):
self._canvas.delete(tkinter.ALL)
column_width = self._canvas.winfo_width()/Othello.COLUMNS
row_height = (self._canvas.winfo_height()-self._scoreBoard)/Othello.ROWS
newBoard = self._game.board
animatedTileCoords = []
color = ''
oppcolor = ''
if self._game.turn == 2:
color = 'black'
oppcolor = 'white'
elif self._game.turn == 1:
color = 'white'
oppcolor = 'black'
for x in range(Othello.COLUMNS):
for y in range(Othello.ROWS):
x1 = x * column_width
y1 = y * row_height
x2 = x1 + column_width
y2 = y1 + row_height
self._canvas.create_rectangle(x1,y1,x2,y2)
if self._game.board[x][y] == 1:
self._canvas.create_oval(x1,y1,x2,y2,fill='black')
elif self._game.board[x][y] == 2:
self._canvas.create_oval(x1,y1,x2,y2,fill='white')
elif self._game.board[x][y] == 3 or self._game.board[x][y] == 4:
animatedTileCoords.append([x,y])
for x, y in animatedTileCoords:
x1 = x * column_width
y1 = y * row_height
x2 = x1 + column_width
y2 = y1 + row_height
if i == 1:
self._canvas.create_oval(x1,y1,x2,y2,fill=oppcolor)
self._canvas.after(50, lambda: self.animateFlips(2))
elif i == 2:
self._canvas.create_oval(x1 + (column_width/4),y1,x1 + (3*column_width/4),y2,fill=oppcolor)
self._canvas.after(50, lambda: self.animateFlips(3))
elif i == 3:
self._canvas.create_oval(x1 + (column_width/2),y1,x1 + (column_width/2),y2,fill=oppcolor)
self._canvas.after(50, lambda: self.animateFlips(4))
elif i == 4:
self._canvas.create_oval(x1 + (column_width/4),y1,x1 + (3*column_width/4),y2,fill=color)
self._canvas.after(50, lambda: self.animateFlips(5))
elif i == 5:
self._canvas.create_oval(x1,y1,x2,y2,fill=color)
newBoard[x][y] = Othello.nextTurn(self._game.turn)
self._game = GameState(board = newBoard, turn = self._game.turn, skipped = 0)
self.displayMoves()
self.displayButtons()
self.displayInfo()
self.displayWinner(self.getWinner())
self._canvas.bind('<Configure>',self.draw_handler)
The simplest solution is to not delete and recreate the game pieces on each iteration. Draw them once, and then use the itemconfig method to alter the appearance of the game pieces.
Even better would be to create a GamePiece class so that each piece is represented by this class. Then, move the animation function inside the class. This will make your main logic much easier to understand.

How to maintain step animation

I am trying to make a program:
simulates a random walk
animates the walk using cs1graphics
starts on center block which is black
takes random steps, never been stepped on turns red, repeat step turns blue.
import random
from cs1graphics import *
from time import sleep
def animationWalk(walk):
print("Animation of Random Walk: ", end = "\n")
window = Canvas(250, 250)
window.setTitle('Random Walk in Manhattan')
for y in range(10) :
for x in range(10) :
cue = Square()
cue.setSize(50)
cue.moveTo(x*25, y*25)
window.add(cue)
(x,y)= (6,6)
squares = Square()
squares.setSize(25)
squares.moveTo((x*25)-14, (y*25)-13)
squares.setFillColor('black')
window.add(squares)
been = Square()
been.setSize(25)
been.moveTo((x*25)-14, (y*25)-13)
window.add(been)
for direction in range (len(walk)):
if walk[direction] == 'N':
#y -= 1
(x,y)=(x,y-1)
elif walk[direction] == 'E':
#x += 1
(x,y)=(x+1,y)
elif walk[direction] == 'S':
#y += 1
(x,y) =(x,y+1)
elif walk[direction] == 'W':
#x -= 1
(x,y) = (x-1,y)
been.setSize(25)
been.moveTo((x*25)-14, (y*25)-13)
been.setFillColor('red')
cue.setSize(25)
sleep(0.25)
cue.moveTo((x*25)-14, (y*25)-13)
cue.setFillColor('blue')
def randomWalk(x,y):
block = []
for i in range (x):
block.append([])
for i in block:
for j in range(y):
i.append(0)
position = (x//2, y//2)
h = position[0]
v = position[1]
walk = ''
block[h][v] += 1
while (h != -1) and (h != (x-1)) and (v != -1) and (v != (y-1)):
directions = random.randrange(1,5)
if directions == 1:
v += 1
walk = walk + 'E'
elif directions == 2:
h += 1
walk = walk + 'S'
elif directions == 3:
v -= 1
walk = walk + 'W'
elif directions == 4:
h -= 1
walk = walk + 'N'
block[h][v] += 1
print("Starting at Center (", x//2, ",", y//2, ")")
print("Walking Directions: ", walk)
print("Track of Random Walk:", end = "\n")
for entry in block:
print(entry)
animationWalk(walk)
def main(): ## define main program
x = 10
y = 10
randomWalk(x,y)
main()
The color of a square is supposed to change to red when it is visited, blue when it is revisited and is changed back to red when it is passed. I cant get the blocks to maintain the color after it has been stepped off of.

Categories