激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Python - 一步步教你用Python實現2048小游戲

一步步教你用Python實現2048小游戲

2020-09-18 10:36HustWolf Python

相信2048這個游戲對大家來說一定不陌生,下面這篇文章就主要給大家介紹了怎么用Python實現2048小游戲,文中通過注釋與示例代碼介紹的很詳細,相信對大家的理解和學習具有一定的參考借鑒價值,有需要的朋友們一起來看看吧。

前言

2048游戲規則:簡單的移動方向鍵讓數字疊加,并且獲得這些數字每次疊加后的得分,當出現2048這個數字時游戲勝利。同時每次移動方向鍵時,都會在這個4*4的方格矩陣的空白區域隨機產生一個數字2或者4,如果方格被數字填滿了,那么就GameOver了。

主邏輯圖

一步步教你用Python實現2048小游戲

邏輯圖解:黑色是邏輯層,藍色是外部方法,紅色是類內方法,稍后即可知道~

一步步教你用Python實現2048小游戲

下面容我逐行解釋主邏輯main()函數,并且在其中穿叉外部定義的函數與類。

主邏輯代碼解讀(完整代碼見文末)

主邏輯main如下,之后的是對主函數中的一些方法的解讀:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
def main(stdscr):
 def init():
 #重置游戲棋盤
 game_field.reset()
 return 'Game'
 
 def not_game(state):
 #畫出 GameOver 或者 Win 的界面
 game_field.draw(stdscr)
 #讀取用戶輸入得到action,判斷是重啟游戲還是結束游戲
 action = get_user_action(stdscr)
 responses = defaultdict(lambda: state) #默認是當前狀態,沒有行為就會一直在當前界面循環
 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'
 
 
 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_actions[state]()

逐條解讀(代碼框內會標注是來自外部,無標注則是來自內部):定義主函數

?
1
def main(stdscr):
?
1
2
3
def init():
#重置游戲棋盤
game_field.reset()

reset出自外部定義的類,game_field=GameField的一個方法reset:

  外部:

?
1
2
3
4
5
6
7
8
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()
#其中highscore為程序初始化過程中定義的一個變量。記錄你win游戲的最高分數記錄。
?
1
return 'Game'

返回一個游戲進行中的狀態。game_field=GameField狀態在后面有定義:

主函數底部定義:

?
1
2
3
4
5
6
state_actions = {
 'Init': init,
 'Win': lambda: not_game('Win'),
 'Gameover': lambda: not_game('Gameover'),
 'Game': game
}
?
1
2
3
def not_game(state):
#畫出 GameOver 或者 Win 的界面
game_field.draw(stdscr)

draw是導入的類game_field=GameField中的方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#來自外部類
 def draw(self, screen):
 help_string1 = '(W)Up (S)Down (A)Left (D)Right'
 help_string2 = ' (R)Restart (Q)Exit'
 gameover_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.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 self.is_gameover():
  cast(gameover_string)
  else:
  cast(help_string1)
 cast(help_string2)
#這里面的draw方法的字函數我就不做多的解釋了,很簡單的一些概念。
#但是又運用到了很優秀的精簡代碼。
#有的地方建議去查一下python的一些高級概念,我就不做多的介紹了。

這里面的draw方法的字函數我就不做多的解釋了,很簡單的一些概念。

但是又運用到了很優秀的精簡代碼。

有的地方建議去查一下python的一些高級概念,我就不做多的介紹了。

?
1
2
#讀取用戶輸入得到action,判斷是重啟游戲還是結束游戲
action = get_user_action(stdscr)

讀取用戶行為,函數來自于代碼初始的定義

?
1
2
3
4
5
6
#來自外部定義的函數
def get_user_action(keyboard):
 char = "N"
 while char not in actions_dict:
 char = keyboard.getch()
 return actions_dict[char]

在結尾處,也即是主函數執行的第三步,定義了state = state_actions[state]()這一實例:

?
1
2
3
4
5
6
#主函數底部:
 state = 'Init'
 
 #狀態機開始循環
 while state != 'Exit':
 state = state_actions[state]()
?
1
2
3
responses = defaultdict(lambda: state) #默認是當前狀態,沒有行為就會一直在當前界面循環
responses['Restart'], responses['Exit'] = 'Init', 'Exit' #對應不同的行為轉換到不同的狀態
return responses[action]
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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()函數的定義類似于上面已經講過的not_game(),只是game()有了內部循環
#即如果不是Restart/Exit或者對move之后的狀態進行判斷,如果不是結束游戲,就一直在game()內部循環。

