2048 Juego en Python

En este artículo, veremos el código y la lógica de Python para diseñar un juego de 2048 que ha jugado con mucha frecuencia en su teléfono inteligente. Si no está familiarizado con el juego, se recomienda encarecidamente que primero juegue para que pueda comprender su funcionamiento básico.

Cómo jugar 2048:

1. Hay una cuadrícula de 4*4 que se puede llenar con cualquier número. Inicialmente, dos celdas aleatorias se llenan con 2. Las celdas de descanso están vacías.

2. Tenemos que presionar cualquiera de las cuatro teclas para movernos hacia arriba, abajo, izquierda o derecha. Cuando presionamos cualquier tecla, los elementos de la celda se mueven en esa dirección de tal manera que si dos números idénticos están contenidos en esa fila en particular (en caso de moverse hacia la izquierda o hacia la derecha) o columna (en caso de moverse hacia arriba o hacia abajo) obtienen sume y la celda extrema en esa dirección se llene con ese número y las celdas restantes se vacían nuevamente.

3. Después de esta compresión de cuadrícula, cualquier celda vacía aleatoria se llena con 2.

4. Siguiendo el proceso anterior, tenemos que duplicar los elementos sumando y hacer 2048 en cualquiera de las celdas. Si somos capaces de hacer eso, ganamos.

5. Pero si durante el juego no queda ninguna celda vacía para llenar con un nuevo 2, entonces el juego termina.

En el proceso anterior, puede ver las instantáneas de la interfaz gráfica de usuario del juego 2048. Pero toda la lógica reside en el código principal. Entonces, para comprender únicamente la lógica detrás de esto, podemos asumir que la cuadrícula anterior es una array de 4 * 4 (una lista con cuatro filas y cuatro columnas). Puede ver a continuación la forma de tomar entrada y salida sin GUI para el juego anterior.

Ejemplo : 

Commands are as follows : 
'W' or 'w' : Move Up
'S' or 's' : Move Down
'A' or 'a' : Move Left
'D' or 'd' : Move Right
[0, 0, 0, 0]
[0, 0, 0, 0]
[0, 0, 0, 0]
[0, 0, 2, 0]
Press the command : a
GAME NOT OVER
[0, 0, 0, 2]
[0, 0, 0, 0]
[0, 0, 0, 0]
[2, 0, 0, 0]
Press the command : s
GAME NOT OVER
[0, 0, 0, 0]
[0, 0, 0, 0]
[0, 0, 2, 0]
[2, 0, 0, 2]
Press the command : d
GAME NOT OVER
[0, 0, 0, 0]
[0, 0, 0, 0]
[2, 0, 0, 2]
[0, 0, 0, 4]
Press the command : a
GAME NOT OVER
[0, 2, 0, 0]
[0, 0, 0, 0]
[4, 0, 0, 0]
[4, 0, 0, 0]
Press the command : s
GAME NOT OVER
[0, 0, 0, 0]
[0, 0, 0, 0]
[0, 0, 0, 0]
[8, 2, 0, 2]
.
.
.
And the series of input output will go on till we lose or win!

Enfoque de programación: 

  1. Diseñaremos cada función lógica como si estuviéramos realizando un deslizamiento hacia la izquierda y luego la usaremos para deslizar hacia la derecha invirtiendo la array y realizando un deslizamiento hacia la izquierda.
  2. Se puede mover hacia arriba tomando la transposición y luego moviéndose hacia la izquierda.
  3. Se puede mover hacia abajo transponiendo el movimiento hacia la derecha.
  4. Toda la lógica del programa se explica en detalle en los comentarios. Muy recomendable pasar por todos los comentarios.

Tenemos dos archivos python a continuación, uno es 2048.py que contiene el código del controlador principal y el otro es logic.py que contiene todas las funciones utilizadas. logic.py debe importarse en 2048.py para usar estas funciones. simplemente coloque ambos archivos en la misma carpeta y luego ejecute 2048.py funcionará perfectamente.

lógica.py  

Python3

# logic.py to be
# imported in the 2048.py file
 
# importing random package
# for methods to generate random
# numbers.
import random
 
# function to initialize game / grid
# at the start
def start_game():
 
    # declaring an empty list then
    # appending 4 list each with four
    # elements as 0.
    mat =[]
    for i in range(4):
        mat.append([0] * 4)
 
    # printing controls for user
    print("Commands are as follows : ")
    print("'W' or 'w' : Move Up")
    print("'S' or 's' : Move Down")
    print("'A' or 'a' : Move Left")
    print("'D' or 'd' : Move Right")
 
    # calling the function to add
    # a new 2 in grid after every step
    add_new_2(mat)
    return mat
 
# function to add a new 2 in
# grid at any random empty cell
def add_new_2(mat):
 
   # choosing a random index for
   # row and column.
    r = random.randint(0, 3)
    c = random.randint(0, 3)
 
    # while loop will break as the
    # random cell chosen will be empty
    # (or contains zero)
    while(mat[r] != 0):
        r = random.randint(0, 3)
        c = random.randint(0, 3)
 
    # we will place a 2 at that empty
    # random cell.
    mat[r] = 2
 
# function to get the current
# state of game
def get_current_state(mat):
 
    # if any cell contains
    # 2048 we have won
    for i in range(4):
        for j in range(4):
            if(mat[i][j]== 2048):
                return 'WON'
 
    # if we are still left with
    # atleast one empty cell
    # game is not yet over
    for i in range(4):
        for j in range(4):
            if(mat[i][j]== 0):
                return 'GAME NOT OVER'
 
    # or if no cell is empty now
    # but if after any move left, right,
    # up or down, if any two cells
    # gets merged and create an empty
    # cell then also game is not yet over
    for i in range(3):
        for j in range(3):
            if(mat[i][j]== mat[i + 1][j] or mat[i][j]== mat[i][j + 1]):
                return 'GAME NOT OVER'
 
    for j in range(3):
        if(mat[3][j]== mat[3][j + 1]):
            return 'GAME NOT OVER'
 
    for i in range(3):
        if(mat[i][3]== mat[i + 1][3]):
            return 'GAME NOT OVER'
 
    # else we have lost the game
    return 'LOST'
 
# all the functions defined below
# are for left swap initially.
 
# function to compress the grid
# after every step before and
# after merging cells.
def compress(mat):
 
    # bool variable to determine
    # any change happened or not
    changed = False
 
    # empty grid
    new_mat = []
 
    # with all cells empty
    for i in range(4):
        new_mat.append([0] * 4)
         
    # here we will shift entries
    # of each cell to it's extreme
    # left row by row
    # loop to traverse rows
    for i in range(4):
        pos = 0
 
        # loop to traverse each column
        # in respective row
        for j in range(4):
            if(mat[i][j] != 0):
                 
                # if cell is non empty then
                # we will shift it's number to
                # previous empty cell in that row
                # denoted by pos variable
                new_mat[i][pos] = mat[i][j]
                 
                if(j != pos):
                    changed = True
                pos += 1
 
    # returning new compressed matrix
    # and the flag variable.
    return new_mat, changed
 
# function to merge the cells
# in matrix after compressing
def merge(mat):
     
    changed = False
     
    for i in range(4):
        for j in range(3):
 
            # if current cell has same value as
            # next cell in the row and they
            # are non empty then
            if(mat[i][j] == mat[i][j + 1] and mat[i][j] != 0):
 
                # double current cell value and
                # empty the next cell
                mat[i][j] = mat[i][j] * 2
                mat[i][j + 1] = 0
 
                # make bool variable True indicating
                # the new grid after merging is
                # different.
                changed = True
 
    return mat, changed
 
# function to reverse the matrix
# means reversing the content of
# each row (reversing the sequence)
def reverse(mat):
    new_mat =[]
    for i in range(4):
        new_mat.append([])
        for j in range(4):
            new_mat[i].append(mat[i][3 - j])
    return new_mat
 
# function to get the transpose
# of matrix means interchanging
# rows and column
def transpose(mat):
    new_mat = []
    for i in range(4):
        new_mat.append([])
        for j in range(4):
            new_mat[i].append(mat[j][i])
    return new_mat
 
# function to update the matrix
# if we move / swipe left
def move_left(grid):
 
    # first compress the grid
    new_grid, changed1 = compress(grid)
 
    # then merge the cells.
    new_grid, changed2 = merge(new_grid)
     
    changed = changed1 or changed2
 
    # again compress after merging.
    new_grid, temp = compress(new_grid)
 
    # return new matrix and bool changed
    # telling whether the grid is same
    # or different
    return new_grid, changed
 
# function to update the matrix
# if we move / swipe right
def move_right(grid):
 
    # to move right we just reverse
    # the matrix
    new_grid = reverse(grid)
 
    # then move left
    new_grid, changed = move_left(new_grid)
 
    # then again reverse matrix will
    # give us desired result
    new_grid = reverse(new_grid)
    return new_grid, changed
 
# function to update the matrix
# if we move / swipe up
def move_up(grid):
 
    # to move up we just take
    # transpose of matrix
    new_grid = transpose(grid)
 
    # then move left (calling all
    # included functions) then
    new_grid, changed = move_left(new_grid)
 
    # again take transpose will give
    # desired results
    new_grid = transpose(new_grid)
    return new_grid, changed
 
# function to update the matrix
# if we move / swipe down
def move_down(grid):
 
    # to move down we take transpose
    new_grid = transpose(grid)
 
    # move right and then again
    new_grid, changed = move_right(new_grid)
 
    # take transpose will give desired
    # results.
    new_grid = transpose(new_grid)
    return new_grid, changed
 
# this file only contains all the logic
# functions to be called in main function
# present in the other file

Python3

# logic.py to be
# imported in the 2048.py file
 
# importing random package
# for methods to generate random
# numbers.
import random
 
# function to initialize game / grid
# at the start
def start_game():
 
    # declaring an empty list then
    # appending 4 list each with four
    # elements as 0.
    mat =[]
    for i in range(4):
        mat.append([0] * 4)
 
    # printing controls for user
    print("Commands are as follows : ")
    print("'W' or 'w' : Move Up")
    print("'S' or 's' : Move Down")
    print("'A' or 'a' : Move Left")
    print("'D' or 'd' : Move Right")
 
    # calling the function to add
    # a new 2 in grid after every step
    add_new_2(mat)
    return mat
 
# function to add a new 2 in
# grid at any random empty cell
def add_new_2(mat):
 
   # choosing a random index for
   # row and column.
    r = random.randint(0, 3)
    c = random.randint(0, 3)
 
    # while loop will break as the
    # random cell chosen will be empty
    # (or contains zero)
    while(mat[r] != 0):
        r = random.randint(0, 3)
        c = random.randint(0, 3)
 
    # we will place a 2 at that empty
    # random cell.
    mat[r] = 2
 
# function to get the current
# state of game
def get_current_state(mat):
 
    # if any cell contains
    # 2048 we have won
    for i in range(4):
        for j in range(4):
            if(mat[i][j]== 2048):
                return 'WON'
 
    # if we are still left with
    # atleast one empty cell
    # game is not yet over
    for i in range(4):
        for j in range(4):
            if(mat[i][j]== 0):
                return 'GAME NOT OVER'
 
    # or if no cell is empty now
    # but if after any move left, right,
    # up or down, if any two cells
    # gets merged and create an empty
    # cell then also game is not yet over
    for i in range(3):
        for j in range(3):
            if(mat[i][j]== mat[i + 1][j] or mat[i][j]== mat[i][j + 1]):
                return 'GAME NOT OVER'
 
    for j in range(3):
        if(mat[3][j]== mat[3][j + 1]):
            return 'GAME NOT OVER'
 
    for i in range(3):
        if(mat[i][3]== mat[i + 1][3]):
            return 'GAME NOT OVER'
 
    # else we have lost the game
    return 'LOST'
 
# all the functions defined below
# are for left swap initially.
 
# function to compress the grid
# after every step before and
# after merging cells.
def compress(mat):
 
    # bool variable to determine
    # any change happened or not
    changed = False
 
    # empty grid
    new_mat = []
 
    # with all cells empty
    for i in range(4):
        new_mat.append([0] * 4)
         
    # here we will shift entries
    # of each cell to it's extreme
    # left row by row
    # loop to traverse rows
    for i in range(4):
        pos = 0
 
        # loop to traverse each column
        # in respective row
        for j in range(4):
            if(mat[i][j] != 0):
                 
                # if cell is non empty then
                # we will shift it's number to
                # previous empty cell in that row
                # denoted by pos variable
                new_mat[i][pos] = mat[i][j]
                 
                if(j != pos):
                    changed = True
                pos += 1
 
    # returning new compressed matrix
    # and the flag variable.
    return new_mat, changed
 
# function to merge the cells
# in matrix after compressing
def merge(mat):
     
    changed = False
     
    for i in range(4):
        for j in range(3):
 
            # if current cell has same value as
            # next cell in the row and they
            # are non empty then
            if(mat[i][j] == mat[i][j + 1] and mat[i][j] != 0):
 
                # double current cell value and
                # empty the next cell
                mat[i][j] = mat[i][j] * 2
                mat[i][j + 1] = 0
 
                # make bool variable True indicating
                # the new grid after merging is
                # different.
                changed = True
 
    return mat, changed
 
# function to reverse the matrix
# means reversing the content of
# each row (reversing the sequence)
def reverse(mat):
    new_mat =[]
    for i in range(4):
        new_mat.append([])
        for j in range(4):
            new_mat[i].append(mat[i][3 - j])
    return new_mat
 
# function to get the transpose
# of matrix means interchanging
# rows and column
def transpose(mat):
    new_mat = []
    for i in range(4):
        new_mat.append([])
        for j in range(4):
            new_mat[i].append(mat[j][i])
    return new_mat
 
# function to update the matrix
# if we move / swipe left
def move_left(grid):
 
    # first compress the grid
    new_grid, changed1 = compress(grid)
 
    # then merge the cells.
    new_grid, changed2 = merge(new_grid)
     
    changed = changed1 or changed2
 
    # again compress after merging.
    new_grid, temp = compress(new_grid)
 
    # return new matrix and bool changed
    # telling whether the grid is same
    # or different
    return new_grid, changed
 
# function to update the matrix
# if we move / swipe right
def move_right(grid):
 
    # to move right we just reverse
    # the matrix
    new_grid = reverse(grid)
 
    # then move left
    new_grid, changed = move_left(new_grid)
 
    # then again reverse matrix will
    # give us desired result
    new_grid = reverse(new_grid)
    return new_grid, changed
 
# function to update the matrix
# if we move / swipe up
def move_up(grid):
 
    # to move up we just take
    # transpose of matrix
    new_grid = transpose(grid)
 
    # then move left (calling all
    # included functions) then
    new_grid, changed = move_left(new_grid)
 
    # again take transpose will give
    # desired results
    new_grid = transpose(new_grid)
    return new_grid, changed
 
# function to update the matrix
# if we move / swipe down
def move_down(grid):
 
    # to move down we take transpose
    new_grid = transpose(grid)
 
    # move right and then again
    new_grid, changed = move_right(new_grid)
 
    # take transpose will give desired
    # results.
    new_grid = transpose(new_grid)
    return new_grid, changed
 
# this file only contains all the logic
# functions to be called in main function
# present in the other file

2048.py 

Python3

# 2048.py
 
# importing the logic.py file
# where we have written all the
# logic functions used.
import logic
 
# Driver code
if __name__ == '__main__':
     
# calling start_game function
# to initialize the matrix
    mat = logic.start_game()
 
while(True):
 
    # taking the user input
    # for next step
    x = input("Press the command : ")
 
    # we have to move up
    if(x == 'W' or x == 'w'):
 
        # call the move_up function
        mat, flag = logic.move_up(mat)
 
        # get the current state and print it
        status = logic.get_current_state(mat)
        print(status)
 
        # if game not ove then continue
        # and add a new two
        if(status == 'GAME NOT OVER'):
            logic.add_new_2(mat)
 
        # else break the loop
        else:
            break
 
    # the above process will be followed
    # in case of each type of move
    # below
 
    # to move down
    elif(x == 'S' or x == 's'):
        mat, flag = logic.move_down(mat)
        status = logic.get_current_state(mat)
        print(status)
        if(status == 'GAME NOT OVER'):
            logic.add_new_2(mat)
        else:
            break
 
    # to move left
    elif(x == 'A' or x == 'a'):
        mat, flag = logic.move_left(mat)
        status = logic.get_current_state(mat)
        print(status)
        if(status == 'GAME NOT OVER'):
            logic.add_new_2(mat)
        else:
            break
 
    # to move right
    elif(x == 'D' or x == 'd'):
        mat, flag = logic.move_right(mat)
        status = logic.get_current_state(mat)
        print(status)
        if(status == 'GAME NOT OVER'):
            logic.add_new_2(mat)
        else:
            break
    else:
        print("Invalid Key Pressed")
 
    # print the matrix after each
    # move.
    print(mat)

Producción :

Publicación traducida automáticamente

Artículo escrito por amit_mangal_ y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *