SoFunction
Updated on 2024-11-17

python uses the tkinter library to implement a game of backgammon.

In this article, we share examples of python to achieve the specific code of the game of backgammon, for your reference, the details are as follows

I. Running screenshots:

II. Codes

# Define a chessboard as an array with a size of 15×15.
# The array index represents the location.
# The element value represents the state of the position: 0 means there are no pieces, 1 means there are black pieces, -1 means there are white pieces.
    
from tkinter import *
from  import *
 
 
class Chess(object):
 
 def __init__(self):
  #############
  # param #
  #######################################
  ,  = 15, 15
   = 25
   = 0.9
  self.board_color = "#CDBA96"
  self.header_bg = "#CDC0B0"
  self.btn_font = ("bold.", 12, "bold")
   =  / 2
  self.chess_r =  * 
  self.point_r =  * 0.2
   = [[0 for y in range()] for x in range()]
  self.is_start = False
  self.is_black = True
  self.last_p = None
 
  ###########
  # GUI #
  #######################################
   = Tk()
  ("Gobang By Young")
  (width=False, height=False)
 
  self.f_header = Frame(, highlightthickness=0, bg=self.header_bg)
  self.f_header.pack(fill=BOTH, ipadx=10)
 
  self.b_start = Button(self.f_header, text="Begin.", command=self.bf_start, font=self.btn_font)
  self.b_restart = Button(self.f_header, text="Starting over.", command=self.bf_restart, state=DISABLED, font=self.btn_font)
  self.l_info = Label(self.f_header, text="Not started", bg=self.header_bg, font=("italics", 18, "bold"), fg="white")
  self.b_regret = Button(self.f_header, text="Repent.", command=self.bf_regret, state=DISABLED, font=self.btn_font)
  self.b_lose = Button(self.f_header, text="Admit defeat.", command=self.bf_lose, state=DISABLED, font=self.btn_font)
 
  self.b_start.pack(side=LEFT, padx=20)
  self.b_restart.pack(side=LEFT)
  self.l_info.pack(side=LEFT, expand=YES, fill=BOTH, pady=10)
  self.b_lose.pack(side=RIGHT, padx=20)
  self.b_regret.pack(side=RIGHT)
 
  self.c_chess = Canvas(, bg=self.board_color, width=( + 1) * ,
        height=( + 1) * , highlightthickness=0)
  self.draw_board()
  self.c_chess.bind("<Button-1>", self.cf_board)
  self.c_chess.pack()
 
  ()
 
 # Draw the grid at x rows and y columns
 def draw_mesh(self, x, y):
  # A multiplier, due to tkinter's fucked up GUI, if you don't add a multiplier, there will be a slight trace of repentance, try changing this to 1 and you can see the
  ratio = (1 - ) * 0.99 + 1
  center_x, center_y =  * (x + 1),  * (y + 1)
  # Draw the background color first
  self.c_chess.create_rectangle(center_y - , center_x - ,
          center_y + , center_x + ,
          fill=self.board_color, outline=self.board_color)
  # Draw the grid lines again, where a b c d are different coefficients, determined from different positions of x,y, requiring some derivation.
  a, b = [0, ratio] if y == 0 else [-ratio, 0] if y ==  - 1 else [-ratio, ratio]
  c, d = [0, ratio] if x == 0 else [-ratio, 0] if x ==  - 1 else [-ratio, ratio]
  self.c_chess.create_line(center_y + a * , center_x, center_y + b * , center_x)
  self.c_chess.create_line(center_y, center_x + c * , center_y, center_x + d * )
 
  # There are special spots to draw little black dots #
  if ((x == 3 or x == 11) and (y == 3 or y == 11)) or (x == 7 and y == 7):
   self.c_chess.create_oval(center_y - self.point_r, center_x - self.point_r,
          center_y + self.point_r, center_x + self.point_r, fill="black")
 
 # Draw the pieces in row x and column y. color specifies the color of the pieces.
 def draw_chess(self, x, y, color):
  center_x, center_y =  * (x + 1),  * (y + 1)
  # It's just drawing a circle #
  self.c_chess.create_oval(center_y - self.chess_r, center_x - self.chess_r,
         center_y + self.chess_r, center_x + self.chess_r,
         fill=color)
 
 # Draw the whole board
 def draw_board(self):
  [self.draw_mesh(x, y) for y in range() for x in range()]
 
 # Display text in the center
 def center_show(self, text):
  width, height = int(self.c_chess['width']), int(self.c_chess['height'])
  self.c_chess.create_text(int(width / 2), int(height / 2), text=text, font=("bold.", 30, "bold"), fill="red")
 
 # Start by setting up the state of each component, variable, initializing the matrix, initializing the board, initializing the message
 def bf_start(self):
  self.set_btn_state("start")
  self.is_start = True
  self.is_black = True
   = [[0 for y in range()] for x in range()]
  self.draw_board()
  self.l_info.config(text="Black plays.")
 
 # Starting over has the same effect as it started
 def bf_restart(self):
  self.bf_start()
 
 # Use last_p to identify the position of the previous move. First cover off the pieces with a grid, manipulate the corresponding variables, matrix[x][y] should be empty, you can only regret one move
 def bf_regret(self):
  if not self.last_p:
   showinfo("Tip.", "You can't repent now.")
   return
  x, y = self.last_p
  self.draw_mesh(x, y)
  [x][y] = 0
  self.last_p = None
  self.trans_identify()
 
 # A couple of state changes, and display text, not much to say #
 def bf_lose(self):
  self.set_btn_state("init")
  self.is_start = False
  text = self.ternary_operator("Black concedes.", "White concedes.")
  self.l_info.config(text=text)
  self.center_show("Cai.")
 
 # Canvas click event
 def cf_board(self, e):
  # Find the coordinates closest to the clicked point
  x, y = int(( - ) / ), int(( - ) / )
  # Find the location of the center of this coordinate
  center_x, center_y =  * (x + 1),  * (y + 1)
  # Calculate the distance from the clicked point to the center
  distance = ((center_x - ) ** 2 + (center_y - ) ** 2) ** 0.5
  # If the distance is not within the specified circle, quit // If there is already a piece in this position, quit // If the game has not started, quit
  if distance >  * 0.95 or [x][y] != 0 or not self.is_start:
   return
  # The color of the piece at this point, and the identity of the piece in the matrix.
  color = self.ternary_operator("black", "white")
  tag = self.ternary_operator(1, -1)
  # Draw the pieces first, modify the values of the corresponding points in the matrix, and record the operation points with last_p.
  self.draw_chess(x, y, color)
  [x][y] = tag
  self.last_p = [x, y]
  # If you win, the game is over, the status is changed, and the center shows that a side won
  if self.is_win(x, y, tag):
   self.is_start = False
   self.set_btn_state("init")
   text = self.ternary_operator("Black wins.", "White wins.")
   self.center_show(text)
   return
  # If the game continues, the players are exchanged
  self.trans_identify()
 
 def is_win(self, x, y, tag):
  # Get a list of oblique directions
  def direction(i, j, di, dj, row, column, matrix):
   temp = []
   while 0 <= i < row and 0 <= j < column:
    i, j = i + di, j + dj
   i, j = i - di, j - dj
   while 0 <= i < row and 0 <= j < column:
    (matrix[i][j])
    i, j = i - di, j - dj
   return temp
 
  four_direction = []
  # Get horizontal and vertical listings
  four_direction.append([[i][y] for i in range()])
  four_direction.append([[x][j] for j in range()])
  # Get a list of oblique directions
  four_direction.append(direction(x, y, 1, 1, , , ))
  four_direction.append(direction(x, y, 1, -1, , , ))
 
  # Check these four directions one by one, have they met the pentominoes #
  for v_list in four_direction:
   count = 0
   for v in v_list:
    if v == tag:
     count += 1
     if count == 5:
      return True
    else:
     count = 0
  return False
 
 # Set whether the four buttons are clickable
 def set_btn_state(self, state):
  state_list = [NORMAL, DISABLED, DISABLED, DISABLED] if state == "init" else [DISABLED, NORMAL, NORMAL, NORMAL]
  self.b_start.config(state=state_list[0])
  self.b_restart.config(state=state_list[1])
  self.b_regret.config(state=state_list[2])
  self.b_lose.config(state=state_list[3])
 
 # Extracted because there's a lot of ternary manipulation associated with it
 def ternary_operator(self, true, false):
  return true if self.is_black else false
 
 # Swap players
 def trans_identify(self):
  self.is_black = not self.is_black
  text = self.ternary_operator("Black plays.", "White plays.")
  self.l_info.config(text=text)
 
 
