Multiplayer Tic-tac-toe [C2][Web2py(Python)][AJAX][Cross-domain]

Index

Attached Files

The following files have been attached to this tutorial:

.capx

space-tic-tac-toe.capx

Download now 7 MB
.zip

web2py-files.zip

Download now 4 KB

Stats

1,851 visits, 5,151 views

Translations

This tutorial hasn't been translated.

Tools

About the server code

As I've read quite a few tutorials here, I saw that cross-domain calls were held as something difficult. So I decided to give it a shot and now I'm providing a working solution for you to evaluate yourself.

What we do with web2py

So, what functionality of web2py do we use here?

Well we use "run" service and DAL(database abstraction layer).

In the default.py file you'll find a function named call(), it allows to decorate other functions with a @service.(run/xml/json/csv... and others) in my example I use the @service.run decorator.

Which means if I define a function say_hello, which takes a name you provide and returns it with a hello:

    @service.run
    def say_hello(name):
        return "hello "+name

I'll be able to access it in a few ways:

1) 127.0.0.1/welcome/default/call/run/say_hello/Tom

2) 127.0.0.1/welcome/default/call/run/say_hello

If the function takes in more variables it would be expanded like:

1) ...say_hello/Tom/Jhon/Nick

2) ...say_hello?name=Tom&name2=Jhon&name3=Nick

I chose the first option as it seems more simple to work with, though you could potentially mistake the order of the variables if working with many. For example by sending ID,Name,Move when the function takes ID,Move,Name. So it's up to you, to choose how you want to formulate your request.

Now the DAL is a nice thing, cause if you use SQLite on your machine, but you want to upload it to some website which only has MySQL or say PostgreSQL databases. All you have to change is the connection string to the database, all your other code stays the same.

AS of now, our database looks like:

    db.define_table('rooms',
                Field('Player_count','integer',default=0),
                Field('P1_id','integer',default=0),
                Field('P1_name','string',default=""),
                Field('P2_id','integer',default=0),
                Field('P2_name','string',default=""),
                Field('TS1','integer',default=0), #Tack 1 state 
                Field('TS2','integer',default=0),
                Field('TS3','integer',default=0),
                Field('TS4','integer',default=0),
                Field('TS5','integer',default=0),
                Field('TS6','integer',default=0),
                Field('TS7','integer',default=0),
                Field('TS8','integer',default=0),
                Field('TS9','integer',default=0),
                Field('New_tac',default=10),
                Field('P_turn','integer',default=0),
                Field('Is_over','integer',default=0),
                )
    db.define_table('room_count',
                Field('total','integer',default=0))

The database "rooms" contains the information:

1) number of players in the room

2) p1 id

3) p1 name

..

6) the valiue of the first position, taking that the 9 rock field is represented in the fashion

1 2 3

4 5 6

7 8 9

..

15) The position which was changed on the last move, so we wouldn't have to send all of the 9 variables to see which one changed

16) Which players turn is it now

17) Is the game over

The "room_count" database, just keeps score of how many rooms exist in the database at the moment. When it hits 10000 the databases are wiped and if you were playing in room 9999 at that time, I'm sorry, it's just a fail-safe :)

Game functions on the server

The server-side of the game consists of 4 main functions:

1) join_room(nickname);

2) check_for_player2(r_id,p_id);

3) set_your_tac(r_id,p_id,t_pos);

4) get_tac_info(r_id,p_id);

And 2 helper functions:

1) is_game_over(tack_list,player_number,new_tack)

2) tac_update(room_id,player_number,tack_position)

The function names probably describe them enough. And I'll go into more detail of the python code in a revision of the tutorial if requested. For now I'll leave it at that.

For cross-domain access every function has a:

response.headers["Access-Control-Allow-Origin"] = client_address

The "client address" variable is located in the top of the default.py file text, so you wouldn't have to rewrite the access header value in every function:

client_address='*' - means requests from any domain will be accepted.

If set it to an address like:

client_address='http://zerostatesociety.com' - requests will only accepted from this domain

  • 0 Comments

  • Order by
Want to leave a comment? Login or Register an account!