The game generates a fixed, "animated" game board via ASCII characters that is reprinted and cleared after each valid move. The format of the input for making moves is described in the script. You select the "difficulty" via a commandline parameter, so the game requires you enter a number (>=3) for the disc count after the filename.
I'm new to classes, so I wasn't sure how to retrieve the latest "top occupied position" on a rod following each addition/removal of a piece besides what I have here and maybe one other way. I'm guessing that I could have had a default self.topindex
and self.top
for a rod, and then updated this upon each call of the methods add()
and remove()
.
import os
import sys
level = int(sys.argv[1])
class rod:
def __init__(self,n):
self.n=n
if n==1: self.state= list(range(1,level+1))
else: self.state=[0]*level
def pos(self, height): #This generates one chunk of the rod and any pieces at that height
width=self.state[height-1]
return " "*(level+1-width)+"-"*width+"|"+"-"*width+" "*(level+1-width)
def topindex(self): #This is meant to return the index of the top occupied position on the rod
for index,i in enumerate(self.state):
if i!=0: return index
elif index==level-1: return index #But if there are no occupied positions (empty rod) it should return the bottom
def top(self):
return self.state[self.topindex()]
def add(self, piece):
if self.top()==0: self.state[level-1]=piece
else: self.state[self.topindex()-1]=piece
def remove(self):
self.state[self.topindex()]=0
rod1=rod(1) #This seems like a waste of lines
rod2=rod(2)
rod3=rod(3)
gamestate=["Welcome to the game. ", "first"]
def printgame():
print gamestate[0]+"The objective is to move all the pieces from rod 1 to another rod."
print "Pieces must be placed in ascending order of size from top to bottom."
print 'Move pieces by typing "n m" (where n and m denote the numbers of the source and destination rods) when requested.'
print ""
for i in range(1,level+1):
print rod1.pos(i)[1:]+rod2.pos(i)+rod3.pos(i)
spacing=(level-3)*" " #Add each block of each rod at the same height to one line, then print the line
print spacing+" Rod 1 "+2*spacing+"Rod 2 "+2*spacing+"Rod 3\n"
def hasdigit(string):
return any(char.isdigit() for char in string)
os.system("clear")
def movepiece():
global rod1 #Too many globals here
global rod2
global rod3
global gamestate
move=raw_input("Which piece will you move {}? ".format(gamestate[1]))
if " " in move and hasdigit(move.split(" ")[0]) and hasdigit(move.split(" ")[1]):
gamestate[0]=""
gamestate[1]="next"
source=move.split(" ")[0]
destination=int(move.split(" ")[1])
piece=eval("rod"+str(source)+".top()")
if (piece<eval("rod"+str(destination)+".top()") or eval("rod"+str(destination)+".top()")==0) and piece!=0:
eval("rod"+str(source)+".remove()")
eval("rod"+str(destination)+".add("+str(piece)+")")
elif piece==0:
print "There's nothing to move from rod {}!\n".format(source)
movepiece()
else:
print "You can't move that there!\n"
movepiece()
elif move=="exit": gamestate=move
else:
print "Please use the specified format: n m (where n and m denote the numbers of the source and destination rods).\n"
movepiece()
steps = 0
while rod2.state!=list(range(1,level+1)) and rod3.state!=list(range(1,level+1)):
if gamestate=="exit": break
printgame()
movepiece()
steps+=1
os.system("clear")
if gamestate!="exit":
printgame()
print "Congratulations, you've finished the game in {} steps.".format(steps)