Torres de Hanoi 1.0
Publicado por Washington Luis de O Santos (última atualização em 25/10/2018)
[ Hits: 4.286 ]
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
#!/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 ) ┌ ─ ┐
# Chr( 179 ) + Chr( 32 ) + Chr( 179 ) │ │
# Chr( 192 ) + Chr( 196 ) + Chr( 217 ) └ ─ ┘
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())
Organizador de Arquivos em Python + tkinter
Adicione a opção Redimensionar e rotacionar imagens ao Nautilus
Plano de fundo rotatório no Gnome
Mighty Are's Tool of Easily Promote Combats
Como extrair chaves TOTP 2FA a partir de QRCODE (Google Authenticator)
Linux em 2025: Segurança prática para o usuário
Desktop Linux em alta: novos apps, distros e privacidade marcam o sábado
IA chega ao desktop e impulsiona produtividade no mundo Linux
Novos apps de produtividade, avanços em IA e distros em ebulição agitam o universo Linux
Como instalar o repositório do DBeaver no Ubuntu
Como instalar o Plex Media Server no Ubuntu
Digitando underscore com "shift" + "barra de espaços"
Como ativar a lixeira e recuperar aquivos deletados em um servidor Linux
Como mudar o nome de dispositivos Bluetooth via linha de comando
Linux é a solução para o fim do Windows10? (6)
Assinador JNLP do Site Portal da Nota Fiscal Eletrônica (0)
Programa fora de escala na tela do pc (29)









