DEV Community

Cover image for Noughts and Crosses using pygame and socket programming
Debasmita Das
Debasmita Das

Posted on

Noughts and Crosses using pygame and socket programming

I participated in 'Ten Days Of Code' conducted by GNU/Linux Users' Group, NIT Durgapur. The project was divided into 4 subtasks and for each subtask we could make a PR which was counted towards completing the Hacktoberfest Challenge.

The problem statements regarding the tasks are here :
https://drive.google.com/drive/u/0/folders/17IKIx3HlIeR6tP5N2IAPBQqFhtvywS1w

You can find my code according to the subtasks given here:
https://github.com/Debasmita-01/TDoC-Noughts-and-Crosses

In this blog I will be helping you to start with socket programming and finally build the multiplayer tic tac toe .However you should be having basic knowledge of python.

You can refer to the following video to learn the basics of python or brush up your memory.
https://www.youtube.com/watch?v=_uQrJ0TkZlc

For socket programming:
https://www.youtube.com/playlist?list=PLhTjy8cBISErYuLZUvVOYsR1giva2payF
So after you watch these videos you are ready to start!

TASK 1:

Problem Statement Ping-Pong Clients

Make 2 client files which send data to each other using two different ports. One should send data (ex. "PING") and then receive some data (ex. "PONG"). While the other should first receive data and then send an appropriate response.

First initialize a socket connection and connect it to different network interfaces, for testing you can use the same hostname: localhost and different ports using socket.gethostname(). Sending data is done using sendto() method. It accepts as arguments, the data and the network interface address as a tuple containing hostname and port number. Receiving data is done using the recv()function; it needs a buffsize argument to denote the size of the data packet to be received. P.S Also do not forget to encode and decode the data.

I made two files ncserver.py and ncclient.py.

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #making a socket instance and passed in two parameters
host='127.0.0.1'
port=12345 #reserving a port 
s.bind((host,port))
s.listen(5) # listening mode
Enter fullscreen mode Exit fullscreen mode

So I followed the usual order of methods:

1)socket()

2)bind()

3)listen()

4)accept()

Resources you can check out:

1)https://docs.python.org/3/library/socket.html

2)https://drive.google.com/file/d/17MDkLEWeBajEyqu-LzXZOhgxW9ZIUqv1/view?usp=sharing

3)https://drive.google.com/file/d/1jaNf0lfPFdChh5KhM1nAlCHPgy6wTrnQ/view?usp=sharing

TASK 2:
Subtask-1

Let’s create our first client and server. We’ll begin with a simple implementation. The server will simply echo
whatever it receives back to the client.

Subtask-2

Now in this part, the server will be handling more than 1 client simultaneously, which can be achieved by threading.

TO BE DONE :

Subtask-1 is fairly simple, almost similar to the first one except the fact that this time the server will echo whatever the client sends.

Subtask-2 is just an extension of Subtask-1.You should be having a basic knowledge of threading. You can check out here to brush up your concepts on threading.Now the main reason why threading is required is because when you handle one client you are receiving and sending data continuously which is basically an infinite loop. Now while this is going, normally the program will not be able to accept other clients, since its stuck in the loop. So, each connection to a client is threaded, and those thread will run simultaneously. Basically, because of one client(a thread) the other clients don't have to wait. That is the main reason why we need threads for this problem.

import socket, threading
class ClientThread(threading.Thread):
    def __init__(self,clientAddress,clientsocket):
        threading.Thread.__init__(self)
        self.csocket = clientsocket
        print ("New connection added: ", clientAddress)
Enter fullscreen mode Exit fullscreen mode
TASK-3:

CLI BASED TIC-TAC-TOE

Problem statement task-3

I hope that you are familiar with the rules of the tic-tac-toe game. If not here you go:

GAME LOGIC :game completion logic check row-wise, column-wise and diagonally for matches also if total number of moves is 9 without a winner then the game would end in a draw.

Here you can go through my codes for tic_tac_toe_client.py and tic_tac_toe_server.py
I have written comments beside each and every function which will help you understand the logic. You can do it without importing re module also.

#if the client has sent a quit message, then break out of the loop
            if(re.search("quit the game", client_move)):
                print(client_move)
                break
#else, convert the client's move to integer type
            else:
                client_move = int(client_move)
Enter fullscreen mode Exit fullscreen mode

The re module offers a set of functions that allows us to search a string for a match:

Function Description
findall Returns a list containing all matches
search Returns a Match object if there is a match anywhere in the string
split Returns a list where the string has been split at each match
sub Replaces one or many matches with a string

For the client and server script its simple socket programming which we have done in the first two tasks.

TASK-4(The Final Task)

Build the game interface using pygame and make it multiplayer with sockets.

So I made three files here servermain.py , clientmain.py and grid.py.For the server side and the client side it are the usual things we have been doing so far.So lets concentrate on the new file grid.py.I have added comments beside each and every line of my task 4 codes so you can check out.

import pygame
import os
Enter fullscreen mode Exit fullscreen mode

I imported os for setting up the relative position of the window.

os.environ['SDL_VIDEO_WINDOW_POS'] = '200,100'  #setting the relative position of the window
Enter fullscreen mode Exit fullscreen mode

This is how the grid will look like

Alt Text

In my grid each cell is 200 X 200. You can set it up to any height and width according to your choice just remember to do the calculation accordingly. Whatever is your cell size put your image size x.png, y.png same.(in my case 200 pixels X 200 pixels)

This is the way to link your images.
letterX = pygame.image.load(os.path.join('imgs', 'x.png')) # adding the images
letterO = pygame.image.load(os.path.join('imgs', 'o.png')) # adding the images
Enter fullscreen mode Exit fullscreen mode

Finally import all the modules required in the main files.

import pygame
from grid import Grid
import os
import threading
import socket
Enter fullscreen mode Exit fullscreen mode

FINAL LOOK

Alt Text

LINK TO THE RESOURCES:

https://drive.google.com/file/d/183vlpHd2tKGp9nfLGCQ4DUPPfuSH_a8c/view?usp=sharing

Top comments (0)