Step-by-step teaching you to implement 2048 mini-games in Python

Source: Internet
Author: User
Believe that 2048 of this game for everyone is not unfamiliar, the following article on the main to introduce how to achieve 2048 games with Python, the text through the comments and sample code is very detailed, I believe that everyone's understanding and learning has a certain reference value, the need for friends to see it together.

Objective

2048 game rules: Simple move the key to let the number overlay, and to obtain these numbers each time after the superposition of the score, when there is 2048 this number when the game wins. At the same time, each time you move the arrow keys, a number 2 or 4 is randomly generated in the blank area of the 4*4 grid, and if the squares are filled with numbers, then Gameover.

Main logic diagram

Logic diagram: Black is the logical layer, blue is an external method, red is an in-class method, you will know later ~


Let me explain the main logical function by line main() , and in which I cross the outer defined functions and classes.

Master Logic Code interpretation (complete code at the end of the article)

The main logic is as follows, followed by an interpretation of some of the methods in the main function:

def main (STDSCR): Def init (): #重置游戏棋盘 game_field.reset () return ' game ' def Not_game (state): #画出 gameover or Win interface Game_f Ield.draw (STDSCR) #读取用户输入得到action, judging whether to restart the game or to end the game action = Get_user_action (STDSCR) responses = defaultdict (lambda:state #默认是当前状态, no behavior will always be in the current interface loop responses[' Restart '], responses[' exit '] = ' Init ', ' exit ' #对应不同的行为转换到不同的状态 return responses[ ACTION] def game (): #画出当前棋盘状态 Game_field.draw (STDSCR) #读取用户输入得到action action = get_user_action (STDSCR) if action = = ' Resta RT ':  return ' Init ' if action = = ' exit ':  return ' exit ' if Game_field.move (action): # Move successful  if Game_fi Eld.is_win ():  return ' win '  if Game_field.is_gameover ():  return ' Gameover ' return ' game ' state_actions = { c6/> ' init ': init,  ' win ': Lambda:not_game (' win '),  ' Gameover ': lambda:not_game (' Gameover '),  ' game ': Game } curses.use_default_colors () Game_field = Gamefield (win=32) state = ' Init ' #状态机开始循环 while state! = ' Exit ': state = State_ Actions[state] ()

Read by article (the Code box will be labeled from outside, no callout is from inside): Define the main function

def main (STDSCR):

DEF init (): #重置游戏棋盘 Game_field.reset ()

Reset is a method from an externally defined class, game_field=GameField Reset:

External:

def reset (self): if Self.score > Self.highscore:  self.highscore = Self.score Self.score = 0 Self.field = [[0 for I In range (Self.width)] to J in range (Self.height)] Self.spawn () self.spawn () #其中highscore为程序初始化过程中定义的一个变量. Record your win game's highest score record.

Return ' Game '

Returns the status of a game in progress. game_field=GameFieldthe state is defined in the following:

The bottom of the main function is defined:

State_actions = {  ' init ': init,  ' win ': Lambda:not_game (' win '),  ' Gameover ': lambda:not_game (' Gameover '),  ' Game ': Game}

def not_game (state): #画出 gameover or Win interface Game_field.draw (STDSCR)

Draw is the method in the imported class game_field=GameField :

#来自外部类 def draw (self, screens): Help_string1 = ' (W) up (S) down (A) left (D) Right ' help_string2 = ' (R) Restart (Q) Exit ' Gameov er_string = ' GAME over ' win_string = ' You win! '  #定义各个字符串 def cast (string): Screen.addstr (string + ' \ n ') def draw_hor_separator (): line = ' + ' + (' +------' * self.width + ' + ') [1:] separator = defaultdict (lambda:line) if not hasattr (Draw_hor_separator, "counter"): Draw_hor_separator.count ER = 0 cast (Separator[draw_hor_separator.counter]) Draw_hor_separator.counter + = 1 def draw_row (row): Cast ('. Join (' |{ : ^5} '. Format (num) if num > 0 Else ' | ' For num in row) + ' | ')  Screen.clear () cast (' Score: ' + str (self.score)) if 0! = Self.highscore:cast (' hghscore: ' + str (self.highscore)) for row In Self.field:draw_hor_separator () draw_row (Row) draw_hor_separator () if Self.is_win (): Cast (win_string) else:if SE Lf.is_gameover (): Cast (gameover_string) Else:cast (help_string1) cast (help_string2) #这里面的draw方法的字函数我就不做多的解释了, Very simple concepts. #但是又运用到了很优秀的精简代码. #有的地方建议去查一下pytHon some high-level concepts, I will not do a long introduction. 

Here's the draw method of the word function I will not do much to explain, very simple some concepts.

But it also uses a very good streamlined code.

Some places suggest to look up some of Python's advanced concepts, I will not do a long introduction.

#读取用户输入得到action, decide whether to restart the game or end the game action = get_user_action (STDSCR)

Read user behavior, function from code initial definition

#来自外部定义的函数def get_user_action (keyboard):  char = "N" while char not in actions_dict:  char = Keyboard.getch () retur N Actions_dict[char]

At the end, which is the third step of the main function execution, defines state = state_actions[state]() This example:

#主函数底部: state = ' Init ' #状态机开始循环 while state! = ' Exit ': state = State_actions[state] ()

Responses = defaultdict (lambda:state) #默认是当前状态, no behavior will always be in the current interface loop responses[' Restart '], responses[' Exit ' = ' Init ', ' Exit ' #对应不同的行为转换到不同的状态 return responses[action]

Def game (): #画出当前棋盘状态 Game_field.draw (STDSCR) #读取用户输入得到action action = get_user_action (STDSCR) if action = = ' Restart ': 
  return ' Init ' if action = = ' exit ':  return ' exit ' if Game_field.move (action): # Move successful  if Game_field.is_ Win ():  return ' win '  if Game_field.is_gameover ():  return ' Gameover ' return ' game ' #game () The definition of a function is similar to the Not_game () that has been said above, except that the game () has an internal loop # that is, if it is not restart/exit or the state after the move is judged, if it is not the end, it will be in the inside loop.

game()The definition of a function is similar to what has been said above not_game() , but game() has an internal loop, that is, if it is not restart/exit or the state after the move, if it is not the end of the game, it is always game() inside the loop.

State_actions = {  ' init ': init,  ' win ': Lambda:not_game (' win '),  ' Gameover ': lambda:not_game (' Gameover '),  ' game ': Game   } Curses.use_default_colors () Game_field = Gamefield (win=32) state = ' Init ' #状态机开始循环 while state! = ' Exit ': state = State_ac Tions[state] () #此处的意思是: State=state_actions[state] can be seen as: #state =init () or State=not_game (' Win ') or another not_game (' Gameover ')/game ()

The meaning here is: state=state_actions[state] can be seen as: state=init() or state=not_game(‘Win') maybe anothernot_game(‘Gameover')/game()

Needless to say, the last of my success diagram, in addition, you can set the final line of the win=32 to determine your final winning conditions!


Full code

#-*-coding:utf-8-*-import cursesfrom random import randrange, Choice # Generate and place new Tilefrom collections Impor t defaultdictletter_codes = [ORD (CH) for ch in ' wasdrqwasdrq ']actions = ["Up", ' left ', ' off ', ' right ', ' Restart ', ' Exit '] actions_dict = dict (Zip (letter_codes, Actions * 2)) def transpose (field): Return [List (row) for row in Zip (*field)]def INVe RT (FIELD): Return [row[::-1] for row in Field]class Gamefield (object): Def __init__ (self, height=4, width=4, win=2048): SE  Lf.height = Height Self.width = width Self.win_value = Win Self.score = 0 Self.highscore = 0 self.reset () def reset (self): If self.score > self.highscore:self.highscore = Self.score self.score = 0 Self.field = [[0 for I in range (self.width )] for J in Range (Self.height)] Self.spawn () self.spawn () def move (self, direction): Def move_row_left (Row): Def tighten ( Row): # Squeese Non-zero elements together new_row = [i-I in row if I! = 0] New_row + = [0 for i in range (len (row)- Len (New_row))] return nEw_row def merge (row): pair = False New_row = [] for i in range (len): If Pair:new_row.append (2 * row[i]) s Elf.score + = 2 * Row[i] pair = False Else:if i + 1 < len (row) and row[i] = = row[i + 1]: pair = True New_ro W.append (0) else:new_row.append (row[i]) assert len (new_row) = = Len (row) return New_row return Tighten (merge (tight En (row))) moves = {} moves[' left '] = lambda field: \ [Move_row_left (row) for row in field] moves[' right '] = lambda fie LD: \ Invert (moves[' left '] (invert (field))) moves["Up" = lambda field: \ Transpose (moves[' left ') (Transpose (field)) ) moves[' down ' = lambda field: \ Transpose (moves["right" (transpose field))) If direction in Moves:if Self.move_is_ Possible (direction): Self.field = Moves[direction] (Self.field) self.spawn () return True Else:return False def Is_win (self): return any (i >= self.win_value for I on row) for row in Self.field) def is_gameover (self): Return no any (s Elf.move_is_possible (move) def draw (self, screens): Help_string1 = ' (W) up (S) down (A) left (D) Right ' help_string2 = ' (R) Restar T (Q) Exit ' gameover_string = ' GAME over ' win_string = ' win! ' def cast (string): Screen.addstr (string + ' \ n ') def D Raw_hor_separator (): line = ' + ' + (' +------' * self.width + ' + ') [1:] separator = defaultdict (lambda:line) if not Hasat TR (draw_hor_separator, "counter"): Draw_hor_separator.counter = 0 cast (Separator[draw_hor_separator.counter]) draw_ Hor_separator.counter + = 1 def draw_row (row): Cast (". Join (' |{: ^5} '. Format (num) if num > 0 Else ' | ' For num in row) + ' | ')  Screen.clear () cast (' Score: ' + str (self.score)) if 0! = Self.highscore:cast (' hghscore: ' + str (self.highscore)) for row In Self.field:draw_hor_separator () draw_row (Row) draw_hor_separator () if Self.is_win (): Cast (win_string) else:if SE  Lf.is_gameover (): Cast (gameover_string) Else:cast (help_string1) cast (HELP_STRING2) def spawn (self): new_element = 4 If Randrange (>) 2 (I,J) = Choice ([(I,J) for I in range (Self.width) for J in range (Self.height) if self.field[i][j] = = 0]) self.fi ELD[I][J] = new_element def move_is_possible (self, Direction): Def row_is_left_movable (Row): def change (i): # True if th Ere ' ll be change in i-th tile if row[i] = = 0 and Row[i + 1]! = 0: # Move return True if row[i]! = 0 and row[i + 1] = =  Row[i]: # Merge return True return False return any (change (i) for I in range (len (row)-1)) check = {} check[' left '] = Lambda field: \ Any (row_is_left_movable (row) for row in field) check["Right" = lambda field: \ check[' left ' "(in Vert (field)) check[' up ' = lambda field: \ check[' left '] (Transpose (field)) check[' down ' = lambda field: \ check['  Right "] (Transpose (field)) If direction in Check:return Check[direction] (Self.field) Else:return falsedef Main (STDSCR):  DEF init (): #重置游戏棋盘 game_field.reset () return ' game ' def Not_game (state): #画出 gameover or Win interface Game_field.draw (STDSCR) #读取用户输入得到action, judging is restarting the gameor end game action = Get_user_action (STDSCR) responses = defaultdict (lambda:state) #默认是当前状态, no behavior will continue to cycle through the current interface responses[' Restart '], responses[' exit '] = ' Init ', ' exit ' #对应不同的行为转换到不同的状态 return responses[action] def game (): #画出当前棋盘状态 Game_field.  Draw (STDSCR) #读取用户输入得到action action = get_user_action (STDSCR) if action = = ' Restart ': Return ' Init ' if action = = ' Exit ': Return ' Exit ' if Game_field.move (action): # Move successful if Game_field.is_win (): Return ' win ' if game_field.is_game Over (): Return ' Gameover ' return ' Game ' state_actions = {' init ': init, ' win ': Lambda:not_game (' win '), ' gameover ': LA Mbda:not_game (' Gameover '), ' Game ': Game} curses.use_default_colors () Game_field = Gamefield (win=32) state = ' Init ' #状态机 Start loop while state! = ' Exit ': state = State_actions[state] () curses.wrapper (main)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.