Wednesday, 2024-04-24, 9:04 PM
Welcome Guest

Distance Education

[ New messages · Members · Forum rules · Search · RSS ]
  • Page 1 of 1
  • 1
Forum moderator: Christos  
Forum » Software Development » RE:Work » No more python? (Is this really all we learn?)
No more python?
Dr4c0niusDate: Saturday, 2009-09-12, 2:17 PM | Message # 1
Major
Group: Users
Messages: 96
Awards: 2
Reputation: 0
Status: Offline
Not to be insulting or anything, but don't we learn anything about libraries? Advanced gui stuff? The rest of it?

Oderint dum metuant

<locokamil> Your belief system is thermodynamically unsound.

 
HaydenJohnsDate: Sunday, 2009-09-13, 6:44 AM | Message # 2
Lieutenant colonel
Group: Checked
Messages: 123
Awards: 0
Reputation: 0
Status: Offline
The python wasn't meant to be the main part of the course. Think of it as the equivalent of the actual woodwork in design tech ( I hope I have the class right).

It was useful in that it gave us an application for and a better grasp on the theory we were learning. I wouldn't have ever grasped the OOP stuff unless we were programming.

Still, I know where you're coming from. I'd like to learn about libraries, etc. as well. But we can take that up in our spare time if we really want to (not me, C++ is next on my to-do list in my path to hackerdom. Perhaps I'll buy Dawson's book on the language).
Perhaps we could have a revision of our connect four game thing, and have a more complex task that we (seeing as I think we're the only two SD people who use this) work on together. What do you think?


~ Click it
 
Dr4c0niusDate: Tuesday, 2009-09-15, 11:59 AM | Message # 3
Major
Group: Users
Messages: 96
Awards: 2
Reputation: 0
Status: Offline
Sounds interesting actually. I posted this mainly because i just assumed we were planning to work through the whole python textbook, and was a little suprised when we finished up on Tkinter.

Connect 4 sounds good. Complex task like graphics or ai? Something like that?


Oderint dum metuant

<locokamil> Your belief system is thermodynamically unsound.

 
HaydenJohnsDate: Wednesday, 2009-09-16, 11:02 AM | Message # 4
Lieutenant colonel
Group: Checked
Messages: 123
Awards: 0
Reputation: 0
Status: Offline
I think a new game - We've done connect four, so all this would be is a test to see how scalable the programming is.

I was planning to get around to making a 3- Tic Tac Toe game. We could do that.

I play this in physics with a friend all the time:

4 4x4 grids, each representing one layer of a 4x4x4 cube. The first is the top, and then it moves downwards. So long as its four in a row, it's a win, even if it's straight down the stacks or on a weird diagonal.

I actually have the prototype GUI done (RAD development), but it doesn't do anything yet. Still need to fix up issues with it and make it clearer.

Added (2009-09-16, 11:02 Am)
---------------------------------------------
So, what do you think? (stupid click without thinking) It should be a challenge, and will test our limits.

By the way, how did you go on your SAC? I got Very High for both categories.


~ Click it
 
Dr4c0niusDate: Thursday, 2009-09-17, 3:49 PM | Message # 5
Major
Group: Users
Messages: 96
Awards: 2
Reputation: 0
Status: Offline
I can adapt the alogrithm from connect 4 to check in 3d fairly easily, i think. That should work well.

What did you use for the gui? Tkinter, or something else? Will the final gui be 4 seperate 2d planes, or something different?

I'm thinking something like board(x, y, z) would be most appropriate to store the board, as it allows us to scroll through logically, with the left top back space being 0.

The sac? High and very high. Not sure what i got wrong, though.


Oderint dum metuant

<locokamil> Your belief system is thermodynamically unsound.

 
HaydenJohnsDate: Saturday, 2009-09-19, 8:45 AM | Message # 6
Lieutenant colonel
Group: Checked
Messages: 123
Awards: 0
Reputation: 0
Status: Offline
I agree on the method of storing the board.

I built in in tkinter (still v0.0.0 though), with four 2d planes. Here's the code

Code
#! /usr/bin/python

#3D Connect 4

from Tkinter import *

class Application:
     Application.turn = ""
     def __init__(self, master):
         self.master = master
         baseframe = Frame(master)
         baseframe.place(width=400, height=300)
          
         title = Label(baseframe, text="3D Tic-Tac-Toe")
         title.place(x=100, y=10, width=200, height=100)

         startbttn = Button(baseframe, text="start game", command=self.loadgame)
         startbttn.place(x=20, y=200, width=200, width=100)

     def loadgame(self):
         w1=Tk()
         w1.geometry("100x100")
         w1.title("1")
         l1 = Layer(w1)
         w1.resizable(0,0)
          
         w2=Tk()
         w2.geometry("100x100")
         w2.title("2")
         l2 = Layer(w2)
         w2.resizable(0,0)

         w3=Tk()
         w3.geometry("100x100")
         w3.title("3")
         l3 = Layer(w3)
         w3.resizable(0,0)

         w4=Tk()
         w4.geometry("100x100")
         w4.title("4")
         l4 = Layer(w4)
         w4.resizable(0,0)
         Application.turn = "red"
          

class Layer:
     def __init__(self, master):
         self.frame = Frame(master)
         self.frame.place(width=100, height=100)

         #Layer - 4x4 grid
         g11 = Button(self.frame)
         g12 = Button(self.frame)
         g13 = Button(self.frame)
         g14 = Button(self.frame)
         g11.place(x=0, y=0, width=25, height=25)
         g12.place(x=25, y=0, width=25, height=25)
         g13.place(x=50, y=0, width=25, height=25)
         g14.place(x=75, y=0, width=25, height=25)
          
         g21 = Button(self.frame)
         g22 = Button(self.frame)
         g23 = Button(self.frame)
         g24 = Button(self.frame)
         g21.place(x=0, y=25, width=25, height=25)
         g22.place(x=25, y=25, width=25, height=25)
         g23.place(x=50, y=25, width=25, height=25)
         g24.place(x=75, y=25, width=25, height=25)

         g31 = Button(self.frame)
         g32 = Button(self.frame)
         g33 = Button(self.frame)
         g34 = Button(self.frame)
         g31.place(x=0, y=50, width=25, height=25)
         g32.place(x=25, y=50, width=25, height=25)
         g33.place(x=50, y=50, width=25, height=25)
         g34.place(x=75, y=50, width=25, height=25)

         g41 = Button(self.frame)
         g42 = Button(self.frame)
         g43 = Button(self.frame)
         g44 = Button(self.frame)
         g41.place(x=0, y=75, width=25, height=25)
         g42.place(x=25, y=75, width=25, height=25)
         g43.place(x=50, y=75, width=25, height=25)
         g44.place(x=75, y=75, width=25, height=25)

         def move(self):
              
              

root = Tk()
root.geometry("400x300")
app=Application(root)
root.mainloop(1) #A very hacky way of fixing an IDLE issue - KILL BEFORE PUBLISH

I was about to build the move function (colours the square, and alters some background settings, eventually leading into checks and perhaps AI) when I realized that I need to rethink the approach (probably just need to add another parameter to the command). Sorry for the lack of comments.


~ Click it
 
Dr4c0niusDate: Saturday, 2009-09-19, 11:31 AM | Message # 7
Major
Group: Users
Messages: 96
Awards: 2
Reputation: 0
Status: Offline
Hmmmm... is there some way to create the buttons dynamically? Something like

Code

def ButtonClicked(self, x,y):
       # do stuff with x and y here

def CreateButtons(self):
           self.ButtonMatrix=[[[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null]], [[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null]], [[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null]],[[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null]]]
           for xpos in range(0,3):
                for ypos in range(0,3):
                     for zpos in range(0,3):
                          ButtonMatrix[x][y][z]=Button(self, text=" ", command=ButtonClicked(int(xpos),int(ypos),int(zpos)))
                          ButtonMatrix[x][y][z].place(x=xpos*25 + zpos* 100, y=ypos*25, width=25, height=25)

That way, you can put code in one seperate function and dont have to have a mass of writing.

Edit: I'm sure it'd be possible to remove that array of nulls somehow, probably by appending the buttons on.


Oderint dum metuant

<locokamil> Your belief system is thermodynamically unsound.

Message edited by Dr4c0nius - Saturday, 2009-09-19, 11:49 AM
 
HaydenJohnsDate: Saturday, 2009-09-19, 3:51 PM | Message # 8
Lieutenant colonel
Group: Checked
Messages: 123
Awards: 0
Reputation: 0
Status: Offline
Once again, you're showing the difference in how we code. You go for the more elegant solution, while I prefer concrete code, even if it does get "verbose" as you so kindly put it tongue

Also, I take it that you would prefer to use grid? I never got it to work, so I just use place instead. Anyways, I'm not exactly sure what the matrix is for. With my way, I would have set it up like:

For each grid:

Code

#using positions based on self.matrix[x][y]
self.matrix= [["white", "white", "white", "white"], ["white", "white", "white", "white"],
                     ["white", "white", "white", "white"],["white", "white", "white", "white"]]

When a button is clicked (give the buttonclick method a few parameters so that it knows what grid position to change), the colours of the buttons are updated using the grid. (a small dynamic piece of code would suffice here).

I'll leave it up to you how we want to do this, but if we go for your way, you're going to have to dumb everything down. I'm not that great with the dynamic algorithms.


~ Click it
 
Dr4c0niusDate: Sunday, 2009-09-20, 6:50 PM | Message # 9
Major
Group: Users
Messages: 96
Awards: 2
Reputation: 0
Status: Offline
Ah k, sorry. Its just that when and if AI coding takes place a grid is a LOT easier to manipulate. The problem with most AIs is that it reaches a stage of complexity where NOT using dynamic alogrithms is moderately suicidal. Although an AI would be by far the hardest thing i could think of coding, so we probably won't get up to that.

Oderint dum metuant

<locokamil> Your belief system is thermodynamically unsound.

 
HaydenJohnsDate: Monday, 2009-09-21, 4:18 PM | Message # 10
Lieutenant colonel
Group: Checked
Messages: 123
Awards: 0
Reputation: 0
Status: Offline
The thing is, I play this game a few times a week. I (and the guy I play with) have yet to come up with a strategy. Basically, what happens is that you just get really good at multi-step thinking and can see a whole bunch of possible moves that the opponent can make. We've yet to discover a decent strategy (but then again, once we do we'll have to move onto something like 3d reversi :p).

Anyway, we could always just use both.
Make ButtonMatrix a global variable, and use it as a reference (for checking, etc). A few lines of code can be added to the ButtonClick method that will update the grid (use a parameter to specify where it has to be). For example:

Code
def bttnclick(self, x, y, z):
       ButtonMatrix[x][y][z] = "red"   #update the grid
       #other stuff here

I just realised that there's a bit of a hiccup: How would you set up the method to work accross all buttons, using the parameters? I mean, something like (using the prototype grid) gxy where x and y are the parameters. Do you know how we would do this? I can think of a few workarounds if we couldn't update the button directly, but all hit the same roadblock of getting the button to reference itself. We could make each layer a superclass of the button, but that's getting over the top.

Oh, and I had another look at the code you wrote (fresh mind and all that). I like the idea of it, except what are you doing with zpos? It looks like you're trying to implement it on a single 4x4 grid. Could get nasty. Also, you don't need to have int() there. The for command should spit out integers as it is.

Added (2009-09-21, 4:18 Pm)
---------------------------------------------
So, essentially what this needs is a way to stitch a bunch of parameters into a class instance. I'll ask around in the linux community tomorrow to see if anyone can help us.


~ Click it
 
Dr4c0niusDate: Wednesday, 2009-09-23, 1:05 PM | Message # 11
Major
Group: Users
Messages: 96
Awards: 2
Reputation: 0
Status: Offline
I'm not entirely sure what your saying here, but I'm fairly sure that ButtonMatrix[x][y][z]=Button(self, text=" ", command=ButtonClicked(int(xpos),int(ypos),int(zpos))) will call the function ButtonClicked with different parameters for each button. As the buttons we are creating will all be part of the grid, they will all have roughly the same requirements when clicked, so we can use a single function to deal them all, as long as we tell that function what position the button we pressed is in.

With the above command, too, the int() brackets are there make sure that ButtonClicked will have numbers as parameters, and not variables. I couldn't fully remember how python deals with this kind of thing, so i put them in.

Edit: with zpos, i simply made the buttons appear 100 pixels (ie the height of one grid - 25px X 4) below the previous one. Not terribly fancy, but it should work.


Oderint dum metuant

<locokamil> Your belief system is thermodynamically unsound.

Message edited by Dr4c0nius - Wednesday, 2009-09-23, 1:09 PM
 
HaydenJohnsDate: Thursday, 2009-09-24, 4:57 AM | Message # 12
Lieutenant colonel
Group: Checked
Messages: 123
Awards: 0
Reputation: 0
Status: Offline
That clears things up with the zpos thing

What I'm saying is how are we going to add into buttonclicked() how it knows what button to change the colour (I'm assuming just make the thing change colour, but we could add text) of?

I mean, self refers to that particular frame. So would we use self.self? I doubt it (haven't tested it though). So we would need to get it to stitch together (say we called it gxyz for g, xpos, ypos, zpos) the button's name. Essentially something that says:

Code
self.g + str(xpos) + str(ypos) +str(zpos).config(...)

Because each button shares the one method, we need to make sure that that method can specify what button activated it (so it knows which one to change)

Although, it just occured to me that we could work around this. Use the x,y and z positions to update the matrix, and then just get the method to update all of the buttons based off of the matrix. It will be verbose if we're not careful, but it will work.

Here's my stab at a dynamic update:

Code

for i,j,k in buttonmatrix: #assuming that buttonmatrix has the colours of the buttons
      self.gijk.config(bg = buttonmatrix[i][j][k]
      if gijk != "white":
           gijk.config(state=DISABLED) #prevent the user from entering a move over a previous one

And hence, we hit the same problem with this one (gijk will screw up). Unless you can think of a way to solve the issue, we're going to have a verbose workaround.


~ Click it
 
Dr4c0niusDate: Saturday, 2009-09-26, 7:23 AM | Message # 13
Major
Group: Users
Messages: 96
Awards: 2
Reputation: 0
Status: Offline
can't you just reference the button by ButtonMatrix[x][y][z]?

Oh shit, in that post i forgot to change that. the coed should read

Code


def ButtonClicked(self, x,y):
         # do stuff with x and y here

def CreateButtons(self):
             self.ButtonMatrix=[[[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null]], [[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null]], [[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null]],[[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null]]]
             for xpos in range(0,3):
                  for ypos in range(0,3):
                       for zpos in range(0,3):
                            ButtonMatrix[xpos][ypos][zpos]=Button(self, text=" ", command=ButtonClicked(int(xpos),int(ypos),int(zpos)))
                            ButtonMatrix[xpos][ypos][zpos].place(x=xpos*25 + zpos* 100, y=ypos*25, width=25, height=25)   

A button is an object, and ButtonMatrix stores the actual buttons, not their colour. Thus, asking for the button at position [xpos][ypos][zpos] in buttonmatrix will return the actual button, and you will be able to manipulate it as you would any other button.

So your code would be:

Code


for i,j,k in buttonmatrix:  
        self.ButtonMatrix[i,j,k].config(bg = CurrentColour)        # CurrentColour is the colour of the person whos turn it is, you can change this if you want.
        if self.ButtonMatrix[i,j,k] != "white":
             self.ButtonMatrix[i,j,k].config(state=DISABLED) #prevent the user from entering a move over a previous one   



Oderint dum metuant

<locokamil> Your belief system is thermodynamically unsound.

Message edited by Dr4c0nius - Saturday, 2009-09-26, 7:44 AM
 
HaydenJohnsDate: Saturday, 2009-09-26, 9:32 AM | Message # 14
Lieutenant colonel
Group: Checked
Messages: 123
Awards: 0
Reputation: 0
Status: Offline
Noddy program to test that? And the limitation with that is that we have possible issues running out of a prebuilt class. Does Button have get_ methods (sure we can use an ugly hack, but we should probably stick to good practice)?

Added (2009-09-26, 9:32 Am)
---------------------------------------------

Code

#Noddy program to test draconius' dynamic algorithm

from Tkinter import *

class Application:
     def __init__(self, master):
         frame = Frame(master)
         frame.place(width= 200, height=100)

         for i in range(2):
             self.button[i] = Button(text = str(i), command = self.cmd(i))
             self.button[i].place(width = 100, height = 100, x = 100*i, y=0)

     def cmd(self, i):
         print "This is button" + str(i)

root = Tk()
root.geometry("200x100")
app = Application(root)
root.mainloop()

I Get this:

Quote
Traceback (most recent call last):
File "/home/hayden/Desktop/noddy.py", line 19, in <module>
app = Application(root)
File "/home/hayden/Desktop/noddy.py", line 11, in __init__
self.button[i] = Button(text = str(i), command = self.cmd(i))
AttributeError: Application instance has no attribute 'button'

button[i] tells python that you're after a slice of button, which it assumes already exists. e.g. if button = 123 then button[0] would equal 1 and button[1] would equal 2, etc.

Similarly, this fails as well:

Code
for i in range(2):
             self.button + i = Button(text = str(i), command = self.cmd(i))
             self.button + i.place(width = 100, height = 100, x = 100*i, y=0)

The lesson: always write a noddy program to test the idea tongue

Anyway, I think that we need to revise the methodology here. If you can think of a way to convert a string to a variable name (i.e. change "button" to button), then we can fix this, but otherwise we need to rethink it.


~ Click it
 
Dr4c0niusDate: Saturday, 2009-09-26, 11:44 AM | Message # 15
Major
Group: Users
Messages: 96
Awards: 2
Reputation: 0
Status: Offline
Fixed your noddy program, it now works:

Code
from Tkinter import *

class Application:
          def __init__(self, master):
              frame = Frame(master)
              frame.place(width= 200, height=100)
              self.button = [None,None,None,None]
              for i in range(4):
                  self.button[int(i)] = Button(text = str(i), command = lambda num = i:self.cmd(num))
                  self.button[int(i)].place(width = 100, height = 100, x = 100*i, y=0)

          def cmd(self, i):
              print "This is button" + str(i)

root = Tk()
root.geometry("400x100")
app = Application(root)
root.mainloop()   

Self.button wasn't set up in your example. Python returned that error because it couldn't find self.button. It couldn't find self.button because self.button did not in fact exist.

And command = lambda num = i:self.cmd(num) creates a temporary function (using lambda), adds a parameter to the function and makes num equal i by default (num = i) then makes the lambda function call the function self.cmd(num).

We have to do this because simply writing self.cmd(i) will immediately return self.cmd(i) and set the the returned value as the command (in this case i think it returns the integer 1 - not very helpful!).

Using lambda: gets around this by creating a temporary function that will not get called when we specify it.

BTW: if you haven't read up about lambda, you should. It's incredibly useful.


Oderint dum metuant

<locokamil> Your belief system is thermodynamically unsound.

Message edited by Dr4c0nius - Saturday, 2009-09-26, 12:23 PM
 
HaydenJohnsDate: Saturday, 2009-09-26, 2:57 PM | Message # 16
Lieutenant colonel
Group: Checked
Messages: 123
Awards: 0
Reputation: 0
Status: Offline
I haven't read about lambda. Looks interesting. Once again, you're showing a more elegant solution to the problem (if lambda can be called elegant. It seems to be a sort of "fast and dirty" hack more than anything) than I can think of.

And I see what I stuffed up with the button assignments (still trying the gxy thing). Its not a method of programming that I've considered before - in fact, its a bit confusing at first glance - a 3D array of buttons for something that comes out to be essentially a 2D grid.

I'm still not exactly sure what your doing with the command thing. Shouldn't we just be able to use the xpos, ypos and zpos attributes in it? Just command = cmd(xpos, ypos, zpos), making cmd look something like this

Code

def cmd(self, x, y, z):
      if turn == "red":    #Change what colour's turn it is through a global variable. Assume it's initially set to "red"
           turn = "black"
      else:
           turn = "red"
      self.ButtonMatrix[x][y][z].config(color=turn) #yes, this should be first. But this is just an example

I don't see why we would need to use lambda.

Added (2009-09-26, 2:57 Pm)
---------------------------------------------
the uselessness of cmd() in my noddy program is just because I was too lazy to make it do anything. I had already demonstrated my point through the creation of the buttons. (the whole dynamically naming them)


~ Click it
 
Dr4c0niusDate: Sunday, 2009-09-27, 12:47 PM | Message # 17
Major
Group: Users
Messages: 96
Awards: 2
Reputation: 0
Status: Offline
There is NO way of specifying which variables to pass to the command tkinter calls without using a dummy function to wrap the function you want to call. I googled the issue and all I could find was either use lambda or make a whole buch of functions.

The reason that happens it because when you write a functions name you give tkinter the memory location of the function so tkinter can find it, but when you add () to the end of a function python treats it like a data type and returns the RESULT of the function being called. If you look at lambda you will notice that lambda is not called, it is simply referenced.

Try both for yourself, it doesn't work. The correct text prints, but it prints when you load the program, and nothing happens when you click either button. Thats because you have told python to call the function, rather than told it where to find the function.

As regards the button assignments, I started off thinking of the game as 3 dimensional, and i realised that checking for rows would be easier if it was a single 3D array rather than 3 different 2D arrays.


Oderint dum metuant

<locokamil> Your belief system is thermodynamically unsound.

 
HaydenJohnsDate: Monday, 2009-10-05, 2:14 PM | Message # 18
Lieutenant colonel
Group: Checked
Messages: 123
Awards: 0
Reputation: 0
Status: Offline
that makes sense. we should probably start to code it.

I would right now, except our desktop's USB ports have died and I'm trying to fix it. I'm saving everyones stuff (trying to FTP everything off of it)

Added (2009-10-05, 2:14 Pm)
---------------------------------------------
well, we fail at coding together.

ah, well. we had a good discussion which expanded my knowledge, to say the least. Did u get anything out of it?


~ Click it
 
Dr4c0niusDate: Tuesday, 2009-10-06, 4:15 PM | Message # 19
Major
Group: Users
Messages: 96
Awards: 2
Reputation: 0
Status: Offline
Yeah. sorry about my absence from the forums. Our home router broke (second one in about a year) and i didn't have internet access for a while. All set up now, but that sort of killed the project for the time I was away. I apologise.

Would it be possible to leave this until after exams? I would be happy to work on it with you but I'm going to be rather short of time.

When we do get around to it I recommend we make a list of what data structures will be needed and work out the data flow, then program a set of functions each, passing them along to the other person and checking for errors and problems then putting it into the program as a whole.


Oderint dum metuant

<locokamil> Your belief system is thermodynamically unsound.

 
HaydenJohnsDate: Wednesday, 2009-10-07, 11:22 AM | Message # 20
Lieutenant colonel
Group: Checked
Messages: 123
Awards: 0
Reputation: 0
Status: Offline
Fair enough. I got distracted during the holidays, and I'm at the theatre all weekend for the next few weeks (playing trumpet for a musical). Until after exams.

Even if it never ends up happening, our discussion about the concepts involved was beneficial for me at least.


~ Click it
 
Forum » Software Development » RE:Work » No more python? (Is this really all we learn?)
  • Page 1 of 1
  • 1
Search: