bash shell實現2048小遊戲詳解
目錄
前言
最近在github上看到一個用bash shell實現2048小遊戲的指令碼感覺挺有意思的,就自己仿照他的樣子稍作修改再實現了一遍我的實現,並記錄下實現的詳細過程。
指令碼的執行如圖:
重要變數
- board 是一個整型陣列,用來儲存所有格子中的當前數值,它的下標即從0到總格子數減1,與介面中的格子從左到右,再從上到下,一一對應。陣列的所有元素,在全新的遊戲開始時用0初始化,而載入遊戲時,用存檔目錄中的檔案初始化。
- pieces 用來儲存當前介面中所有非零的格子數。
- score 用來儲存當前的得分總數。
- flag_skip 用來防止一個格子在同一回合中被操作兩次。
- moves 用來測試遊戲還能不能被操作,是否已經輸掉遊戲。
- ESC 作為Escape螢幕控制碼,在輸出顏色格式的時候使用,\e或者\033等都可以。
- header 也就是介面的標題,介紹性質的,可以自己定義
- start_time 記錄程式開始的時間
這四個變數作為預設值,可以通過選項改變
- board_size 即遊戲介面的每邊的大小,限制在3至9之間
- target 即遊戲成功的目標,可以自己設定,但需要是2的冪
- reload_flag 即是否載入存檔
- config_dir 即存檔檔案的目標目錄
- last_added 即最新生成的塊的位置
- first_round 即第一個生成的塊的位置。因為遊戲最開始必須要生成兩個塊,而我定義用黃色表現這兩個塊以及用黃色表示以後每次最新生成的塊。
- index_max 因為陣列的下標從0開始,所以定義這個變數為遊戲介面的每邊的大小減一
- fields_total 即遊戲介面中格子的總數
定義一個陣列用來儲存各個數字的顏色表現,搭配前面定義的$ESC構成Escape螢幕控制碼,64及以上新增了高亮和白底,這些可以自行修改。
功能函式
退出處理
這裡呼叫end_game函式處理INT訊號,亦即使用ctrl+c
發出退出請求,由end_game進行退出流程。
print_board
83 function print_board(){
84 clear
85 printf "**************************************************************\n"
86 printf "***********************$header*************************\n"
87 printf "*$ESC[1;5;33mpieces=%-11d target=%-11d score=%-12d$ESC[0m*\n" $pieces $target $score
88 printf "**************************************************************\n"
89 echo
90 printf "/------"
91 for((row=1;row<=index_max;row++))
92 do
93 printf "+------"
94 done
95 printf '\\\n'
96 for((row=0;row<=index_max;row++))
97 do
98 printf "|"
99 for((line=0;line<=index_max;line++))
100 do
101 if let ${board[$row*$board_size+$line]}
102 then
103 if let '(last_added==(row*board_size+line))|(first_round==(row*board_size+line))'
104 then
105 printf "$ESC[1;33m %4d $ESC[0m|" ${board[$row*$board_size+$line]}
106 else
107 printf "$ESC[${colors[${board[$row*$board_size+$line]}]}m %4d $ESC[0m|" ${board[$row*$board_size+$line]}
108 fi
109 else
110 printf " |"
111 fi
112 done
113 if ((row!=index_max))
114 then
115 printf "\n|------"
116 for((r=1;r<=index_max;r++))
117 do
118 printf "+------"
119 done
120 printf "|\n"
121 fi
122 done
123 printf '\n\\------'
124 for((row=1;row<=index_max;row++))
125 do
126 printf "+------"
127 done
128 printf "/\n"
129 }
print_board函式用來列印遊戲介面
-
86至88行列印臺頭
-
90至95行及123至128行分別列印遊戲介面的
和
-
96至122行用一個雙重迴圈遍歷整個介面,外迴圈row即行,內迴圈line即列。
- 其中101行用來判斷當前位置的格子內的值是否為0,若非零則輸出。103行是在格子內的值非零的情況下,判斷是否為最新生成的塊或第一回合的塊,如果是的話,用特定的黃色輸出,如果不是的話,則按前面定義好的數值對應的顏色輸出。
- 113至121行用來輸出介面每兩行中間的
generate_piece
function generate_piece(){
137 while true
138 do
139 ((pos=RANDOM%fields_total))
140 let ${board[$pos]} ||{ let value=RANDOM%10?2:4;board[$pos]=$value;last_added=$pos;break;}
141 done
142 ((pieces++))
143 }
generate_piece函式用來生成塊
- 139行隨機生成塊位置
- 140行先判斷生成的塊的位置是否有非零值,如果沒有的話就生成2或4作為該塊的值,並跳出迴圈。
- 142行將當前介面中所有非零格子數加一
push_pieces
155 function push_pieces(){
156 case $4 in
157 "up")
158 let "first=$2*$board_size+$1"
159 let "second=($2+$3)*$board_size+$1"
160 ;;
161 "down")
162 let "first=($index_max-$2)*$board_size+$1"
163 let "second=($index_max-$2-$3)*$board_size+$1"
164 ;;
165 "left")
166 let "first=$1*$board_size+$2"
167 let "second=$1*$board_size+$2+$3"
168 ;;
169 "right")
170 let "first=$1*$board_size+($index_max-$2)"
171 let "second=($1*$board_size)+($index_max-$2-$3)"
172 ;;
173 esac
174 if ((board[$first]))
175 then
176 if ((board[$second]))
177 then
178 let flag_skip=1
179 fi
180 if ((board[$first]==board[$second]))
181 then
182 if [ -z $5 ]
183 then
184 let board[$first]*=2
185 if ((board[$first]==target))
186 then
187 end_game 1
188 fi
189 let board[$second]=0
190 let pieces-=1
191 let change=1
192 let score+=${board[$first]}
193 else
194 let moves++
195 fi
196 fi
197 else
198 if ((board[$second]))
199 then
200 if [ -z $5 ]
201 then
202 let board[$first]=${board[$second]}
203 let board[$second]=0
204 let change=1
205 else
206 let moves++
207 fi
208 fi
209 fi
210 }
push_pieces函式處理遊戲操作,即接受到上下左右的操作訊號時,處理格子內的數值。
它接受五個引數,引數1、2、3用來確定first及second的位置,引數4用來確定上下左右的操作訊號,引數5用來確認是否只是測試而不改變遊戲狀態。
它的基本邏輯是,first格子作為容器存放處理後的數值,second格子則提供值等待處理。
-
174行判斷first內是否存在非零值,如果存在非零值的話:
- 176至179行判斷如果second存在非零值的話,就只處理這一次,防止重複處理。
- 180至196行判斷,如果first和second內的值相同的話,就相加,並把結果存在first內。
-
如果first內不存在非零值的話:
- 189至209行判斷,如果second記憶體在非零值,則將其移到first內。
-
182及200行,配合check_moves函式測試是否還有可以進行的操作,不改變當前遊戲狀態。
apply_push
212 function apply_push(){
213 for((i=0;i<=index_max;i++))
214 do
215 for((j=0;j<=index_max;j++))
216 do
217 let flag_skip=0
218 let increment_max=index_max-j
219 for((k=1;k<=increment_max;k++))
220 do
221 if ((flag_skip))
222 then
223 break
224 fi
225 push_pieces $i $j $k $1 $2
226 done
227 done
228 done
229 }
apply_push函式遍歷整個介面並呼叫push_pieces函式處理遊戲操作。
- 上下操作時,i代表列,j代表行。向上時,它的邏輯是從上到下,從左到右。向下時,它的邏輯是從下到上,從左到右。
- 左右操作時,i代表行,j代表列。向左時,它的邏輯是從左到右,從上到下。向右時,它的邏輯是從右到左,從上到下。
check_moves
230 function check_moves(){
231 let moves=0
232 apply_push "up" fake
233 apply_push "down" fake
234 apply_push "left" fake
235 apply_push "right" fake
}
check_moves函式用來測試是否還有可以進行的操作,如果沒有的話,遊戲失敗。
key_react
237 function key_react(){
238 let change=0
239 read -d '' -sn 1
240 if [ "$REPLY" = "$ESC" ]
241 then
242 read -d '' -sn 1
243 if [ "$REPLY" = "[" ]
244 then
245 read -d '' -sn 1
246 case $REPLY in
247 A)
248 apply_push up;;
249 B)
250 apply_push down;;
251 C)
252 apply_push right;;
253 D)
254 apply_push left;;
255 esac
256 fi
257 else
258 case $REPLY in
259 k)
260 apply_push up;;
261 j)
262 apply_push down;;
263 h)
264 apply_push left;;
265 l)
266 apply_push right;;
267
268 w)
269 apply_push up;;
270 s)
271 apply_push down;;
272 a)
273 apply_push left;;
274 d)
275 apply_push right;;
276 esac
277 fi
278 }
key_react函式用來讀取鍵盤操作,並呼叫apply_push進行相應處理。
例如↑鍵,它的控制碼是\e[A,239、242、245行分別讀取\e
[
A
,並在接下來進行判斷。同時258至276行表示,也接受kjhl
和wsad
作為上下左右。
save_game和reload_game
280 function save_game(){
281 rm -rf "$config_dir"
282 mkdir -p "$config_dir"
283 echo "${board[*]}">"$config_dir/board"
284 echo "$board_size">"$config_dir/board_size"
285 echo "$pieces">"$config_dir/pieces"
286 echo "$target">"$config_dir/target"
287 echo "$score">"$config_dir/score"
288 echo "$first_round">"$config_dir/first_round"
289 }
290
291 function reload_game(){
292 if [ ! -d "$config_dir" ]
293 then
294 return
295 else
296 board=(`cat "$config_dir/board"`)
297 board_size=`cat "$config_dir/board_size"`
298 pieces=`cat "$config_dir/pieces"`
299 target=`cat "$config_dir/target"`
300 score=`cat "$config_dir/score"`
301 first_round=`cat "$config_dir/first_round"`
302 let fields_total=board_size**2
303 let index_max=board_size-1
304 fi
305 }
這兩個函式分別利用資料流重定向生成儲存檔案,和從檔案中讀取資料以載入上次遊戲,其他沒什麼好說的了。
end_game
312 function end_game(){
313 stty echo
314 end_time=`date +%s`
315 let total_time=end_time-start_time
316 duration=`date -u -d @${total_time} +%T`
317 print_board
318 printf "Your score: $score\n"
319 printf "Your game lasted $duration.\n"
320 if (($1))
321 then
322 printf "Congratulations you have achieved $target!\n"
323 exit 0
324 fi
325 if [ ! -z $2 ]
326 then
327 read -n1 -p "Do you want to overwrite saved game?[Y|N]: "
328 if [ "$REPLY" = "Y" ]||[ "$REPLY" = "y" ]
329 then
330 save_game
331 printf "\nGame saved! Use -r option next to load this game.\n"
332 exit 0
333 else
334 printf "\nGame not saved!\n"
335 exit 0
336 fi
337 fi
338 printf "\nYou have lost, better luck next time.\n"
339 exit 0
340 }
end_game函式處理遊戲的結束。
- 320至324行,它接受一個非零的引數1來表示遊戲達成目標。
- 325至337行,即表示在使用
ctrl+c
主動結束遊戲的情況下,詢問是否儲存。 - 338、339行,表示遊戲失敗。
344 while getopts ":b:t:l:rhv" opt
345 do
346 case $opt in
347 b)
348 let board_size="$OPTARG"
349 let '(board_size>=3)&(board_size<=9)'||{ printf "Invalid board size, please choose size between 3 and 9\n";exit 1;}
350 ;;
351 t)
352 let target="$OPTARG"
353 printf "obase=2;$target\n"|bc|grep -e '^1[^1]*$'
354 let $? && { printf "Invalid target, have to be power of two\n";exit 1;}
355 ;;
356 l)
357 echo "This function have not be implement."
358 exit 0
359 ;;
360 r)
361 let reload_flag=1
362 ;;
363 h)
364 help $0
365 exit 0
366 ;;
367 v)
368 version
369 exit 0
370 ;;
371 \?)
372 printf "Invalid option -$opt, please $0 -h\n">&2
373 exit 1
374 ;;
375 :)
376 printf "Option -$opt requires an argument, please $0 -h\n">&2
377 exit 1
378 ;;
379 esac
380 done
334至380行,即利用getopts處理相關選項,-l我並沒有實現,主要是懶的。至於help和version函式沒什麼好說的。353行,利用grep的返回值測試-t選項所指定的target是否符合2的冪。
382 let index_max=board_size-1
383 let fields_total=board_size**2
384
385 for((index=0;index<fields_total;index++))
386 do
387 let board[$index]=0
388 done
389 generate_piece
390 let first_round=$last_added
391 generate_piece
392 if ((reload_flag))
393 then
394 reload_game
395 fi
396
397 while true
398 do
399 print_board
400 key_react
401 let change&&generate_piece
402 let first_round=-1
403 if ((pieces==fields_total))
404 then
405 check_moves
406 if ((moves==0))
407 then
408 end_game 0
409 fi
410 fi
411 done
- 385至388行初始化board陣列。
- 389至391行,產生第一回合的兩個塊。
- 392至395行,判斷是否載入上次儲存的遊戲。
- 403至410行,判斷遊戲是否失敗。
完整指令碼
1 #!/bin/bash
2
3
4 #help information
5 function help(){
6 cat <<EOF
7 --------------------------------------------------------------------------------------------------
8 Usage: $1 [-b INTEGER] [-t INTEGER] [-l FILE] [-r] [-h] [-v]
9
10 -b INTEGER -- specify game board size (sizes 3-9 allowed)
11 -t INTEGER -- specify target score to win (needs to be power of 2)
12 -l FILE -- logged debug information to specified file
13 -r -- reload the previous game
14 -h -- help information
15 -v -- version information
16 ---------------------------------------------------------------------------------------------------
17 EOF
18 }
19
20 #version information
21 function version(){
22 cat <<EOF
23 ----------------------------------------------------------------------------------------------------
24 Name: bash2048
25 Version: 1.00
26 Author: goddog312
27 ----------------------------------------------------------------------------------------------------
28 EOF
29 }
30 ###########################
31 #some important variables##
32 ###########################
33 declare -ia board #this array keep all values for each piece on the board
34 declare -i pieces=0 #number of pieces present on board
35 declare -i score=0 #store the current score
36 declare -i flag_skip #flag that prevents doing more than one operation on single field in one step
37 declare -i moves #store number of possible moves to determine are you lost the game or not
38 declare ESC=$'\e' #escape byte
39 declare header="Bash 2048 v1.0" #print on the top of screen
40
41 #start time of the program
42 declare -i start_time=$(date +%s)
43
44
45 #############################################
46 #default config, some can modify by options##
47 #############################################
48 declare -i board_size=4
49 declare -i target=2048
50 declare -i reload_flag=0
51 declare config_dir="$HOME/.bash2048"
52
53
54 ################################
55 ##temp variables for once game##
56 ################################
57 declare last_added #the piece latest generated
58 declare first_round #the piece that generate in the first round
59 declare -i index_max=$[$board_size-1]
60 declare -i fields_total=$[$board_size*$board_size]
61
62 ########################
63 #for colorizing number##
64 ########################
65 declare -a colors
66 colors[2]=32 #green text
67 colors[4]=34 #blue text
68 colors[8]=33 #yellow text
69 colors[16]=36 #cyan text
70 colors[32]=35 #purple text
71
72 colors[64]="1;47;32" #white background green text
73 colors[128]="1;47;34" #white background bule text
74 colors[256]="1;47;33" #white background yellow text
75 colors[512]="1;47;36" #white background cyan text
76 colors[1024]="1;47;35" #white background purple text
77 colors[2048]="1;41;32" #red background green text
78
79
80 trap "end_game 0 1" INT #handle INT signal
81
82 #print current status of the game, the last added piece are red text
83 function print_board(){
84 clear
85 printf "**************************************************************\n"
86 printf "***********************$header*************************\n"
87 printf "*$ESC[1;5;33mpieces=%-11d target=%-11d score=%-12d$ESC[0m*\n" $pieces $target $score
88 printf "**************************************************************\n"
89 echo
90 printf "/------"
91 for((row=1;row<=index_max;row++))
92 do
93 printf "+------"
94 done
95 printf '\\\n'
96 for((row=0;row<=index_max;row++))
97 do
98 printf "|"
99 for((line=0;line<=index_max;line++))
100 do
101 if let ${board[$row*$board_size+$line]}
102 then
103 if let '(last_added==(row*board_size+line))|(first_round==(row*board_size+line))'
104 then
105 printf "$ESC[1;33m %4d $ESC[0m|" ${board[$row*$board_size+$line]}
106 else
107 printf "$ESC[${colors[${board[$row*$board_size+$line]}]}m %4d $ESC[0m|" ${board[$row*$board_size+$line]}
108 fi
109 else
110 printf " |"
111 fi
112 done
113 if ((row!=index_max))
114 then
115 printf "\n|------"
116 for((r=1;r<=index_max;r++))
117 do
118 printf "+------"
119 done
120 printf "|\n"
121 fi
122 done
123 printf '\n\\------'
124 for((row=1;row<=index_max;row++))
125 do
126 printf "+------"
127 done
128 printf "/\n"
129 }
130
131 #generate new piece on board
132 #generate a pos
133 #generate a value in board[pos]
134 #update last_added
135 #update pieces
136 function generate_piece(){
137 while true
138 do
139 ((pos=RANDOM%fields_total))
140 let ${board[$pos]} ||{ let value=RANDOM%10?2:4;board[$pos]=$value;last_added=$pos;break;}
141 done
142 ((pieces++))
143 }
144
145 #perform push operation between two pieces
146 #variables:
147 # $1:push position, for horizontal push is column,for vertical is row
148 # $2:recipient piece, this will store result if moving or join
149 # $3:originator piece, after moving or join this piece will left empty
150 # $4:direction of push, can be either "up" , "donw" , "left" or "right"
151 # $5:if anything was passed, do not perform the push, but only update number of valid moves. Used for function check_moves
152 # $board:the status of the game board
153 # $change:indicates if the board was changed this round
154 # $flag_skip:indicates the recipient piece cannot be modified further
155 function push_pieces(){
156 case $4 in
157 "up")
158 let "first=$2*$board_size+$1"
159 let "second=($2+$3)*$board_size+$1"
160 ;;
161 "down")
162 let "first=($index_max-$2)*$board_size+$1"
163 let "second=($index_max-$2-$3)*$board_size+$1"
164 ;;
165 "left")
166 let "first=$1*$board_size+$2"
167 let "second=$1*$board_size+$2+$3"
168 ;;
169 "right")
170 let "first=$1*$board_size+($index_max-$2)"
171 let "second=($1*$board_size)+($index_max-$2-$3)"
172 ;;
173 esac
174 if ((board[$first]))
175 then
176 if ((board[$second]))
177 then
178 let flag_skip=1
179 fi
180 if ((board[$first]==board[$second]))
181 then
182 if [ -z $5 ]
183 then
184 let board[$first]*=2
185 if ((board[$first]==target))
186 then
187 end_game 1
188 fi
189 let board[$second]=0
190 let pieces-=1
191 let change=1
192 let score+=${board[$first]}
193 else
194 let moves++
195 fi
196 fi
197 else
198 if ((board[$second]))
199 then
200 if [ -z $5 ]
201 then
202 let board[$first]=${board[$second]}
203 let board[$second]=0
204 let change=1
205 else
206 let moves++
207 fi
208 fi
209 fi
210 }
211
212 function apply_push(){
213 for((i=0;i<=index_max;i++))
214 do
215 for((j=0;j<=index_max;j++))
216 do
217 let flag_skip=0
218 let increment_max=index_max-j
219 for((k=1;k<=increment_max;k++))
220 do
221 if ((flag_skip))
222 then
223 break
224 fi
225 push_pieces $i $j $k $1 $2
226 done
227 done
228 done
229 }
230 function check_moves(){
231 let moves=0
232 apply_push "up" fake
233 apply_push "down" fake
234 apply_push "left" fake
235 apply_push "right" fake
236 }
237 function key_react(){
238 let change=0
239 read -d '' -sn 1
240 if [ "$REPLY" = "$ESC" ]
241 then
242 read -d '' -sn 1
243 if [ "$REPLY" = "[" ]
244 then
245 read -d '' -sn 1
246 case $REPLY in
247 A)
248 apply_push up;;
249 B)
250 apply_push down;;
251 C)
252 apply_push right;;
253 D)
254 apply_push left;;
255 esac
256 fi
257 else
258 case $REPLY in
259 k)
260 apply_push up;;
261 j)
262 apply_push down;;
263 h)
264 apply_push left;;
265 l)
266 apply_push right;;
267
268 w)
269 apply_push up;;
270 s)
271 apply_push down;;
272 a)
273 apply_push left;;
274 d)
275 apply_push right;;
276 esac
277 fi
278 }
279
280 function save_game(){
281 rm -rf "$config_dir"
282 mkdir -p "$config_dir"
283 echo "${board[*]}">"$config_dir/board"
284 echo "$board_size">"$config_dir/board_size"
285 echo "$pieces">"$config_dir/pieces"
286 echo "$target">"$config_dir/target"
287 echo "$score">"$config_dir/score"
288 echo "$first_round">"$config_dir/first_round"
289 }
290
291 function reload_game(){
292 if [ ! -d "$config_dir" ]
293 then
294 return
295 else
296 board=(`cat "$config_dir/board"`)
297 board_size=`cat "$config_dir/board_size"`
298 pieces=`cat "$config_dir/pieces"`
299 target=`cat "$config_dir/target"`
300 score=`cat "$config_dir/score"`
301 first_round=`cat "$config_dir/first_round"`
302 let fields_total=board_size**2
303 let index_max=board_size-1
304 fi
305 }
306
307
308 #print game duration
309 #print total score
310 #print end or achieve information
311 #choose save game or not
312 function end_game(){
313 stty echo
314 end_time=`date +%s`
315 let total_time=end_time-start_time
316 duration=`date -u -d @${total_time} +%T`
317 print_board
318 printf "Your score: $score\n"
319 printf "Your game lasted $duration.\n"
320 if (($1))
321 then
322 printf "Congratulations you have achieved $target!\n"
323 exit 0
324 fi
325 if [ ! -z $2 ]
326 then
327 read -n1 -p "Do you want to overwrite saved game?[Y|N]: "
328 if [ "$REPLY" = "Y" ]||[ "$REPLY" = "y" ]
329 then
330 save_game
331 printf "\nGame saved! Use -r option next to load this game.\n"
332 exit 0
333 else
334 printf "\nGame not saved!\n"
335 exit 0
336 fi
337 fi
338 printf "\nYou have lost, better luck next time.\n"
339 exit 0
340 }
341
342
343 #parse command line options
344 while getopts ":b:t:l:rhv" opt
345 do
346 case $opt in
347 b)
348 let board_size="$OPTARG"
349 let '(board_size>=3)&(board_size<=9)'||{ printf "Invalid board size, please choose size between 3 and 9\n";exit 1;}
350 ;;
351 t)
352 let target="$OPTARG"
353 printf "obase=2;$target\n"|bc|grep -e '^1[^1]*$'
354 let $? && { printf "Invalid target, have to be power of two\n";exit 1;}
355 ;;
356 l)
357 echo "This function have not be implement."
358 exit 0
359 ;;
360 r)
361 let reload_flag=1
362 ;;
363 h)
364 help $0
365 exit 0
366 ;;
367 v)
368 version
369 exit 0
370 ;;
371 \?)
372 printf "Invalid option -$opt, please $0 -h\n">&2
373 exit 1
374 ;;
375 :)
376 printf "Option -$opt requires an argument, please $0 -h\n">&2
377 exit 1
378 ;;
379 esac
380 done
381
382 let index_max=board_size-1
383 let fields_total=board_size**2
384
385 for((index=0;index<fields_total;index++))
386 do
387 let board[$index]=0
388 done
389 generate_piece
390 let first_round=$last_added
391 generate_piece
392 if ((reload_flag))
393 then
394 reload_game
395 fi
396
397 while true
398 do
399 print_board
400 key_react
401 let change&&generate_piece
402 let first_round=-1
403 if ((pieces==fields_total))
404 then
405 check_moves
406 if ((moves==0))
407 then
408 end_game 0
409 fi
410 fi
411 done
相關文章
- javascript實現前端小遊戲2048JavaScript前端遊戲
- Python小遊戲2048Python遊戲
- [ 邏輯鍛鍊] 用 JavaScript 做一個小遊戲 ——2048 (詳解版)JavaScript遊戲
- 2048小遊戲設計思路遊戲設計
- 小遊戲2048最佳演算法怎麼實現?思路全解析!遊戲演算法
- C語言在linux終端下實現2048小遊戲:第二版C語言Linux遊戲
- 2048 雙人創新小遊戲【JavaFX-FXGL遊戲框架】遊戲Java框架
- 我的簡易2048小遊戲記錄整理遊戲
- vue 開發 2048/圍住神經貓 小遊戲Vue遊戲
- vue實現2048Vue
- 【IDL】開發遊戲"2048"開發遊戲
- HTML小遊戲2—— 2048網頁版(附完整原始碼)HTML遊戲網頁原始碼
- 詳解shell中source、sh、bash、./執行指令碼的區別指令碼
- 100行Python程式碼實現貪吃蛇小遊戲(超詳細)Python遊戲
- linux實現猜數字小遊戲Linux遊戲
- Android實現買賣商品小遊戲Android遊戲
- Python程式碼實現“FlappyBird”小遊戲PythonAPP遊戲
- [ 邏輯鍛鍊] 用 JavaScript 做一個小遊戲 ——2048 (初級版)JavaScript遊戲
- [20180930]bash shell &.txt
- shell Bash變數變數
- 詳解Linux bash變數Linux變數
- Python實現三子棋小遊戲Python遊戲
- 小鎮青年的網遊實踐與現實生活:從“遊戲即生活”到“遊戲只是遊戲”遊戲
- 批次網站DNS區域傳送漏洞檢測——bash shell實現網站DNS
- 一小時學會用Python實現「2048」,還能解鎖新花樣Python
- Shell(Bash)學習· 總章
- [20210908]Reverse Shell with Bash.txt
- 小遊戲群聊分享又有新套路,小程式實現全面佈局遊戲
- TP5開發海賊王版2048遊戲遊戲
- Shell猜數字遊戲遊戲
- bash shell 程式與磁碟資料
- [20181212]bash shell 字串 補零.txt字串
- shell程式設計–bash變數程式設計變數
- [20201116]bash shell IO重定向.txt
- bash shell多執行緒方案執行緒
- Linux深入探索04-Bash shellLinux
- [20210913]bash shell $* and $@ 的區別.txt
- Java實現簡易聯網坦克對戰小遊戲Java遊戲