Baixe o app para aproveitar ainda mais
Prévia do material em texto
1 FACULDADE DE COMPUTAÇÃO E INFORMÁTICA BACHARELADOS EM CIÊNCIA DA COMPUTAÇÃO E SISTEMAS DE INFORMAÇÃO E TECNOLOGIA EM ANÁLISE E DESENVOLVIMENTO DE SISTEMAS Linguagem de Programação I – Semana 03 TEORIA: MATRIZES Nossos objetivos nesta semana são: Conhecer o conceito de matriz e como defini-las em Java. Conhecer o processo de leitura e gravação de dados em arquivos em Java. A referência para esta semana é o Capítulo 7 (Arrays e Listas de Arrays) do nosso livro da referencia básica: HORSTMANN, C. Conceitos de Computação com Java. 5.ed. Porto Alegre: Bookman, 2009. Não deixem de ler este capítulo depois desta aula! Para acessar a versão eletrônica deste livro: Acesse o link da Biblioteca Virtual MINHA BIBLIOTECA (https://www3.mackenzie.com.br/bibl ioteca_v irtual/index .php?tipoBiblio=minhabiblioteca&flashObg=n) Faça o login conforme as instruções apresentadas na tela. Faça a busca fornecendo os dados do livro. MATRIZES Até o momento, conhecemos o conceito de vetor. Essencialmente, um vetor armazena informações com indexação em uma única dimensão (índice). Assim, um vetor também é conhecido pelo nome de array unidimensional. Por exemplo: double data[] = new double [10]; data[2]=29.95; 2 Podemos pensar numa extensão para duas dimensões. Esta estrutura bidimensional é chamada array bidimensional ou, comumente, matriz. Arrays bidimensionais formam um arranjo bidimensional tabular. Você acessa os elementos com um par de índices a[i][j]. Abaixo temos um exemplo de matriz: A declaração e alocação de matrizes em Java é bastante simples: tipo A[ ][ ] = new tipo [quantidade linhas][quantidade colunas]; Exemplos: int A[ ][ ]= new int[2][3]; char M[ ][ ] = new char[3][2]; Matrizes também podem ser declaradas e inicializadas junto com a declaração. Neste contexto, o tamanho da matriz é definido pela inicialização. Para os dois exemplos acima teríamos: int A[ ][ ] = { {0,4,5}, {-5,6,8}}; char M[ ][ ] = {{‘A’,’B’},{‘C’,’D’},{‘E’,’F’}}; O acesso aos elementos de uma matriz é feito através de dois índices: um para a linha e, outro, para a coluna. Por exemplo, considerando-se a matriz A, o acesso A[0][1] irá recuperar o valor 4 (linha 0, coluna 1). De forma similar, podemos ter arrays de qualquer dimensão: A[ ][ ][ ], A[ ][ ][ ][ ],... . Para cada dimensão, utilizamos um índice de acesso. Na verdade, uma array bidimensional em Java é uma array de arrays. 3 EXERCÍCIO COM DISCUSSÃO EM DUPLAS Construa uma função que receba a quantidade de linhas(lin) e de colunas(col) e devolva uma matriz de dimensão lin x col contendo números inteiros aleatórios entre 0 e 100. Teste sua função. public static int [ ][ ] generateMatrix (int lin,int col){ } EXERCÍCIO COM DISCUSSÃO EM DUPLAS Construa um procedimento que receba uma matriz de números inteiros e exiba o seu conteúdo na formatação gráfica de uma matriz. Teste seu procedimento. public static void printMatrix(int m[ ][ ]){ } EXERCÍCIO COM DISCUSSÃO EM DUPLAS Construa uma função que receba uma matriz de números inteiros e devolva o maior valor presente nesta matriz. Teste sua função. public static int max(int m[ ][ ]){ } 4 EXERCÍCIO 1 Em um jogo de batalha naval, os jogadores posicionam suas embarcações em um grid de 10 linhas por 10 colunas. Na nossa versão do jogo, as seguintes embarcações devem ser distribuídas no grid: • 1 porta-aviões (ocupa 5 células lineares do grid) • 1 encouraçado (ocupa 4 células lineares do grid) • 1 cruzador (ocupa 3 células lineares do grid) • 1 submarino (ocupa 2 células lineares do grid) Cada embarcação pode ser posicionada na direção vertical ou na horizontal em relação ao grid. As embarcações não podem se sobrepor, e elas devem caber integralmente dentro do grid. Para desenvolver um jogo de batalha naval em Java, vamos utilizar uma matriz de caracteres de dimensão 10x10. Cada posição da matriz será preenchida usando a seguinte notação: O caractere ponto (.) indica que a célula não é ocupada por nenhuma embarcação. O caractere P indica que a célula está sendo ocupada por uma célula do porta-aviões. O caractere E indica que a célula está sendo ocupada por uma célula do encouraçado. O caractere C indica que a célula está sendo ocupada por uma célula do cruzador. O caractere S indica que a célula está sendo ocupada por uma célula do submarino. A tabela abaixo apresenta um exemplo de preenchimento válido do grid com as embarcações: 0 1 2 3 4 5 6 7 8 9 0 . . . . . . . . . . 1 . P P P P P . . . . 2 . . . . . . . S . . 3 . . . E . . . S . . 4 . . . E . . . . . . 5 . . . E . . . . . . 6 . . . E . . C C C . 7 . . . . . . . . . . 8 . . . . . . . . . . 9 . . . . . . . . . . a) Declara uma classe com o nome BatalhaNaval e desenvolva um método que retorne uma matriz 10x10 preenchida em todas as suas posições com o caractere ponto. public static char[][] inicializarGrid(){ } 5 b) Desenvolva um método para posicionar um porta-aviões no grid de batalha. O método receberá como parâmetros: a referência para a matriz do grid; os índices da linha e da coluna da primeira posição a ser preenchida; a informação indicando se o porta-aviões deverá ser posicionado na vertical (o valor true indica orientação vertical e false indica orientação horizontal). Se a orientação for horizontal, as demais partes do porta-aviões deverão ocupar as células à direita da célula identificada pelos parâmetros linha e coluna. Se a orientação for horizontal, deverão ocupar as células abaixo da célula identificada. O método retornará um valor booleano indicando se foi ou não possível posicionar o porta- aviões no grid. O porta-aviões só poderá ser posicionado se: Nenhuma de suas partes for ficar fora do grid. Não houver nenhuma outra embarcação nas células que o porta-aviões iria ocupar. public static boolean posicionarPortaAvioes(char[][] grid, int linha, int coluna, boolean vertical){ } 6 c) Desenvolva um método para imprimir o conteúdo do grid na tela do computador. public static void imprimir(char[][] grid){ } d) Escreva o método main da classe BatalhaNaval de forma a: Inicializar o grid da batalha. Posicionar um porta-aviões em uma posição válida. Tentar posicionar um porta-aviões em uma posição que faria ele ficar fora do grid. Tentar posicionar um porta-aviões em uma posição que ocasionaria sobreposição com o primeiro porta-aviões. Imprimir o conteúdo do grid. public static void main(String[] args){ } Execute e verifique se o resultado apresentado corresponde ao esperado. e) Utilizando como modelo o método posicionarPortaAvioes, desenvolva os métodos para posicionar encouraçado, cruzador e submarino. f) Acrescente ao método main chamadas aos métodos criados no item (e) e verifique se estão funcionando conforme o esperado. 7 EXERCÍCIO 2 O programa desenvolvido no exercício anterior só permite inicializar o grid e posicionar as embarcações. Incremente o programa de forma a gerar um jogo de batalha naval. a) Desenvolva o método atirar. O método receberá como parâmetros: a referência para a matriz do grid; os índices da linha e da coluna onde o tiro está sendo realizado. O método retornará um caractere com o valor que estava armazenado naquela posição do grid. A execução do método deverá alterar o conteúdo do grid: Se a posição não tinha nenhuma embarcação (“água”), o novo valor deverá ser ‘x’ (minúsculo). Se a posição estava ocupada por uma embarcação, o novo valor deverá ser ‘X’ (maiúsculo). public char void atirar(char[][] grid, int linha, int coluna){ } b) Implemente o fluxo principal do jogo no método main de forma a: Inicializar o grid da batalha. Posicionar de forma aleatória, em posições válidas, um porta-aviões, um encouraçado, um cruzador e um submarino. Dar ao jogador 20 chances para atirar. A cada tiro o programa deverá informar ao jogador o resultado do tiro (água ou parte de uma das embarcações). Caso o jogador tente atirar pela segunda vez em uma mesma posição, o programa deverá informá-lo disto e dar uma nova chance sem descontar esta tentativa do total de tiros. Imprimir o conteúdo do grid ao final do jogo. 8 MANIPULAÇÃO DE ARQUIVOS EM JAVA O processo de leitura e gravação de dados em arquivos, em Java, é feito através de streams. Existem diversas classes que implementam streams no pacote java.io. Neste primeiro contato, utilizaremos as classes BufferedReader e BufferedWriter. Trabalhar com arquivos é muito parecido com trabalhar com livros. Para utilizar um livro, você tem que abri-lo. Quando você termina, você tem que fechá-lo. Enquanto o livro estiver aberto, você pode tanto ler quanto escrever nele. Na maioria das vezes, você lê o livro inteiro em sua ordem natural, uma página após a outra. Para abrir um arquivo em Java utilizamos o seguinte trecho de código baixo, com a uti lização das classes FileReader e BufferedReader do pacote java.io.* BufferedReader entrada=new BufferedReader(new FileReader(<Nome arquivo entrada >)); Para realizar a leitura de uma linha de um arquivo texto, vamos supor entrada.txt, basta realizar a chamada da linha acima e após a abertura do arquivo basta ler as linhas do arquivo com o método readLine(), e ao final devemos fechar o arquivo com método close(). Note que no método main() informamos que caso ocorra um erro (exceção) este será repassado, isso será explicado melhor nas próximas aulas. import java.io.*; public class ManipulacaoArquivo { public static void main(String[] args) throws IOException { // abre o arquivo para leitura BufferedReader entrada=new BufferedReader( new FileReader("entrada.txt")); // le uma linha String linha = entrada.readLine(); System.out.println(linha); // fecha arquivo de entrada entrada.close(); } } } EXERCÍCIO COM DISCUSSÃO EM DUPLAS Construa uma função que receba o nome de um arquivo de entrada (String file) e lê a matriz que está armazenada no arquivo de entrada com o seguinte formato: 3 4 10 20 30 40 50 60 70 80 90 100 110 120 9 Na primeira linha do arquivo temos dois inteiros informando o número de linhas e colunas da matriz seguir temos a matriz com várias linhas, e em cada linha os elementos separados por um espaço em branco. Ao final a função retorna uma matriz alocada com as informações do arquivo de entrada, depois de implementar a função tente escrever a função main() para testá-lo. public static int [ ][ ] readMatrixFile(String file) throws IOException { } EXERCÍCIO COM DISCUSSÃO EM DUPLAS Construa uma função principal que receba uma matriz de números inteiros e devolva o maior valor presente nesta matriz a partir de dados armazenados em um arquivo. 10 ATIVIDADE DE LABORATÓRIO Uma agência bancária tem 5 clientes e cada cliente possui uma conta corrente e uma conta poupança. Cliente Saldo em conta corrente Saldo em conta poupança Marcos R$ 1.000,00 R$ 2.500,00 Júlia R$ 250,00 R$ 1.500,00 João R$ 2.500,00 R$ 750,00 Roberto R$ 3.000,00 R$ 50,00 Janaína R$ 4.500,00 R$ 3.200,00 Vamos desenvolver uma aplicação em Java para gerenciar os saldos destas contas. Para armazenar os saldos, vamos utilizar uma matriz 5x2 e inicializar esta matriz com os saldos das contas. Para armazenar os nomes dos clientes, vamos utilizar um vetor de strings. Inicialização public class BancoAppV1 { public static void main(String[] args) { String[] nomes = {"Marcos", "Júlia", "João", "Roberto", "Janaína"}; int[][] saldos = {{1000,2500},{250,1500},{2500,750},{3000,50},{4500,3200}}; } } Impressão dos saldos Vamos adicionar um método que imprima na tela os saldos de todas as contas. O método mostrarSaldos recebe o vetor com os nomes dos clientes e a matriz com os saldos e imprime todas as informações na tela do computador. public class BancoAppV2 { public static void mostrarSaldos(String[] nomes, int[][] saldos) { System.out.println("Saldos de todos os clientes:"); for (int i=0; i<nomes.length; i++) { String msg = i + ") " + nomes[i] + ": "; msg += saldos[i][0] + " (conta corrente) e "; msg += saldos[i][1] + " (poupança)"; System.out.println(msg); } System.out.println(); } 11 public static void main(String[] args) { String[] nomes = {"Marcos", "Júlia", "João", "Roberto", "Janaína"}; int[][] saldos = {{1000,2500},{250,1500},{2500,750},{3000,50},{4500,3200}}; mostrarSaldos(nomes, saldos); } } Operações de saque e depósito Como as operações principais envolvendo os saldos das contas são as de saque e depósito, vamos desenvolver os métodos sacar e depositar. O método sacar recebe a matriz de saldos, o valor do saque e a identificação da conta onde deverá ser efetuado o saque. Note que a conta pode ser identificada pelo índice do cliente (no caso, de 0 a 4) e pelo tipo de conta (0 para conta corrente e 1 para poupança). O método depositar recebe a matriz de saldos, o valor do depósito e a identificação da conta onde deverá ser efetuado o depósito. public class BancoAppV3 { public static void sacar(int[][] saldos, int valor, int cliente, int tipoConta) { saldos[cliente][tipoConta] -= valor; } public static void depositar(int[][] saldos, int valor, int cliente, int tipoConta) { saldos[cliente][tipoConta] += valor; } public static void mostrarSaldos(String[] nomes, int[][] saldos) { System.out.println("Saldos de todos os clientes:"); for (int i=0; i<nomes.length; i++) { String msg = i + ") " + nomes[i] + ": "; msg += saldos[i][0] + " (conta corrente) e "; msg += saldos[i][1] + " (poupança)"; System.out.println(msg); } System.out.println(); } public static void main(String[] args) { String[] nomes = {"Marcos", "Júlia", "João", "Roberto", "Janaína"}; int[][] saldos = {{1000,2500},{250,1500},{2500,750},{3000,50},{4500,3200}}; mostrarSaldos(nomes, saldos); sacar(saldos, 100, 1, 1); System.out.println("Saldos após o saque:"); mostrarSaldos(nomes,saldos); depositar(saldos, 1000, 4, 0); System.out.println("Saldosapós o depósito:"); mostrarSaldos(nomes, saldos); } } 12 Interações com o usuário Vamos agora adicionar as interações dos nossos programas com o usuário. Para isso, serão criados os métodos interacaoSacar e interacaoDepositar, e implementaremos um menu de opções na aplicação. import java.util.Scanner; public class BancoAppV4 { public static Scanner entrada; public static void sacar(int[][] saldos, int valor, int cliente, int tipoConta) {...} public static void depositar(int[][] saldos, int valor, int cliente, int tipoConta) {...} public static void mostrarSaldos(String[] nomes, int[][] saldos) {...} public static void interacaoSacar(int[][] saldos) { boolean clienteValido = false; int cliente = -1; while (!clienteValido) { System.out.print("O saque será efetuado na conta de qual cliente? (0 a " + (saldos.length-1) + "): "); cliente = entrada.nextInt(); if (cliente >=0 && cliente < saldos.length) { clienteValido = true; } else { System.out.println("Índice de cliente inválido!"); } } boolean contaValida = false; int tipoConta = -1; while (!contaValida) { System.out.print("Em qual conta será efetuado o saque? " + "(0 - conta corrente; 1 - poupança): "); tipoConta = entrada.nextInt(); if (tipoConta == 0 || tipoConta == 1) { contaValida = true; } else { System.out.println("Valor inválido!"); } } System.out.print("Qual o valor do saque? "); int saque = entrada.nextInt(); sacar(saldos, saque, cliente, tipoConta); } public static void interacaoDepositar (int[][] saldos) { System.out.println("Em construção..."); } 13 public static void main(String[] args) { String[] nomes = {"Marcos", "Júlia", "João", "Roberto", "Janaína"}; int[][] saldos = {{1000,2500},{250,1500},{2500,750},{3000,50},{4500,3200}}; entrada = new Scanner(System.in); boolean sair = false; while(!sair) { System.out.println("Escolha uma operação:"); System.out.println("(1) mostrar saldos de todos os clientes"); System.out.println("(2) sacar"); System.out.println("(3) depositar"); System.out.println("(4) sair"); System.out.print("Opção escolhida: "); int escolha = entrada.nextInt(); System.out.println(); switch(escolha) { case 1: mostrarSaldos(nomes, saldos); break; case 2: interacaoSacar(saldos); break; case 3: interacaoDepositar(saldos); break; case 4: sair = true; break; default: System.out.println("Opção inválida!"); } System.out.println(); } System.out.println("Fim do programa!"); } } O objetivo é que você complemente as funcionalidades dessa aplicação. Para tanto: 1) Utilizando como modelo o método interacaoSacar, implemente o método interacaoDepositar. 2) Desenvolva um método para efetuar a operação de transferência. Utilize a assinatura abaixo: public static void transferir(int[][] saldos, int valor, int clienteOrigem, int tipoContaOrigem, int clienteDestino, int tipoContaDestino) Este método deverá transferir o valor especificado da conta de origem (identificada por clienteOrigem e tipoContaOrigem) para a conta de destino (identificada por clienteDestino e tipoContaDestino). 3) Desenvolva o método interacaoTransferir, que deverá solicitar os dados necessários para a operação de transferência e efetuá-la. 14 EXERCÍCIOS EXTRA-CLASSE 1. Dizemos que uma matriz quadrada A é simétrica se e somente se A[i][j]=A[j][i]. Implemente uma função para verificar se uma matriz de números inteiros é simétrica. Teste a sua função. 2. Dizemos que uma matriz quadrada A é anti-simétrica se e somente se A[i][j]=−A[j][i]. Implemente uma função para verificar se uma matriz de números inteiros é anti -simétrica. Teste a sua função. 3. A matriz identidade (I) é uma matriz quadrada onde os elementos da diagonal principal são todos iguais a 1 e, os demais elementos, todos iguais a 0. Construa uma função que receba um número inteiro n e devolva uma matriz identidade de dimensão nxn. Teste a sua função. 4. Implemente uma função que verifique se duas matrizes de números inteiros são iguais. Teste a sua função. 5. Uma matriz B é chamada de inversa de uma matriz A se e somente se AxB=I, ou seja, se o produto entre elas for a matriz identidade. Implemente uma função que receba duas matrizes A e B e verifique se B é a matriz inversa de A. Teste a sua função. 6. O traço de uma matriz é a soma dos elementos de sua diagonal principal. Implemente uma função que receba uma matriz quadrada (número de linhas = número de colunas) e devolva o seu traço. Teste a sua função. 7. Construa uma função que receba duas matrizes - A, de dimensão nxm e, b, de dimensão mxp – e devolva uma matriz de dimensão nxp, resultante do produto de A por B. Teste a sua função. 8. A transposta de uma matriz A, de dimensão n por m, é a matriz AT, de dimensão m por n, onde o elemento AT[j][i] da transposta corresponde ao elemento A[i][j] da matriz original. Implemente uma função que receba uma matriz de números inteiros A e devolva a sua transposta. 9. Dizemos que uma matriz A é hermitiana se e somente se A=AT. Implemente uma função que receba uma matriz de números inteiros A e devolva true, caso ela seja hermitiana e false, caso contrário. Teste a sua função. 15 10. O Sr. Krika deseja fazer vários orçamentos de custo de uma compra de materiais para construção. Os três produtos P1, P2 e P3 são necessários nas quantidades Q1, Q2 e Q3, respectivamente. Ao pesquisar os preços em 5 estabelecimentos comerciais, o Sr. Krika encontrou a seguinte tabela de preço: Escreva um programa que calcula o custo da compra dos três produtos em cada um dos estabelecimentos. Considere que as informações a respeito dos estabelecimentos são fornecidas via arquivo texto. 11. O Jogo da Velha é um jogo bem conhecido e pode ser implementado com base na teoria que aprendemos nesta semana. No Jogo da Velha, temos dois jogadores, O e X, que jogam sob um tabuleiro 3x3. Ganha o jogo quem preencher primeiro uma linha, uma coluna ou uma das diagonais. Seu objetivo neste exercício será implementar este jogo no modo texto. Para tanto: 1. Vamos representar o nosso tabuleiro como uma matriz de caracteres 3x3. Sua primeira função deverá devolver uma matriz de caracteres 3x3, com algum valor preenchido para indicar que uma posição não foi ocupada. char [ ][ ] initialize() {...} 2. Implemente uma função que receba uma matriz do jogo da velha, uma posição (linha, coluna) e o código do jogador (X ou O) e devolva a matriz com a posição preenchida com o código do jogador, caso esteja livre. Se a posição conseguiu ser preenchida, step deve retornar true e, caso não puder ser preenchida, false. Boolean step (char M[ ][ ], int lin, int col, char gamer){...} 16 3. Implemente uma função que receba umamatriz do jogo do jogo da velha e verifique o estado do jogo: alguém venceu, ocorreu um empate ou o jogo deve continuar. Vamos usar o seguinte código: -1 (o jogo pode continuar), 0 (ocorreu um empate), 1 (O venceu) e 2 (X venceu). int status (char M[ ][ ]){...} 4. Implemente um procedimento para executar a lógica deste jogo. Suponha que o jogador O sempre começa. A cada jogada, a matriz do jogo deverá ser exibida na tela. Ao final do jogo, seu procedimento deve mostrar o estado a que se chegou (vitória ou empate). Teste o seu jogo. void game(){...}
Compartilhar