if __name__ == '__main__':
 Chess()

Third, add the function of replaying and saving the chess game

Directly post the source code that works, adding two buttons and a page.

# Define a chessboard as an array with a size of 15×15.
# The array index represents the location.
# The element value represents the state of the position: 0 means there are no pieces, 1 means there are black pieces, -1 means there are white pieces.
 
from tkinter import *
from  import *
import os
 
TAG_BLACK = "1"
TAG_EMPTY = "."
TAG_WHITE = "0"
ROOT_DIR = (((__file__)) +  + ".")
 
 
class Chess(object):
 
 def bf_save(self):
 
  path = (ROOT_DIR, "")
  file = open(path, "w")
  for i in range(len()):
   x, y = [i]
   ("{}: [{}, {}]\n".format("Black." if i % 2 == 0 else "White Fang.", x, y))
  ()
 
 def init_matrix(self):
  return [[TAG_EMPTY for y in range()] for x in range()]
 
 def __init__(self):
  #############
  # param #
  #######################################
  ,  = 15, 15
   = 25
   = 0.9
  self.board_color = "#CDBA96"
  self.header_bg = "#CDC0B0"
  self.btn_font = ("bold.", 12, "bold")
   =  / 2
  self.chess_r =  * 
  self.point_r =  * 0.2
   = self.init_matrix()
  self.is_start = False
  self.is_black = True
   = []
 
  ###########
  # GUI #
  #######################################
   = Tk()
  ("Gobang By Young")
  (width=False, height=False)
 
  self.f_header = Frame(, highlightthickness=0, bg=self.header_bg)
 
  self.b_start = Button(self.f_header, text="Begin.", command=self.bf_start, font=self.btn_font)
  self.b_restart = Button(self.f_header, text="Starting over.", command=self.bf_restart, state=DISABLED, font=self.btn_font)
  self.l_info = Label(self.f_header, text="Not started", bg=self.header_bg, font=("italics", 18, "bold"), fg="white")
  self.b_regret = Button(self.f_header, text="Repent.", command=self.bf_regret, state=DISABLED, font=self.btn_font)
  self.b_lose = Button(self.f_header, text="Admit defeat.", command=self.bf_lose, state=DISABLED, font=self.btn_font)
 
  self.c_chess = Canvas(, bg=self.board_color, width=( + 1) * ,
        height=( + 1) * , highlightthickness=0)
  self.draw_board()
  self.c_chess.bind("<Button-1>", self.cf_board)
 
  self.b_record = Button(, text="Review.", command=self.bf_record, font=self.btn_font, bg="lightblue")
  self.b_save = Button(, text="Preservation", command=self.bf_save, font=self.btn_font, bg="lightblue")
 
  self.f_header.pack(side=TOP, fill=BOTH, ipadx=10)
  self.b_start.pack(side=LEFT, padx=20)
  self.b_restart.pack(side=LEFT)
  self.l_info.pack(side=LEFT, expand=YES, fill=BOTH, pady=10)
  self.b_lose.pack(side=RIGHT, padx=20)
  self.b_regret.pack(side=RIGHT)
 
  self.c_chess.pack(side=TOP)
 
  self.b_record.pack(side=TOP, expand=YES, fill=X)
  self.b_save.pack(side=TOP, expand=YES, fill=X)
 
  ()
 
 # Draw the grid at x rows and y columns
 def draw_mesh(self, x, y):
  # A multiplier, due to tkinter's fucked up GUI, if you don't add a multiplier, there will be a slight trace of repentance, try changing this to 1 and you can see the
  ratio = (1 - ) * 0.99 + 1
  center_x, center_y =  * (x + 1),  * (y + 1)
  # Draw the background color first
  self.c_chess.create_rectangle(center_y - , center_x - ,
          center_y + , center_x + ,
          fill=self.board_color, outline=self.board_color)
  # Draw the grid lines again, where a b c d are different coefficients, determined from different positions of x,y, requiring some derivation.
  a, b = [0, ratio] if y == 0 else [-ratio, 0] if y ==  - 1 else [-ratio, ratio]
  c, d = [0, ratio] if x == 0 else [-ratio, 0] if x ==  - 1 else [-ratio, ratio]
  self.c_chess.create_line(center_y + a * , center_x, center_y + b * , center_x)
  self.c_chess.create_line(center_y, center_x + c * , center_y, center_x + d * )
 
  # There are special spots to draw little black dots #
  if ((x == 3 or x == 11) and (y == 3 or y == 11)) or (x == 7 and y == 7):
   self.c_chess.create_oval(center_y - self.point_r, center_x - self.point_r,
          center_y + self.point_r, center_x + self.point_r, fill="black")
 
 # Draw the pieces in row x and column y. color specifies the color of the pieces.
 def draw_chess(self, x, y, color):
  center_x, center_y =  * (x + 1),  * (y + 1)
  # It's just drawing a circle #
  self.c_chess.create_oval(center_y - self.chess_r, center_x - self.chess_r,
         center_y + self.chess_r, center_x + self.chess_r,
         fill=color)
 
 # Draw the whole board
 def draw_board(self):
  [self.draw_mesh(x, y) for y in range() for x in range()]
 
 # Display text in the center
 def center_show(self, text):
  width, height = int(self.c_chess['width']), int(self.c_chess['height'])
  self.c_chess.create_text(int(width / 2), int(height / 2), text=text, font=("bold.", 30, "bold"), fill="red")
 
 def bf_record(self):
  Record()
  pass
 
 # Start by setting up the state of each component, variable, initializing the matrix, initializing the board, initializing the message
 def bf_start(self):
  self.set_btn_state("start")
  self.is_start = True
  self.is_black = True
   = self.init_matrix()
  self.draw_board()
   = []
  self.l_info.config(text="Black plays.")
 
 # Starting over has the same effect as it started
 def bf_restart(self):
   = []
  self.bf_start()
 
 # Use last_p to identify the position of the previous move. First cover off the pieces with a grid, manipulate the corresponding variables, matrix[x][y] should be empty, you can only regret one move
 def bf_regret(self):
  if len() == 0:
   showinfo("Tip.", "You can't repent now.")
   return
  x, y = [-1]
  self.draw_mesh(x, y)
  [x][y] = TAG_EMPTY
   = [:-1]
  self.trans_identify()
 
 # A couple of state changes, and display text, not much to say #
 def bf_lose(self):
  self.set_btn_state("init")
  self.is_start = False
  text = self.ternary_operator("Black concedes.", "White concedes.")
  self.l_info.config(text=text)
  self.center_show("Cai.")
 
 def go_chess(self, x, y):
  # The color of the piece at this point, and the identity of the piece in the matrix.
  color = self.ternary_operator("black", "white")
  tag = self.ternary_operator(TAG_BLACK, TAG_WHITE)
  # Draw the pieces first, modify the values of the corresponding points in the matrix, and record the operation points with last_p.
  self.draw_chess(x, y, color)
  [x][y] = tag
  ([x, y])
  # If you win, the game is over, the status is changed, and the center shows that a side won
  if self.is_win(x, y, tag):
   self.is_start = False
   self.set_btn_state("init")
   text = self.ternary_operator("Black wins.", "White wins.")
   self.center_show(text)
   return
  # If the game continues, the players are exchanged
  self.trans_identify()
 
 # Canvas click event
 def cf_board(self, e):
  # Find the coordinates closest to the clicked point
  x, y = int(( - ) / ), int(( - ) / )
  # Find the location of the center of this coordinate
  center_x, center_y =  * (x + 1),  * (y + 1)
  # Calculate the distance from the clicked point to the center
  distance = ((center_x - ) ** 2 + (center_y - ) ** 2) ** 0.5
  # If the distance is not within the specified circle, quit // If there is already a piece in this position, quit // If the game has not started, quit
  if distance >  * 0.95 or [x][y] != TAG_EMPTY or not self.is_start:
   return
  self.go_chess(x, y)
 
 def is_win(self, x, y, tag):
  # Get a list of oblique directions
  def direction(i, j, di, dj, row, column, matrix):
   temp = []
   while 0 <= i < row and 0 <= j < column:
    i, j = i + di, j + dj
   i, j = i - di, j - dj
   while 0 <= i < row and 0 <= j < column:
    (matrix[i][j])
    i, j = i - di, j - dj
   return temp
 
  four_direction = []
  # Get horizontal and vertical listings
  four_direction.append([[i][y] for i in range()])
  four_direction.append([[x][j] for j in range()])
  # Get a list of oblique directions
  four_direction.append(direction(x, y, 1, 1, , , ))
  four_direction.append(direction(x, y, 1, -1, , , ))
 
  # Check these four directions one by one, have they met the pentominoes #
  for v_list in four_direction:
   if tag * 5 in "".join(v_list):
    return True
  return False
 
 # Set whether the four buttons are clickable
 def set_btn_state(self, state):
  state_list = [NORMAL, DISABLED, DISABLED, DISABLED] if state == "init" else [DISABLED, NORMAL, NORMAL, NORMAL]
  self.b_start.config(state=state_list[0])
  self.b_restart.config(state=state_list[1])
  self.b_regret.config(state=state_list[2])
  self.b_lose.config(state=state_list[3])
 
 # Extracted because there's a lot of ternary manipulation associated with it
 def ternary_operator(self, true, false):
  return true if self.is_black else false
 
 # Swap players
 def trans_identify(self):
  self.is_black = not self.is_black
  text = self.ternary_operator("Black plays.", "White plays.")
  self.l_info.config(text=text)
 
 def print_process(self):
  pass
 
 
