Thread: My first python project =)

  1. #1
    Registered User
    Join Date
    May 2006
    Posts
    903

    My first python project =)

    Alright guys. Since ASM has failed on me, I tried giving a shot at Python. I've tried writing a tic-tac-toe game and I ended up succeeding in 30-45 minutes ! That's not quite bad as I read documentation for about 15-20 minutes only ! =D

    Here's the code. It must be pretty darn ugly code... but still, it compiles and works as intended.
    Code:
    symbols = { 0:' ', 1:'x', 2:'o' }
    table = [0,0,0,0,0,0,0,0,0]
    wantsToPlay = 'y'
    
    def displayTable(table):
    	for i in range(len(table)):
    		if (i+1)%3 is 0:
    			print symbols[table[i]]
    		else:
    			print symbols[table[i]], '|',
    
    def resetTable(table):
    	for i in range(len(table)):
    		table[i] = 0
    		
    def isWinner(table, player):
    	if (table[0] is player and table[1] is player and table[2] is player) or \
    		(table[3] is player and table[4] is player and table[5] is player) or \
    		(table[6] is player and table[7] is player and table[8] is player) or \
    		(table[0] is player and table[3] is player and table[6] is player) or \
    		(table[1] is player and table[4] is player and table[7] is player) or \
    		(table[2] is player and table[5] is player and table[8] is player) or \
    		(table[0] is player and table[4] is player and table[8] is player) or \
    		(table[2] is player and table[4] is player and table[6] is player):
    			return 1
    	else:
    		return 0
    
    while(wantsToPlay is 'y'):
    	resetTable(table)
    
    	playerTurn = 2
    	while(isWinner(table, 1) is not 1 and isWinner(table, 2) is not 1):
    		displayTable(table)
    
    		playerTurn = (2 - playerTurn) + 1
    		while 1 is 1:
    			coord = int(raw_input("What coord do you want to play ? (0-8) "))
    			if table[coord] is 0:
    				table[coord] = playerTurn
    				break
    				
    	
    	print "Congratulations player %d you have won !" % (playerTurn)
    	
    	wantsToPlay = raw_input("Do you want to play again ? (y/n) ")
    Last edited by Desolation; 06-17-2007 at 11:46 PM. Reason: Used a dictionary for symbols and moved globals up at the top.

  2. #2
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    Pretty fancy, not that I can read any of it

  3. #3
    Fear the Reaper...
    Join Date
    Aug 2005
    Location
    Toronto, Ontario, Canada
    Posts
    625
    Solid stuff. I hope all your indentations were with spaces...
    Teacher: "You connect with Internet Explorer, but what is your browser? You know, Yahoo, Webcrawler...?" It's great to see the educational system moving in the right direction

  4. #4
    l'Anziano DavidP's Avatar
    Join Date
    Aug 2001
    Location
    Plano, Texas, United States
    Posts
    2,743
    on the contrary, i hope they were all with tabs

    but we won't get into that discussion again haha

    i love python. it's a great language. powerful and easy to use. my favorite feature of python is its built-in command-line argument parser.
    My Website

    "Circular logic is good because it is."

  5. #5
    Registered User
    Join Date
    May 2006
    Posts
    903
    Hey ! Thanks for the replies!

    @Happy_Reaper: What do you mean by "solid stuff" ?

    I did all of that... with tabs. I hate it when I'm on the fourth or fifth scope (pair of {}, for example) and I have to type all those spaces.. Gneh ! Tabs do it for me =)

  6. #6
    Fear the Reaper...
    Join Date
    Aug 2005
    Location
    Toronto, Ontario, Canada
    Posts
    625
    Solid stuff means good. Good stuff.

    And the only reason I bourght up the spaces is that at one time I'd made this Sudoku game in python which had like 20 or some classes with someone else. The problem was that mine and her coding styles conflicted, namely on the aspect that she used spaces for her code, and I used tabs. Which, when we were develloping on the Linux platform, seemd ok because everything was lining up correctly. But then, when we moved to windows, the size of the tabs changed, and all of our code was broken, and we had to go through like 3 hours of refactoring. Since then, I've been reluctant to use anything but spaces in my indentation.
    Teacher: "You connect with Internet Explorer, but what is your browser? You know, Yahoo, Webcrawler...?" It's great to see the educational system moving in the right direction

  7. #7
    Registered User
    Join Date
    May 2006
    Posts
    903
    Pffft ! The problem is not tabs, then, it's because you let a woman code... [/sarcasm]

    Edit: I'd be more than happy to have comments and suggestions on the code, though.
    Last edited by Desolation; 06-19-2007 at 06:16 PM.

  8. #8
    Registered User
    Join Date
    May 2006
    Posts
    903
    I have added more meat to it, I wanted it to be multi-player, but I can't test it right now... I've coded it but I am behind a router... and I can't forward ports because my father's girlfriend has changed the router's login and password... MEH ! Here's the code though, don't be shy and tell me if something's wrong with it.
    Code:
    import socket
    
    # turnInfo is used to know wether the current application is
    # player 1 (host) or player 2 (client)
    turnInfo = { 'y':1, 'n':2 }
    	
    # symbols is used to display the status of the game table
    symbols = { 0:' ', 1:'x', 2:'o' }
    
    # The game table is represented by a serie of zeros (empty),
    # ones (player 1) and twos (player 2)
    table = [0,0,0,0,0,0,0,0,0]
    
    wantsToPlay = 'y'
    port = 1234
    host = "127.0.0.1"
    
    
    def displayTable(table):
    	for i in range(len(table)):
    		if (i+1)%3 is 0:
    			print symbols[table[i]]
    		else:
    			print symbols[table[i]], '|',
    
    def resetTable(table):
    	for i in range(len(table)):
    		table[i] = 0
    		
    def isWinner(table, player):
    	if (table[0] is player and table[1] is player and table[2] is player) or \
    		(table[3] is player and table[4] is player and table[5] is player) or \
    		(table[6] is player and table[7] is player and table[8] is player) or \
    		(table[0] is player and table[3] is player and table[6] is player) or \
    		(table[1] is player and table[4] is player and table[7] is player) or \
    		(table[2] is player and table[5] is player and table[8] is player) or \
    		(table[0] is player and table[4] is player and table[8] is player) or \
    		(table[2] is player and table[4] is player and table[6] is player):
    			return 1
    	else:
    		return 0
    
    
    # Initialize socket and decide who is the server
    discussionSocket = 0
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    isHost = raw_input("Is this the server side ? (y/n) ") 
    
    # If current application is host, bind socket and listen for connection
    if isHost is 'y':
    	s.bind(("127.0.0.1", port))
    	s.listen(1)
    	discussionSocket, addr = s.accept()
    	
    	print "Successfully connected to %s" % (addr)
    	
    # Otherwise, try connecting to host
    else:
    	if s.connect_ex((host, port)) is 0:
    		print "Successfully connected to host"
    	discussionSocket = s
    	
    while(wantsToPlay is 'y'):
    	resetTable(table)
    
    	# We start with player one, so we need to set playerTurn as 2
    	playerTurn = 2
    	
    	# While nobody wins
    	while(isWinner(table, 1) is not 1 and isWinner(table, 2) is not 1):
    		displayTable(table)
    
    		# Change player turn. This trick recquired playerTurn to be set as 2 previously
    		# in order to start the game with player 1
    		playerTurn = (2 - playerTurn) + 1
    		
    		# If current application matches player turn (host = 1, client = 2)
    		if turnInfo[isHost] is playerTurn:
    			# Wait until the player has entered a valid input
    			while 1 is 1:
    				coord = int(raw_input("What coord do you want to play ? (0-8) "))
    				if table[coord] is 0:
    					table[coord] = playerTurn
    					discussionSocket.send(coord)
    					break
    					
    		# Otherwise, wait for distant player's move
    		else:
    			answer = discussionSocket.recv(4)
    			table[int(answer)] = playerTurn
    	
    	print "Congratulations player %d you have won !" % (playerTurn)
    	
    	wantsToPlay = raw_input("Do you want to play again ? (y/n) ")
    I've added comments on the previous code, by the way.

  9. #9
    semi-colon generator ChaosEngine's Avatar
    Join Date
    Sep 2005
    Location
    Chch, NZ
    Posts
    597
    looks good but you haven't allowed for the most common outcome of a game of tic-tac-toe... a draw!
    "I saw a sign that said 'Drink Canada Dry', so I started"
    -- Brendan Behan

    Free Compiler: Visual C++ 2005 Express
    If you program in C++, you need Boost. You should also know how to use the Standard Library (STL). Want to make games? After reading this, I don't like WxWidgets anymore. Want to add some scripting to your App?

  10. #10
    Registered User
    Join Date
    May 2006
    Posts
    903
    Thanks for that note ! Ah ah, it was only to practice the language though so it doesn't matter if there's a logical error like that ;-)

    Here's my second project, it's only a rough draft and is very limited in features, but it works as intended. I simply write a band name and a song name and my program fetches me the tab and saves it on a file =D

    Code:
    import urllib, string
    
    def FindTab(band, song):
    	url = "http://www.ultimate-guitar.com/tabs/" + band[0]
    	url += '/' + band + '/' + song + '_tab.htm'
    	
    	sock = urllib.urlopen(url)
    	
    	file_text = sock.read()
    	sock.close()
    	
    	file_text = StripCode(file_text)
    	
    	file = open(band + " - " + song + ".txt", 'w')
    	file.write(file_text)
    	
    def StripCode(file_text):
    	tmp1 = file_text.partition("<xmp>")[2]
    	tmp2 = tmp1.partition("</xmp>")[0]
    	return tmp2
    
    def FormatString(string):
    	return string.replace(' ', '_')
    	
    band = raw_input("Please enter the band's name: ")
    song = raw_input("Please enter the song's name: ")
    FindTab(FormatString(band), FormatString(song))
    I'd need to add quite a bit of error checking but I have don't have much time to do that right now.
    Last edited by Desolation; 06-26-2007 at 09:35 AM.

  11. #11
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Welcome to the obsession, er, language. For a first attempt, you've got a pretty Pythonic style. Not too ugly at all. Congrats!

    Quote Originally Posted by Desolation View Post
    Code:
    def isWinner(table, player):
    	if (table[0] is player and table[1] is player and table[2] is player) or \
    		(table[3] is player and table[4] is player and table[5] is player) or \
    		(table[6] is player and table[7] is player and table[8] is player) or \
    		(table[0] is player and table[3] is player and table[6] is player) or \
    		(table[1] is player and table[4] is player and table[7] is player) or \
    		(table[2] is player and table[5] is player and table[8] is player) or \
    		(table[0] is player and table[4] is player and table[8] is player) or \
    		(table[2] is player and table[4] is player and table[6] is player):
    			return 1
    	else:
    		return 0
    Might I suggest a slightly more efficient form of this, that you might not be aware of:

    Code:
    def isWinner(table, player):
            winning_lines = ((table[0], table[1], table[2]), (table[3], table[4], table[5]),
                             (table[6], table[7], table[8]), (table[0], table[3], table[6]),
                             (table[1], table[4], table[7]), (table[2], table[5], table[8]),
                             (table[0], table[4], table[8]), (table[2], table[4], table[6]))
            return (player, player, player) in winning_lines

  12. #12
    Registered User
    Join Date
    May 2006
    Posts
    903
    Hey thank you ! How does that latter form work ?

    Also, do you know why the following code doesn't write to any file at all ? The first draft of it worked like a charm for a single file... So I wanted to try it on a whole directory. The URLs printed match the real URLs. I have tested one (i.e. manually write the URL in firefox and go to the page) so I know the URL is not the problem...

    Code:
    import urllib, os
    
    def FindTab(band, song):
    	url = "http://www.ultimate-guitar.com/tabs/" + band[0]
    	url += '/' + band + '/' + song + '_tab.htm'
    	
    	sock = urllib.urlopen(url)
    	
    	file_text = sock.read()
    	sock.close()
    	
    	print url
    	
    	file_text = StripCode(file_text)
    	if len(file_text) > 0:
    		file = open(band + " - " + song + ".txt", 'w')
    		file.write(file_text)
    		file.close()
    	
    def StripCode(file_text):
    	tmp1 = file_text.partition("<xmp>")[2]
    	tmp2 = tmp1.partition("</xmp>")[0]
    	return tmp2
    
    def FormatString(string):
    	return string.replace(' ', '_')
    
    file_list = os.listdir("d:\\Musique\\")
    for entry in file_list:
    	band = entry.partition(' - ')[0]
    	song = (entry.partition(' - ')[2]).partition('.')[0]
    	FindTab(FormatString(band), FormatString(song))
    Thanks again to you all !

  13. #13
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by Desolation View Post
    Hey thank you ! How does that latter form work ?
    The winning_lines tuple contains tuples of all possible winning lines -- same numbers as in your version. Then this sequence of tuples is searched to find a match with (player, player, player). In other words, it checks to see that player exist in all three spots in at least one of those winning lines. It performs the exact same logic as your code but is somewhat more efficient since it takes advantage of Python's tuple construction and comparison efficiencies.

    For this program it doesn't actually matter, but if you'd been writing an AI to play tic-tac-toe, this function would be called many many times, and the efficiency might make a difference. Also, in my opinion, it is somewhat clearer. But no biggie.

    Also, do you know why the following code doesn't write to any file at all ? The first draft of it worked like a charm for a single file... So I wanted to try it on a whole directory. The URLs printed match the real URLs. I have tested one (i.e. manually write the URL in firefox and go to the page) so I know the URL is not the problem...
    Don't see anything really wrong off the top. I can only suggest lots and lots of debug prints Also, building strings by concatenation is not the best way to go about things in Python. Use the string formatting operator. For instance, instead of:

    Code:
    url = "http://www.ultimate-guitar.com/tabs/" + band[0]
    url += '/' + band + '/' + song + '_tab.htm'
    You might do something like:

    Code:
    url = "http://www.ultimate-guitar.com/tabs/%s/%s/%s_tab.htm" % (band[0], band, song)

  14. #14
    Registered User
    Join Date
    May 2006
    Posts
    903
    Thanks again ! I don't know how I could check *more* the strings since the url is in the good form so... I'll try though, thank !

  15. #15
    Registered User
    Join Date
    May 2006
    Posts
    903
    I think I have found the problem... It's because the site uses many different naming conventions and uses different prefixes. I will try implementing those naming conventions in my code but right now I'm a bit tired for that.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problem Displaying a Struct
    By rockstarpirate in forum C++ Programming
    Replies: 16
    Last Post: 05-05-2008, 09:05 AM
  2. added start menu crashes game
    By avgprogamerjoe in forum Game Programming
    Replies: 6
    Last Post: 08-29-2007, 01:30 PM
  3. Dynamic Binding
    By gpr1me in forum C++ Programming
    Replies: 1
    Last Post: 03-24-2006, 09:01 AM
  4. Game Independent Anti-cheat Project Needs Programmers
    By GIA Project Lea in forum Projects and Job Recruitment
    Replies: 3
    Last Post: 09-15-2005, 07:41 PM