aula 120

JOGO CAMPO MINADO EM PORTUGOL | Parte III

Nesta aula vamos finalizar o desenvolvimento do nosso Jogo Campo Minado em Portugol, desenvolvendo o loop principal do jogo e finalizando a impressão do tabuleiro na tela.

Jogo Campo Minado Parte I
Jogo Campo Minado Parte II

O procedimento a seguir é fundamento em nosso jogo campo minado. É neste procedimento que as ações de imprimir tabuleiro, ler as coordenadas, abrir posições e verificar se o jogador ganhou ou perdeu serão repetidas até que uma das situações de encerramento (vitória ou derrota) seja alcançada.

/*
 * procedimento com o loop principal do jogo
*/
	funcao jogar(){
		inteiro perdeu, ganhou

		faca{
			imprimirTabuleiro()
			leCoordenadas()
			abrirPosicao(linha, coluna)
			perdeu = Perdeu(linha, coluna)
			ganhou = Ganhou(linha, coluna)
		}enquanto(perdeu == 0 e ganhou == 0)

		se(perdeu == 1)
			escreva("\n\tVocê perdeu!!!\n")
		se(ganhou == 1)
			escreva("\n\tPARABÉNS. VOCÊ GANHOU!!!\n")
	}

Agora podemos finalizar o procedimento para imprimir nosso tabuleiro na tela. Este procedimento é alterado realmente na tentativa e erro, ajustando e testando, até atingir a impressão desejada.

// procedimento para imprimir nosso campo minado
	funcao imprimirTabuleiro(){

		escreva("\n\n\t  0   1   2   3   4   5   6   7   8   9\n") // índice das colunas
		escreva("\t-----------------------------------------\n")
		para(linha = 0; linha < tamanho; linha++){
			escreva("\t|") // primeira coluna de barras à esquerda
			para(coluna = 0; coluna < tamanho; coluna++){
				se(estaAberta(linha, coluna) == 1){
					se(eBomba(linha, coluna) == 1)
						escreva(" * |") // posição está aberta e é uma bomba
					senao{
						// posição está aberta mas não é uma bomba
						escreva(" ", Texto.extrair_subtexto(tabuleiro[linha][coluna],2,3)," |")
					}
				}
				senao
					escreva("   |") // posição fechada
				se(coluna == tamanho - 1)
					escreva("   ", linha) // índice das linhas impresso à direita
			}
			escreva("\n\t-----------------------------------------\n")
		}
	}

Dentro do procedimento inicio podemos perguntar ao jogador se ele deseja jogar novamente ao terminar um jogo, como feito a seguir. Observe que todo o processamento inicial para inicializar a matriz, sortear bombas e contar as bombas vizinhas precisam ser feitos novamente, pois um novo jogo será iniciado.

	funcao inicio(){
		inteiro opcao

		faca{
			inicializarTabuleiro()
			sortearBombas(10)
			contarBombasVizinhas()
			jogar()

			escreva("\n\tDigite 1 para jogar novamente: \n")
			leia(opcao)
		}enquanto(opcao == 1)
	}

Código completo em Portugol para o Jogo Campo Minado

programa{
	inclua biblioteca Util
	inclua biblioteca Texto

	
/*	
 * 	Escrito por Wagner Gaspar
 * 	Abril de 2021
 * 	
 * 	
 * 	O tabuleiro é uma matriz de caracteres
 * 	índice 0 da cadeia indica posição aberta ou fechada:
 * 		A = aberta
 * 		F = fechada
 * 	índice 1 da cadeia indica se é bomba ou não:
 * 		* = é uma bomba
 * 		+ = não é uma bomba
 * 	índice 2 da cadeia significa a quantidade de bombas vizinhas
 * 		0 = zero bombas na vizinhança
 * 		1 = uma bomba na vizinhança
 * 		2 = duas bombas na vizinhança
 * 		3 = três bombas na vizinhança
 * 		4 = quatro bombas na vizinhança
 * 	OBSERVAÇÃO: são consideradas vizinhas de uma posição l c apenas 4 posições:
 * 		- imediatamente acima
 * 		- imediatamente abaixo
 * 		- imediatamente à direita
 * 		- imediatamente à esquerda
 * 	EXEMPLOS:
 * 		F+1 -> ainda fechada, não é bomba e possui 1 bomba vizinha
 * 		A+2 -> aberta, não é bomba e possui duas bombas vizinhas
 * 		F*0 -> ainda fechada, é uma bomba
*/

        // Variáveis globais
	cadeia tabuleiro[10][10]
	inteiro tamanho = 10, linha, coluna

/*
 * Este procedimento inicializa nosso matriz
 * F significa fechado
 * A - aberto
 * * - bomba
 * + - não é bomba
 * 0 - zero bombas vizinhas
*/
	funcao inicializarTabuleiro(){
		para(linha = 0; linha < tamanho; linha++){
			para(coluna = 0; coluna < tamanho; coluna++){
				tabuleiro[linha][coluna] = "F+0"
			}
		}
	}

// procedimento para imprimir nosso campo minado
	funcao imprimirTabuleiro(){

		escreva("\n\n\t  0   1   2   3   4   5   6   7   8   9\n")
		escreva("\t-----------------------------------------\n")
		para(linha = 0; linha < tamanho; linha++){
			escreva("\t|")
			para(coluna = 0; coluna < tamanho; coluna++){
				se(estaAberta(linha, coluna) == 1){
					se(eBomba(linha, coluna) == 1)
						escreva(" * |")
					senao{
						escreva(" ", Texto.extrair_subtexto(tabuleiro[linha][coluna],2,3)," |")
					}
				}
				senao
					escreva("   |")
				se(coluna == tamanho - 1)
					escreva("   ", linha)
			}
			escreva("\n\t-----------------------------------------\n")
		}
	}

/*
 * procedimento que sorteia bombas
 * recebe como parâmetro a quantidade de bombas que deve ser gerado
*/
	funcao sortearBombas(inteiro quantidade){
		inteiro l, c

		para(linha = 1; linha <= quantidade; linha++){
			l = Util.sorteia(0, tamanho - 1) // 0 até 9
			c = Util.sorteia(0, tamanho - 1)
			// F+0 trocar o + por um *
			tabuleiro[l][c] = Texto.substituir(tabuleiro[l][c], "+", "*")
		}
	}

/*
 * função que verifica se uma coordenada é válida
 * 1 - é válida
 * 0 - não é válida
*/
	funcao inteiro eValida(inteiro l, inteiro c){
		se(l >= 0 e l < tamanho e c >= 0 e c < tamanho)
			retorne 1 // é válido
		retorne 0 // não é válido
	}

/*
 * Função que verifica se uma posição é bomba ou não
 * 1 - é bomba
 * 0 - não é bomba
*/
	funcao inteiro eBomba(inteiro l, inteiro c){
		se(eValida(l, c) == 1){
			se(Texto.posicao_texto("*", tabuleiro[l][c], 1) != -1)
				retorne 1 // é uma bomba
			senao
				retorne 0 // não é uma bomba
		}
		retorne 0 // não é bomba ou é inválida
	}

/*
 * Procedimento para contar a quantidade de bombas na vizinhança para cada posição
*/
	funcao contarBombasVizinhas(){
		inteiro quantidade = 0
		
		para(linha = 0; linha < tamanho; linha++){
			para(coluna = 0; coluna < tamanho; coluna++){
				quantidade += eBomba(linha - 1, coluna) // acima
				quantidade += eBomba(linha + 1, coluna) // abaixo
				quantidade += eBomba(linha, coluna + 1) // à direita
				quantidade += eBomba(linha, coluna - 1) // à esquerda
				tabuleiro[linha][coluna] = Texto.substituir(tabuleiro[linha][coluna], "0", ""+quantidade)
				quantidade = 0
			}
		}
	}

/*
 * função que lê uma única coordenada 
 * retorna a coordenada lida quando for válida
*/
	funcao inteiro leCoordenada(){
		inteiro x

		leia(x)
		enquanto(x < 0 ou x >= tamanho){
			escreva("\n\tÍndice Inválido. Digite um valor entre 0 e ", tamanho -1, ".\n")
			leia(x)
		}
		retorne x
	}

/*
 * função que verifica se uma posição já foi aberta
 * 1 - aberta
 * 0 fechada
*/
	funcao inteiro estaAberta(inteiro l, inteiro c){
		se(Texto.posicao_texto("A", tabuleiro[l][c], 0) != -1)
			retorne 1 // está aberta
		retorne 0 // está fechada
	}

/*
 * procedimento que faz a leitura das coordenadas de linha e coluna
*/
	funcao leCoordenadas(){
		faca{
			escreva("\n\tDigite a coordenada de linha:\n")
			linha = leCoordenada()
			escreva("\n\tDigite a coordenada de coluna:\n")
			coluna = leCoordenada()

			se(estaAberta(linha, coluna) == 1)
				escreva("\n\tEsta posição já foi aberta. Digite outra posição!\n")
		}enquanto(estaAberta(linha, coluna) == 1)
	}

/*
 * procedimento para abrir posição jogada
 * se tiver 0 bombas vizinhas, seus vizinhos devem ser abertos também
*/
	funcao abrirPosicao(inteiro l, inteiro c){
		se(eValida(l, c) == 1 e estaAberta(l, c) == 0){
			tabuleiro[l][c] = Texto.substituir(tabuleiro[l][c], "F", "A")
			se(Texto.posicao_texto("0", tabuleiro[l][c], 2) != -1){
				abrirPosicao(l - 1, c) // acima
				abrirPosicao(l + 1, c) // abaixo
				abrirPosicao(l, c + 1) // direita
				abrirPosicao(l, c - 1) // esquerda
			}
		}
	}

/*
 * função que verifica se o jogador perdeu
 * 1 - perdeu
 * 0 - não perdei ainda
*/
	funcao inteiro Perdeu(inteiro l, inteiro c){
		se(eBomba(l, c) == 1)
			retorne 1 // perdeu
		retorne 0 // ainda não perdeu
	}

/*
 * função que conta e retorna a quantidade de posições fechadas que não são bombas
*/
	funcao inteiro totalFechadas(){
		inteiro quantidade = 0

		para(linha = 0; linha < tamanho; linha++){
			para(coluna = 0; coluna < tamanho; coluna++){
				se(eBomba(linha, coluna) == 0 e estaAberta(linha, coluna) == 0)
					quantidade++
			}
		}
		//escreva("\n==== quantidade: ", quantidade, "====\n")
		retorne quantidade
	}

/*
 * função para verificar se o jogador ganhou
 * 1 - ganhou
 * 0 - não ganhou ainda
*/
	funcao inteiro Ganhou(inteiro l, inteiro c){
		se(totalFechadas() == 0)
			retorne 1 // jogador ganhou
		retorne 0 // jogador não ganhou ainda
	}

/*
 * procedimento com o loop principal do jogo
*/
	funcao jogar(){
		inteiro perdeu, ganhou

		faca{
			imprimirTabuleiro()
			leCoordenadas()
			abrirPosicao(linha, coluna)
			perdeu = Perdeu(linha, coluna)
			ganhou = Ganhou(linha, coluna)
		}enquanto(perdeu == 0 e ganhou == 0)

		se(perdeu == 1)
			escreva("\n\tVocê perdeu!!!\n")
		se(ganhou == 1)
			escreva("\n\tPARABÉNS. VOCÊ GANHOU!!!\n")
	}
	

	funcao inicio(){
		inteiro opcao

		faca{
			inicializarTabuleiro()
			sortearBombas(10)
			contarBombasVizinhas()
			jogar()

			escreva("\n\tDigite 1 para jogar novamente: \n")
			leia(opcao)
		}enquanto(opcao == 1)
	}
}

Deixe um comentário

19 + treze =

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.