game()函數的定義類似于上面已經講過的not_game() ,只是game()有了內部循環,即如果不是Restart/Exit或者對move之后的狀態進行判斷,如果不是結束游戲,就一直在game()內部循環。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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_actions[state]()
#此處的意思是:state=state_actions[state] 可以看做是:
#state=init()或者state=not_game(‘Win')或者是另外的not_game(‘Gameover')/game()

此處的意思是:state=state_actions[state] 可以看做是:state=init()或者state=not_game(‘Win')或者是另外的not_game(‘Gameover')/game()

廢話不多說,上一個我的成功的圖,另外,可以通過設置最后幾行中的win=32來決定你最終獲勝的條件!

一步步教你用Python實現2048小游戲

完整代碼

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
#-*- coding:utf-8 -*-
import curses
from random import randrange, choice # generate and place new tile
from collections import defaultdict
letter_codes = [ord(ch) for ch in 'WASDRQwasdrq']
actions = ['Up', 'Left', 'Down', 'Right', 'Restart', 'Exit']
actions_dict = dict(zip(letter_codes, actions * 2))
def transpose(field):
 return [list(row) for row in zip(*field)]
 
def invert(field):
 return [row[::-1] for row in field]
 
class GameField(object):
 def __init__(self, height=4, width=4, win=2048):
 self.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 for 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(row)):
   if pair:
   new_row.append(2 * row[i])
   self.score += 2 * row[i]
   pair = False
   else:
   if i + 1 < len(row) and row[i] == row[i + 1]:
    pair = True
    new_row.append(0)
   else:
    new_row.append(row[i])
  assert len(new_row) == len(row)
  return new_row
  return tighten(merge(tighten(row)))
 
 moves = {}
 moves['Left'] = lambda field:    \
  [move_row_left(row) for row in field]
 moves['Right'] = lambda field:    \
  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(any(i >= self.win_value for i in row) for row in self.field)
 
 def is_gameover(self):
 return not any(self.move_is_possible(move) for move in actions)
 
 def draw(self, screen):
 help_string1 = '(W)Up (S)Down (A)Left (D)Right'
 help_string2 = ' (R)Restart (Q)Exit'
 gameover_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.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 self.is_gameover():
  cast(gameover_string)
  else:
  cast(help_string1)
 cast(help_string2)
 
 def spawn(self):
 new_element = 4 if randrange(100) > 89 else 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.field[i][j] = new_element
 
 def move_is_possible(self, direction):
 def row_is_left_movable(row):
  def change(i): # true if there'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'](invert(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 False
def main(stdscr):
 def init():
 #重置游戲棋盤
 game_field.reset()
 return 'Game'
 def not_game(state):
 #畫出 GameOver 或者 Win 的界面
 game_field.draw(stdscr)
 #讀取用戶輸入得到action,判斷是重啟游戲還是結束游戲
 action = get_user_action(stdscr)
 responses = defaultdict(lambda: state) #默認是當前狀態,沒有行為就會一直在當前界面循環
 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'
 
 
 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_actions[state]()
curses.wrapper(main)

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流。

原文鏈接:http://www.jianshu.com/p/7a3a7545d2fb

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 天天草天天干天天射 | 国产一区二区三区视频免费 | 亚洲无线看 | 午夜视频色 | 深夜免费视频 | 免费看a级片 | 国产午夜精品视频免费不卡69堂 | 欧美成人精品欧美一级乱黄 | 亚洲精品成人悠悠色影视 | 91在线视频福利 | 91av亚洲 | 特级毛片免费视频 | 成年人免费视频播放 | 91九色丨porny丨国产jk | 国产91精品一区二区麻豆亚洲 | 免费一级欧美大片视频在线 | 成年人在线免费 | 久久久久久久久91 | 91在线播放国产 | 免费国产| 精品成人av一区二区三区 | 精品久久久一二三区播放播放播放视频 | 毛片a区| 天天操天天碰 | 91精品国啪老师啪 | lutube成人福利在线观看污 | av电影免费播放 | 成人午夜高清 | 99国产精品国产免费观看 | 久久成人国产精品 | 成人三级电影在线 | 久久国产免费 | 九一免费国产 | 欧美精品videos | 激情视频免费观看 | 久久久久久久一区二区 | 欧美国产精品久久 | 国产精品久久久久久久亚洲按摩 | 日本高清视频网站www | 国产亚洲精品成人a | 国产精品亚洲一区二区三区在线观看 |