SoFunction
Updated on 2024-11-21

A pygame implementation of Tic-Tac-Toe's second logical move.

I. Preface

We're inPrevious Blog.The implementation of the nine-grid drawing in has laid the groundwork for us.
This time we'll implement basic logic, such as the logic for determining winners and losers, and for the player and computer to play separately.

II. Playing Chess

2.1 Players

We've done this before inLatticeclass, there is a stats variable to represent the state of the grid.

# 0 for initial, 1 for personal - 1 for computer
 = 0

So playing chess is essentially modifying this variable.
First of all, we are using mouse clicks to implement chess, so the event response section should be modified:

for event in ():
		# Exit
        if  == :
            ()
        # Click the mouse
        elif  == :
        	# Get the position of the mouse click
            mouse_x, mouse_y = .get_pos()
            for i in rect:
                # Make sure the player's next
                if  not  and (mouse_x,mouse_y):
                	 = -1

Modules are mainly responsible for events in the game.
The first event indicates that clicking the close button in the upper right corner of the interface exits the program;
The second event is a mouse click, and you can use .get_pos to get the click position.
Since the previous lattice (the Lattice class) had an instance of the rect class, we can use the collidepoint function, passing in the coordinates to determine which lattice it is in.
Subsequently we need to determine if the grid is occupied or not, and if it's not, then we can modify stats.

2.2 Computers

For computers, the reality is pretty much the same, but we chose to generate it randomly:

def computer():
    """Computer's turn. Randomly generate a location."""
    global judge
    random_num = [i for i in range(len(rect)) if not rect[i].stats]
    # There's no room, it's a draw
    if not random_num:
        judge = 1
        print("draw")
        exit()
    rect[(random_num)].stats = 1
    return #result = Button("your choice")

We first give all the unoccupied grids and use list parsing to form a list.
If the list is empty and no bits are played, it's a draw (after each drop, there is a win/loss judgment, more on that later);
Instead, we'll use a function that selects an element in the list (this element is an instance of the Lattice class) and changes its stats to 1.

judge This is a flag to determine if the game is over, initially 0.

III. Winning and losing judgments

This one might be a bit of a pain in the ass.
Here, my idea is to have a subscript for each grid and write out the subscripts for all possible winning grid combinations.

 win_list = [
    	# Row
        [0, 1, 2],
        [3, 4, 5],
        [6, 7, 8],
        # Columns
        [0, 3, 6],
        [1, 4, 7],
        [2, 5, 8],
        # Diagonal
        [0, 4, 8],
        [2, 4, 6]
    ]

在这里插入图片描述

Subsequently, we use the same list parsing to form two lists of all stats of 1 and -1:

 stats1 = [i for i in range(len(rect)) if rect[i].stats == 1]
    stats2 = [i for i in range(len(rect)) if rect[i].stats == -1]

So here's the problem, in stats1 and 2, only some of the elements may be in win_list, instantly finding the fear of being dominated by leecode.

 for i in win_list:
    	# Take out every possible winning condition
        if i == [j for j in i if j in stats1]:
            judge = 1
            print("Computer win!")
            exit()
        elif i == [j for j in i if j in stats2]:
            judge = 1
            print("You win!")
            exit()

Our logic is to take out each element for each possible winning combination and look it up in the stats list, and if we can find them all, the result of the list parser must be the same as the original winning combination, at which point we can determine that one side has won.

IV. One Man, One Son

Tic-Tac-Toe is played in much the same way as Backgammon, so it must be done so that the computer can make a move after the player has made a move.
(Normal computers can react much faster than players.

It's certainly possible to set a variable with 0 and 1 to indicate who's due to play, but I have a better option - outputting after a player has played.

if  not  and (mouse_x,mouse_y):
# Players playing chess
 = -1
win_or_lose()
# Computer chess
computer()
win_or_lose()

There's also the issue that we need to make a judgment call on winning or losing, regardless of which side has played.

V. Display issues

When you're done with the above, you'll realize that you can't actually see anything on the screen.
Because we don't have an icon showing the grid yet.
Here I chose to use the classic 'x' and 'o' and implement it with rendered text. (You can also find your own image to paste on this part)

Steps for rendering text:

  • = Setting fonts
  • function that generates an image with text information
  • Align the image by processing it into a rectangle using the get_rect method
  • Rendering with the blit method

Documentation:

import pygame
class Lattice():
    def __init__(self,rect,screen):
         = rect
         = screen
        # 0 for initial, 1 for personal - 1 for computer
         = 0
        # Text color
        self.text_color = (30, 30, 30)
        # The background color, which is the color our screen renders in
        self.bg_color = (255, 255, 255)
        # Set the font
         = (None,48)

    def draw(self):
        # Text messages assigned by status
        msg = ""
        if  == -1:
            msg = "x"
        elif  == 1:
            msg = "o"
        
        if msg:
            self.msg_image = (msg,True,self.text_color,self.bg_color)
            self.msg_rect = self.msg_image.get_rect()
            self.msg_rect.center = 
            (self.msg_image,self.msg_rect)

render function:
Incoming parameters: text message, Boolean (controls whether the curve is smooth or not, didn't try), text color, background color (which is the color our screen renders)
Returns an image type.

The get_rect() method:
Processing images as rectangles, one of the nice things about pygame is that it doesn't matter what kind of shape it is, it can be treated as a rectangle

The rect object, with centerx, centery, x, y, and a host of other attributes, facilitates our alignment operations, which we won't expand on here.

blit method:
Input image and rectangle (the rectangle here essentially indicates to the method the coordinates to display), the
Displayed on screen.

in the main module:

def update():
    for i in rect:
        ()
    # Display the interface
    ()

If we just write an update at the beginning of the while loop, we'll find that we can't actually see the results in time, which obviously has an impact, so after each drop, we do a refresh before determining winners and losers.

if  not  and (mouse_x,mouse_y):
# Players playing chess
 = -1
update()
win_or_lose()
# Computer chess
computer()
update()
win_or_lose()

VI. Conclusion

This basically makes our tic-tac-toe game playable, but we still need to make some modifications.
Next blog, I'll be overhauling the details.

To this article on the pygame tic-tac-toe implementation of the second logical implementation of the article is introduced to this, more related pygame tic-tac-toe game content please search for my previous articles or continue to browse the following related articles I hope you will support me in the future!