Torres de Hanoi 1.0

Publicado por Washington Luis de O Santos (última atualização em 25/10/2018)

[ Hits: 4.048 ]

Download hanoi-1.0.py




Jogo de Quebra Cabeça feito para rodar em um terminal com o Python 3.

É bom para quem quer aprender um pouco sobre o uso do módulo 'curse' no Python

  



Esconder código-fonte

#!/usr/bin/env python
# -*- coding:UTF-8 -*-

#coding: cp1252
#coding: latin1

u'''
   Torres de Hanoi version 1.0 - Program
   
   Este programa, primeiro, foi desenvolvido em clipper 5.2 por mim em novembro de
   1994 e agora foi convertido e adaptado para o python3 com o uso do módulo 'curses'

   Copyright (c) 2002-2004 Washington Luis de O. Santos < owashington[arroba]terra.com.br >

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License along
   with this program; if not, write to the Free Software Foundation, Inc.,
   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

   POR: Washington Luis de Oliveira Santos
   
   Taubaté - SP,  de 7 a 10 de outubro de 2018
'''

import sys
import os
import random
import time
import curses

# janela principal
screen = curses.initscr()
screen.notimeout(False)
screen.keypad(True)
screen.clear()
#screen.set_title('T O R R E S   D E   H A N O I')

# iniciando cores
curses.start_color()
curses.init_pair( 1, curses.COLOR_RED, curses.COLOR_WHITE)
curses.init_pair( 2, curses.COLOR_GREEN, curses.COLOR_WHITE)
curses.init_pair( 3, curses.COLOR_YELLOW, curses.COLOR_WHITE)
curses.init_pair( 4, curses.COLOR_BLUE, curses.COLOR_WHITE)
curses.init_pair( 5, curses.COLOR_MAGENTA, curses.COLOR_WHITE)
curses.init_pair( 6, curses.COLOR_CYAN, curses.COLOR_WHITE)
curses.init_pair( 7, curses.COLOR_RED, curses.COLOR_WHITE)
curses.init_pair( 8, curses.COLOR_GREEN, curses.COLOR_WHITE)
curses.init_pair( 9, curses.COLOR_YELLOW, curses.COLOR_WHITE)
curses.init_pair(10, curses.COLOR_MAGENTA, curses.COLOR_WHITE)

# Define cor das Colunas e da Base da Torre (azul e branco)
curses.init_pair(11, curses.COLOR_BLUE, curses.COLOR_WHITE)

# Define cor da Barra de Status (branco e cyan)
curses.init_pair(12, curses.COLOR_WHITE, curses.COLOR_CYAN)

curses.init_pair(13, curses.COLOR_GREEN, curses.COLOR_WHITE)

curses.init_pair(14, curses.COLOR_BLUE, curses.COLOR_WHITE)
curses.init_pair(15, curses.COLOR_WHITE, curses.COLOR_BLUE)
curses.init_pair(16, curses.COLOR_BLACK, curses.COLOR_WHITE)
curses.init_pair(17, curses.COLOR_BLACK, curses.COLOR_BLUE)
curses.init_pair(18, curses.COLOR_BLACK, curses.COLOR_WHITE)

curses.cbreak()

# Não retorna caracteres na tela
curses.noecho()

# esconde o cursor do mouse e do terminal
curses.curs_set(0)

# Define Constantes
K_CTRL_Q = 17
K_ESC    = 27
K_F1     = 59  # Win
K_1      = 49
K_2      = 50
K_3      = 51
N_DISCOS = 10
PG_CODE  = 9440


# Define Constantes usadas como caracteres especiais
# Single-line
# Chr( 218 ) + Chr( 196 ) + Chr( 191 ) &#9484; &#9472; &#9488;
# Chr( 179 ) + Chr(  32 ) + Chr( 179 ) &#9474;   &#9474;
# Chr( 192 ) + Chr( 196 ) + Chr( 217 ) &#9492; &#9472; &#9496;

c_032 =   32
c_168 = 9608
c_177 = 9617
c_178 = 9618
c_179 = 9474
c_191 = 9488
c_192 = 9492
c_196 = 9472
c_217 = 9496
c_218 = 9484
c_219 = 9604
c_223 = 9600

# Determina a posicao inicial da torre que contera os discos de forma aleatoria
pos_0 = random.randint( 1, 3 )
pos_1 = 2 if pos_0 == 1 else 1
pos_2 = 2 if pos_0 == 3 else 3

TORRE = {}
TORRE[pos_0] = [1,2,3,4,5,6,7,8,9,10]
TORRE[pos_1] = []
TORRE[pos_2] = []

COR = {}
#COR[pos_0] = [ 1, 2, 3, 4, 5, 6, 7, 8, 9,10]
COR[pos_0] = random.sample( range(1,11), 10)
COR[pos_1] = []
COR[pos_2] = []


# Esta é uma tentativa de manter o prg compativel com o python 2.7
# para isto comente as duas linhas abaixo
def unichr(ch):
   return chr(ch)

def Hchr(strhex):
   '''
   Funcao para transformar uma cadeia de valores
   em hexadecimal para uma cadeia de caracteres
   '''
   STRING = ''

   for pos in strhex.split(','):
      i = int(pos, 16)
      
      if i < 128:
         STRING = STRING + unichr(i)
      else:
         STRING = STRING + unichr(i + PG_CODE)
         
   return (STRING)


DISCO = {}
DISCO[ 1] = Hchr('20,20,20,20,20,20,20,20,20,B1,B2,B1,20,20,20,20,20,20,20,20,20')
DISCO[ 2] = Hchr('20,20,20,20,20,20,20,20,B1,B1,B2,B1,B1,20,20,20,20,20,20,20,20')
DISCO[ 3] = Hchr('20,20,20,20,20,20,20,B1,B1,B1,B2,B1,B1,B1,20,20,20,20,20,20,20')
DISCO[ 4] = Hchr('20,20,20,20,20,20,B1,B1,B1,B1,B2,B1,B1,B1,B1,20,20,20,20,20,20')
DISCO[ 5] = Hchr('20,20,20,20,20,B1,B1,B1,B1,B1,B2,B1,B1,B1,B1,B1,20,20,20,20,20')
DISCO[ 6] = Hchr('20,20,20,20,B1,B1,B1,B1,B1,B1,B2,B1,B1,B1,B1,B1,B1,20,20,20,20')
DISCO[ 7] = Hchr('20,20,20,B1,B1,B1,B1,B1,B1,B1,B2,B1,B1,B1,B1,B1,B1,B1,20,20,20')
DISCO[ 8] = Hchr('20,20,B1,B1,B1,B1,B1,B1,B1,B1,B2,B1,B1,B1,B1,B1,B1,B1,B1,20,20')
DISCO[ 9] = Hchr('20,B1,B1,B1,B1,B1,B1,B1,B1,B1,B2,B1,B1,B1,B1,B1,B1,B1,B1,B1,20')
DISCO[10] = Hchr('B1,B1,B1,B1,B1,B1,B1,B1,B1,B1,B2,B1,B1,B1,B1,B1,B1,B1,B1,B1,B1')

if 0:
   DISCO[ 1] = ('         #T#         ')
   DISCO[ 2] = ('        ##T##        ')
   DISCO[ 3] = ('       ###T###       ')
   DISCO[ 4] = ('      ####T####      ')
   DISCO[ 5] = ('     #####T#####     ')
   DISCO[ 6] = ('    ######T######    ')
   DISCO[ 7] = ('   #######T#######   ')
   DISCO[ 8] = ('  ########T########  ')
   DISCO[ 9] = (' #########T######### ')
   DISCO[10] = ('##########T##########')


def pause(tempo):
   # Atualiza a tela
   screen.refresh()

   # Pausa por um tempo
   time.sleep(tempo)


#******************************************
#* FUNCAO PARA IMPRIMIR A TELA DE ABERTURA
#*
def autor():

   DispBox_Shadow(2,10,21,68, 11)

   screen.addstr( 3, 22, ' _____', curses.color_pair(13))
   screen.addstr( 4, 22, '|_   _|__  _ __ _ __ ___  ___', curses.color_pair(13))
   screen.addstr( 5, 22, '  | |/ _ \\| \'__| \'__/ _ \\/ __|', curses.color_pair(13))
   screen.addstr( 6, 22, '  | | (_) | |  | | |  __/\\__ \\', curses.color_pair(13))
   screen.addstr( 7, 22, '  |_|\\___/|_|  |_|  \\___||___/', curses.color_pair(13))
   screen.addstr( 8, 22, '              _', curses.color_pair(13))
   screen.addstr( 9, 22, '           __| | ___', curses.color_pair(13))
   screen.addstr(10, 22, '          / _` |/ _ \\', curses.color_pair(13))
   screen.addstr(11, 22, '         | (_| |  __/', curses.color_pair(13))
   screen.addstr(12, 22, '  _   _   \\__,_|\\___|     _', curses.color_pair(13))
   screen.addstr(13, 22, ' | | | | __ _ _ __   ___ (_)', curses.color_pair(13))
   screen.addstr(14, 22, ' | |_| |/ _` | \'_ \\ / _ \\| |', curses.color_pair(13))
   screen.addstr(15, 22, ' |  _  | (_| | | | | (_) | |', curses.color_pair(13))
   screen.addstr(16, 22, ' |_| |_|\\__,_|_| |_|\\___/|_|', curses.color_pair(13))
   
   screen.addstr(11, 52, 'Versão 1.0', curses.color_pair(18))

   screen.addstr(18, 15, 'Autor: Washington Luis de Oliveira Santos', curses.color_pair(11))
   screen.addstr(19, 15, 'End. : Av. Campinas, 749 - Chácara do Visconde', curses.color_pair(11))
   screen.addstr(20, 28, 'Taubaté - São Paulo', curses.color_pair(11))


def Hprompt():

   while True:

      key = screen.getch()
      #curses.getmouse()
      
      '''
      if  key = K_LBUTTONUP // botao esquerdo pressionado

         // Verifica em que posicao foi pressionado
         if     TST_BOTAO(04,03,20,23)
            return 1

         elif TST_BOTAO(04,29,20,49)
            return 2

         elif TST_BOTAO(04,55,20,75)
            return 3

      '''

      if key in (K_ESC, K_CTRL_Q):
         # encerra o programa
         ENCERRA(True)

      elif key in (curses.KEY_F1, ord('h'), ord('H')):
         # help acionado
         autor()
         screen.addstr(24, 1, ' ' * 80, curses.color_pair(12))
         screen.addstr(24, 1, ' Tecle algo para sair...', curses.color_pair(12) | curses.A_BOLD)
         screen.getch()
         pause(.05)

         display_tela()
         return 0

      elif key == K_1:
         return 1

      elif key == K_2:
         return 2

      elif key == K_3:
         return 3


def bt_press(n_bt):
   '''
   desenha os botoes acionados
   n_bt = numero do botao
   '''
   screen.addstr(20, n_bt*26-15,  '{:^7}'.format(n_bt), curses.color_pair(14) | curses.A_BOLD)
   #screen.addstr(20, n_bt*26-15,  '{:^7}'.format(n_bt), curses.color_pair(1) | curses.A_BOLD)

   screen.addstr(20, n_bt*26-16, ' ', curses.color_pair(15))
   screen.addstr(21, n_bt*26-15, ' ' * 7, curses.color_pair(15))


def bt_solto(n_bt):
   '''
   desenha os botoes não acionados
   n_bt = numero do botao
   '''
   screen.addstr(20, n_bt*26-16, '{:^7}'.format(n_bt), curses.color_pair(16))
   #screen.addstr(20, n_bt*26-16, '{:^7}'.format(n_bt), curses.color_pair(3))

   screen.addstr(20, n_bt*26- 9, unichr(c_219), curses.color_pair(17))
   screen.addstr(21, n_bt*26-15, unichr(c_223) * 7, curses.color_pair(17))


def Box(lt,ce,lb,cd, cor):
   
   for x in range(lt,lb):
      screen.addstr(x, ce, ' ' * (cd-ce+1), curses.color_pair(cor))


def DispBox(lt,ce,lb,cd, cor):
   
   Box(lt,ce,lb,cd, cor)

   screen.addstr(lt, ce, unichr(c_196) * (cd-ce), curses.color_pair(cor))
   screen.addstr(lt, ce, unichr(c_218), curses.color_pair(cor))
   screen.addstr(lt, cd, unichr(c_191), curses.color_pair(cor))
   
   screen.addstr(lb, ce, unichr(c_196) * (cd-ce), curses.color_pair(cor))
   screen.addstr(lb, ce, unichr(c_192), curses.color_pair(cor))
   screen.addstr(lb, cd, unichr(c_217), curses.color_pair(cor))

   for x in range(lt+1,lb):
      screen.addstr(x, ce, unichr(c_179), curses.color_pair(cor))
      screen.addstr(x, cd, unichr(c_179), curses.color_pair(cor))


def DispBox_Shadow(lt,ce,lb,cd, cor):
   
   DispBox(lt,ce,lb,cd, cor)

   #Desenha a Sombra da Caixa
   for x in range(lt+1,lb+1):
      screen.addstr(x, cd+1, unichr(c_168), curses.color_pair(18))
   
   screen.addstr(lb+1, ce+1, unichr(c_168) * (cd-ce+1), curses.color_pair(18))


def display_tela():

   #Cria uma quadro na tela com char azul e fundo branco
   DispBox( 1,1,18,80, 11)

   #Escreve o titulo
   screen.addstr(3, 24, 'T O R R E S   D E   H A N O I', curses.color_pair(11) | curses.A_BOLD)

   #Desenha a base 
   screen.addstr(18, 1, unichr(c_178) * 80, curses.color_pair(11))

   #Desenha as colunas 
   for i in range(0,11):
      screen.addstr(i+7, 13, unichr(c_178), curses.color_pair(11))
      screen.addstr(i+7, 65, unichr(c_178), curses.color_pair(11))
      screen.addstr(i+7, 39, unichr(c_178), curses.color_pair(11))

   #Apaga/Muda a cor na parte de baixo da tela
   Box(19,1,24,80, 15)

   #Desenha os discos
   for pos_x in range(1,4):
      col = 26 * pos_x - 23

      lin = len(TORRE[pos_x])
      nd = 9-(10-lin)

      for y in range(lin):
         screen.addstr(17-y, col,  DISCO[TORRE[pos_x][nd-y]], curses.color_pair(COR[pos_x][nd-y]))
         pause(0.03)


def ENCERRA(abortado):
   if abortado:
      screen.addstr(24, 1, ' Jogo abortado...                  ', curses.color_pair(12) | curses.A_BOLD)
      pause(2)

   else:
      screen.addstr(24, 1, ' Meus parabéns...  você conseguiu!!!', curses.color_pair(12) | curses.A_BOLD)
      pause(.5)
      screen.getch()

   #Restaura a cor do terminal
   screen.refresh()
   screen.clear()
   screen.keypad(False)
   curses.nocbreak()
   curses.echo()
   curses.endwin()
   sys.exit(0)


def main():

   n_mov = 0

   #Imprimi a tela de abertura
   display_tela()
   autor()
   pause(3)

   '''
   # Fica piscando a tela (mudando de cor)
   for i in range(6):
      pause(.3)
      curses.init_pair(11, curses.COLOR_GREEN, curses.COLOR_WHITE)
      pause(.3)
      curses.init_pair(11, curses.COLOR_BLUE, curses.COLOR_WHITE)
   '''

   display_tela()

   while True:
      # Desenha os botoes
      bt_solto(1)
      bt_solto(2)
      bt_solto(3)

      screen.addstr(24, 1, (' ' * 80), curses.color_pair(12))
      screen.addstr(24, 63, 'Movimentos: %5i' % n_mov, curses.color_pair(12) | curses.A_BOLD)

      #Pede para o usuario fazer o movimento
      screen.addstr(24, 1, ' Entre com o nº da torre de origem ', curses.color_pair(12) | curses.A_BOLD)
      origem = Hprompt()
      if origem == 0: continue
      bt_press(origem)

      if TORRE[origem] == []:
         # Torre vazia
         curses.beep()
         screen.addstr(24, 1, ' Esta torre esta vazia...          ', curses.color_pair(12) | curses.A_BOLD)
         pause(2)
         continue

      screen.addstr(24, 1, ' Entre com o nº da torre de destino', curses.color_pair(12) | curses.A_BOLD)
      destino = Hprompt()
      if destino == 0: continue
      bt_press(destino)
      pause(.1)

      if destino == origem:
         curses.beep()
         continue

      # Verifica se o movimento e valido 
      if TORRE[origem] > TORRE[destino] and TORRE[destino] != []:
         curses.beep()
         screen.addstr(24, 1, ' Movimento ilegal...               ', curses.color_pair(12) | curses.A_BOLD)
         pause(2)
         continue


      #Move o disco de uma torre para a outra

      #Apaga o disco
      col = 26 * origem - 23
      lin = 18 - len(TORRE[origem])
      screen.addstr(lin, col, " "*10 + unichr(c_178) + " "*10, curses.color_pair(11))
      
      n_disco = TORRE[origem][0]
      TORRE[origem] = TORRE[origem][1:]
      TORRE[destino] = [n_disco] + TORRE[destino]

      cor_disco = COR[origem][0]
      COR[origem] = COR[origem][1:]
      COR[destino] = [cor_disco] + COR[destino]

      #Desenha o disco
      col = 26 * destino - 23
      lin = 18 - len(TORRE[destino])
      screen.addstr(lin, col, DISCO[n_disco], curses.color_pair(cor_disco))
      
      n_mov = n_mov + 1

      #Verifica se chegou no fim do jogo
      if len(TORRE[pos_1]) == N_DISCOS or len(TORRE[pos_2]) == N_DISCOS:
         ENCERRA(False)


if __name__ == '__main__':
   try:
      curses.wrapper(main())
   except KeyboardInterrupt:
      curses.endwin()

#   sys.exit(main())
    

Scripts recomendados

Troca de wallpaper temporizado para LXDE

Bandwidth plugin para xchat

Jogo labirinto

Unescape de caracteres especiais ISO-8859-1

Verificador de números primos


  

Comentários
[1] Comentário enviado por fabio em 25/10/2018 - 10:19h

Ficou legal o negócio hein!

[2] Comentário enviado por maurixnovatrento em 24/09/2020 - 13:43h


Muito bom.

___________________________________________________________
[code]Conhecimento não se Leva para o Túmulo.
https://github.com/MauricioFerrari-NovaTrento [/code]


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts