200 lines of python code to realize 2048 game

  • 2021-07-22 10:18:18
  • OfStack

Python Practical Series is used to record the ideas, code implementation, problems and solutions and feasible improvement directions in practical projects

This article implements 2048 for the second 200-line Python code

1. Analysis and function design

1.1 Gameplay

2048 This game is very simple, you can choose to slide up and down, left and right every time, every time you slide, all the digital squares will move closer to the sliding direction, and the system will also randomly count a digital square in a blank place, and the squares with the same number will be added when they move closer and collide. (Introduction from Baidu Encyclopedia)

1.2 Function Design

_ init _ () initializes 4*4 game maps, scores and other basic game data is_gameover () Determines whether to end the game rannumber () randomly generates 2, 4 on the map every time the player moves show () prints out a 4*4 game map on the console print_score () prints the current score on the console up (), upmove () move up down (), downmove () move down left (), leftmove () shift left right (), rightmove () shift to the right nextstep () reads the player key

2. Code implementation

Note: IDE is Spyder, Python version 3.6


# -*- coding: utf-8 -*-
"""
Created on Sat Sep 29 16:29:04 2018

@author: PastoralDog
"""
import random

class game2048(object):
  def __init__(self):
    self.score=0
    self.number=[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]
    self.move=0
    seed=random.randint(0,15)
    line=int(seed/4)
    row=seed%4
    self.number[line][row]=2    
  
  def is_gameover(self):
    numbersum=0
    for i in range(4):
      for j in range(4):
        if (self.number[i][j]!=0):
          numbersum+=1
    if(numbersum!=16): return False
    for i in range(4):
      for j in range(3):
        if(self.number[i][j+1]==self.number[i][j]): return False
    for i in range(3):
      for j in range(4):
        if(self.number[i+1][j]==self.number[i][j]): return False
    print(" Game over ")
    print(" Your score is: "+str(self.score))
    self.__init__()
    return True
  
  def rannumber(self):
    rannumber=random.randint(1,10)   
    if(rannumber<=8): rannumber=2
    else: rannumber=4
    done=0
    count=0
    for i in range(4):
      for j in range(4):
        if(self.number[i][j]==0):
          count+=1
    while(done==0 and count!=0):
      ranplace=random.randint(0,15)
      line=int(ranplace/4)
      row=ranplace%4
      if(self.number[line][row]==0):
        done=1
        self.number[line][row]=rannumber      
    
  def show(self):
    print(self.number[0])
    print(self.number[1])
    print(self.number[2])
    print(self.number[3])
    
  def print_score(self):
    print(" Score: "+str(self.score))
    
  def upmove(self):
    for i in range(1,4):
      for j in range(4):
        temp=i
        while(temp>=1 and self.number[temp-1][j]==0):
          box=self.number[temp-1][j]
          self.number[temp-1][j]=self.number[temp][j]
          self.number[temp][j]=box
          if(self.number[temp][j]!=0):self.move=1
          temp-=1
  
  def up(self):
    self.upmove()
    for i in range(1,4):
      for j in range(4):
        if(self.number[i-1][j]==self.number[i][j]):
          if(self.number[i-1][j]!=2048):
            self.score+=self.number[i][j]
            self.number[i][j]=0
            self.number[i-1][j]=2*self.number[i-1][j]         
    self.upmove()      
    if(self.move!=0):self.rannumber()
    self.move=0
    self.show()
    self.is_gameover()
    self.print_score()
  
  def downmove(self):
     for i in range(2,-1,-1):
       for j in range(4):
        temp=i
        while(temp<=2 and self.number[temp+1][j]==0 ):
          box=self.number[temp+1][j]
          self.number[temp+1][j]=self.number[temp][j]
          self.number[temp][j]=box
          if(self.number[temp+1][j]!=0):self.move=1
          temp+=1
      
  def down(self):
    self.downmove()
    for i in range(2,-1,-1):
      for j in range(4):
        if(self.number[i+1][j]==self.number[i][j]):
          if(self.number[i+1][j]!=2048):
            self.score+=self.number[i][j]
            self.number[i][j]=0
            self.number[i+1][j]=2*self.number[i+1][j] 
    self.downmove()
    if(self.move!=0):self.rannumber()
    self.move=0
    self.show()
    self.is_gameover()
    self.print_score()
  
  def leftmove(self):
    for i in range(4):
      for j in range(1,4):    
        temp=j
        while(temp>=1 and self.number[i][temp-1]==0 ):
          box=self.number[i][temp-1]
          self.number[i][temp-1]=self.number[i][temp]
          self.number[i][temp]=box
          if(self.number[i][temp-1]!=0):self.move=1
          temp-=1
  
  def left(self):
    self.leftmove()
    for i in range(4):
      for j in range(0,3):
        if(self.number[i][j+1]==self.number[i][j]):
          if(self.number[i][j+1]!=2048):
            self.score+=self.number[i][j]
            self.number[i][j+1]=0
            self.number[i][j]=2*self.number[i][j] 
    self.leftmove()
    if(self.move!=0):self.rannumber()
    self.move=0
    self.show()
    self.is_gameover()
    self.print_score()
  
  def rightmove(self):
    for i in range(4):
      for j in range(2,-1,-1):    
        temp=j
        while(temp<=2 and self.number[i][temp+1]==0 ):
          box=self.number[i][temp+1]
          self.number[i][temp+1]=self.number[i][temp]
          self.number[i][temp]=box
          self.move=1
          temp+=1
  
  def right(self):
    self.rightmove()
    for i in range(4):
      for j in range(2,-1,-1):
        if(self.number[i][j+1]==self.number[i][j]):
          if(self.number[i][j+1]!=2048):
            self.score+=self.number[i][j]
            self.number[i][j]=0
            self.number[i][j+1]=2*self.number[i][j+1] 
    self.rightmove()
    if(self.move!=0):self.rannumber()
    self.move=0
    self.show()
    self.is_gameover()
    self.print_score()
  
  def nextstep(self,step):
    if(step=='w'): self.up()
    elif(step=='s'): self.down()
    elif(step=='a'): self.left()  
    elif(step=='d'): self.right()
    else: pass
       
if __name__ == '__main__':
  game=game2048()
  game.show()
  while(True):
    step=input()
    if(step=='b'):break
    game.nextstep(step)

3. Problems and Solutions

1. Map storage and representation: There is no interface design at present, so it is directly stored and represented by 2-dimensional array

2. Array out of bounds: It has been encountered 56 times in debugging code. Besides keeping in mind edge detection, the order of left and right conditions of and statement should also be particular.

Example: while (temp < = 2 and self. number [temp+1] [j] = = 0) Note: self. number is a 4*4 2D array
When temp = 3, the statement is in temp < = 2 is blocked, no self. number [temp+1] [j] = = 0, no problem;
If the statement is changed to while (self. number [temp+1] [j] ==0 and temp < = 2), self. number [temp+1] [j] = = 0, at which time the compiler reports an error array out of bounds

4. Possible directions for improvement

1. Add visual interface, and consider Tkinter, QT, etc.

2. Expand the game map size to N x N

My level is limited, so you are welcome to put forward questions and suggestions.


Related articles: