Improve your skills by writing Minesweeper game Bash

Those good old classic game but good material to improve the programming capabilities. Today, let us explore carefully about it, how to write a demining program in Bash.

I am not an expert in teaching programming, but when I want a better grasp of a thing, will try to find yourself in the music of these methods. For example, when I want to go further in terms of shell programming, I decided to write a Bash with Minesweeper game to practice them.

If you are an experienced programmer Bash, hoping to improve skills at the same time fun, then please follow me write you a minesweeper game run in the terminal. The complete code can in this GitHub repository found in.

be ready

Before I write any code, I have listed a few necessary part of the game:

  1. Display minefield
  2. Create a game logic
  3. Determining whether to create alternative logic cell
  4. Available identified and recorded (has mine) the number of cells
  5. Create a logical end of the game

Display minefield

Mine clearance, the game interface is of a 2D array (rows and columns) small square opaque composition. At each grid are likely in possession of mines. The player's task is to find those free squares mine, and in the process, can not point to the mines. This version of Minesweeper using Bash 10x10 matrix, the actual logic array by a simple Bash to complete.

First of all, my husband became some random numbers. This will be the location of mines in the minefield. Control the number of mines, before you start writing code, doing so will be easier. Logic to achieve this function could be better, but I did it to make the game to achieve Keep it simple, and there is room for improvement. (I wrote this game is purely entertainment, but if you can modify it better, I am also very happy.)

The following variables are constant throughout the process, in order to declare that they randomly generated number. As the following a- gthe variables that will be used to calculate the value of the mines can be ruled out:

  1. #变量
  2. score=0#会用来存放游戏分数
  3. #下面这些变量,用来随机生成可排除地雷的实际值
  4. a="1 10 -10 -1"
  5. b="-1 0 1"
  6. c="0 1"
  7. d="-1 0 1 -2 -3"
  8. e="1 2 20 21 10 0 -10 -20 -23 -2 -1"
  9. f="1 2 3 35 30 20 22 10 0 -10 -20 -25 -30 -35 -3 -2 -1"
  10. g="1 4 6 9 10 15 20 25 30 -30 -24 -11 -10 -9 -8 -7"
  11. #
  12. #声明
  13. declare-a room #声明一个 room 数组,它用来表示雷区的每一格。

Next, I will show a column (0-9) and rows (aj) the game interface, and uses a 10x10 matrix as a minefield. ( M[10][10]An index from 0-99, an array of 100 values.)

Creating a called ploughfunction, we first title displayed: two empty row, column head, and his party -, in a schematic interface of the game is down:

  1. printf'\n\n'
  2. printf'%s'"     a   b   c   d   e   f   g   h   i   j"
  3. printf'\n   %s\n'"-----------------------------------------"

Then I initialize a counter variable called r, it will be used to record how much rampant displayed. Note that later in the game code, we will use the same variable r, as our array index. In Bash for loop, with the seqcommand from 0 to 9. I (digital d%) placeholder to display line numbers ( $rowby seqdefinition):

  1. r=0#计数器
  2. for row in $(seq 09);do
  3. printf'%d '"$row"#显示行数0-9

Before we went down to do, let us look at what has been done up to now. We first show sideways [a-j]and then [0-9]the line number is displayed, we will use these two ranges, to determine the exact location of the user's mine.

Then, in each row, insert columns, so it's time to write a new forcycle of. This cycle management with each column, that is, in fact, the game interface is generated for each grid. I added some auxiliary functions, you can see its complete implementation in the source code. For each cell, we need some things to make it look like mines, so we will start with a dot ( .) to initialize the space. In order to realize this idea, we use is called a is_null_fieldcustom function. At the same time, we need a memory cell array for each specific value, here will use the global array previously defined room, and with a variable ras an index. With the rincrease, through all the cells and randomly deploy mines.

  1.   for col in $(seq 09);do
  2. ((r+=1))#循环完一列行数加一
  3. is_null_field $r #假设这里有个函数,它会检查单元格是否为空,为真,则此单元格初始值为点(.)
  4. printf'%s \e[33m%s\e[0m '"|""${room[$r]}"#最后显示分隔符,注意,${room[$r]}的第一个值为'.',等于其初始值。
  5. #结束 col 循环
  6. done

Finally, in order to keep the game interface is pretty neat, I'll be in every line with a vertical line as the end, and the end of the last line of the cycle:

  1. printf'%s\n'"|"#显示出行分隔符
  2. printf' %s\n'"-----------------------------------------"
  3. #结束行循环
  4. done
  5. printf'\n\n'

Complete ploughcode is as follows:

  1. plough()
  2. {
  3.   r=0
  4.   printf'\n\n'
  5.   printf'%s'"     a   b   c   d   e   f   g   h   i   j"
  6.   printf'\n   %s\n'"-----------------------------------------"
  7.   for row in $(seq 09);do
  8.     printf'%d  '"$row"
  9.     for col in $(seq 09);do
  10.        ((r+=1))
  11.        is_null_field $r
  12.        printf'%s \e[33m%s\e[0m '"|""${room[$r]}"
  13.     done
  14.     printf'%s\n'"|"
  15.     printf'   %s\n'"-----------------------------------------"
  16.   done
  17.   printf'\n\n'
  18. }

It took me some time to think, is_null_fieldwhat specific functions yes. Let's see, in the end what it can do. In the beginning, we need to have a game fixed. You can easily choose initial value can be a number or any character. I finally decided, the initial value of a point all the cells ( .), because I think this will make the game interface look better. Here is the complete code for this function:

  1. is_null_field()
  2. {
  3. local e=$1 #在数组 room 中,我们已经用过循环变量'r'了,这次我们用'e'
  4. if[[-z "${room[$e]}"]];then
  5. room[$r]="."#这里用点(.)来初始化每一个单元格
  6. fi
  7. }

Now, I have initialized all the cabinets, and now just use a very simple function will be able to draw current game how many cells can operate:

  1. get_free_fields()
  2. {
  3. free_fields=0#初始化变量
  4. for n in $(seq 1 ${#room[@]});do
  5. if[["${room[$n]}"="."]];then#检查当前单元格是否等于初始值(.),结果为真,则记为空余格子。
  6. ((free_fields+=1))
  7.     fi
  8.   done
  9. }

This is shown in the game interface, [a-j]a column, [0-9]a row.

Minefield

Minefield

Players create a logical

In that the logic behind the operation of the player, starting with stdin read data as the coordinates, and then find the corresponding position of the actual value contained. Here used Bash of parameter expansion , to try to get the number of ranks. The letters represent the number of columns is then passed to branch statement, thus yielding the corresponding columns. To better understand this process, we can see the following code variables, othe corresponding values. For example, a player input c3, then it is divided into two characters Bash: cand 3. For simplicity, I skipped the section on how to handle invalid input.

  1. colm=${opt:0:1}#得到第一个字符,一个字母
  2. ro=${opt:1:1}#得到第二个字符,一个整数
  3. case $colm in
  4. a ) o=1;;#最后,通过字母得到对应列数。
  5. b ) o=2;;
  6.     c ) o=3;;
  7.     d ) o=4;;
  8.     e ) o=5;;
  9.     f ) o=6;;
  10.     g ) o=7;;
  11.     h ) o=8;;
  12.     i ) o=9;;
  13.     j ) o=10;;
  14.   esac

The following calculation code corresponding to the actual user of the selected cell number, then stores the result in a variable.

There is also used a lot of shufcommand, shufit is designed to generate a random sequence of Linux command . -iLater option need to provide a desired range or number of disrupted, -noption to return up to a predetermined number of output required value. Bash can be carried out within two parentheses math , here we used many times.

Or follow the previous example, the player input c3. Then, it was converted into ro=3and o=3. Thereafter, the above statement is a branch code, cconverted to the corresponding integer, into the formula to obtain the final result ivalue.

  1. i=$(((ro*10)+o))#遵循运算规则,算出最终值
  2. is_free_field $i $(shuf-i 0-5-n 1)#调用自定义函数,判断其指向空/可选择单元格。

Carefully observe this calculation to see if the end result iis how calculated:

  1. i=$(((ro*10)+o))
  2. i=$(((3*10)+3))=$((30+3))=33

33 is the final result. Show up in our game interface, players enter the coordinates of the point to the first 33 cells, that is, line 3 (starting at 0, otherwise this becomes 4), the first three.

Determining whether to create alternative logic cell

To find the mines, after coordinate transformation, and to find the actual location, the program checks whether the cell is optional. If not available, the program displays a warning message, and requires the player to re-enter coordinates.

In this code, whether the cell is optional whether the array is a value corresponding to point ( .) determined. If Alternatively, a value corresponding to the cell is reset, and updated score. Conversely, since it is not a value corresponding to the point, is set variable not_allowed. For simplicity, the game warning message this part of the source code, I'll leave readers to explore their own.

  1. is_free_field()
  2. {
  3.   local f=$1
  4.   local val=$2
  5.   not_allowed=0
  6.   if[["${room[$f]}"="."]];then
  7.     room[$f]=$val
  8.     score=$((score+val))
  9.   else
  10.     not_allowed=1
  11.   fi
  12. }

Extracting mines

Extracting mines

The effective input coordinates, and the corresponding position of landmines, as shown below. Players enter the h6game interface will be some random value generated. After the discovery of mines, these values will be added to the user score.

Extracting mines

Extracting mines

Remember the variables we defined at the beginning, a- gyou, I will use them to determine specific values randomly generated mines. Therefore, the input coordinates based on the player, based on the program ( mnumber) randomly generated to generate the values of the surrounding other cells (shown above). After all of the initial input values and the coordinates of the addition, the results on the final i(calculated as above) in.

Please note that the following code X, which is our only marks the end of the game. We will add it to a random list. In shufunder command of magic, Xyou can appear in any case, but if you are lucky, it may have been not appear.

  1. m=$(shuf-e a b c d e f g X -n 1)# X 添加到随机列表中,当 m=X,游戏结束
  2. if[["$m"!="X"]];then# X 将会是我们爆炸地雷(游戏结束)的触发标志
  3. for limit in ${!m};do#!m 代表 m 变量的值
  4. field=$(shuf-i 0-5-n 1)#然后再次获得一个随机数字
  5. index=$((i+limit))# m 中的每一个值和 index 加起来,直到列表结尾
  6. is_free_field $index $field
  7.     done

I want the game interface, all displayed random cells, the cells are close to the player selection.

Extracting mines

Extracting mines

And recording the number of selected cells available

The program needs to record the game interface which cells are selectable. Otherwise, the program will always allow users to input data, even if all the cells are selected too. To accomplish this, I created a named free_fieldsvariable, the initial value 0. With a forcycle, the number of records in the selectable game interface cells. If the cell corresponding to the value of the point ( .) is free_fieldsincremented by one.

  1. get_free_fields()
  2. {
  3.   free_fields=0
  4.   for n in $(seq 1 ${#room[@]});do
  5.     if[["${room[$n]}"="."]];then
  6.       ((free_fields+=1))
  7.     fi
  8.   done
  9. }

Wait, if free_fields=0it? This means that the player has been selected all the cells. To get a better understanding of this section, you can see where the source code .

  1. if[[ $free_fields -eq 0]];then#这意味着你已选择过所有格子
  2. printf'\n\n\t%s: %s %d\n\n'"You Win""you scored""$score"
  3.       exit0
  4. fi

Create a logical end of the game

For the end of the game this case, we're using some very clever tricks , the results are displayed in the center of the screen. I call this part left to the reader to explore their own friends.

  1. if[["$m"="X"]];then
  2. g=0#为了在参数扩展中使用它
  3. room[$i]=X #覆盖此位置原有的值,并将其赋值为X
  4. for j in{42..49};do#在游戏界面中央,
  5. out="gameover"
  6. k=${out:$g:1}#在每一格中显示一个字母
  7. room[$j]=${k^^}
  8.       ((g+=1))
  9.     done
  10. fi

Finally, we show two lines of players are most concerned about.

  1. if[["$m"="X"]];then
  2.       printf'\n\n\t%s: %s %d\n'"GAMEOVER""you scored""$score"
  3.       printf'\n\n\t%s\n\n'"You were just $free_fields mines away."
  4.       exit0
  5. fi

Minecraft Gameover

Minecraft Gameover

Article to end here, my friends! If you want to know more details, refer to my GitHub repository , where there is this demining game's source code, and you'll find more games written with Bash. I hope this article will arouse your interest in learning Bash and fun.


via: https://opensource.com/article/19/9/advanced-bash-building-minesweeper

Author: Abhishek Tamrakar topics: lujun9972 Translator: wenwensnow proofread: wxy

This article from the LCTT original compiler, Linux China is proud

Guess you like

Origin www.linuxidc.com/Linux/2019-10/160937.htm
Recommended