Torres de Hanoi 1.0
Publicado por Washington Luis de O Santos (última atualização em 25/10/2018)
[ Hits: 4.018 ]
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())
Exercício com números randômicos - randint
Modificação do Ubuntu Tweak para Debian
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 atualizar o Debian 8 para o 10 (10)
Dica sobre iptables ACCEPT e DROP (6)
NGNIX - Aplicar SNAT para evitar roteamento assimetrico (29)
[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