aula 110

JOGO DA VELHA com funções e procedimentos na linguagem Portugol

Na aula 101 nós desenvolvemos o jogo da velha com a linguagem de programação Portugol. Contudo, todo nosso código estava dentro do procedimento início. Nesta aula vamos dividir o jogo da velha em funções e procedimentos para praticar o que aprendemos nas aulas anteriores.

Inicialmente vamos declarar algumas variáveis globais. A variável jogo será nosso tabuleiro, nossa matriz de caracteres. As variáveis linha e coluna serão utilizadas para ler as coordenadas digitadas pelos jogadores enquanto que as variáveis l e c serão utilizadas como índices nas estruturas de repetição.

	// variáveis globais
	caracter jogo[3][3]
	inteiro linha, coluna, l, c

Inicialmente nossa matriz está vazia. Assim, antes de iniciar o jogo, precisamos inicializar cada posição com vazio (espaço) a fim de garantir que qualquer lixo de memória que esteja ali seja apagado.

	funcao inicializarJogo(){
		para(l = 0; l < 3; l++){
			para(c = 0; c < 3; c++)
				jogo[l][c] = ' ' // cada posição recebe um espaço
		}
	}

Na sequencia precisamos imprimir o tabuleiro na tela para que cada jogador tenha ciência de como está o jogo. Este processo é realmente na tentativa e erro, ajustando a impressão até que fique como desejado.

	// procedimento para imprimir o jogo
	funcao imprimirJogo(){
		escreva("\n\n 0   1    2\n\n") // índices das colunas
		para(l = 0; l < 3; l++){
			para(c = 0; c < 3; c++){
				escreva(" ", jogo[l][c])
				se(c < 2)
					escreva(" | ") // barras das colunas
				se(c == 2)
					escreva("  ", l) // índices das linhas impressos à direita
			}
			se(l < 2)
				escreva("\n------------") // linha que divide as linhas
			escreva("\n")
		}
	}

Agora estamos prontos para ler as coordenadas digitadas pelos jogadores.

Ao ler as coordenadas perceba que precisamos fazer algumas validações. Primeiro precisamos garantir que os índices digitados pelos jogador são índices válidos, ou seja, estão entre 0 e 2. Também precisamos verificar se a posição jogada está vazia, ou seja, se não foi jogada por nenhum dos jogadores ainda.

Este procedimento recebe o índice do jogador 1 ou 2 como parâmetro. O controle do jogador será feito em outra parte do jogo.

	// procedimento para ler as coordenadas digitadas pelo usuário
	funcao lerCoordenadas(inteiro jogador){
		faca{
			faca{
				escreva("\nJogador ",jogador, " digite linha e coluna da posição desejada: ")
				leia(linha, coluna)
			}enquanto(linha < 0 ou linha > 2 ou coluna < 0 ou coluna > 2)
		}enquanto(jogo[linha][coluna] != ' ')
	}

Como mencionado acima, a cada jogada precisamos atualizar o jogador. Isso é feito com a função a seguir. Se o jogador atual foi o jogador 1, então o próximo é o jogador 2. Caso contrário, significa que foi o jogador 2 que acabou de jogar, então o próximo é o jogador 1.

	// função para atualizar o jogador
	funcao inteiro atualizarJogador(inteiro jogador){
		se(jogador == 1)
			jogador = 2
		senao
			jogador = 1
		retorne jogador
	}

Além de ler as coordenadas jogadas, também precisamos salvar esta jogada. Isso significa que a coordenada jogada precisa receber um 0 ou um X dependendo de qual jogador está jogando. Isso é feito com a função a seguir.

	// função para salvar uma jogada
	funcao inteiro salvarJogada(inteiro jogador){
		se(jogador == 1)
			jogo[linha][coluna] = '0' // jogador 1
		senao
			jogo[linha][coluna] = 'X' // jogador 2
		retorne 1
	}

A verificação da vitória será dividida em várias partes. A função a seguir verifica se um jogador c (0 ou X) ganhou em alguma linha.

	// função que verifica se jogador ganhou por linha
	funcao inteiro ganhouPorLinha(caracter c){
		para(l = 0; l < 3; l++){
			se(jogo[l][0] == c e jogo[l][1] == c e jogo[l][2] == c)
				retorne 1 // jogador ganhou
		}
		retorne 0 // jogador não ganhou
	}

A função a seguir faz uso da função anterior para verificar vitória por linha para os dois jogadores.

	// função que utiliza a função anterior para os dois jogadores
	funcao inteiro ganhouPorLinhas(){
		se(ganhouPorLinha('0') == 1)
			retorne 1 // jogador 1 ganhou
		se(ganhouPorLinha('X') == 1)
			retorne 2 // jogador 2 ganhou
		retorne 0 // ninguém ganhou ainda
	}

De forma semelhante, precisamos também de uma função que verifica vitória por colunas para um determinado jogador. Esta função é apresentada a seguir.

	// função que verifica se alguém ganhou por coluna
	funcao inteiro ganhouPorColuna(caracter s){
		para(c = 0; c < 3; c++){
			se(jogo[0][c] == s e jogo[1][c] == s e jogo[2][c] == s)
				retorne 1 // jogador ganhou
		}
		retorne 0 // ninguém ganhou
	}

