bash shell實現2048小遊戲詳解

fuluoyide312發表於2020-10-23

前言

 最近在github上看到一個用bash shell實現2048小遊戲的指令碼感覺挺有意思的,就自己仿照他的樣子稍作修改再實現了一遍我的實現,並記錄下實現的詳細過程。
 指令碼的執行如圖:
在這裡插入圖片描述

重要變數

在這裡插入圖片描述

  1. board 是一個整型陣列,用來儲存所有格子中的當前數值,它的下標即從0到總格子數減1,與介面中的格子從左到右,再從上到下,一一對應。陣列的所有元素,在全新的遊戲開始時用0初始化,而載入遊戲時,用存檔目錄中的檔案初始化。
  2. pieces 用來儲存當前介面中所有非零的格子數。
  3. score 用來儲存當前的得分總數。
  4. flag_skip 用來防止一個格子在同一回合中被操作兩次。
  5. moves 用來測試遊戲還能不能被操作,是否已經輸掉遊戲。
  6. ESC 作為Escape螢幕控制碼,在輸出顏色格式的時候使用,\e或者\033等都可以。
  7. header 也就是介面的標題,介紹性質的,可以自己定義
  8. start_time 記錄程式開始的時間

在這裡插入圖片描述這四個變數作為預設值,可以通過選項改變

  1. board_size 即遊戲介面的每邊的大小,限制在3至9之間
  2. target 即遊戲成功的目標,可以自己設定,但需要是2的冪
  3. reload_flag 即是否載入存檔
  4. config_dir 即存檔檔案的目標目錄

在這裡插入圖片描述

  1. last_added 即最新生成的塊的位置
  2. first_round 即第一個生成的塊的位置。因為遊戲最開始必須要生成兩個塊,而我定義用黃色表現這兩個塊以及用黃色表示以後每次最新生成的塊。
  3. index_max 因為陣列的下標從0開始,所以定義這個變數為遊戲介面的每邊的大小減一
  4. 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即列。

    1. 其中101行用來判斷當前位置的格子內的值是否為0,若非零則輸出。103行是在格子內的值非零的情況下,判斷是否為最新生成的塊或第一回合的塊,如果是的話,用特定的黃色輸出,如果不是的話,則按前面定義好的數值對應的顏色輸出。
    2. 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格子則提供值等待處理。

  1. 174行判斷first內是否存在非零值,如果存在非零值的話:

    • 176至179行判斷如果second存在非零值的話,就只處理這一次,防止重複處理。
    • 180至196行判斷,如果firstsecond內的值相同的話,就相加,並把結果存在first內。
  2. 如果first內不存在非零值的話:

    • 189至209行判斷,如果second記憶體在非零值,則將其移到first內。
  3. 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函式處理遊戲操作。

  1. 上下操作時,i代表列,j代表行。向上時,它的邏輯是從上到下,從左到右。向下時,它的邏輯是從下到上,從左到右。
  2. 左右操作時,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行表示,也接受kjhlwsad作為上下左右。


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函式處理遊戲的結束。

  1. 320至324行,它接受一個非零的引數1來表示遊戲達成目標。
  2. 325至337行,即表示在使用ctrl+c主動結束遊戲的情況下,詢問是否儲存。
  3. 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

相關文章