Python makes small games 2 2048 part 1

I have nothing to do recently, and I made a small game similar to 2048. The algorithm ideas, if any, were all thought up by myself in a little time, without any reference to any tutorials at all, so it is possible (in fact, it is definitely) that the method used is a bit stupid, which is considered to be an introduction.

In order to make this game, I first downloaded a 2048 mini game to play in order to learn the rules. According to the 20-minute play experience, the rules I summarized are roughly as follows:

  1. 4*4 squares.
  2. The game starts with 2 2s.
  3. Then a new 2 appears every time you move, and if you cannot move in a certain direction, no new 2 will be added.
  4. Only identical numbers can be added.
  5. The newly added will only appear 2
  6. When adding, it will only be added once and will not be accumulated. I don't know why.
  7. Game over checks that there are no empty spaces and no identical numbers around any number, if there are none, the game is over.
  8. Sensitively aware that there is no need for external picture materials, only picture frames and numbers are needed.
  9. The animation process should be the most troublesome. I don't have much confidence in drawing animation with pygame.

Because I have made a lot of similar board games before, such as Minesweeper and Five Sons Connect (I have the opportunity to write them together), so it is very easy to draw the board part of 2048. The difficulty lies in the color matching. Fortunately, I don’t care whether the color looks good or not. , so get started directly.

First of all, it is still the basic pygame configuration code, which involves various initialization configurations, color codes, etc., and there are a lot of margins. Basically, I am common to board games, and it can be used after a few modifications.

import pygame
import sys
import random
from pygame.locals import *
board_width = 4
board_height = 4
tile_size = 80
screen_width = 640
screen_height = 480
fps = 30


white = (255, 255, 255)
bright_blue = 'sky blue'
dark_turquoise = (250, 234, 211)
green = 'green'

bg_color = (107, 81, 82)
tile_color = bright_blue
text_color = (144, 59, 28)
border_color = bright_blue
basic_font_size = 30
message_color = white
x_margin = int((screen_width-(tile_size*board_width + (board_width-1)))/2)
y_margin = int((screen_height-(tile_size*board_height + (board_height - 1)))/2)

up = 'up'
down = 'down'
left = 'left'
right = 'right'

# 四个方向
directions = [(0, 1), (0, -1), (-1, 0), (1, 0)]

Come to a main function to set up the pygame framework

if __name__ == '__main__':

    pygame.init()
    fps_clock = pygame.time.Clock()
    display = pygame.display.set_mode((screen_width, screen_height))
    pygame.display.set_caption('2048')
    basic_font = pygame.font.Font('freesansbold.ttf', basic_font_size)

    while True:
        for event in pygame.event.get():
           if event.type == QUIT:
                pygame.quit()
        pygame.display.update()
        fps_clock.tick(fps)

What it looks like after running
Please add a picture description

Next, write a function that generates a two-dimensional list. The generated two-dimensional list corresponds to the game interface, directly corresponding to the game interface. For example, if the two-dimensional list is long
[
[0, 2, 0, 2],
[0, 0, 0, ],
[0, 0, 0, 0],
[0, 0, 0, 0]
]
then we use When pygame draws, all the positions of 0 are blank small blocks, and where there are numbers, the numbers will be drawn directly, and the positions correspond to the positions of the two-dimensional list one by one. That is, the two-dimensional list [0][0] corresponds to the first small block in the upper left corner, and [3][3] corresponds to the last small block in the lower right corner. The advantage of this correspondence is intuitive, and the disadvantage is that when we need to calculate the horizontal and vertical coordinates of the small block, that is, the position in the pygame interface, the first subscript is used to calculate the y value, that is, the vertical position, and the second subscript is used for Calculating the x value is the horizontal position, which contradicts the general cognition, which is easy to get wrong.

Now let’s write a function to generate a two-dimensional list. It is relatively simple. First, generate a list whose values ​​are all None, and then generate two values ​​2 at random positions. Then return the value of this two-dimensional list.

def get_starting_board():
    counter = 2
    board = [[None for _ in range(board_width)] for _ in range(board_height)]
    while counter > 0:
        random_x = random.randint(0, board_height-1)
        random_y = random.randint(0, board_width-1)
        if board[random_x][random_y] is None:
            board[random_x][random_y] = 2
            counter -= 1
    return board

In this way, we generated a two-dimensional list and randomly generated the position of the number 2. Next, we can't start drawing small blocks directly. We also need a function to convert the subscript of the two-dimensional list into the actual position in pygmae.

x_margin = int((screen_width-(tile_size*board_width + (board_width-1)))/2)
y_margin = int((screen_height-(tile_size*board_height + (board_height - 1)))/2)

This is the defined spacing in the horizontal and vertical directions. Use this spacing and calculate the position of each element of the two-dimensional list in the pygame game interface, that is, the chessboard.

# 将board[x][y]转为游戏屏幕对应的坐标点
def get_left_top_of_tile(x, y):
    left = x_margin + y * tile_size + (y - 1)
    top = y_margin + x * tile_size + (x - 1)
    return left, top

Finally, you can start writing the drawing function, which draws the corresponding graphics to the specified position according to the data content of the two-dimensional list.

# 绘制游戏背景面板,此处开始根据board中的内容绘制游戏主界面了,一开始绘制的是已经完成好的界面
def draw_board(board, message):
# 填充背景
    display.fill(bg_color)
    # 如果有信息,则将信息写在左上角
    if message:
        text_surf, text_rect = make_text(message, message_color, bg_color, 0, 0)
        display.blit(text_surf, text_rect)
    # 遍历二维列表中所有内容,绘图
    for x in range(board_width):
        for y in range(board_height):
            if board[x][y]:
            # 如果有数字则绘制数字
                draw_tile(x, y, board[x][y])
            else:
            # 否则仅绘制小块
                draw_tile(x, y, '')

    # 绘制游戏边框
    left, top = get_left_top_of_tile(0, 0)
    width = board_width * tile_size
    height = board_height * tile_size
    # 边框不要和滑片重合,所以稍微往四周挪动一点距离
    pygame.draw.rect(display, border_color, (left-11, top-11, width+16, height+16), 4)
   

Next, the bottom-level drawing graphics function

#绘制游戏界面上的小滑片,其中adj_x,y偏移量是用来后期做动#画用的
def draw_tile(board_x, board_y, number, adj_x=0, adj_y=0):
#获取实际位置
    left, top = get_left_top_of_tile(board_x, board_y)
    # 画出滑片的背景色,即一个填充了颜色的矩形

    # 在同样的位置显示滑片对应的数字,即board[x][y]中对应的数字
    # 画数字时修改了一下位置,看起来更合适一些
    if number:
        pygame.draw.rect(display, dark_turquoise, (left + adj_x, top + adj_y, tile_size - 10, tile_size - 10))
        text_surf = basic_font.render(str(number), True, text_color)
        text_rect = text_surf.get_rect()
        text_rect.center = left + int((tile_size-10)/2) + adj_x, top + int((tile_size-10)/2) + adj_y
        # text_rect.center = left + adj_x, top + adj_y
        display.blit(text_surf, text_rect)
    else:
        pygame.draw.rect(display, bright_blue, (left + adj_x, top + adj_y, tile_size - 10, tile_size - 10))

Then define a comprehensive function to generate the game interface

# 创建新游戏谜题
def generate_new_puzzle():

   board = get_starting_board()
   draw_board(board, '')
   pygame.display.update()
   pygame.time.wait(500)
   last_move = None

   return board

Called in the main function and get a two-dimensional list

if __name__ == '__main__':

   pygame.init()
   fps_clock = pygame.time.Clock()
   display = pygame.display.set_mode((screen_width, screen_height))
   pygame.display.set_caption('2048')
   basic_font = pygame.font.Font('freesansbold.ttf', basic_font_size)

   # 配置三个按键位置以及颜色,大小
   # reset_surf, reset_rect = make_text('Reset', text_color, tile_color, screen_width - 120, screen_height - 90)
   main_board = generate_new_puzzle()
   while True:
       for event in pygame.event.get():
           if event.type == QUIT:
               pygame.quit()
       pygame.display.update()
       fps_clock.tick(fps)

Run the program, it's a bit interesting
Please add a picture description

to be continued…

Guess you like

Origin blog.csdn.net/jackwsd/article/details/126429853