A função a seguir faz uso da função anterior para verificar a vitória por coluna para ambos os jogadores.

	// função que faz uso da função anterior para verificar vitória em todas as colunas
	funcao inteiro ganhouPorColunas(){
		se(ganhouPorColuna('0') == 1)
			retorne 1 // jogador 1 venceu
		se(ganhouPorColuna('X') == 1)
			retorne 2 // jogador 2 venceu
		retorne 0 // ninguém venceu ainda
	}

A função a seguir verifica se um jogador s ganhou na diagonal principal.

	// função que verifica se alguém ganhou na diagonal principal
	funcao inteiro ganhouNaDiagPrincipal(caracter s){
		se(jogo[0][0] == s e jogo[1][1] == s e jogo[2][2] == s)
			retorne 1
		retorne 0
	}

A função a seguir faz uso da função anterior para verificar se um dos jogadores ganhou na diagonal principal.

	// função que retornar quem foi o ganhador pela diagonal principal
	funcao inteiro ganhadorDiagPrincipal(){
		se(ganhouNaDiagPrincipal('0') == 1)
			retorne 1
		se(ganhouNaDiagPrincipal('X') == 1)
			retorne 2
		retorne 0
	}

A função a seguir verifica se o jogador s ganhou na diagonal secundária.

	// função que verifica se alguém ganhou na diagonal secundária
	funcao inteiro ganhouDiagSecundaria(caracter s){
		se(jogo[0][2] == s e jogo[1][1] == s e jogo[2][0] == s)
			retorne 1
		retorne 0
	}

Enquanto a função a seguir utiliza a função anterior para verificar se um dos jogadores ganhou na diagonal secundária.

	// função que retorna quem foi o ganhador pela diagonal secundária, se houver
	funcao inteiro ganhadorDiagSecundaria(){
		se(ganhouDiagSecundaria('0') == 1)
			retorne 1
		se(ganhouDiagSecundaria('X') == 1)
			retorne 2
		retorne 0
	}

Agora que já temos todas as funções e procedimentos necessários, precisamos fazer o loop (repetição) que deverá funcionar até que um dos jogadores vença ou termine as possibilidades de jogadas. Isso é feito na função a seguir.

	// função para o loop do jogo
	funcao inteiro jogar(inteiro jogador, inteiro jogadas, inteiro ganhou){
		faca{
			imprimirJogo() // impressão do tabuleiro
			lerCoordenadas(jogador) // ler coordenadas
			
			// salvar cordenadas
			jogadas += salvarJogada(jogador)
			jogador = atualizarJogador(jogador)
			
			ganhou += ganhouPorLinhas()// verificar ganhador por linhas
			ganhou += ganhouPorColunas()// verificar ganhador por colunas
			ganhou += ganhadorDiagPrincipal()// verificar ganhador na diagonal principal			
			ganhou += ganhadorDiagSecundaria()// verificar ganhador na diagonal secundária
		}enquanto(ganhou == 0 e jogadas < 9)

		retorne ganhou
	}

Por fim temos o procedimento início por onde inicia a execução do nosso programa. Perceba que acrescentamos aqui a possibilidade de iniciar uma nova rodada assim que um jogo finalizar, para isso basta o usuário digitar 1 e um novo jogo será iniciado.

	funcao inicio(){

		inteiro jogador, ganhou, jogadas, opcao

		faca{
			jogador = 1
			ganhou = 0
			jogadas = 0

			inicializarJogo()
	
			ganhou = jogar(jogador, jogadas, ganhou)
	
			// impressão do tabuleiro
			imprimirJogo()
	
			se(ganhou == 1)
				escreva("\n\tParabéns Jogador 1. Você ganhou!\n\n")

			se(ganhou == 2)
				escreva("\n\tParabéns Jogador 2. Você ganhou!\n\n")
	
			escreva("Digite 1 para jogar novamente: ")
			leia(opcao)
		}enquanto(opcao == 1)
	}

Código completo em Portugol para o jogo da velha

programa{
	/*	Aula 110: Jogo da velha com funções e procedimentos.
	 * 	
	 * 	  |  |
	 * 	--------
	 * 	  |  |
	 * 	--------
	 * 	  |  |
	 * 
	 * Escrito por Wagner Gaspar
	 * Março de 2021
	*/

	// variáveis globais
	caracter jogo[3][3]
	inteiro linha, coluna, l, c

	funcao inicializarJogo(){
		para(l = 0; l < 3; l++){
			para(c = 0; c < 3; c++)
				jogo[l][c] = ' '
		}
	}

	// procedimento para imprimir o jogo
	funcao imprimirJogo(){
		escreva("\n\n 0   1    2\n\n")
		para(l = 0; l < 3; l++){
			para(c = 0; c < 3; c++){
				escreva(" ", jogo[l][c])
				se(c < 2)
					escreva(" | ")
				se(c == 2)
					escreva("  ", l)
			}
			se(l < 2)
				escreva("\n------------")
			escreva("\n")
		}
	}

	// procedimento para ler as coordenadas digitadas pelo usuário
	funcao lerCoordenadas(inteiro jogador){
		faca{
			faca{
				escreva("\nJogador ",jogador, " digite linha e coluna da posição desejada: ")
				leia(linha, coluna)
			}enquanto(linha < 0 ou linha > 2 ou coluna < 0 ou coluna > 2)
		}enquanto(jogo[linha][coluna] != ' ')
	}

	// função para atualizar o jogador
	funcao inteiro atualizarJogador(inteiro jogador){
		se(jogador == 1)
			jogador = 2
		senao
			jogador = 1
		retorne jogador
	}

	// função para salvar uma jogada
	funcao inteiro salvarJogada(inteiro jogador){
		se(jogador == 1)
			jogo[linha][coluna] = '0'
		senao
			jogo[linha][coluna] = 'X'
		retorne 1
	}

	// função que verifica se jogador ganhou por linha
	funcao inteiro ganhouPorLinha(caracter c){
		para(l = 0; l < 3; l++){
			se(jogo[l][0] == c e jogo[l][1] == c e jogo[l][2] == c)
				retorne 1 // jogador ganhou
		}
		retorne 0 // jogador não ganhou
	}

	// função que utiliza a função anterior para os dois jogadores
	funcao inteiro ganhouPorLinhas(){
		se(ganhouPorLinha('0') == 1)
			retorne 1 // jogador 1 ganhou
		se(ganhouPorLinha('X') == 1)
			retorne 2 // jogador 2 ganhou
		retorne 0 // ninguém ganhou
	}

	// função que verifica se alguém ganhou por coluna
	funcao inteiro ganhouPorColuna(caracter s){
		para(c = 0; c < 3; c++){
			se(jogo[0][c] == s e jogo[1][c] == s e jogo[2][c] == s)
				retorne 1 // jogador ganhou
		}
		retorne 0 // ninguém ganhou
	}

	// função que faz uso da função anterior para verificar vitória em todas as colunas
	funcao inteiro ganhouPorColunas(){
		se(ganhouPorColuna('0') == 1)
			retorne 1 // jogador 1 venceu
		se(ganhouPorColuna('X') == 1)
			retorne 2 // jogador 2 venceu
		retorne 0 // ninguém venceu ainda
	}

	// função que verifica se alguém ganhou na diagonal principal
	funcao inteiro ganhouNaDiagPrincipal(caracter s){
		se(jogo[0][0] == s e jogo[1][1] == s e jogo[2][2] == s)
			retorne 1
		retorne 0
	}

	// função que retornar quem foi o ganhador pela diagonal principal
	funcao inteiro ganhadorDiagPrincipal(){
		se(ganhouNaDiagPrincipal('0') == 1)
			retorne 1
		se(ganhouNaDiagPrincipal('X') == 1)
			retorne 2
		retorne 0
	}

	// função que verifica se alguém ganhou na dig secundária
	funcao inteiro ganhouDiagSecundaria(caracter s){
		se(jogo[0][2] == s e jogo[1][1] == s e jogo[2][0] == s)
			retorne 1
		retorne 0
	}

	// função que retornar quem foi o ganhador pela diagonal secundária
	funcao inteiro ganhadorDiagSecundaria(){
		se(ganhouDiagSecundaria('0') == 1)
			retorne 1
		se(ganhouDiagSecundaria('X') == 1)
			retorne 2
		retorne 0
	}

	// função para o loop do jogo
	funcao inteiro jogar(inteiro jogador, inteiro jogadas, inteiro ganhou){
		faca{
			imprimirJogo() // impressão do tabuleiro
			lerCoordenadas(jogador) // ler coordenadas
			
			// salvar cordenadas
			jogadas += salvarJogada(jogador)
			jogador = atualizarJogador(jogador)
			
			ganhou += ganhouPorLinhas()// verificar ganhador por linhas
			ganhou += ganhouPorColunas()// verificar ganhador por colunas
			ganhou += ganhadorDiagPrincipal()// verificar ganhador na diagonal principal			
			ganhou += ganhadorDiagSecundaria()// verificar ganhador na diagonal secundária
		}enquanto(ganhou == 0 e jogadas < 9)

		retorne ganhou
	}
	
	
	funcao inicio(){

		inteiro jogador, ganhou, jogadas, opcao

		faca{
			jogador = 1
			ganhou = 0
			jogadas = 0

			inicializarJogo()
	
			ganhou = jogar(jogador, jogadas, ganhou)
	
			// impressão do tabuleiro
			imprimirJogo()
	
			se(ganhou == 1)
				escreva("\n\tParabéns Jogador 1. Você ganhou!\n\n")

			se(ganhou == 2)
				escreva("\n\tParabéns Jogador 2. Você ganhou!\n\n")
	
			escreva("Digite 1 para jogar novamente: ")
			leia(opcao)
		}enquanto(opcao == 1)
	}
}

Deixe um comentário

dois − 1 =

Wagner Gaspar

Capixaba de São Gabriel da Palha, Espírito Santo. Bacharel em Ciência da Computação pela Universidade Federal do Amazonas e mestre em informática pela Universidade Federal do Espírito Santo.