#!/bin/bash
#-------------CopyRight-------------
# Name:Mine Sweeping
# Version Number:1.00
# Type:game
# Language:bash shell
# Date:2005-10-26
# Author:BitBull
# Email:BitBull.cn(at)gmail.com
#------------Environment------------
# Terminal: column 80 line 24
# Linux 2.6.9 i686
# GNU Bash 3.00.15
#-----------------------------------
#---------------Define--------------
ECHO="echo -ne"
ESC="\033["
OK=0
FALSE=1
#--------------Variable--------------
#ANSI ESC action
FLASH=5
REV=7
#color
NULL=0
BLACK=30
RED=31
GREEN=32
ORANGE=33
BLUE=34
PURPLE=35
SBLUE=36
GREY=37
#back color
BBLACK=40
BRED=41
BGREEN=42
BORANGE=43
BBLUE=44
BPURPLE=45
BSBLUE=46
BGREY=47
MINE='@'
FLAG='F'
NUL=' '
SHADOW='X'
X=0
Y=0
CurX=1#cur's X
CurY=1#cur's Y
OCurX=1#old cur's X
OCurY=1#old cur's Y
MCount=0#count mine
FCount=0#count flag
SCount=0#count shadow
MXYp=0#MXY Array's ptr
#---------------Array----------------
#if ${XY[]} == M { mine }
#if ${XY[]} == F { flag }
#if ${XY[]} == N { null }
#if ${XY[]} == S { shadow }
#if ${XY[]} == [1-8] { tip_num }
#${XY[]} init in XYInit(i)
MXY[0]=""
#--------------Function--------------
function SttyInit ()
{
stty_save=$(stty -g)#backup stty
clear
trap"GameExit;"215
stty -echo
$ECHO"${ESC}?25l"#hidden cursor
return$OK
}
function GameExit ()
{
stty $stty_save
stty echo
clear
trap215
$ECHO"${ESC}?25h${ESC}0;0H${ESC}0m"
exit $OK
}
#print help
function Help ()
{
msg="Move:w s a d Dig:j Flag:f NewGame:n Exit:x --CopyRight-- -2005-10-28 BitBull--"
$ECHO"${ESC}${REV};${RED}m${ESC}24;1H${msg}${ESC}${NULL}m"
return$OK
}
#print dialog window in screen
function PMsg ()
{
local title="$1"content="$2"greeting="$3"
$ECHO"${ESC}${RED}m"
$ECHO"${ESC}11;20H ------------------------------------------- "
$ECHO"${ESC}12;20H| ======>$title<====== |"
$ECHO"${ESC}13;20H| $content |"
$ECHO"${ESC}14;20H| ======>$greeting<====== |"
$ECHO"${ESC}15;20H ------------------------------------------- "
$ECHO"${ESC}${NULL}m"
return$OK
}
#print menu and player choose level,then ${X,Y,MCount,FCount,SCount} init
function Menu ()
{
local key
$ECHO"${ESC}6;1H${ESC}${RED}m"
cat<
+++++++++++++++++++++++++++++
+ (1) Easy +
+ (2) Normal +
+ (3) Hardly +
+ (4) Exit +
+++++++++++++++++++++++++++++
MENUEND
$ECHO"${ESC}${NULL}m"
whileread -s -n1key
do
case $keyin
1) X=10;Y=10;MCount=10;FCount=10;SCount=100;break
;;
2) X=20;Y=14;MCount=28;FCount=28;SCount=280;break
;;
3) X=36;Y=18;MCount=65;FCount=65;SCount=648;break
;;
4) GameExit
;;
esac
done
return$OK
}
#receive CurX CurY,put it into XY[CurX+X*(CurY-1))]
#if $# == 3;write into XY[]
#if $# == 2;read from XY[]
function XYFormat ()
{
local XTmp=$1YTmp=$2
if[[ $# -eq 3 ]]
then XY[$XTmp+$X*($YTmp-1)]=$3
elseecho ${XY[$XTmp+$X*($YTmp-1)]}
fi
return$OK
}
function DrawInit ()
{
local DIline DIline2
DIline=$(for(( i=1; i
DIline2=$(for(( i=0; i
clear
Help
$ECHO"${ESC}1;1H+${DIline}+"
for(( i=0; i
do
$ECHO"${ESC}$((i+2));1H${DIline2}|"
done
$ECHO"${ESC}$((Y+2));1H+${DIline}+"
return$OK
}
#${XY[*]}=S
function XYInit ()
{
for(( i=1; i<=$X; i++ ))
do
for(( j=1; j<=$Y; j++ ))
do
XYFormat $i $j S
done
done
return$OK
}
#check X Y
function CheckXY ()
{
local XYTmp="$1 $2"
for(( i=0; i
do
if[["${MXY[i]}"=="$XYTmp"]]
thenreturn$FALSE
fi
done
return$OK
}
#RANDOM mine's X Y
function XYRand ()
{
local XTmp YTmp
for(( i=0; i
do
while:
do
XTmp=$(( RANDOM % ( X -1) +1))
YTmp=$(( RANDOM % ( Y -1) +1))
CheckXY $XTmp $YTmp
if[["$?"=="$OK"]]
then
XYFormat $XTmp $YTmp M
MXY[i]="$XTmp $YTmp"
(( ++MXYp ))
break
elsecontinue
fi
done
done
return$OK
}
#DEBUG
# print ${XY[*]} into ./mine.tmp
#you can read mine.tmp to know where is mine,xixi~~:)
#M is mine
function DEBUGPXY ()
{
rm mine.tmp>/dev/null2>&1
for(( i=1; i<=$Y; i++ ))
do
for(( j=1; j<=$X; j++))
do
$ECHO"$(XYFormat $j $i)">>mine.tmp
done
$ECHO"\n">>mine.tmp
done
return$OK
}
#move cur
#usage:CurMov [UP|DOWN|LEFT|RIGHT]
function CurMov ()
{
local direction=$1Xmin=1Ymin=1Xmax=$X Ymax=$Y
OCurX=$CurX
OCurY=$CurY
case $directionin
"UP")if[[ $CurY -gt $Ymin ]];then (( CurY-- ));fi
;;
"DOWN")if[[ $CurY -lt $Ymax ]];then (( CurY++ ));fi
;;
"LEFT")if[[ $CurX -gt $Xmin ]];then (( CurX-- ));fi
;;
"RIGHT")if[[ $CurX -lt $Xmax ]];then (( CurX++ ));fi
;;
esac
if[[ $CurX != $OCurX || $CurY != $OCurY ]]
then DrawPoint $CurX $CurY CUR
fi
return$OK
}
#display point
#include cur,flag,mine,shadow,nul,tip [1-8]
function DrawPoint ()
{
local TCurX=$(( $1*2)) TCurY=$(( $2+1)) Type=$3
local TOCurX=$(( OCurX *2)) TOCurY=$(( OCurY +1))
local colr=0osign=0sign=0
case $Typein
"CUR")
case $(XYFormat $OCurX $OCurY)in
F) colr=$PURPLE;osign=$FLAG;;
N) colr=$NULL;osign=$NUL;;
[1-8]) colr=$ORANGE;osign=$(XYFormat $OCurX $OCurY);;
[SM]) colr=$SBLUE;osign=$SHADOW;;
esac
case $(XYFormat $CurX $CurY)in
F) sign=$FLAG;;
N) sign=$NUL;;
[1-8]) sign=$(XYFormat $CurX $CurY);;
[SM]) sign=$SHADOW;;
esac
$ECHO"${ESC}${colr}m${ESC}${TOCurY};${TOCurX}H${osign}${ESC}${NULL}m"
$ECHO"${ESC}${REV};${FLASH};${ORANGE}m${ESC}${TCurY};${TCurX}H${sign}${ESC}${NULL}m"
;;
"SHADOW")
$ECHO"${ESC}${SBLUE}m${ESC}${TCurY};${TCurX}H${SHADOW}${ESC}${NULL}m"
;;
"MINE")
$ECHO"${ESC}${REV};${RED}m${ESC}${TCurY};${TCurX}H${MINE}${ESC}${NULL}m"
;;
"FLAG")
$ECHO"${ESC}${TCurY};${TCurX}H${ESC}${PURPLE}m${FLAG}${ESC}${NULL}m"
;;
[1-8])
$ECHO"${ESC}${TCurY};${TCurX}H${ESC}${ORANGE}m${Type}${ESC}${NULL}m"
;;
"NUL")
$ECHO"${ESC}${TCurY};${TCurX}H${NUL}"
esac
return$OK
}
#check xy
function Loop ()
{
local XYTmp="$1 $2"
for(( i=0; i
do
if[["$XYTmp"=="${MXY[i]}"]]
then $ECHO1
fi
done
return$OK
}
#count around mine
#A B C
#D X E
#F G H
#return mine's number
function CountM ()
{
local Xmin=1Ymin=1Xmax=$X Ymax=$Y minecount=0n=0
#A
if[[ ( $CurX -gt $Xmin ) && ( $CurY -gt $Ymin ) ]]
then
n=$( Loop $((CurX-1)) $((CurY-1)) )
(( minecount += n ))
n=0
fi
#B
if[[ $CurY -gt $Ymin ]]
then
n=$( Loop $CurX $((CurY-1)) )
(( minecount += n ))
n=0
fi
#C
if[[ ( $CurX -lt $Xmax ) && ( $CurY -gt $Ymin ) ]]
then
n=$( Loop $((CurX+1)) $((CurY-1)) )
(( minecount += n ))
n=0
fi
#D
if[[ $CurX -gt $Xmin ]]
then
n=$( Loop $((CurX-1)) $CurY )
(( minecount += n ))
n=0
fi
#E
if[[ $CurX -lt $Xmax ]]
then
n=$( Loop $((CurX+1)) $CurY )
(( minecount += n ))
n=0
fi
#F
if[[ ( $CurX -gt $Xmin ) && ( $CurY -lt $Ymax ) ]]
then
n=$( Loop $((CurX-1)) $((CurY+1)) )
(( minecount += n ))
n=0
fi
#G
if[[ $CurY -lt $Ymax ]]
then
n=$( Loop $CurX $((CurY+1)) )
(( minecount += n ))
n=0
fi
#H
if[[ ( $CurX -lt $Xmax ) && ( $CurY -lt $Ymax ) ]]
then
n=$( Loop $((CurX+1)) $((CurY+1)) )
(( minecount += n ))
n=0
fi
return$minecount
}
#dig
#if mine ,gameover
#else tip around mine's number
function Dig ()
{
local key minenum=0
case $(XYFormat $CurX $CurY)in
M)
DrawPoint $CurX $CurY MINE
read -s -n1key
GameOver"Game Over"
;;
S)
CountM
minenum=$?
if[[ $minenum -eq $NULL ]]
then
XYFormat $CurX $CurY N
DrawPoint $CurX $CurY NUL
else
XYFormat $CurX $CurY $minenum
DrawPoint $CurX $CurY $minenum
fi
(( SCount-- ))
if[[ $SCount -eq $MCount ]]
then GameOver"Well Done"
fi
;;
esac
DrawPoint $CurX $CurY CUR
return$OK
}
#draw flag's number
function DrawFCount ()
{
$ECHO"${ESC}22;34H${ESC};${PURPLE}mFLAG=${FCount} ${ESC}${NULL}m"
}
#sign mine
function Flag ()
{
local XYTmp="$CurX $CurY";stat=$FALSE
case $(XYFormat $CurX $CurY)in
F)
for(( i=1; i
do
if[["${MXY[i]}"=="$XYTmp"]]
then XYFormat $CurX $CurY M;stat=$OK;break
fi
done
if[[ $stat == $FALSE ]]
then XYFormat $CurX $CurY S
fi
DrawPoint $CurX $CurY SHADOW
(( FCount++ ))
DrawFCount
;;
[SM])
if[[ $FCount -eq $NULL ]]
thenreturn$FALSE
fi
DrawPoint $CurX $CurY FLAG
XYFormat $CurX $CurY F
(( FCount-- ))
DrawFCount
;;
esac
DrawPoint $CurX $CurY CUR
return$OK
}
function GameOver ()
{
local key msgtitle=$1
PMsg"$msgtitle""Do you want replay?""Thank You"
whileread -s -n1key
do
case $keyin
[yY])exec$(dirname $0)/$(basename $0);;
[nN]) GameExit;;
*)continue;;
esac
done
return$OK
}
#main
#drawscreen and control
function Main ()
{
local key
XYInit
XYRand
############################
# if you enable DEBUGPXY,
#you can know where is mine
# DEBUGPXY #delete this line's #
#then cat ./mine.tmp
############################
DrawPoint $CurX $CurY CUR
DrawFCount
whileread -s -n1key
do
case $keyin
[wW]) CurMov UP;;
[sS]) CurMov DOWN;;
[aA]) CurMov LEFT;;
[dD]) CurMov RIGHT;;
[jJ]) Dig;;
[fF]) Flag;;
[nN])exec$(dirname $0)/$(basename $0);;
[xX]) GameExit;;
esac
done
return$OK
}
#---------------Main-----------------
SttyInit
Menu#X Y MCount FCount SCount OK!
DrawInit
Main