class Record(object):
 
 def __init__(self, record):
  #############
  # param #
  #######################################
  ,  = 15, 15
   = 25
   = 0.9
  self.board_color = "#CDBA96"
  self.header_bg = "#CDC0B0"
  self.btn_font = ("bold.", 12, "bold")
   =  / 2
  self.chess_r =  * 
  self.point_r =  * 0.2
  ###########
  self.is_black = True
   = -1
   = record
  ###########
  # GUI #
  #######################################
   = Tk()
  ("Review.")
  (width=False, height=False)
  ("<Key>", self.kf_step)
 
  self.f_header = Frame(, highlightthickness=0, bg=self.header_bg)
  self.l_info = Label(self.f_header, text="Not started", bg=self.header_bg, font=("italics", 18, "bold"), fg="white")
 
  self.c_chess = Canvas(, bg=self.board_color, width=( + 1) * ,
        height=( + 1) * , highlightthickness=0)
  self.draw_board()
 
  self.f_header.pack(fill=BOTH, ipadx=10)
  self.l_info.pack(side=LEFT, expand=YES, fill=BOTH, pady=10)
  self.c_chess.pack()
 
  ()
 
 def kf_step(self, e):
  if  not in [37, 39]:
   return
  if  == 37:
   if  == -1:
    self.l_info.config(text="It's gone as far as it can go.")
    return
   x, y = []
   self.draw_mesh(x, y)
   if  == 0:
    self.l_info.config(text="Not started")
   else:
    self.l_info.config(text="Black moves." if self.is_black else "White moves.")
   self.is_black = not self.is_black
    -= 1
   if  > 0:
    x, y = []
    color = "white" if self.is_black else "black"
    self.draw_chess(x, y, color, "red")
 
  elif  == 39:
   if  == len() - 1:
    self.l_info.config(text="It's come down to the wire.")
    return
    += 1
   x, y = []
   color = "black" if self.is_black else "white"
   self.draw_chess(x, y, color, "red")
   if  > 0:
    x, y = [ - 1]
    color = "white" if self.is_black else "black"
    self.draw_chess(x, y, color)
   self.l_info.config(text="Black moves." if self.is_black else "White moves.")
   self.is_black = not self.is_black
  else:
   pass
 
 # Draw the grid at x rows and y columns
 def draw_mesh(self, x, y):
  # A multiplier, due to tkinter's fucked up GUI, if you don't add a multiplier, there will be a slight trace of repentance, try changing this to 1 and you can see the
  ratio = (1 - ) * 0.99 + 1
  center_x, center_y =  * (x + 1),  * (y + 1)
  # Draw the background color first
  self.c_chess.create_rectangle(center_y - , center_x - ,
          center_y + , center_x + ,
          fill=self.board_color, outline=self.board_color)
  # Draw the grid lines again, where a b c d are different coefficients, determined from different positions of x,y, requiring some derivation.
  a, b = [0, ratio] if y == 0 else [-ratio, 0] if y ==  - 1 else [-ratio, ratio]
  c, d = [0, ratio] if x == 0 else [-ratio, 0] if x ==  - 1 else [-ratio, ratio]
  self.c_chess.create_line(center_y + a * , center_x, center_y + b * , center_x)
  self.c_chess.create_line(center_y, center_x + c * , center_y, center_x + d * )
 
  # There are special spots to draw little black dots #
  if ((x == 3 or x == 11) and (y == 3 or y == 11)) or (x == 7 and y == 7):
   self.c_chess.create_oval(center_y - self.point_r, center_x - self.point_r,
          center_y + self.point_r, center_x + self.point_r, fill="black")
 
 # Draw the pieces in row x and column y. color specifies the color of the pieces.
 def draw_chess(self, x, y, color, outline="black"):
  center_x, center_y =  * (x + 1),  * (y + 1)
  # It's just drawing a circle #
  self.c_chess.create_oval(center_y - self.chess_r, center_x - self.chess_r,
         center_y + self.chess_r, center_x + self.chess_r,
         fill=color, outline=outline)
 
 # Draw the whole board
 def draw_board(self):
  [self.draw_mesh(x, y) for y in range() for x in range()]
 
 # Display text in the center
 def center_show(self, text):
  width, height = int(self.c_chess['width']), int(self.c_chess['height'])
  self.c_chess.create_text(int(width / 2), int(height / 2), text=text, font=("bold.", 30, "bold"), fill="red")
 
 # Start by setting up the state of each component, variable, initializing the matrix, initializing the board, initializing the message
 
 
if __name__ == '__main__':
 Chess()

This is the whole content of this article.