aula 118

JOGO CAMPO MINADO EM PORTUGOL | Parte I

Nesta aula vamos iniciar o desenvolvimento do Jogo Campo Minado em Portugol. Durante a criação do jogo campo minado iremos praticar e aplicar tudo que estudamos até aqui em nosso curso de Algoritmos e Lógica de Programação.

Logo no início precisamos tomar uma decisão de projeto extremamente importante. Quantas e quais estruturas de dados utilizar.

Para este projeto usaremos uma matriz de cadeia, ou seja, cada posição da matriz pode armazenar uma cadeia de caracteres. Esta escolha se deve ao fato de precisarmos saber três informações sobre cada posição do campo minado:
– Se está aberta ou fechada;
– Se é uma bomba ou não;
– Quantas bombas há na vizinhança.

Para sabermos estas informações, cada cadeia de nossa matriz possuirá três caracteres:
– Uma letra (A para aberto e F para fechado);
– um símbolo (* é uma bomba e + não é uma bomba);
– e um número que indica a quantidade de bombas na vizinhança (0 a 4).

Assim, as seguintes cadeias possuem o seguintes significados:
– 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.

Agora que decidimos a estrutura a ser utilizada e para facilitar a elaboração de nossas funções e procedimentos, vamos criar nossa matriz como uma variável global.

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

No início do nosso jogo campo minado nós não sabemos o estado de cada posição do tabuleiro. Assim, vamos fazer um procedimento para inicializar nosso jogado, limpando todas as posições da matriz. Esse procedimento inicializa cada posição da matriz com a cadeia “F+0” que significa fechado, não é bomba e possui zero bombas vizinhas.

/*
 * Este procedimento inicializa nossa 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"
			}
		}
	}

O procedimento seguinte é para imprimir o campo minado na tela. Este procedimento é construído na tentativa e erro, fazendo, testando, corrigindo, até que seja atingido a impressão desejada para nosso campo minado. Por enquanto vamos apenas imprimir a cadeia de cada posição da nossa matriz.

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

		para(linha = 0; linha < tamanho; linha++){
			para(coluna = 0; coluna < tamanho; coluna++){
				escreva(tabuleiro[linha][coluna], "\n")
			escreva("\n")
		}
	}

Uma parte fundamental do jogo campo minado é o sorteio das bombas. O procedimento a seguir realiza esse processo. São gerados dois números inteiros entre 0 e o tamanho da matriz menos 1. Estes números representam a posição que irá receber uma bomba. Para registrar uma bomba basta trocar o caracter + por um *.

/*
 * 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], "+", "*")
		}
	}

Também precisaremos saber se, dada uma coordenada de linha e coluna, se a mesma é válida. A função a seguir faz exatamente isso, retornando 1 se a coordenada for válida e 0 caso contrário.

/*
 * 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
	}

Outra ação que precisaremos e saber se uma determinada coordenada é uma bomba ou não. A função a seguir resolve este problema. Perceba que esta função faz uso da função anterior para apenas verificar nossa matriz apenas para coordenadas válidas.

/*
 * 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) // existe um *
				retorne 1 // é uma bomba
			senao
				retorne 0 // não é uma bomba
		}
		retorne 0 // não é bomba ou é inválida
	}

Antes de iniciar nosso jogo ainda precisamos descobrir quantas bombas há na vizinhança de cada posição. O procedimento a seguir percorre toda a matriz verificando os quatro vizinhos (acima, abaixo, à direita e à esquerda) de cada posição, contando as bombas e salvando em cada campo.

/*
 * 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
			}
		}
	}

Para testar o que fizemos até o momento podemos chamar nossas funções e procedimentos em inicio, como feito a seguir.

	funcao inicio(){

		inicializarTabuleiro()
		sortearBombas(10)
		contarBombasVizinhas()
		imprimirTabuleiro()
	}

Parte I do código em Portugol para o jogo Campo Minado

programa{
	inclua biblioteca Util
	inclua biblioteca Texto

	
/*	
 * 	Código 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 nossa 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(){

		para(linha = 0; linha < tamanho; linha++){
			para(coluna = 0; coluna < tamanho; coluna++){
				escreva(tabuleiro[linha][coluna], "\n")
			escreva("\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
			}
		}
	}

	funcao inicio(){

		inicializarTabuleiro()
		sortearBombas(10)
		contarBombasVizinhas()
		imprimirTabuleiro()
	}
}

Deixe um comentário

dezenove + 17 =

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.