Snake [ALFA] em Shell Script
Publicado por marcelo cavalca filho (última atualização em 30/09/2013)
[ Hits: 7.376 ]
Homepage: https://www.facebook.com/Colgatera
Download 1380562200.snake.bsh (versão 2)
Fala pessoal do VOL!
Como treinamento de lógica avançada de programação estou tentando recriar jogos clássicos sem olhar nenhum código fonte (ou seja, fazer na raça mesmo :P).
Com isso decidi que meu primeiro jogo seria nada mais nada menos do que aquele que todos jogavam nos seus "Tijorolas": Snake!
Sim, aquela cobra simpática que vai aumentando conforme come a ração. :P
Estou há aproximadamente 3 meses mexendo no GNU/Linux e aprendendo Shell Script desde então. Nunca havia visto nenhum dos dois antes. :o
Enfim, segue abaixo o meu código, lembrando que ainda está na VERSÃO ALFA, portanto, existem mil e um bugs que ainda precisam ser encontrados e resolvidos.
Obs.: para movimentar-se utilize as teclas WASD (para quem não conhece: W - cima; A - esquerda; S - baixo; D - direita).
Espero que gostem e me deem um feedback, Cya. :D
Versão 2 - Enviado por marcelo cavalca filho em 30/09/2013
Changelog: (ATUALIZADO)
Essa é a melhor versão de Snake feita em Shell Script (ou não hehe), ela agora não possui erros e é bem mais enxuta que a anterior.
Me digam o que acharam e no que ainda posso melhorá-lo.
Meu próximo jogo a ser feito em shell será TETRIS (também a partir do zero :P)
#!/bin/bash #=====================================================================================# # # Programa: snake.bsh # # Autor: Cavalca Filho, Marcelo (15/09/2013) # # Objetivo: Jogo snake em shell :D # #=====================================================================================# # # Versão: 1.0 - 19/09/2013 # > Utiliza um vetor para exibir a cobra e reinicia o mapa inteiro a # cada movimento. # # 1.1 - 21/09/2013 # > Ideia para criação de uma nova lógica pois a versão 1.0 trava mais # conforme a cobra vai aumentando. # Agora a cobra se move sozinha com o tempo, não necessitando o # "readkey" para cada próximo movimento. # # 1.2 - 22/09/2013 # > Lógica melhorada para a posição da "nova comida" pois antes gerava # comida nas bordas ou dentro da cobra, bugando o jogo. # # 1.3 - 25/09/2013 # > Versão alfa completa! # Agora o jogo não gera "lag" devido ao aumento da cobra pois com a # nova lógica a cobra não é uma matriz e sim o próprio terreno, por # assim dizer. # Pode parecer simples mas a lógica para a movimentação da cobra # conforme ela faz curvas é um pouco complexa. Leia o apêndice abaixo # #=====================================================================================# #=============================== CURVAS: COMO LIDAR ==================================# # # O grande problema no início foi que a cobra era uma matriz e o terreno # era outra. Isso gerava um pequeno "lag" conforme a cobra aumentava. Foi pensada # então em uma lógica que fizesse com que a cobra fosse parte do terreno. # O maior empecilho para isso foi quando ela se curvava: Para onde o "rabo" dela # vai quando ela vira? E se ela fizer mais de uma curva? # Então foi pensada na seguinte lógica: Existe uma matriz que guarda as curvas # feitas. Existe também um vetor que vai indicar qual o próximo movimento da # cabeça e qual o próximo movimento do rabo. Uma posição de CURVA armazena a # quantidade de curvas que ela ainda tem de realizar. Conforme ela vai fazendo # as curvas esse valor é decrementado e o vetor é renovado para que ele saiba # para onde ir na próxima curva. # # ex.: a cobra vira: # baixo - direita - cima - direita - baixo # [4] - [1] - [3] - [1] - [4] # # CURVA[0,0]= 5 (total) # CURVA[0,1]= 4 (valor de "baixo") # # O rabo encontrou a posição onde ele deve ir para baixo logo a matriz será # atualizada para: # # CURVA[0,0]= 4 # CURVA[0,1]= 1 (valor de "direita") # # Portanto, na próxima curva que ela chegar ela saberá que tem de ir para a # direita, e depois "cima", e por aí vai :) # # # tl;dr: Tem uma matriz que guarda o movimento da próxima curva. Ao chegar lá # essa matriz é atualizada para os valores das outras curvas. # #=====================================================================================# #================================= GERAR TERRENO =====================================# clear # Declaração das matrizes do campo declare -A CAMPO declare -A CURVA # Aqui voce pode alterar a altura e a largura conforme desejar # ___________ #| | HEIGHT=15 # ALTURA WIDTH=30 # LARGURA #|___________| # Verdadeira geração do terreno. Ele irá colocar o campo na tela e inserir os caracteres # para uma boa visualização do mesmo. let m=${HEIGHT}+1 let n=${WIDTH}+1 let i=$n while [ $i -ge 0 ]; do let j=$m while [ $j -ge 0 ]; do if [ $i -eq 0 ] || [ $j -eq 0 ] || [ $i -eq $n ] || [ $j -eq $m ]; then if [ $i -eq 0 ] && [ $j -eq 0 ]; then tput cup $j $i echo -ne "#" elif [ $i -eq $n ] && [ $j -eq 0 ]; then tput cup $j $i echo -ne "#" elif [ $i -eq $n ] && [ $j -eq $m ]; then tput cup $j $i echo -ne "#" elif [ $i -eq 0 ] && [ $j -eq $m ]; then tput cup $j $i echo -ne "#" elif [ $i -eq 0 ] || [ $i -eq $n ]; then tput cup $j $i echo -ne "‖" else tput cup $j $i echo -ne "=" fi CAMPO[$i,$j]=1 # echo -ne "█" else CAMPO[$i,$j]=0 fi let j=$j-1 done let i=$i-1 done #=====================================================================================# #=============================== INICIALIZAR VARIAVEIS ===============================# DIFIC=0.05 # Dificuldade ou velocidade de atualização do movimento # [!] De preferência não alterar as variáveis abaixo, a menos que saiba o que esteja # fazendo # _____________________________________________________________________________________ #| | y[0]=1 x[0]=2 x[1]=1 y[1]=1 CURVA[0,0]=0 m=$((RANDOM%${WIDTH}+1)) # Gerando... n=$((RANDOM%${HEIGHT}+1)) # ...a primeira... CAMPO[$m,$n]=2 # ...bolinha dentro da caixa. LASTMOV[0]=1 # A cobra andará para a direita primeiramente. LASTMOV[1]=1 PONT=0 INPUT="d" # Inicialização da entrada. WHATDO="d" # Qual movimento será o primeiro. REVDO="a" # Reverso do primeiro movimento para evitar cobra louca. LOSTGAME=false # Detecção de game perdido. tput civis tput cup $n $m echo -ne "*" tput cup ${y[0]} ${x[0]} echo -ne "ᕙ" tput cup ${y[1]} ${x[1]} echo -ne "∎" let n=$HEIGHT+4 # Exibição dos controles. tput cup $n 1 #|_______________________________________________________________________________________| #=====================================================================================# read -s -n 1 INPUT while :; do let n=$HEIGHT+2 tput cup $n 3 stty echo echo " X[0]=${x[0]} Y[0]=${y[0]} " echo " PONTUACAO = $PONT " stty -echo read -s -t ${DIFIC} -n 1 INPUT if [ $INPUT = "d" ] 2>&- || [ $INPUT = "a" ] 2>&- || [ $INPUT = "s" ] 2>&- || [ $INPUT = "w" ] 2>&- ; then if [ $INPUT != $WHATDO ] && [ $INPUT != $REVDO ]; then WHATDO=$INPUT fi fi if [ ${CAMPO[${x[1]},${y[1]}]} -eq 3 ]; then CAMPO[${x[1]},${y[1]}]=1 LASTMOV[1]=${CURVA[0,1]} let CURVA[0,0]=${CURVA[0,0]}-1 CURVA[1,0]=1 while [ ${CURVA[1,0]} -le ${CURVA[0,0]} ]; do let CURVA[1,1]=${CURVA[1,0]}+1 CURVA[0,${CURVA[1,0]}]=${CURVA[0,${CURVA[1,1]}]} CURVA[0,${CURVA[1,1]}]=0 let CURVA[1,0]=${CURVA[1,0]}+1 done fi if [ $WHATDO = "d" ]; then let m=${x[0]}+1 let n=${y[0]} REVDO="a" if [ ${LASTMOV[0]} -ne 1 ]; then CAMPO[${x[0]},${y[0]}]=3 let CURVA[0,0]=${CURVA[0,0]}+1 CURVA[0,${CURVA[0,0]}]=1 fi case ${CAMPO[$m,$n]} in 0 ) CAMPO[${x[1]},${y[1]}]=0 tput cup ${y[1]} ${x[1]} stty echo echo -ne " " case ${LASTMOV[1]} in 1) let x[1]=${x[1]}+1;; 2) let x[1]=${x[1]}-1;; 3) let y[1]=${y[1]}-1;; 4) let y[1]=${y[1]}+1;; esac tput cup ${y[0]} ${x[0]} echo -ne "∎" x[0]=$m CAMPO[${x[0]},${y[0]}]=1 tput cup ${y[0]} ${x[0]} echo -ne "ᕙ" stty -echo ;; 1 ) LOSTGAME=true break ;; 2 ) let PONT=$PONT+1 stty echo tput cup ${y[0]} ${x[0]} echo -ne "∎" x[0]=$m CAMPO[${x[0]},${y[0]}]=1 tput cup ${y[0]} ${x[0]} echo -ne "ᕙ" NOYOUCANT=true while [ $NOYOUCANT = true ]; do m=$((RANDOM%${WIDTH}+1)) n=$((RANDOM%${HEIGHT}+1)) if [ ${CAMPO[$m,$n]} -eq 0 ]; then tput cup $n $m NOYOUCANT=false fi done CAMPO[$m,$n]=2 echo -ne "*" stty -echo ;; 3 ) LOSTGAME=true break ;; esac LASTMOV[0]=1 fi if [ $WHATDO = "a" ]; then let m=${x[0]}-1 let n=${y[0]} REVDO="d" if [ ${LASTMOV[0]} -ne 2 ]; then CAMPO[${x[0]},${y[0]}]=3 let CURVA[0,0]=${CURVA[0,0]}+1 CURVA[0,${CURVA[0,0]}]=2 fi case ${CAMPO[$m,$n]} in 0 ) CAMPO[${x[1]},${y[1]}]=0 tput cup ${y[1]} ${x[1]} stty echo echo -ne " " case ${LASTMOV[1]} in 1) let x[1]=${x[1]}+1;; 2) let x[1]=${x[1]}-1;; 3) let y[1]=${y[1]}-1;; 4) let y[1]=${y[1]}+1;; esac tput cup ${y[0]} ${x[0]} echo -ne "∎" x[0]=$m CAMPO[${x[0]},${y[0]}]=1 tput cup ${y[0]} ${x[0]} echo -ne "ᕗ" stty -echo ;; 1 ) LOSTGAME=true break ;; 2 ) let PONT=$PONT+1 stty echo tput cup ${y[0]} ${x[0]} echo -ne "∎" x[0]=$m CAMPO[${x[0]},${y[0]}]=1 tput cup ${y[0]} ${x[0]} echo -ne "ᕗ" NOYOUCANT=true while [ $NOYOUCANT = true ]; do m=$((RANDOM%${WIDTH}+1)) n=$((RANDOM%${HEIGHT}+1)) if [ ${CAMPO[$m,$n]} -eq 0 ]; then tput cup $n $m NOYOUCANT=false fi done CAMPO[$m,$n]=2 echo -ne "*" stty -echo ;; esac LASTMOV[0]=2 fi if [ $WHATDO = "w" ]; then let m=${x[0]} let n=${y[0]}-1 REVDO="s" if [ ${LASTMOV[0]} -ne 3 ]; then CAMPO[${x[0]},${y[0]}]=3 let CURVA[0,0]=${CURVA[0,0]}+1 CURVA[0,${CURVA[0,0]}]=3 fi case ${CAMPO[$m,$n]} in 0 ) CAMPO[${x[1]},${y[1]}]=0 tput cup ${y[1]} ${x[1]} stty echo echo -ne " " case ${LASTMOV[1]} in 1) let x[1]=${x[1]}+1;; 2) let x[1]=${x[1]}-1;; 3) let y[1]=${y[1]}-1;; 4) let y[1]=${y[1]}+1;; esac tput cup ${y[0]} ${x[0]} echo -ne "∎" y[0]=$n CAMPO[${x[0]},${y[0]}]=1 tput cup ${y[0]} ${x[0]} echo -ne "ᕓ" stty -echo ;; 1 ) LOSTGAME=true break ;; 2 ) let PONT=$PONT+1 stty echo tput cup ${y[0]} ${x[0]} echo -ne "∎" y[0]=$n CAMPO[${x[0]},${y[0]}]=1 tput cup ${y[0]} ${x[0]} echo -ne "ᕓ" NOYOUCANT=true while [ $NOYOUCANT = true ]; do m=$((RANDOM%${WIDTH}+1)) n=$((RANDOM%${HEIGHT}+1)) if [ ${CAMPO[$m,$n]} -eq 0 ]; then tput cup $n $m NOYOUCANT=false fi done CAMPO[$m,$n]=2 echo -ne "*" stty -echo ;; esac LASTMOV[0]=3 fi if [ $WHATDO = "s" ]; then let m=${x[0]} let n=${y[0]}+1 REVDO="w" if [ ${LASTMOV[0]} -ne 4 ]; then CAMPO[${x[0]},${y[0]}]=3 let CURVA[0,0]=${CURVA[0,0]}+1 CURVA[0,${CURVA[0,0]}]=4 fi case ${CAMPO[$m,$n]} in 0 ) CAMPO[${x[1]},${y[1]}]=0 tput cup ${y[1]} ${x[1]} stty echo echo -ne " " case ${LASTMOV[1]} in 1) let x[1]=${x[1]}+1;; 2) let x[1]=${x[1]}-1;; 3) let y[1]=${y[1]}-1;; 4) let y[1]=${y[1]}+1;; esac tput cup ${y[0]} ${x[0]} echo -ne "∎" y[0]=$n CAMPO[${x[0]},${y[0]}]=1 tput cup ${y[0]} ${x[0]} echo -ne "ᕕ" stty -echo ;; 1 ) LOSTGAME=true break ;; 2 ) let PONT=$PONT+1 stty echo tput cup ${y[0]} ${x[0]} echo -ne "∎" y[0]=$n CAMPO[${x[0]},${y[0]}]=1 tput cup ${y[0]} ${x[0]} echo -ne "ᕕ" NOYOUCANT=true while [ $NOYOUCANT = true ]; do m=$((RANDOM%${WIDTH}+1)) n=$((RANDOM%${HEIGHT}+1)) if [ ${CAMPO[$m,$n]} -eq 0 ]; then tput cup $n $m NOYOUCANT=false fi done CAMPO[$m,$n]=2 echo -ne "*" stty -echo ;; esac LASTMOV[0]=4 fi if [ $INPUT = "q" ] 2>/dev/null; then clear tput cnorm exit 0 fi done if [ $LOSTGAME ]; then clear echo "Voce perdeu! Conseguiu um total de $PONT pontos!" echo fi tput cnorm exit
Script que conta quantas barras tem em um diretorio
Testar várias portas TCP para um único host/IP
ARS Vídeos - Cortador de vídeos e webcam shooter
Agora temos uma assistente virtual no fórum!!! (246)
Compartilhando a tela do Computador no Celular via Deskreen
Como Configurar um Túnel SSH Reverso para Acessar Sua Máquina Local a Partir de uma Máquina Remota
Configuração para desligamento automatizado de Computadores em um Ambiente Comercial
Efeito "livro" em arquivos PDF
Como resolver o erro no CUPS: Unable to get list of printer drivers
Flatpak: remover runtimes não usados e pacotes
Mudar o gerenciador de login (GDM para SDDM e vice-versa) - parte 2
Como eu faço para ativar o sistema de gestos do mousepad? (4)
NGNIX - Aplicar SNAT para evitar roteamento assimetrico (13)
[Python] Automação de scan de vulnerabilidades
[Python] Script para analise de superficie de ataque
[Shell Script] Novo script para redimensionar, rotacionar, converter e espelhar arquivos de imagem
[Shell Script] Iniciador de DOOM (DSDA-DOOM, Doom Retro ou Woof!)
[Shell Script] Script para adicionar bordas às imagens de uma pasta