Bash MineSweeper from Heise.de
Version vom 6. Januar 2021, 13:20 Uhr von Raz0rsedge (Diskussion | Beiträge)
1 #!/bin/bash
2
3 declare -a mine
4 if [ -z "$1" ] ; then w=10 ; else w=${1} ; shift ;fi
5 if [ -z "$1" ] ; then h=10 ; else h=${1} ; shift ;fi
6 if [ -z "$1" ] ; then n=10 ; else n=${1} ; shift ;fi
7
8 function getfield() {
9 if [ "${1}" -lt 0 \
10 -o "${1}" -ge "${w}" \
11 -o "${2}" -lt 0 \
12 -o "${2}" -ge "${h}" \
13 ]; then
14 echo "-"
15 else
16 echo "${mine[$((${2}*${w}+${1}))]}"
17 fi
18 }
19
20 function minecount() {
21 local x y e=""
22 local IFS=$'\n'
23 for ((x=${1}-1; ${x}<=${1}+1; x++)) do
24 for ((y=${2}-1; ${y}<=${2}+1; y++)) do
25 e+=$(getfield ${x} ${y})$'\n'
26 done
27 done
28 grep -c "*" <<< ${e}
29 }
30
31 function fieldcount() {
32 local IFS=$'\n'
33 tr ' ' '\012' <<< ${mine[*]} | grep -c "\\${1}"
34 }
35
36 function showmatrix () {
37 local i x y e
38 # Drucke X-Achse
39 #b=$(seq -s " " 1 $(((${w}-1)/10))); echo -n -e "\e[42m ${b}"
40 echo -e -n "\e[42m "
41 for i in $(seq 0 $((${w}-1))) ; do
42 echo -n $(($i/10))
43 echo -n "|"
44 done
45 echo
46 echo -n " "
47 for i in $(seq 0 $((${w}-1))) ; do
48 if [ $i -ge 10 ] ; then
49 echo -n $(($i%10))
50 echo -n "|"
51 else
52 echo -n $i
53 echo -n "|"
54 fi
55 done
56 echo -e "\e[49m" # grün aus
57 for ((y=0; ${y}<${h}; y++)) do
58 printf "\e[42m%02d\e[49m " ${y}
59 for ((x=0; ${x}<${w}; x++)) do
60 e="${mine[$((${y}*${w}+${x}))]}"
61 echo -e -n "${e/${1}/${2}}"
62 echo -n "|"
63 done
64 echo
65 done
66 }
67
68 function searchmine() {
69 local x y m
70 case "${mine[$((${2}*${w}+${1}))]}" in
71 '.')
72 m=$(minecount ${1} ${2})
73 mine[$((${2}*${w}+${1}))]=${m}
74 if [ ${m} -eq 0 ] ; then
75 for ((x=${1}-1; ${x}<=${1}+1; x++)) do
76 for ((y=${2}-1; ${y}<=${2}+1; y++)) do
77 if [ "${mine[$((${y}*${w}+${x}))]}" == "." ] && [ ${x} -ne ${1} -o ${y} -ne ${2} ] && \
78 [ ${x} -ge 0 -a ${x} -lt ${w} -a ${y} -ge 0 -a ${y} -lt ${h} ]; then
79 searchmine ${x} ${y}
80 fi
81 done
82 done
83 fi
84 ;;
85 '*')
86 clear
87 echo "Boom!"
88 mine[((${2}*${w}+${1}))]="\e[41mX\e[49m"
89 showmatrix
90 exit
91 esac
92
93 }
94
95 function searchall() {
96 local i
97 for ((i=0;
98 ${i}<${w}*${h};
99 i++)) do
100 if [[ "${mine[i]}" =~ [*.] ]]; then
101 searchmine $(((${i})%${w})) $(((${i}-(${i})%${w})/${h}))
102 fi
103 done
104 }
105
106 for ((i=0;
107 ${i}<${w}*${h};
108 i++)) do
109 mine[${i}]="."
110 done
111
112 for i in $(shuf -i 0-$((${w}*${h}-1)) -n ${n}); do
113 mine[$i]="*"
114 done
115
116 while true; do
117 clear
118 if [ $(fieldcount '.') == 0 ]; then
119 echo "Geschafft!"
120 showmatrix
121 break
122 else
123 echo "Noch $(fieldcount '.') Feld(er) und $(($(fieldcount '*')-$(fieldcount '\\e'))) Minen"
124 fi
125 showmatrix "\*" "."
126 echo "Enter x y or"
127 echo "Enter s for search all unmarked Fields"
128 echo "Enter x y m (m for mark/unmark a mine)"
129 echo -n "x y?"
130 read x y z
131
132 if [ "${z}" == "m" ] ; then # Markieren einer Mine
133 if grep -q '\\e\[41' <<<${mine[$((${y}*${w}+${x}))]} ; then
134 mine[$((${y}*${w}+${x}))]=${mine[$((${y}*${w}+${x}))]:6:1}
135 elif [[ "${mine[$((${y}*${w}+${x}))]}" =~ [*.] ]] ; then
136 mine[$((${y}*${w}+${x}))]="\e[41m${mine[$((${y}*${w}+${x}))]}\e[49m"
137 fi
138 elif [ "${x}" == "s" ] ; then # open all unmarked fields
139 searchall
140 else
141 if [ "${x}" -ge 0 \
142 -a "${y}" -ge 0 \
143 -a "${y}" -lt "${h}" \
144 -a "${x}" -lt "${w}" \
145 ]; then
146 searchmine ${x} ${y}
147 fi
148 fi
149 done