Jump to content


Check out our Community Blogs

DanielTan

Member Since 22 Jul 2013
Offline Last Active Apr 16 2014 04:09 PM
-----

Posts I've Made

In Topic: D Programming Language.

14 April 2014 - 06:12 PM

I find D actually suits me, someone who loves Python well, in spite of all the curly braces and small library(compared to python). Too bad D does not really have a mature IDE of it's own yet (Codeblocks works well though)


In Topic: Tkinter ball snake game

04 August 2013 - 06:36 PM

Right, now then, we would want to add some goals for our game, and I'll set it to be getting the highest points within a minute. Going along that, let's write some code for food that will give points, and to give a better challenge, let our ball grow.

def create_food(self,ball):
        if len(self.foodX) <self.time//1500 +1:
            self.foodX.append(randint(50,250))
        if len(self.foodY) <self.time//1500 +1:
            self.foodY.append(randint(50,250))
        for i in range(0,len(self.foodX)):
            self.canvas.create_rectangle(self.foodX[i], self.foodY[i], self.foodX[i]+10, self.foodY[i]+10, fill="blue")
        for i in range(0,len(self.foodX)):
            if len(self.canvas.find_overlapping(self.foodX[i], self.foodY[i], self.foodX[i]+10, self.foodY[i]+10)) is not 1:
                if ball in self.canvas.find_overlapping(self.foodX[i], self.foodY[i], self.foodX[i]+10, self.foodY[i]+10):
                    self.point+=100
                    self.size+=0.5 
                    self.foodX.pop(i)
                    self.foodY.pop(i)
                    self.create_food(ball)

I have used the canvas.find_overlapping as a collision handler for the food (It will eat it if it touches it), but you can also change it to <find_enclosed> so that it will devour it only if the food is inside the circle. 

The increased size can be a boon or bane for the player because next, we will also be creating traps to cut the game points and decrease the size.

def create_trap(self,ball):
        if len(self.trapX) <self.time//1500 +1:
            self.trapX.append(randint(50,250))
        if len(self.trapY) <self.time//1500 +1:
            self.trapY.append(randint(50,250))
        for i in range(0,len(self.trapX)):    
            self.canvas.create_rectangle(self.trapX[i], self.trapY[i], self.trapX[i]+10, self.trapY[i]+10, fill="red")            
        for i in range(0,len(self.trapX)):
            if len(self.canvas.find_overlapping(self.trapX[i], self.trapY[i], self.trapX[i]+10, self.trapY[i]+10)) is not 1:
                if ball in self.canvas.find_overlapping(self.trapX[i], self.trapY[i], self.trapX[i]+10, self.trapY[i]+10):
                    self.point-=50
                    self.size-=1
                    self.trapX.pop(i)
                    self.trapY.pop(i)
                    self.create_trap(ball)

The [self.time//1500] code means that squares will increase every 15 seconds (time is ticked by the millisecond).

The blue square is food while the red square is a trap.

 

Attached File  game4.gif   14.39KB   138 downloads

 

Then we'll also be doing some powerups, that will appear for about a second and a half, every ten seconds.

def create_powersize(self,ball):
        if len(self.trapY) is 0 or self.time%1000 == 0 :
            self.powerupX[0].append(randint(50,250))
            self.powerupY[0].append(randint(50,250))      
        for i in range(0,len(self.powerupX[0])):    
            self.canvas.create_rectangle(self.powerupX[0][i], self.powerupY[0][i], self.powerupX[0][i]+10, self.powerupY[0][i]+10, fill="yellow")            
        for i in range(0,len(self.powerupX[0])):
            if len(self.canvas.find_overlapping(self.powerupX[0][i], self.powerupY[0][i], self.powerupX[0][i]+10, self.powerupY[0][i]+10)) is not 1:
                if ball in self.canvas.find_overlapping(self.powerupX[0][i], self.powerupY[0][i], self.powerupX[0][i]+10, self.powerupY[0][i]+10):
                    self.point+=150
                    self.size+=2
                    self.powerupX[0].pop(i)
                    self.powerupY[0].pop(i)
                    self.create_powersize(ball)

    def create_powercoin(self,ball):
        if len(self.trapY) is 0 or self.time%1000 == 0 :
            self.powerupX[1].append(randint(50,250))
            self.powerupY[1].append(randint(50,250))      
        for i in range(0,len(self.powerupX[1])):    
            self.canvas.create_rectangle(self.powerupX[1][i], self.powerupY[1][i], self.powerupX[1][i]+10, self.powerupY[1][i]+10, fill="yellow")            
        for i in range(0,len(self.powerupX[1])):
            if len(self.canvas.find_overlapping(self.powerupX[1][i], self.powerupY[1][i], self.powerupX[1][i]+10, self.powerupY[1][i]+10)) is not 1:
                if ball in self.canvas.find_overlapping(self.powerupX[1][i], self.powerupY[1][i], self.powerupX[1][i]+10, self.powerupY[1][i]+10):
                    self.point+=500
                    self.size-=0.5
                    self.powerupX[1].pop(i)
                    self.powerupY[1].pop(i)
                    self.create_powercoin(ball)

Now then, let's put everything into our <paint> code and voila! the basic game is completed.

from tkinter import *
from random import*

'''New game to illustrate the use of tkinter to make a game that can handle collisions.
'''


class game:
    def __init__(self):
        self.root=Tk()
        self.RUN=False
        
        self.frame=Frame(bg="black")
        self.frame.pack();
        
        self.canvas=Canvas(self.frame, bg="black",width=300,height=300)
        self.canvas.pack()
        
        self.clock=Label(self.frame, bg="black", fg="white")
        self.clock.pack()
        self.points=Label(self.frame, bg="black", fg="white")
        self.points.pack()
        self.button=Button(self.frame, bg="black", fg="white", text="Click to start" ,command=self.start)
        self.button.pack()
        
        self.root.mainloop()

    def start(self):
        self.time=0
        self.RUN=True
        
        self.foodX=[]
        self.foodY=[]

        self.trapX=[]
        self.trapY=[]

        self.powerupX=[[],[]]
        self.powerupY=[[],[]]

        self.TEXT="Welcome to tkinter"
        self.point=0
        
        self.x=100
        self.y=100
        self.tempx=100
        self.tempy=100
        self.UP=False
        self.DOWN=False
        self.LEFT=False
        self.RIGHT=False

        self.size=3
        self.canvas.bind("<ButtonPress-1>", self.onMClick)
        self.run()

    def run(self):
        if self.RUN is True:
            self.time+=1
            self.clock['text']="TIME:" + str(self.time//100)
            self.points['text']="Points gathered: " + str(self.point)
            self.move(10*self.size,2)
            self.paint()
            self.root.after(10, self.run)

    def end(self):
        self.RUN=False
        self.canvas.unbind("<ButtonPress-1>")

    def create_food(self,ball):
        if len(self.foodX) <self.time//1500 +1:
            self.foodX.append(randint(50,250))
        if len(self.foodY) <self.time//1500 +1:
            self.foodY.append(randint(50,250))
        for i in range(0,len(self.foodX)):
            self.canvas.create_rectangle(self.foodX[i], self.foodY[i], self.foodX[i]+10, self.foodY[i]+10, fill="blue")
        for i in range(0,len(self.foodX)):
            if len(self.canvas.find_overlapping(self.foodX[i], self.foodY[i], self.foodX[i]+10, self.foodY[i]+10)) is not 1:
                if ball in self.canvas.find_overlapping(self.foodX[i], self.foodY[i], self.foodX[i]+10, self.foodY[i]+10):
                    self.point+=100
                    self.size+=0.5 
                    self.foodX.pop(i)
                    self.foodY.pop(i)
                    self.create_food(ball)

    def create_trap(self,ball):
        if len(self.trapX) <self.time//1500 +1:
            self.trapX.append(randint(50,250))
        if len(self.trapY) <self.time//1500 +1:
            self.trapY.append(randint(50,250))
        for i in range(0,len(self.trapX)):    
            self.canvas.create_rectangle(self.trapX[i], self.trapY[i], self.trapX[i]+10, self.trapY[i]+10, fill="red")            
        for i in range(0,len(self.trapX)):
            if len(self.canvas.find_overlapping(self.trapX[i], self.trapY[i], self.trapX[i]+10, self.trapY[i]+10)) is not 1:
                if ball in self.canvas.find_overlapping(self.trapX[i], self.trapY[i], self.trapX[i]+10, self.trapY[i]+10):
                    self.point-=50
                    self.size-=1
                    self.trapX.pop(i)
                    self.trapY.pop(i)
                    self.create_trap(ball)

    def create_powersize(self,ball):
        if len(self.trapY) is 0 or self.time%1000 == 0 :
            self.powerupX[0].append(randint(50,250))
            self.powerupY[0].append(randint(50,250))      
        for i in range(0,len(self.powerupX[0])):    
            self.canvas.create_rectangle(self.powerupX[0][i], self.powerupY[0][i], self.powerupX[0][i]+10, self.powerupY[0][i]+10, fill="yellow")            
        for i in range(0,len(self.powerupX[0])):
            if len(self.canvas.find_overlapping(self.powerupX[0][i], self.powerupY[0][i], self.powerupX[0][i]+10, self.powerupY[0][i]+10)) is not 1:
                if ball in self.canvas.find_overlapping(self.powerupX[0][i], self.powerupY[0][i], self.powerupX[0][i]+10, self.powerupY[0][i]+10):
                    self.point+=150
                    self.size+=2
                    self.powerupX[0].pop(i)
                    self.powerupY[0].pop(i)
                    self.create_powersize(ball)

    def create_powercoin(self,ball):
        if len(self.trapY) is 0 or self.time%1000 == 0 :
            self.powerupX[1].append(randint(50,250))
            self.powerupY[1].append(randint(50,250))      
        for i in range(0,len(self.powerupX[1])):    
            self.canvas.create_rectangle(self.powerupX[1][i], self.powerupY[1][i], self.powerupX[1][i]+10, self.powerupY[1][i]+10, fill="yellow")            
        for i in range(0,len(self.powerupX[1])):
            if len(self.canvas.find_overlapping(self.powerupX[1][i], self.powerupY[1][i], self.powerupX[1][i]+10, self.powerupY[1][i]+10)) is not 1:
                if ball in self.canvas.find_overlapping(self.powerupX[1][i], self.powerupY[1][i], self.powerupX[1][i]+10, self.powerupY[1][i]+10):
                    self.point+=500
                    self.size-=0.5
                    self.powerupX[1].pop(i)
                    self.powerupY[1].pop(i)
                    self.create_powercoin(ball)
            
    def paint(self):
        self.canvas.delete(ALL)
        self.canvas.create_text(100,100, text=self.TEXT, fill="green")

        if self.time//100<=60:
            if 10*self.size >0:
                self.TEXT="Welcome to tkinter"
                ball=self.canvas.create_oval(self.x-10*self.size,self.y-10*self.size,self.x+10*self.size,self.y+10*self.size, fill="white")
                self.create_food(ball)
                self.create_trap(ball)
                if self.time%1000 <=100 :
                    if randint(0,100)%2==0:
                        self.create_powersize(ball)
                    else:
                        self.create_powercoin(ball)
            elif 10*self.size>150:
                self.clock['text']="You lost"
                self.end()
            else:
                self.clock['text']="You lost"
                self.end()
        else:
            self.clock['text']="Time's up"
            self.end()
        
    def move(self, b,speed):
        if self.UP==True and self.y-b>0:
            self.y-=speed
        elif self.UP==True and self.y-b<=0:
            self.UP=False
            self.DOWN=True
        if self.DOWN==True and self.y+b<300:
            self.y+=speed
        elif self.DOWN==True and self.y+b>=300:
            self.DOWN=False
            self.UP=True
        if self.LEFT==True and self.x-b>0:
            self.x-=speed
        elif self.LEFT==True and self.x-b<=0:
            self.LEFT=False
            self.RIGHT=True
        if self.RIGHT==True and self.x+b<300:
            self.x+=speed
        elif self.RIGHT==True and self.x+b>=300:
            self.RIGHT=False
            self.LEFT=True

    def onMClick(self,event):
        self.tempx=event.x
        self.tempy=event.y
        if event.x> self.x and self.x is not self.tempx :
            self.RIGHT=True
            self.LEFT=False
        elif event.x< self.x and self.x is not self.tempx :
            self.LEFT=True
            self.RIGHT=False
        else:
            self.x=self.tempx    
            self.RIGHT=False
            self.LEFT=False
        if event.y> self.y and self.y is not self.tempy :
            self.DOWN=True
            self.UP=False
        elif event.y< self.y and self.y is not self.tempy :
            self.UP=True
            self.DOWN=False
        else:
            self.y=self.tempy
            self.DOWN=False
            self.UP=False
        

app=game()        

The game will look something like this:

Attached File  game5.gif   15.44KB   134 downloads

 

That's it for now! :)

 


In Topic: 100 ways to print out "Hello CodeCall"

25 July 2013 - 03:28 AM

There's always still python  ;)

#101 python

from tkinter import *

class main:
    def __init__(self):
        self.mess=messagebox.showinfo("Test", "Hello Codecall")
        
main=main()

In Topic: Tkinter Tic Tac Toe tutorial

23 July 2013 - 05:37 AM

There was some bug with the game AI in ticTT.py so I attached a new version, ticTT2.py, complete with documentation and complete AI(the original only had two aspects of game AI)

 

Attached File  ticTT2.py   13.91KB   2212 downloads

 

This is how the interface looks like:

Attached File  GUITTT1.gif   27.78KB   153 downloads

Now then, on to the single player programming, working from the main class we had(with double players).

First, we will start by initiating our single player function, self.start2()

def start2(self):
        #Starts single player
        self.canvas.delete(ALL)
        self.label['text']=('Tic Tac Toe Game')
        self.canvas.bind("<ButtonPress-1>", self.dgplayer)  
        self._board()
        self.TTT=[[0,0,0],[0,0,0],[0,0,0]]
        self.i=0
        self.j=False
        #Trigger to check the validity of the move
        self.trigger=False

Note that it's almost the same as the double player function, except that this binds self.dgplayer and an extra self.trigger boolean variable, which we will be using later in the code.

 

then, it's on to the single player code. This time, we'll just copy paste the double player function, and simply change the second player into our game AI player.

def dgplayer(self,event):
        for k in range(0,300,100):
            for j in range(0,300,100):
                if self.i%2==0:
                    if event.x in range(k,k+100) and event.y in range(j,j+100):
                        if self.canvas.find_enclosed(k,j,k+100,j+100)==():
                            X=(2*k+100)/2
                            Y=(2*j+100)/2
                            X1=int(k/100)
                            Y1=int(j/100)
                            self.canvas.create_oval( X+25, Y+25, X-25, Y-25, width=4, outline="black")
                            self.TTT[Y1][X1]+=1
                            self.i+=1
                            self.check()
                            self.trigger=False                           
                else:
                    #check for wins/losts/draws first 
                    #before allowing the computer to make its turn
                    self.check()
                    #Game AI code
                    self.AIcheck()
                    #refresh validity of move
                    self.trigger=False

Note that we should check if the game has ended before we let the AI player play. 

 

Now then, comes the tricky part of designing an AI player.

 

Keep a few things in mind when coding an AI player:

1) Keep your code concise and precise as the AI is going to play every game loop。

2) Reuse your code if possible. Identify parts that keep repeating and write a function for it.

3) If possible, list out all the conditions that the player will meet.

4) There are three aspects of the game AI:Offense, Defense and Neutral.

 

Right, before I started coding, I played tic tac toe for some time and noted down what I did and what I thought at which conditions, which was basically doing (3) from above.

In this game:

 

1) the player starts first. If he chooses the center, the second player is going to have a tough time. If not, then the second player might just get the center.

2) I might not know what to do on the second move.

3) By the second and third move, I will start to attack, or block the other guy's attack. 

4) I need to check the whole board for solutions. 

5) Repeated draws circles or crosses.

 

From this, I gather that:

1)The AI needs to try to get the center.

2) There is a need for a random move function.

3) I need a function to loop through every row, column and diagonal to attack or defend.

4) I might need a function to draw circles and crosses.

 

And with that in mind, let's start writing code with (4) from the latter.

The circle drawing has been taken care of (in the self.dgplayer function)so we'll have to write code for the cross.

def cross(self, k, j):
        # k is the x coords
        # j is the y coords
        X=(200*k+100)/2
        Y=(200*j+100)/2
        X1=int(k)
        Y1=int(j)
        self.canvas. create_line( X+20, Y+20, X-20, Y-20, width=4, fill="black")
        self.canvas. create_line( X-20, Y+20, X+20, Y-20, width=4, fill="black")
        self.TTT[Y1][X1]+=9
        self.check()
        self.i+=1
        self.trigger=True

Now then, we'll move on to the randmove function, which is (2)

def randmove(self):
        # In case there's nothing for the computer to do
        while True:
            k=(randint(0,2))
            j=(randint(0,2))
            if self.TTT[j][k]==0:
                self.cross(k,j)
                break
            else:
                k=(randint(0,2))*100
                j=(randint(0,2))*100

Our matrix, self.TTT has only, 0,1,2, elements.

 

Then it's time for the juiciest part, the AIcheck function, which loops through every part of the matrix in search of a loophole.

Since the AI should have a desire to win, we should put OFFENSE code at the top (first to loop through), then DEFENSE, then finally NEUTRAL (when everything is exhausted)

Using self.trigger to signal that a move has been made eliminates the need for the error-prone elif statement ( since the code might jump here and there )

Again, we should recycle code that has already been written to save time and energy. 

We'll recycle the check function to check for two circles or crosses in a row, then write the corresponding code to check for an empty space and draw a cross

Here's the code in it's full glory.

def AIcheck(self):
        #Offense should come before defense so that the AI will try to win if possible
        #This is built on the self.check function
        self.ttt=[[row[i] for row in self.TTT] for i in range(3)]
        #OFFENSE
        #this is the vertical checklist    
        for h in range(0,3):
            k=0
            j=0
            if sum(self.TTT[h])==18:
                while k <3:
                    if k==h:
                        while j <3:
                            if self.trigger==False:
                                if self.TTT[k][j]==0:
                                    self.cross(j,k)
                                    break
                            j+=1
                    k+=1
        #this is the horizontal checklist    
        for h in range(0,3):
            k=0
            j=0
            if sum(self.ttt[h])==18:                        
                while k <3:
                    if k==h:
                        while j <3:
                            if self.trigger==False:
                                if self.ttt[k][j]==0:
                                    self.cross(k,j)
                                    break
                            j+=1
                    k+=1
        #this is the diagonal checklist    
        if self.TTT[1][1]==9:
            if self.TTT[0][0]==9:
                if self.trigger==False:
                    if self.TTT[2][2]==0:
                        self.cross(2,2)
            if self.TTT[0][2]==9:
                if self.trigger==False:
                    if self.TTT[2][0]==0:
                        self.cross(0,2)
            if self.TTT[2][0]==9:
                if self.trigger==False:
                    if self.TTT[0][2]==0:
                        self.cross(2,0)
            if self.TTT[2][2]==9:
                if self.trigger==False:
                    if self.TTT[0][0]==0:
                        self.cross(0,0)
        #DEFENSE
        #this is the horizontal checklist    
        for h in range(0,3): 
            k=0
            j=0            
            if sum(self.TTT[h])==2:
                while k <3:
                    if k==h:
                        while j <3:
                            if self.trigger==False:
                                if self.TTT[k][j]==0:
                                    self.cross(j,k)
                                    break
                            j+=1
                    k+=1
        #this is the vertical checklist
        for h in range(0,3):
            k=0
            j=0
            if sum(self.ttt[h])==2:                        
                while k <3:
                    if k==h:
                        while j <3:
                            if self.trigger==False:
                                if self.ttt[k][j]==0:
                                    self.cross(k,j)
                                    break
                            j+=1
                    k+=1                    
        #this is the diagonal checklist
        if self.TTT[1][1]==1:
            if self.TTT[0][0]==1:
                if self.trigger==False:
                    if self.TTT[2][2]==0:
                        self.cross(2,2)
            if self.TTT[0][2]==1:
                if self.trigger==False:
                    if self.TTT[2][0]==0:
                        self.cross(0,2)
            if self.TTT[2][0]==1:
                if self.trigger==False:
                    if self.TTT[0][2]==0:
                        self.cross(2,0)
            if self.TTT[2][2]==1:
                if self.trigger==False:
                    if self.TTT[0][0]==0:
                        self.cross(0,0)
        #NEUTRAL
        if self.TTT[1][1]==0:
            if self.trigger==False:
                self.cross(1,1)
                self.trigger=True
        else:
            if self.trigger==False:
                self.randmove()

I used while loops since the break statement is damn useful when I want to stop the loop after the move has been made.

Since we used a function to draw the cross, the code remains clean and easily understood. 

I did not use a for loop for the diagonal checking since there are just 4 cases and it isn't worth the effort to design a for loop for this when we could have just copy pasted, and also since it's easy to maintain.

 

And we're done! Just put everything in, and you've a functional AI player! 

 

Also, you can change the "personality" of your AI by changing the order of the OFFENSE, DEFENSE, NEUTRAL code. Try it out! LOL

 

I'm welcome to comments and bug explorers. Happy coding(and playing)!

 

 

This is a screenshot of an endgame:

Attached File  GUITTT2.gif   27.25KB   157 downloads


In Topic: Java:Tutorial - Tic-Tac-Toe

22 July 2013 - 04:29 AM

You also could have use a 2d array to store int values to mean cross and circles, then do summation to see if they add up to the winning scores

 

i.e. cross =>1, circle =>9, cross win=>3, circle win=>27 

 

instead of using boolean calculation because they are three states: null, circle, cross,since you're already using an array to set up the buttons.
I tried it in python and it works fine. Also it keeps the code clean because you don't have to manually check every row/column.


Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download