Refinamentos sucessivos

Documentos relacionados
Sintaxe do Pascal Simplificado Estendido de 12 novas construções em Notação EBNF (BNF estendida)

Linguagem de programação: Pascal

LISTA DE EXERCÍCIOS 15 ( Matrizes (7Cs))

Linguagem Pascal. Prof. Antonio Almeida de Barros Junior

Pascal. -Cabeçalho do programa. - label - const - type - var - procedure - function. - integer - real - byte - boolean - char - string

Departamento de Engenharia Rural Centro de Ciências Agrárias. Programação I

Sumário. Ciência da Computação. Prof. Dr. Leandro Alves Neves. Aula 10. Algoritmos e Programação. Enquanto (Teste no início) Repeat (Teste no final)

Linguagem e Técnicas em Programação. Gilson de Souza Carvalho

Linguagem Computacional. Estruturas de Controle: Estruturas de Repetição. Prof. Dr. Adriano Cansian Prof. Dr. Leandro Alves Neves

Teoria da Computação e Algoritmos. Introdução à Linguagem Pascal. ALGORITMO <Nome do algoritmo>; <definições>; INÍCIO <Comandos>; FIM.

O AMBIENTE DE PROGRAMAÇÃO VISUAL -PLANO DE ENSINO. Prof. Angelo Augusto Frozza, M.Sc.

UNISINOS - UNIVERSIDADE DO VALE DO RIO DOS SINOS CENTRO DE CIÊNCIAS EXATAS E TECNOLÓGICAS (C6/6) Curso: Informática

tipoveiculo = (bicicleta, motociclo, motorizada, automovel, autocomreb, camioneta, autocarro, camiao, reboque); veiculo : tipoveiculo;

I1, I2 e In são instruções simples ou estruturadas da linguagem Pascal.

Introdução à Ciência da Computação

PROGRAMAÇÃO de COMPUTADORES: LINGUAGEM FORTRAN 90/95

Exercícios. Resposta: a) var valor: real; i: integer. b)

Elementos básicos das linguagens de programação

Linguagem Pascal. Definição e Tipos de Dados. Professora Lara Popov Zambiasi Bazzi Oberderder. Linguagem PASCAL 1

Exercícios sobre o Capítulo III

Introdução à Programação 2006/07. Algoritmos

MAC 115 Introdução à Ciência da Computação ROTHELO

Modularidade. Objetivos: Introduzir noções básicas de modularidade. Funções e procedimentos

PROGRAMAÇÃO DE COMPUTADORES I BCC Aula Prática 15

Procedimento. Função. Selecção Condicional - a instrução if-then-else. expressão if lógica then instrução else instrução

Aula Anterior. Decomposição algorítmica (continuação)

Programação Introdução

UNISINOS - UNIVERSIDADE DO VALE DO RIO DOS SINOS CENTRO DE CIÊNCIAS EXATAS E TECNOLÓGICAS (C6/6) Curso: Informática

Disciplina Programação Prof. Esp. Armando Hage. Programação em Turbo Pascal

Tutorial de Turbo Pascal

Laços de repetição for, while, do-while

Programação de Computadores II

Capítulo V : A Linguagem Pascal Um Tipo Estruturado de Dados: o array 18. Para limite de n até 2 (* passagens de 1 até (n-1) *)

Lista 2 TP060. Exercícios Vetores

Linguagem Pascal. Prof. Sérgio Rodrigues. É a descrição, de forma lógica, dos passos a serem executados no cumprimento de determinada tarefa;

Considere uma máquina que utiliza uma palavra de 10 bits. Suponha o seguinte padrão de bits:

Universidade Federal de Uberlândia Faculdade de Computação. Linguagem C: estruturas de repetição While / Do While / For

1ª Lista de Exercícios

Estrutura de Dados Polinómio

Exemplos. Alocação Dinâmica de Pilhas. Pilhas. Pilhas. Implementação Seqüencial X Encadeada. SCE 182 Algoritmos e Estruturas de Dados I

SME Introdução à Programação de Computadores Primeiro semestre de Trabalho: jogo Semáforo

Complexidade de Algoritmos

IFTO TÉCNICO EM INFORMÁTICA DESENVOLVIMENTO DE SISTEMAS AULA 01

Linguagem e Técnicas em Programação. Gilson de Souza Carvalho

Variáveis Compostas Heterogêneas. Variável Composta Heterogênea. Variável Composta Heterogênea

Programação Orientada a Objetos

Revisão C++ - Parte 1

1, caso haja uma mina na posição (i, j),

Manipulação de Arquivos em Pascal

Arquivos Sequenciais. Estruturas de Dados II Vanessa Braganholo

Ciclo com Contador : instrução for. for de variável := expressão to. expressão do instrução

LISTA 14 Gabarito. 1) Preparar um algoritmo para calcular a soma de 100 termos da seguinte série:

Notas de Aula de Algoritmos e Programação de Computadores

PROGRAMAÇÃO I AULA 08

Introdução ao Pascal. Computação I. Níveis de Linguagens de Programação. Níveis de Linguagens de Programação. Como um Programa é Executado?

Programação: Vetores

Aulas Anteriores. Detalhes da linguagem de programação

Lógica de Programação I. Gilson de Souza Carvalho

Linguagem de Programação Pascal - Introdução

Sumário. 1.1 Variáveis Globais e Locais Passagem de Parâmetro (por valor por referência) 1

LINGUAGEM C: ARRAY: VETORES E MATRIZES

Estruturas de Repetição. for() while() do-while() break; continue;

3. 1. Teste no Início do Ciclo (Repetição enquanto ):

TAD: Tipo Abstrato de Dados (parte 1)

LISTA DE EXERCÍCIOS: 1ª Unidade

Aula 3 PROFESSOR TUTA

Transcrição:

Refinamentos sucessivos Objetivos: Estudar a técnica de refinamentos sucessivos

Jogo: 2048 Implementaremos o jogo 2048, com o objetivo de estudar a manipulação dos elementos de uma matriz Utilizaremos a técnica de refinamentos sucessivos

Jogo: 2048 - Regras Este jogo é jogado em um tabuleiro 4x4, no qual inicialmente existem duas posições com peças de valor 2 ou 4 em posições aleatórias. As outras casas contém posições vazias

Jogo: 2048 - Regras As peças podem ser movimentadas para cima, para baixo, para a direita ou para esquerda Ao fim de cada movimento, uma peça com o valor 2 ou com o valor 4, esta com menor probabilidade, é colocada no tabuleiro, em uma posição vazia

Jogo: 2048 - Regras Ao fazer um movimento para alguma direção, todas as peças são movimentadas para o extremo desta direção Se existe um movimento válido ele deve ser feito Quando duas peças de igual valor se chocam, elas viram uma só peça de valor igual à soma das peças originais

Jogo: 2048 - Regras O objetivo é obter uma peça com o valor 2048 em alguma posição do tabuleiro, embora seja possível obter valores maiores O jogo mostra uma pontuação, que é a soma total das peças que foram fundidas durante o jogo

Refinamentos sucessivos Programar por refinamentos sucessivos é propor uma solução em alto nível e progressivamente tomar decisões sobre estruturas de dados e algoritmos Neste processo, procura-se deixar os detalhes para as próximas fases, mantendo código de alto nível em várias das subfases do projeto

Jogo: 2048 Algoritmo base Um primeiro algoritmo em alto nível pode ser este

2048: primeiro algoritmo Begin Iniciar Jogo ; Mostra o tabuleiro e os pontos Enquanto existe movimento possível faça Begin Escolhe direção do movimento Movimenta peças e atualiza os pontos Sorteia nova peça e sua posição Mostra o tabuleiro e os pontos End; End.

Refinando o algoritmo Com isto é possível estabelecer os procedimentos e funções iniciais, independentemente das estruturas de dados No entanto, é possível que possa haver necessidade de alguma alteração em função de alguma necessidade que venha a surgir

Refinando o algoritmo Procedure IniciarJogo (var T: tabuleiro; var Pontos: integer); Faz a inicialização das estruturas de dados e variáveis globais do programa

Refinando o algoritmo Function ExisteMovimento (var T: tabuleiro): boolean; Verifica a existência de movimento possível. Retorna true caso algum existe e false caso contrário

Refinando o algoritmo Function EscolherDirecao: tipodirecao; A princípio não precisa de parâmetros, apenas faz a interface com o usuário, que informa a direção desejada do movimento: para a direita, para a esquerda, para cima ou para baixo Retorna algum código referente ao movimento escolhido

Refinando o algoritmo Procedure MovimentarPeca (var T: tabuleiro; Direcao: tipodirecao; var Pontos: integer); Com a garantia de que existe movimento possível, aplica o movimento escolhido: atualiza o tabuleiro segundo as regras do jogo, movimentando as peças na direção desejada. Retorna a pontuação obtida com o movimento. Deve garantir que um movimento ocorra

Refinando o algoritmo Procedure InserirNovaPeca (var T: tabuleiro); Com a garantia de que existe posição livre, faz a escolha de uma posição aleatória que ainda esteja vazia e sorteia um valor que pode ser 2 ou 4, sendo este último valor de menor probabilidade do que o primeiro

Refinando o algoritmo Procedure MostrarJogoAtual (var T: tabuleiro; Pontos: integer); Cuida da parte visual do programa, mostrando o tabuleiro atual e a pontuação obtida até o momento

1 o refinamento do algoritmo Begin IniciarJogo (T,Pontos); MostrarJogoAtual (T,Pontos); While ExisteMovimento (T) do Begin Direcao:= EscolheDirecao; MovimentarPecas (T,Direcao,Pontos); InserirNovaPeca (T); MostrarJogoAtual (T,Pontos); End; End.

Análise do 1 o refinamento Não é possível entrar em loop infinito, pois quando se entra no laço é porque existiu movimento válido, logo no pior caso uma casa ficou vazia e ela seria escolhida Na próxima rodada, se o tabuleiro ficou cheio, o teste do laço identifica e aborta o laço

Estruturas de dados Agora podemos escolher a(s) estrutura(s) de dados para representar o jogo Deve-se levar em conta uma ideia dos algoritmos que serão necessários

Estruturas de dados No nosso caso, precisaremos movimentar peças, somar valores, etc. Nossa primeira decisão será a utilização de uma matriz

Estruturas de dados Como iremos somar peças, nada mais intuitivo do que fazer uma matriz de números inteiros, originalmente 4 x 4, mas prevista para poder ser maior, caso desejemos jogar um jogo com tabuleiro maior Problema: como representar as posições vazias?

Estruturas de dados Podemos usar o número zero para representar as posições vazias Para fins de efeito visual, basta trocar zeros por brancos, e o usuário terá a impressão de que as casas estão vazias Trivialmente, basta imprimir os valores das casas não nulas e o visual está completo

2048: primeira estrutura de dados CONST MAX = 4; TYPE tabuleiro = array [1..MAX,1..MAX] of integer; Var T: tabuleiro; Direcao, Pontos: integer;

2 o refinamento podemos detalhar melhor as funções e procedimentos que são possíveis a partir da decisão tomada com base na estrutura de dados escolhida

Detalhamento das subrotinas Como iniciar o jogo? Basta uma rotina para zerar todas as casas da matriz e sortear duas posições para conter as primeiras duas peças A pontuação será zerada também.

Detalhamento das subrotinas Procedure IniciarJogo (var T: tabuleiro; var Pontos: integer); Var i,j: integer; Begin For i:= 1 to max do For j:= 1 to max do T[i,j]:= 0; For i:= 1 to 2 do InserirNovaPeca (T); Pontos:= 0; End;

Detalhamento das subrotinas Como mostrar o jogo na tela? Basta imprimir a matriz, trocando zeros por espaços em branco. Para a diagramação correta usaremos o : do comando write Usaremos a procedure clrscr (clear screen) da biblioteca CRT para imprimir a nova matriz sobre a anterior, criando o aspecto visual de um jogo

Detalhamento das subrotinas Procedure MostrarJogoAtual (var T: tabuleiro; Pontos: integer); Var i,j: integer; Begin For i:= 1 to max do Begin For j:= 1 to max do If T[i,j] = 0 then Write (' ') // 6 espacos em branco Else Write (T[i,j]:6,' '); Writeln; End; Writeln ('Pontuação: ', Pontos); End;

Detalhamento das subrotinas Como inserir uma nova peça? São duas ações diferentes: uma para sortear uma posição vazia e outra para sortear um valor para a nova peça Este procedimento é usado no programa principal e também na procedure IniciarJogo, portanto deve funcionar em ambas

Detalhamento das subrotinas Procedure InserirNovaPeca (var T: tabuleiro); Var x,y: integer; Begin SortearNovaPosicao (T,x,y); T[x,y]:= SortearValor (MAXVALORPECA); End; A função de sorteio do valor deve se preocupar em dar maior probabilidade para sortear o valor 2 e menor probabilidade para o valor 4

Detalhamento das subrotinas Como sortear uma posição vazia? Não queremos percorrer a matriz inteira a cada novo sorteio, logo a questão é: como fazer a operação de maneira eficiente? O algoritmo seguinte é uma primeira tentativa

Detalhamento das subrotinas Procedure SortearNovaPosicao (var T: tabuleiro; var x,y: integer); Begin End; Repeat x:= random (max) + 1; y:= random (max) + 1; Until T[x,y] = 0;

Primeiro problema Este algoritmo pode ser ineficiente no caso da matriz estar muito cheia Qual seria uma boa alternativa? Ela existe?

Segunda tentativa Podemos manter uma lista com as posições livres? Por exemplo um vetor com pares de elementos com garantia de serem posições vazias Quais as vantagens e desvantagens?

Vantagens Facilitaria sortear as posições livres, bastaria sortear um único índice deste vetor Criar esta lista é simples, basta iniciá-la com todos os elementos da matriz original, menos as duas posições originalmemente sorteadas Mas, e para manter a lista ao longo do jogo?

Desvantagens Manter esta lista pode se tornar difícil ao longo do processo de movimentação das peças Mas ainda não sabemos como será o movimento das peças...

Decisão Por enquanto vamos usar o algoritmo com o repeat Se resolvermos alterar isto, o restante do código não deverá sofrer alterações, pois a implementação está sendo feita de maneira bastante modular

Detalhamento das subrotinas Como sortear um valor para uma nova peça? Pelas regras do jogo, os valores sorteados devem ser 2 ou 4, mas a probabilidade de sortear o 4 deve ser menor do que sortear o 2 O algoritmo seguinte é uma primeira tentativa

Detalhamento das subrotinas CONST PERCENT = 5; MAXVALORPECA = 4; Function SortearValor (MaxValor:integer ) : integer; Begin SortearValor:= 2; If random (PERCENT) = 0 then SortearValor:= MaxValor; End;

Detalhamento das subrotinas Como escolher a direção do movimento? Queremos que o usuário use as flechas do teclado, então teremos que usar a rotina readkey, da biblioteca CRT, que permite ler algo do teclado sem ter que apertar enter Definiremos os seguintes códigos: DIR=1 ; ESQ=2; CIMA=3; BAIXO=4;

Detalhamento das subrotinas Definiremos os seguintes códigos: DIR=1 ; ESQ=2; CIMA=3; BAIXO=4; Portanto, o tipodirecao pode ser Integer Usaremos, para facilidade visual, um novo comando do Pascal, o comando case

Lendo das flechas do teclado Function EscolheDirecao: integer; Var ch: char; begin ch:= readkey; case ch of #0: begin ch:= readkey; case ch of #72 : escolhedirecao:= cima; (*^*) #75 : escolhedirecao:= esq; (*<*) #77 : escolhedirecao:= dir; (*>*) #80 : escolhedirecao:= baixo; (*v*) end; end; End; End;

Revisão Voltemos ao algoritmo principal em seu estado atual Por onde continuaremos?

1 o refinamento do algoritmo Begin IniciarJogo (T,Pontos); MostrarJogoAtual (T,Pontos); While ExisteMovimento (T) do Begin Direcao:= EscolheDirecao; MovimentarPecas (T,Direcao,Pontos); InserirNovaPeca (T); MostrarJogoAtual (T,Pontos); End; End.

Revisão Falta a implementação de duas rotinas: ExisteMovimento (T) MovimentarPecas (T,Direcao,Pontos)

Detalhamento das subrotinas Como descobrir se existe movimento válido? Existe movimento válido se houver pelo menos uma casa vazia No pior caso, se a matriz estiver completamente cheia, ainda existe um movimento se houver pelo menos duas peças vizinhas de igual valor, na horizontal ou vertical

Detalhamento das subrotinas Uma implementação ingênua exige passar por toda a matriz no pior caso Uma implementação mais eficiente exigiria outras estruturas de dados: lista com as casas vazias; localização das peças vizinhas de igual valor A primeira tentativa é passar por toda a matriz

Detalhamento das subrotinas Passar por toda a matriz é simples, basta parar quando uma casa vazia for encontrada, ou quando dois vizinhos tiverem igual valor

Modificação da estrutura de dados O algoritmo seguinte mostra uma primeira tentativa para o código de testar movimentos válidos Por questões de espaço mostraremos o código com o comando for, mas pode-se usar while e parar a execução tão logo se descubra que existe um movimento

Detalhamento das subrotinas Function ExisteMovimento (var T: tabuleiro): boolean; Var i,j: integer; Begin ExisteMovimento:= false; For i:= 1 to max do For j:= 1 to max do If (T[i,j] = 0) or ExisteVizinhoIgual (T,i,j) then ExisteMovimento:= true; End;

Detalhamento das subrotinas Como fazer para saber se existe vizinho igual? O teste é mais complicado para as bordas, por isto vamos criar uma borda no tabuleiro com valores nulos e evitar uma série de testes (if's) que testam as bordas separadamente

Refinamento da estrutura de dados A nova matriz agora tem uma borda adicional, que só será utilizada pelo programador e não será exibida ao usuário tabuleiro= array [0..MAX+1,0..MAX+1] of integer; Basta agora modificar a procedure IniciarJogo

Refinamento de IniciarJogo Procedure IniciarJogo (var T: tabuleiro; var Pontos: integer); Var i,j: integer; Begin For i:= 0 to max+1 do For j:= 0 to max+1 do T[i,j]:= 0; For i:= 1 to 2 do InserirNovaPeca (T); Pontos:= 0; End;

Detalhamento das subrotinas Desta forma o processo se torna muito simples, conforme mostrado no algoritmo seguinte Este algoritmo supõe que as coordenadas da posição em questão correspondem a uma posição válida da matriz e também que a borda foi corretamente inicializada

Detalhamento das subrotinas Function ExisteVizinhoIgual (var T: tabuleiro; l,c: integer): boolean; Begin End; ExisteVizinhoIgual:= false; If (T[l+1,c] = T[l,c]) or (T[l-1,c] = T[l,c]) or (T[l,c+1] = T[l,c]) or (T[l,c-1] = T[l,c]) then ExisteVizinhoIgual:= true;

Detalhamento das subrotinas Em uma próxima aula poderemos estudar se existe uma técnica mais eficiente para este subproblema Por enquanto, só nos resta implementar uma última procedure: MovimentarPecas (T,Direcao,Pontos)