Introdução ao QBasic e Programação
Introdução ao QBasic e Programação
Computação
22 de abril de 2024
Sumário
1 Introdução 1
1.1 Conteúdo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2 Passos futuros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3 Instalando o QBasic . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.4 Um primeiro programa em QBasic . . . . . . . . . . . . . . . . . . 4
1.5 Uso do help e especificação da sintaxe . . . . . . . . . . . . . . . . 11
1.6 Comentários . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.7 Palavras-chave ou keywords . . . . . . . . . . . . . . . . . . . . . . 13
1.8 Literais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.9 Tipos de dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.10 Identificadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.11 Variáveis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.12 Constantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
1.13 Expressões . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
1.13.1 Expressões numéricas . . . . . . . . . . . . . . . . . . . . . . 17
1.13.2 Expressões de strings . . . . . . . . . . . . . . . . . . . . . . 19
1.14 Funções elementares . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
1.14.1 Funções numéricas . . . . . . . . . . . . . . . . . . . . . . . 20
1.14.2 Funções de strings . . . . . . . . . . . . . . . . . . . . . . . . 23
1.15 Entrada de dados no console . . . . . . . . . . . . . . . . . . . . . . 24
1.16 Saı́da de dados no console . . . . . . . . . . . . . . . . . . . . . . . 25
1.17 Exercı́cios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2 Controle de fluxo 29
2.1 Saltos condicionais . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
2.1.1 Instrução IF . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
2.1.2 Instrução SELECT . . . . . . . . . . . . . . . . . . . . . . . 31
2.2 Laços . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
2.2.1 Instrução FOR . . . . . . . . . . . . . . . . . . . . . . . . . . 33
2.2.2 Instrução WHILE...WEND . . . . . . . . . . . . . . . . . . 34
2.2.3 Instrução DO...LOOP . . . . . . . . . . . . . . . . . . . . . 36
2.3 Exercı́cios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
iii
3 Tipos de dados compostos 41
3.1 Estruturas compostas homogêneas . . . . . . . . . . . . . . . . . . 41
3.2 Estruturas compostas heterogêneas . . . . . . . . . . . . . . . . . . 42
3.3 Exercı́cios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
4 Funções e procedimentos 45
4.1 Funções . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
4.2 Procedimentos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
4.3 Recursividade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
4.4 Arrays como parâmetros . . . . . . . . . . . . . . . . . . . . . . . . 49
4.5 Exercı́cios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
5 Som e gráficos 51
5.1 Som . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
5.2 Gráficos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
5.2.1 Tiles and sprites . . . . . . . . . . . . . . . . . . . . . . . . . 60
5.3 Exercı́cios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
A Tabela ASCII 91
iv
Capı́tulo 1
Introdução
1
1.1 Conteúdo
O objetivo deste curso é tornar o aluno apto a resolver problemas computáveis
com o uso de uma linguagem imperativa.
Os objetivos especı́ficos são
• Tipos de dados.
• Instruções condicionais.
• Instruções de repetição.
• Recursividade.
2
1.2 Passos futuros
Uma vez que o leitor tenha completado o curso e esteja familiarizado com os
conceitos apresentados, pode abordar problemas mais avançados. Nesse caso,
outras linguagens podem ser necessárias a depender do problema a ser resolvido.
Os conceitos apresentados neste curso podem ser encontrados em qualquer lin-
guagem imperativa.
• Programação de páginas dinâmicas para a web: PHP, Python, Javascript.
• Interfaces gráficas: Visual Basic (.NET), Python com Tkinter.
• Computação gráfica: C++ com OpenGL.
• Jogos complexos: C++ com Unreal.
• Computação cientı́fica: Python, Fortran.
• Computação paralela: C++ com CUDA, OpenCL ou GLSL.
• Análises estatı́sticas: R.
A depender da aplicação, uma linguagem declarativa pode ser necessária.
• Bancos de dados: SQL.
• Programação funcional: Haskell.
• Programação lógica: Lisp, Prolog.
• Demonstração de teoremas: Coq, Isabelle, Lean.
3
online, porém, não possui todas as funcionalidades e keywords implementados,
apenas os mais simples, e portanto sua funcionalidade é limitada. A Figura 1.3
mostra uma tela de exemplo do QBJS.
Existe ainda a possibilidade de rodar o QuickBasic 4.5 online5 . Esta versão
possui compatibilidade total com o QuickBasic 4.5. O problema é a impossibi-
lidade de salvar os programas inseridos.
Todo código será mostrado em caixas com fundo azul. A saı́da resultante
será mostrada em caixas com fundo preto. Abaixo está a saı́da do programa.
Hello world !
4
É uma boa prática salvar frequentemente o código sendo desenvolvido. Isso
evita a perda do trabalho em caso de encerramento acidental do ambiente de
programação ou desligamento do computador. A Figura 1.6 mostra a janela de
diálogo usada para salvar o código fonte. Use sempre o formato de texto, para
que o código fonte possa ser lido por outros programas.
Podemos também imprimir valores numéricos, inteiros ou de ponto flutuante
(não inteiros), positivos ou negativos. Caso o número seja de ponto flutuante
com mais do que sete dı́gitos, o interpretador automaticamente adicionará o
sı́mbolo # para explicitar que o número é de dupla precisão.
PRINT 256
PRINT 3.14
PRINT -10
PRINT .00000001#
PRINT 1234.56789#
Abaixo está a saı́da gerada. Observe que os números positivos são precedidos
por um espaço em branco e os negativos por um sinal de menos. A partir daqui
omitiremos a mensagem “Press any key to continue” da saı́da do programa.
256
3.14
-10
.00000001
1234.56789
5 6 7 8 9
5
O QBasic pode ser usado como calculadora. Um programa em QBasic pode
mandar imprimir o resultado de expressões aritméticas e lógicas. Alternativa-
mente, pressione a tecla [F6] para alternar para a janela Immediate. A janela
Immediate permite a execução de uma linha de código de cada vez para fazer
cálculos e outros testes rápidos.
Operação Operador
Soma +
Subtração, menos unário -
Produto *
Divisão /
Divisão inteira \
Potenciação ^
Módulo MOD
Sinais de pontuação ( )
6
PRINT dez * pi
PRINT pi / 2
7
Figura 1.1: Tela inicial do QuickBasic 4.5.
8
Figura 1.3: Tela do QBJS.
9
Figura 1.5: Tela de saı́da do programa.
10
Abaixo está a saı́da gerada.
1000
31.415
1.57075
Operação Função
Seno SIN
Cosseno COS
Tangente TAN
Raiz quadrada SQR
Logaritmo Neperiano LOG
Sinal SGN
11
• KEYWORDS: em letras maiúsculas são mostradas as palavras-chave da lin-
guagem. Devem ser digitados exatamente como aparecem no help.
12
Ambos estão entre chaves, o que significa que é possı́vel escolher um ou o ou-
tro. Além disso, estão entre colchetes, o que significa que podem ser omitidos.
Quando a linha termina por vı́rgula, a próxima impressão será no próximo bloco
de 14 caracteres; quando termina em ponto e vı́rgula, será logo em seguida, e
quando termina sem nenhum dos dois, será na próxima linha.
1.6 Comentários
Comentários são textos ignorados pelo compilador. Dentro de um comentário é
possı́vel escrever qualquer coisa, sem risco de erros de compilação. Comentários
são importantes para documentar o código, facilitando o entendimento por ou-
tros programadores que precisem usá-lo e até mesmo para o próprio criador
do código lembrar detalhes importantes sobre seu funcionamento. Em QBasic
existem dois tipos de comentário:
13
Estruturas de decis~
ao: IF...ELSE Operadores ABS
SELECT...CASE funcionais: SIN
COS
Construç~
ao de laços: FOR...NEXT TAN
DO...LOOP ATN
WHILE...WEND LOG
EXP
Entrada e saı́da LOCATE SGN
no console: PRINT SQR
PRINT USING INT
INPUT$ RND
INKEY$
Operadores NOT
Entrada e saı́da OPEN lógicos: AND
em arquivo: WRITE # OR
INPUT # XOR
EQV
Entrada e saı́da SCREEN IMP
gráfica: DRAW
COLOR Funç~
oes de ASC
PALETTE string: CHR$
LINE LEN
CIRCLE LEFT$
PSET MID$
RIGHT$
Saı́da de áudio: BEEP VAL
PLAY STR$
1.8 Literais
Literais são valores que ocorrem no programa. Podem ser de diversos tipos.
Números inteiros: 0
-1
333
Números reais: 2.0
3.1415
-1000.0
Strings: "Hello world"
"bom dia"
"Idade = 22 anos"
14
1.9 Tipos de dados
O QBasic suporta cinco tipos de dados primitivos. São usados para declarar
explicitamente o tipo das variáveis. Suporta ainda um tipo user-defined que é
uma composição de tipos primitivos usados como campos de um registro. Outro
tipo de dado composto é o vetor ou matriz, que armazena valores de um mesmo
tipo indexados, ou seja, acessı́veis através de um ı́ndice inteiro.
1.10 Identificadores
Identificadores são os nomes de variáveis, funções, constantes e outros objetos
criados pelo usuário. É uma sequência de caracteres tal que
• Possui de um a 40 caracteres
• O primeiro caractere pode ser letra
• Os demais caracteres podem ser letras ou dı́gitos.
• Não pode ser igual a nenhuma palavra reservada.
• Pode terminar em um sufixo de tipo como da Tabela 1.3.
• Exemplos:
1.11 Variáveis
Variáveis são posições de memória com um nome, usadas para armazenar va-
lores. Os valores armazenados podem ser modificados a qualquer momento.
O nome de uma variável deve ser um identificador válido, como descrito na
Seção 1.10. Sua declaração e inicialização devem aparecer no código antes de
seu primeiro uso.
15
• A declaração de uma variável é onde definimos seu tipo e seu identificador,
isto é, seu nome.
Variáveis numéricas não inicializadas possuem valor igual a zero e strings não
inicializadas são vazias. A declaração de uma variável possui a sintaxe abaixo.
DIM variable [ AS type ]
16
1.12 Constantes
Como variáveis, constantes são posições de memória que armazenam algum
valor. Porém ao contrário de variáveis, o valor não pode ser modificado. A
declaração de uma constante possui a sintaxe abaixo.
CONST constant_name = expression
1.13 Expressões
Expressões podem ser numéricas ou strings. Expressões numéricas por sua vez
podem ser aritméticas ou lógicas.
17
Expressões numéricas compostas são uma concatenação de operadores e ope-
randos. Os operandos podem ser expressões primitivas ou outras expressões
compostas. Os operadores podem ser aritméticos, de comparação ou lógicos.
Expressões numéricas retornam algum valor numérico. Expressões aritméticas
são o resultado de operações aritméticas. Expressões lógicas são o resultado de
comparações ou de operações Booleanas. Seu resultado também é numérico mas
é interpretado como verdadeiro ou falso. Em QBasic não há um tipo Booleano
nativo, então o 0 é interpretado como falso e -1 como verdadeiro.
Operadores podem ser unários ou binários. Operadores unários operam so-
bre um operando, enquanto os binários operam sobre dois. Abaixo está a sintaxe
de expressões numéricas compostas.
expression binary_operator expression
unary_operator expression
18
a = 2 * 3 + 1;
b = 1 + 2 * 3;
c = 10 / 2 * 5;
d = 10 MOD 3;
e = 2 * 10 MOD 4;
f = 3 * (2 + 1) ;
19
O código abaixo mostra a declaração de uma variável e de uma constante.
Em seguida mostra exemplos de instruções PRINT imprimindo o resultado de
expressões com strings.
CONST a = " aaa " ’ Declaracao de constante
b = " bbb " ’ Declaracao de variavel
’ Abaixo as expressoes sucedem o PRINT
PRINT " Hi " ’ Expressao com literal
PRINT CHR$ (65) ’ Funcao que retorna valor
PRINT b ’ Expressao com variavel
PRINT a ’ Expressao com constante
PRINT a + b ’ Expressao com concatenacao
PRINT a <= b ’ Expressao comparacao
20
Tabela 1.4: Funções numéricas do QBasic
Operação Função
Seno SIN
Cosseno COS
Tangente TAN
Arco tangente ATN
Raiz quadrada SQR
Logaritmo Neperiano LOG
Exponencial Neperiana EXP
Sinal SGN
Valor absoluto ABS
Truncar FIX
Piso (floor) INT
Arredondar CINT
Arredondar para LONG CLNG
Converte para SINGLE CSNG
Converte para DOUBLE CDBL
String para número VAL
Código ASCII do caractere ASC
Segundos desde meia-noite TIMER
Gera número aleatório RND
Altera random seed RANDOMIZE
As funções LOG e EXP possuem a sintaxe abaixo. A função LOG retorna o lo-
garitmo natural, i.e., logaritmo Neperiano, do parâmetro numeric_expression.
O parâmetro deve ser maior que zero. A função EXP retorna o valor da função
exponencial natural, i.e., o número de Euler elevado ao valor do parâmetro
numeric_expression.
LOG ( nu me ri c_ exp re ss io n )
EXP ( nu me ri c_ exp re ss io n )
As funções FIX, INT, CINT, CLNG, CSNG e CDBL possuem a sintaxe abaixo.
A função FIX retorna a parte inteira do parâmetro numeric_expression. A
21
função INT retorna o piso (floor) de numeric_expression, ou seja, o maior
inteiro menor que o parâmetro. As funções CINT e CLNG arredondam o valor de
numeric_expression retornando respectivamente um INTEGER e um LONG. As
funções CSNG e CLNG convertem o valor de numeric_expression para os tipos
SINGLE e DOUBLE respectivamente.
FIX ( nu me ri c_ exp re ss io n )
INT ( nu me ri c_ exp re ss io n )
CINT ( num er ic _e xp re ss io n )
CLNG ( num er ic _e xp re ss io n )
CSNG ( num er ic _e xp re ss io n )
CDBL ( num er ic _e xp re ss io n )
As funções VAL e ASC são ditas numéricas pois retornam valores numéricos.
Também são funções de processamento de strings pois recebem uma string como
parâmetro. A função VAL retorna o valor numérico representado no parãmetro
string_expression. A função ASC retorna o valor ASCII do primeiro caractere
de string_expression. O Apêndice A lista os valores ASCII dos caracteres.
VAL ( s tring_ expres sion )
ASC ( s tring_ expres sion )
22
1.14.2 Funções de strings
As funções de strings retornam uma string como resultado. Podem ser usadas
para compor expressões de strings. A Tabela 1.5 lista as funções de strings
descritas nesta seção.
Operação Função
Número para string STR$
Número para hexadecimal HEX$
Número para octal OCT$
Caractere do código ASCII CHR$
Caracteres à esquerda LEFT$
Caracteres à direita RIGHT$
Caracteres do meio MID$
String com n espaços SPACE$
String com n caracteres STRING$
As funções STR$, HEX$, OCT$e CHR$ são ditas de strings pois retornam strings
como resultado. A função STR$ converte o valor numérico de numeric_expression
para sua representação em forma de string. A função HEX$ converte o valor
numérico para uma string com sua representação em hexadecimal e OCT$ para
sua representação em octal. Já a função CHR$ retorna o caractere ASCII cor-
respondente ao valor do parâmetro numeric_expression. O Apêndice A lista
os valores ASCII dos caracteres.
STR$ ( nu me ri c_ ex pr es si on )
HEX$ ( nu me ri c_ ex pr es si on )
OCT$ ( nu me ri c_ ex pr es si on )
CHR$ ( nu me ri c_ ex pr es si on )
23
STRING, será usado seu primeiro caractere; se for número, será usado o caractere
com o código ASCII correspondente. O n é expressão numérica. No Apêncide A
há uma tabela ASCII.
SPACE$ ( n )
STRING$ (n , expression )
24
1.16 Saı́da de dados no console
Nesta seção descrevemos algumas funções úteis para saı́da de dados formatada
no console. A Tabela 1.6 lista as funções descritas nesta seção.
Operação Função
Tabulação TAB
Espaçamento SPC
Linha atual do cursor CSRLIN
Coluna atual do cursor POS
Posiciona o cursor LOCATE
Impressão formatada PRINT USING
25
1.17 Exercı́cios
1. Crie um programa e dentro dele declare as seguintes variáveis
(a) 2.
(b) 3.
(c) 4.
(d) 5.
(a) 2.
(b) 3.
(c) 4.
(d) 5.
26
6. Crie um programa que calcule e imprima a área das figuras planas especi-
ficadas. Para um paralelogramo com lados 10 e 4, com ângulo de 60 graus
entre eles, por exemplo:
pi = 3.141592#
l1 = 10
l2 = 4
deg = 60
h = l2 * SIN ( deg * pi / 180)
area = l1 * h
PRINT " area = " ; area
area = 20
27
(f) uma viga de 4 × 9 cm e comprimento de 4 m.
(g) um tarugo com diâmetro de 15 mm e comprimento de 60 cm.
9. Considere os vetores v = (2, 2, 0) e w = (3, −3, 0). Crie um programa que
calcule e imprima
(a) o vetor v + w.
(b) o vetor v − w.
(c) a norma de v.
(d) a norma de w.
(e) o coeficiente angular de v, i.e. o ângulo formado entre o vetor e o
eixo x.
(f) o coeficiente angular de w.
(g) o produto escalar de v por w.
(h) o produto vetorial de v por w.
28
Capı́tulo 2
Controle de fluxo
2.1.1 Instrução IF
A sintaxe do salto condicional com as instruções IF...THEN...END IF é a seguinte:
IF b oo le an _e xp re ss io n THEN
[ block_then ]
END IF
29
Caso boolean_expression retorne um valor verdadeiro, o bloco de ins-
truções block_then é executado. Abaixo está um exemplo de uso de salto
condicional. O programa solicita ao usuário que insira sua idade. Caso ela seja
menor que zero, a mensagem de aviso é impressa na tela.
INPUT " Digite sua idade : " , idade &
IF idade & < 0 THEN
PRINT " Aviso : sua idade deve ser >= 0. "
END IF
30
Outro formato do salto condicional permite o teste de várias condições. Isso
é feito com a instrução ELSEIF.
IF b o o l e a n _ e x p r e s s i o n _ 1 THEN
[ block_1 ]
[ ELSEIF b o o l e a n _ e x p r e s s i o n _ 2 THEN
[ block_2 ]]
...
[ ELSE
[ block_else ]]
END IF
31
A expressão test_expression pode ter tipo numérico ou string. Cada uma
das expression_list é uma lista de uma ou mais expressões de mesmo tipo
que test_expression separadas por vı́rgula. Caso o valor de test_expression
corresponda ao valor de uma das expression_list, o bloco de instruções cor-
respondente é executado. Caso não corresponda, block_else é executado. As
expressões devem possuir a sintaxe abaixo.
32
2.2 Laços
Um laço é uma instrução que executa um bloco repetidas vezes. É possı́vel exe-
cutar um bloco um número predefinido de vezes ou enquanto alguma condição
seja satisfeita.
O laço FOR inicializa counter com valor igual a start. A cada execução
de block, counter por padrão é incrementado de 1. O laço termina quando
counter atinge o valor de end. Caso a instrução opcional STEP seja usada, o
incremento ao invés de 1 é dado por increment. O incremento pode também
ser negativo, mas nesse caso, end precisa ser menor que start.
O exemplo abaixo imprime os inteiros de 1 a 10.
FOR i = 1 TO 10
print i
NEXT i
33
s = 0
FOR i = 1 TO 10
s = s + i
NEXT i
PRINT " A somatoria eh " , s
34
Abaixo está o exemplo que calcula a soma dos inteiros de 1 a 10.
s = 0
i = 1 ’ Inicializacao
WHILE i <= 10
s = s + i
i = i + 1 ’ Incremento
WEND
PRINT s
∞
1
∑ i
=2
i=0 2
35
2.2.3 Instrução DO...LOOP
A instrução DO...LOOP é ainda mais flexı́vel que WHILE...WEND. Ela permite que o
teste da condição de continuidade seja feito no inı́cio ou no final do laço. Sua
sintaxe equivalente a WHILE...WEND é a seguinte:
DO WHILE condition
[ block ]
LOOP
Esta última sintaxe pode ser conveniente quando precisamos que o laço seja
executado ao menos uma vez. No último exemplo visto, é possı́vel observar
que o cálculo de parcela ocorre em duas linhas de código diferentes. Pode ser
interessante eliminar essa redundância para evitar inconsistências e erros. Isso
é possı́vel se deixarmos para testar a condição no final do laço.
36
epsilon = 10 ^ -20
s# = 0
i = 0 ’ Inicializacao
DO
parcela = 1 / 2 ^ i
s # = s # + parcela
PRINT i , parcela , s #
i = i + 1 ’ Incremento
LOOP WHILE parcela > epsilon
PRINT i , parcela
37
2.3 Exercı́cios
1. Crie um programa que calcula com um laço o produtório abaixo para
n = 10.
(a)
n
∏ i = n!
i=1
(c)
n
∑ 2i − 1 = n
2
i=1
(d)
n
∑2 = 2 −1
i n+1
i=0
(e)
n
1
∑ i = n(n + 1)(2n + 1)
2
i=1 6
(f)
2
n
n(n + 1)
∑i = ( )
3
i=1 2
(g)
n
i n
∑ =
i=1 i + 1 n+1
(h)
n
n(3n − 1)
∑ 3i − 2 =
i=1 2
(i)
n
n(10 + 2(n − 1))
∑ 5 + 2(i − 1) =
i=1 2
38
(j)
n
∑ i(2)
i−1
= 1 + (n − 1)2n
i=1
(k)
n
1
lim ∑ =e
n→∞
k=0 k!
(l)
n
(−1)k π
lim ∑ =
k=0 2k + 1 4
n→∞
(m)
m n
mn(m + 1)(n + 1)
∑ ∑ ij =
i=1 j=1 4
(b)
∞
1
∑ i
i=0 2
6. Crie um programa que calcula as séries da questão anterior enquanto a
parcela é maior que 10− 3.
7. Uma relação de recorrência é uma equação segundo a qual o n-ésimo termo
de uma sequência é dado por alguma combinação dos termos anteriores.
O método de Newton é um exemplo de relação de recorrência.
f (xn )
xn+1 = xn −
f ′ (xn )
39
(a)
∞
2k 2k 224466 π
∏( )= =
k=1 2k − 1 2k + 1 133557 4
9. O número de combinações de n itens k a k é dado pela equação abaixo.
n n!
( )=
k k!(n − k)!
10. Crie um programa que testa se um certo n é primo. Use um laço para
testar se os inteiros menores que n o dividem.
(a) Teste para n = 101.
(b) Solicite para o usuário que insira algum valor de n.
(c) Teste para n variando de 2 a 1000 e imprima o total de números
primos encontrados.
(d) Teste para n variando de 3 a 9999 pulando os pares e imprima o total
de números primos encontrados.
40
Capı́tulo 3
Nem todos os problemas podem ser resolvidos com variáveis simples como as
primitivas já vistas. Bancos de dados requerem o uso de registros com cam-
pos diferentes para armazenar por exemplo o nome, endereço, estado civil etc
de cada cliente. Problemas que envolvem matrizes, vetores, listas e sequências
requerem o uso de estruturas indexadas, ou seja, que permitam acessar compo-
nentes individuais através de ı́ndices inteiros. Neste capı́tulo veremos como criar,
modificar e consultar estruturas com tipos de dados compostos, que podem ser
homogêneas, compostas por itens de mesmo tipo, ou heterogêneas, compostas
por itens de tipos diferentes.
41
novos valores de lower e upper devem ser adicionados separados por vı́rgula
dentro dos parênteses. Abaixo estão exemplos de declarações de arrays.
DIM array (1 TO 3) AS DOUBLE ’ Vetor com tres posicoes
DIM matrix (2 , 4) AS SINGLE ’ Matriz 3 x5
DIM mat3 (4 , 5 , 6) AS LONG ’ Volume tridimensional
42
TYPE user_type
item_name as item_type
[ item_name as item_type ]
...
END TYPE
O nome do tipo de dados é dado por user_type. O nome dos itens indi-
viduais é dado por cada um dos item_name. Os tipos permitidos são os tipos
de dados primitivos ou algum outro tipo definido pelo usuário. Quando o tipo
é STRING, sua definição é feita com STRING * n onde n é o tamanho máximo
permitido da STRING. Abaixo está o exemplo de criação de dois tipos de registro
diferentes.
TYPE Date
day AS INTEGER
month AS INTEGER
year AS INTEGER
END TYPE
TYPE Customer
cname AS STRING * 10
address AS STRING * 20
city AS STRING * 10
state AS STRING * 2
birth AS Date
END TYPE
43
DIM arrEntry (10) AS Customer
arrEntry (0) = entry
DIM e AS Customer
e = arrEntry (0)
3.3 Exercı́cios
1. Crie um tipo de dados chamado TAluno com os seguintes campos: id com
tipo LONG, nome com tipo STRING de tamanho 20, matricula com tipo
string de tamanho 12, e os campos dianasc, mesnasc e anonasc com tipo
INTEGER. Com esse tipo de dados
(a) crie uma variável chamada umAluno de tipo TAluno.
(b) crie um array chamado arrAluno com ı́ndices de 1 a 10 e de tipo
TAluno.
(c) crie um laço que solicita ao usuário que preencha o vetor arrAluno.
O laço é interrompido quando algum aluno tiver nome vazio.
2. Crie um programa que aloca um array com tamanho 4×10. Use o array
para armazenar os valores abaixo considerando x variando de 1 a 10.
44
Capı́tulo 4
Funções e procedimentos
4.1 Funções
Funções são blocos de instruções que executam uma certa tarefa. Recebem
parâmetros de entrada, retornam dados de saı́da e sua chamada pode ser usada
em expressões.
Podemos dizer que a definição de uma função tem quatro partes: identifi-
cador ou nome, lista de parâmetros, bloco de instruções e valor de retorno. A
sintaxe de uma definição de função é a seguinde:
FUNCTION name [( parameter_list ) ][ STATIC ]
[ statements ]
name = expression
[ statements ]
END FUNCTION
45
O nome da função é dado por name. A função retorna um valor através da
atribuição do valor de uma expressão ao nome da função. O uso do keyword
opcional STATIC faz com que os valores das variáveis da função sejam mantidos
entre as chamadas. Os parâmetros são passados por referência, ou seja, se
forem modificados dentro da função, serão modificados também fora do escopo
da função. A lista parameter list possui a sintaxe abaixo:
variable [ AS type ][ , variable [ AS type ]]...
Para chamar uma função, é preciso criar uma expressão onde seu nome
precede a lista de parâmetros entre parênteses. Os parâmetros também são
expressões, e podem ser literais, variáveis, operações com outras expressões ou
até mesmo chamadas a outras funções.
46
v = 5
PRINT fatorial (4) ’ Parametro como literal
PRINT fatorial ( v ) ’ Parametro como variavel
PRINT fatorial ( v + 1) ’ Parametro como expressao
PRINT fatorial ( SQR (16) ) ’ Parametro como chamada
result1 = fatorial ( v + 2) ’ Resultado em atribuicao
result2 = 3 * fatorial ( v ) ’ Resultado em expressao
4.2 Procedimentos
Procedimentos são também chamados subrotinas. Os procedimentos, assim
como funções, são blocos de instruções e recebem parâmetros de entrada. Ao
contrário das funções, porém, não retornam dados de saı́da e sua chamada não
pode ser usada em expressões.
A definição de um procedimento é praticamente igual à de uma função. As
diferenças estão no uso da palavra chave SUB e na ausência de atribuição de um
valor de retorno. A sintaxe de uma definição de procedimento é a seguinde:
SUM name [( parameter_list ) ][ STATIC ]
[ statements ]
END SUB
Uma chamada a subrotina não pode fazer parte de uma expressão. A sintaxe
da chamada a uma subrotina é a seguinte
CALL name ( parameter_list )
47
Outro possı́vel uso de um procedimento é quando precisamos retornar vários
valores simultaneamente. Nesse caso, os valores de retorno são passados como
parâmetros e são modificados dentro do procedimento. Abaixo está um exemplo
de procedimento que calcula a soma de dois vetores bidimensionais e retorna os
valores dos dois componentes de saida como s1 e s2.
SUB somaV2 ( a1 , a2 , b1 , b2 , s1 , s2 )
s1 = a1 + b1
s2 = a2 + b2
END SUB
4.3 Recursividade
Uma função recursiva é uma função que chama a si mesma. Toda recursão
precisa ter uma base, ou seja, um caso de parada. Considere a definição do
fatorial. O fatorial pode ser definido como na equação abaixo.
n
n! = ∏ i
i=1
⎧
⎪
⎪(n − 1)! se n > 1
n! = ⎨
⎪
⎪1 se n ≤ 1
⎩
Quando n > 1 a função chama ela mesma passando como parâmetro n − 1. O
caso base desta recursão é o caso em que n ≤ 1. Quando o parâmetro de entrada
n é igual a 1 por exemplo, a função retorna sem fazer chamadas adicionais.
Abaixo está um exemplo de uma função recursiva que calcula o fatorial de n.
48
FUNCTION fatorial ( n )
IF n <= 1 THEN
fatorial = 1
ELSE
fatorial = n * fatorial ( n - 1)
END IF
END FUNCTION
4.5 Exercı́cios
1. A sequência de Fibonacci é definida pela relação de recorrência abaixo.
⎧
⎪F0 = 0
⎪
⎪
⎪
⎨F1 = 1
⎪
⎪
⎪
⎪
⎩Fn = Fn−1 + Fn−2 se n > 1
Crie um programa que pede ao usuário um valor de n e calcula a sequência
de Fibonacci de F0 até Fn usando uma função recursiva.
49
2. Para cada série das questões 3 e 5 do capı́tulo anterior, escreva uma função
que recebe n como parâmetro e que calcula a somatória até n
(a) de maneira iterativa, ou seja, com um laço.
(b) de maneira recursiva, ou seja, chamando a própria função.
3. Crie a função
(a) logab(a, b) que calcula e retorna loga b.
(b) atan2(x, y) que calcula e retorna o arco tangente do ângulo formado
pelo vetor (x, y) e o eixo x. O resultado deve estar no intervalo
(−π, π].
4. Considere que os vetores abaixo são arrays com duas posições. Crie uma
função
(a) norma(v) que retorna a norma de v.
(b) ang(v) que retorna o coeficiente angular de v.
(c) soma(v, w) que retorna a soma de v e w.
(d) prodEsc(v, w) que retorna o produto escalar entre v e w.
v⋅w
(e) proj(v, w) que retorna a projeção de v sobre w, ou seja, w⋅w
w.
5. Considere que os números complexos abaixo são representados como ar-
rays com duas posições. Crie uma função
50
Capı́tulo 5
Som e gráficos
Neste capı́tulo veremos como usar o QBasic para produzir sons e saı́da gráfica.
5.1 Som
Nesta seção descrevemos algumas instruções que podem ser usadas para gerar
sons no QBasic. A Tabela 5.1 lista as funções descritas nesta seção. As funções
iniciadas com sublinhado são exclusivas do QB64.
Operação Função
Emite som de bipe BEEP
Som com certa frequência e duração SOUND
Notas definidas em string PLAY
Abre arquivo com som _SndOpen
Toca som salvo em variável _SndPlay
Toca som gerado por função _SndRaw
Pausa _Delay
O código abaixo emite um bipe, que pode ser usado para alertar o usuário.
BEEP
51
O código abaixo toca duas vezes o primeiro compasso do Prelúdio em Dó
Maior de Bach.
c = 262 ’ C4
r1 = 1.26 ’ terca
r2 = 1.5 ’ quinta
r = 2 ’ oitava acima
t = 3 ’ 3/18 segundos
FOR i = 1 TO 4
SOUND c , t ’ C4
SOUND c * r1 , t ’ E4
SOUND c * r2 , t ’ G4
SOUND c * r , t ’ C5
SOUND c * r * r1 , t ’ E5
SOUND c * r2 , t ’ G4
SOUND c * r , t ’ C5
SOUND c * r * r1 , t ’ E5
NEXT i
52
Tabela 5.2: Comandos musicais para a instrução PLAY.
Descrição Comando
Especifica oitava (n = 0-6) On
Desce uma oitava <
Sobe uma oitava >
Toca notas (A = Lá, B = Si,...,G = Sol) A-G
Sustenido +
Bemol -
Toca notas (n = 0-84) Nn
Quartos de nota por minuto (n = 32-255, padrão = 120) Tn
Define duração (n = 1-64, duração = 1/n) Ln
Duração de 3/4 da definida por L MS
Duração de 7/8 da definida por L MN
Retorna à duração definida por L ML
Pausa de n quartos de nota (n = 1-64) Pn
Toca música em foreground MF
Toca música em background MB
53
são exclusivas do QB64. A instrução SndOpen carrega o sinal de áudio de um
arquivo e o retorna para que seja armazenado em uma variável. A instrução
SndPlay toca o som armazenado na variável.
variable = _SndOpen ( filename )
_SndPlay variable
bpm = 120
beat = 60.0 / 120
Print " BPM = " ; bpm ; " beat = " ; beat * 1000; " ms "
For i = 1 To 4
_SndPlay kick &
_Delay beat / 2
_SndPlay hihat &
_Delay beat / 2
_SndPlay snare &
_Delay beat / 2
_SndPlay hihat &
_Delay beat / 2
Next i
54
Abaixo está um exemplo de uso da instrução SndRaw. O código gera uma
onda senoidal multiplicada por um envelope exponencial que causa um decai-
mento na amplitude do sinal ao longo do tempo.
FREQ = 440 ’ frequencia de 36 a 10 ,000
Pi2 = 8 * Atn (1) ’2 * pi
Amplitude = .3 ’ 30% da amplitude maxima
SampleRate = _SndRate ’ define sample rate
FRate = FREQ / SampleRate ’ periodo em segundos
FPeriod = SampleRate / FREQ ’ amostras por periodo
Print " SndRate = " ; _SndRate
Print " FRate = " ; FRate
Print " FPeriod = " ; FPeriod
5.2 Gráficos
Nesta seção descrevemos algumas instruções que podem ser usadas para gerar
saı́da gráfica no QBasic. A Tabela 5.4 lista as funções descritas nesta seção. As
funções iniciadas com sublinhado são exclusivas do QB64.
Operação Função
Ativa modo gráfico SCREEN
Define tamanho da fonte WIDTH
Desenha ponto na tela PSET
Desenha cı́rculo CIRCLE
Desenha linha ou retângulo LINE
Muda paleta de cores PALETTE
55
WIDTH. A Tabela 5.5 mostra os valores possı́veis de colunas e linhas que podem
ser passados como parâmetro para WIDTH. Caso um número não permitido de
colunas ou linhas seja usado, uma mensagem de erro Illegal function call será
mostrada. O QB64 é mais flexı́vel e permite valores que o QuickBasic 4.5 não
permite. A instrução COLOR muda a cor do texto e do fundo. O modo gráfico 12
permite 16 cores e o modo 13 permite 256. Abaixo está a sintaxe das instruções
SCREEN, WIDTH e COLOR.
SCREEN mode
WIDTH [ columns ][ , lines ]
COLOR [ foreground ][ , background ]
56
O código abaixo pode ser usado para visualizar as cores do modo gráfico 12.
A Figura 5.1 mostra a saı́da resultante.
Screen 12
For i = 0 To 15
Locate i + 1 , 1
c = i
If i <= 1 Then
Color 15 , c
Else
Color 0 , c
End If
Print Using " ## " ; Spc (39) , c , Spc (39) ;
Next
O código abaixo pode ser usado para visualizar as cores do modo gráfico 13.
A Figura 5.2 mostra a saı́da resultante.
Screen 13
For j = 0 To 15
For i = 0 To 15
Locate ( i + 1) , (2 * j + 1)
c = i * 16 + j
If c <= 1 Or c >= 104 Or ( c >= 16 And c <= 23)
Then
Color 15 , c
Else
Color 0 , c
End If
If c < 16 Then
Print " 0 " ;
End If
Print Hex$ ( c )
Next
Next
57
Figura 5.2: Cores do modo gráfico 13.
A instrução PALETTE pode ser usada para modificar as cores nos modos
gráficos. O parâmetro color é um inteiro de 0 a 15 no modo 12 ou um inteiro
de 0 a 255 no modo 13. Os parâmetros red, green e blue são inteiros de 0 a
63. Quando os três valores são iguais, a cor obtida é um tom de cinza.
PALETTE [ color , red + ( green * 2^8) + ( blue * 2^16) ]
58
Abaixo está um exemplo de uso de PALETTE e COLOR. O código abaixo pre-
enche a tela com caracteres em posições e cores aleatórias.
Screen 12
nRow = 30 ’ 30 or 60
Width 80 , nRow
For n = 1 To 15
Palette n , 0 + (4 * n * 256) + (0 * 65536)
Next n
For n = 1 To 10001
i = Int ( Rnd * ( nRow - 1) ) + 1
j = Int ( Rnd * 80) + 1
f = Int ( Rnd * 16)
b = Int ( Rnd * 16)
c = Int ( Rnd * 93) + 33
Locate i , j
Color f , b
Print Chr$ ( c ) ;
_Delay 0.001
Next n
For n = 1 To 15
Palette n , (4 * n ) + (4 * n * 256) + ((63 - 4 * n )
* 65536)
Next n
w = 640
h = 480
For n = 1 To 10001
x0 = Int ( Rnd * w )
y0 = Int ( Rnd * h )
x1 = Int ( Rnd * w )
y1 = Int ( Rnd * h )
f = Int ( Rnd * 16)
Line ( x0 , y0 ) -( x1 , y1 ) , f ’[ ,{ B | BF }]
_Delay 0.001
Next n
59
O código abaixo desenha faixas coloridas na tela. O modo gráfico é o 13,
que possui 256 cores. As 16 primeiras são as mesmas do modo gráfico 12. A
seguir temos 16 escalas de cinza e 24 cores do arco-ı́ris saturadas, ou seja, sem
mistura com branco ou preto. As demais são variações não saturadas das cores
do arco-ı́ris. A variável c é usada para armazenar a cor, que irá variar de 16
a 55. A instrução LINE desenha faixas no canto superior esquerdo da tela. A
instrução CIRCLE desenha os arcos no canto inferior direito. Observe que a
instrução CIRCLE está repetida com um raio 0.5 pixels maior que na instrução
anterior para evitar falhas, que aparecem como pixels pretos, no preenchimento
dos arcos.
Screen 13
For i = 0 To 39
c = i + 16
Line (0 , 100 + i ) -(100 + i , 0) , c
Circle (320 , 200) , 100 + i , c
Circle (320 , 200) , 100.5 + i , c
Next i
A Figura 5.3 mostra exemplos de sprites que podem ser usadas lado a lado
para preencher uma cena1 . A Figura 5.4 mostra exemplos de jogos bidimensio-
nais para PC. A Figura 5.5 mostra outros exemplos de jogos bidimensionais.
1 [Link]
60
Figura 5.3: Exemplos de pixel art. Fonte: Shutterstock.
61
O código abaixo desenha quatro sprites diferentes com 16×16 pixels, os salva
em um vetor e os desenha na tela repetidamente.
Screen 13
scW = 320 ’ Screen width
scH = 200 ’ Screen height
W = 16 ’ Sprite width
H = 16 ’ Sprite height
spOffset = W * H / 2 + 2
spN = 4
Dim arrSprite ( spN * spOffset ) As Integer
62
For x = 0 To Int ( scW / W ) - 1
For y = 0 To Int ( scH / H ) - 1
spId = Int ( spN * y / ( scH / H - 1) )
Put ( x * W , y * H ) , arrSprite ( spId * spOffset ) ,
PSet
Next y
Next x
Figura 5.6: Tela de saı́da com sprites definidas com figuras geométricas, como
segmentos de reta, retângulos, cı́rculos e arcos de cı́rculo.
63
Data 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,01
Data 01 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02
Data 01 ,02 ,06 ,03 ,06 ,06 ,05 ,06 ,06 ,06 ,07 ,06 ,06 ,06 ,05 ,06 ,06 ,03 ,06 ,02
Data 01 ,02 ,03 ,03 ,03 ,04 ,06 ,06 ,06 ,07 ,08 ,07 ,06 ,06 ,06 ,04 ,03 ,03 ,03 ,02
Data 01 ,02 ,06 ,03 ,04 ,04 ,06 ,06 ,07 ,08 ,09 ,08 ,07 ,06 ,06 ,04 ,04 ,03 ,06 ,02
Data 01 ,02 ,06 ,04 ,04 ,04 ,06 ,07 ,08 ,09 ,10 ,09 ,08 ,07 ,06 ,04 ,04 ,04 ,06 ,02
Data 01 ,02 ,06 ,06 ,06 ,06 ,07 ,08 ,09 ,10 ,11 ,10 ,09 ,08 ,07 ,06 ,06 ,06 ,05 ,02
Data 01 ,02 ,06 ,06 ,06 ,07 ,08 ,09 ,10 ,11 ,12 ,11 ,10 ,09 ,08 ,07 ,06 ,06 ,06 ,02
Data 01 ,02 ,06 ,06 ,07 ,08 ,09 ,10 ,11 ,12 ,13 ,12 ,11 ,10 ,09 ,08 ,07 ,06 ,06 ,02
Data 01 ,02 ,06 ,07 ,08 ,09 ,10 ,11 ,12 ,13 ,14 ,13 ,12 ,11 ,10 ,09 ,08 ,07 ,06 ,02
Data 01 ,02 ,07 ,08 ,09 ,10 ,11 ,12 ,13 ,14 ,15 ,14 ,13 ,12 ,11 ,10 ,09 ,08 ,07 ,02
Data 01 ,02 ,06 ,07 ,08 ,09 ,10 ,11 ,12 ,13 ,14 ,13 ,12 ,11 ,10 ,09 ,08 ,07 ,06 ,02
Data 01 ,02 ,06 ,06 ,07 ,08 ,09 ,10 ,11 ,12 ,13 ,12 ,11 ,10 ,09 ,08 ,07 ,06 ,06 ,02
Data 01 ,02 ,06 ,06 ,06 ,07 ,08 ,09 ,10 ,11 ,12 ,11 ,10 ,09 ,08 ,07 ,06 ,06 ,06 ,02
Data 01 ,02 ,06 ,06 ,06 ,06 ,07 ,08 ,09 ,10 ,11 ,10 ,09 ,08 ,07 ,06 ,06 ,06 ,05 ,02
Data 01 ,02 ,06 ,04 ,04 ,04 ,06 ,07 ,08 ,09 ,10 ,09 ,08 ,07 ,06 ,04 ,04 ,04 ,06 ,02
Data 01 ,02 ,06 ,03 ,04 ,04 ,06 ,06 ,07 ,08 ,09 ,08 ,07 ,06 ,06 ,04 ,04 ,03 ,06 ,02
Data 01 ,02 ,03 ,03 ,03 ,04 ,06 ,06 ,06 ,07 ,08 ,07 ,06 ,06 ,06 ,04 ,03 ,03 ,03 ,02
Data 01 ,02 ,06 ,03 ,06 ,06 ,05 ,06 ,06 ,06 ,07 ,06 ,06 ,06 ,05 ,06 ,06 ,03 ,06 ,02
Data 01 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02
Os laços abaixo preenchem a tela com tantas cópias do sprite quanto ne-
cessário.
For X = 0 To scW \ spW - 1
For Y = 0 To scH \ spH - 1
Call spDraw ( arrSprite () , X * spW , Y * spH )
Next Y
Next X
64
A função abaixo faz a leitura dos pixels do sprite armazenados nas instruções
DATA e os transfere para o vetor arrSprite.
Sub spRead ( arrSprite () As Integer , spW , spH )
For Y = 0 To spH - 1 ’ For each row
For X = 0 To spW - 1 ’ For each column
Read DotColor
PSet (X , Y ) , DotColor
Next X
Next Y
Get (0 , 0) -( spW - 1 , spH - 1) , arrSprite (0)
End Sub
Figura 5.7: Tela de saı́da com sprites definidas com DATA e sorteio de cores.
65
Abaixo são definidos 13 sprites com Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
16×16 pixels cada. A variável nSprite Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
armazena o número de sprites, a vari- Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,00 ,00 ,00
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,00 ,10 ,10 ,10
vel spW armazena a largura em pixels Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,00 ,10 ,10 ,10 ,10
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,10 ,10 ,10 ,10 ,10
de cada sprite, spH armazena a altura e Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,00 ,00 ,10 ,10 ,10 ,10 ,10
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,00 ,10 ,10 ,10 ,10 ,10 ,10 ,10
spOffset armazena o espaço necessário Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,00 ,10 ,10 ,10 ,10 ,10 ,10 ,10
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,00 ,10 ,10 ,10 ,10 ,10 ,10
em um array de inteiros para armaze- spBuTM = 6
Data 09 ,09 ,09 ,09 ,09 ,09 ,00 ,00 ,00 ,00 ,09 ,09 ,09 ,09 ,09 ,09
nar cada sprite. Data 09 ,09 ,09 ,09 ,09 ,00 ,10 ,10 ,10 ,10 ,00 ,09 ,09 ,09 ,09 ,09
Data 09 ,09 ,09 ,00 ,00 ,10 ,10 ,10 ,10 ,10 ,10 ,00 ,09 ,09 ,09 ,09
Screen 13 Data 09 ,09 ,00 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,00 ,09 ,00 ,09 ,09
Data 09 ,09 ,00 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,00 ,10 ,00 ,09
spSky = 1 Data 09 ,09 ,00 ,10 ,10 ,10 ,10 ,10 ,10 ,02 ,10 ,10 ,10 ,10 ,10 ,00
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 Data 09 ,00 ,10 ,10 ,10 ,02 ,02 ,10 ,10 ,10 ,02 ,10 ,10 ,10 ,10 ,00
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 Data 00 ,10 ,10 ,10 ,02 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,00
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 Data 10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 Data 10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 Data 10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 Data 10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 Data 10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 Data 10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 Data 10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 Data 10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 spBuTR = 7
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
spFloor = 2 Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 06 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,00 ,06 ,12 ,12 ,12 ,12 ,06 Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 12 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,00 ,12 ,06 ,06 ,06 ,06 ,00 Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 12 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,00 ,12 ,06 ,06 ,06 ,06 ,00 Data 00 ,09 ,09 ,00 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 12 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,00 ,12 ,06 ,06 ,06 ,06 ,00 Data 00 ,09 ,00 ,10 ,00 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 12 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,00 ,06 ,00 ,00 ,00 ,00 ,06 Data 10 ,00 ,10 ,10 ,00 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 12 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,00 ,12 ,12 ,12 ,12 ,12 ,00 Data 10 ,10 ,10 ,10 ,00 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 12 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,00 ,12 ,06 ,06 ,06 ,06 ,00 Data 10 ,10 ,10 ,10 ,10 ,00 ,10 ,00 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 12 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,00 ,12 ,06 ,06 ,06 ,06 ,00 Data 10 ,10 ,10 ,10 ,10 ,10 ,10 ,00 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 12 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,00 ,12 ,06 ,06 ,06 ,06 ,00 Data 10 ,10 ,10 ,10 ,10 ,10 ,10 ,00 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 12 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,00 ,12 ,06 ,06 ,06 ,06 ,00 Data 10 ,10 ,10 ,10 ,10 ,10 ,00 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 00 ,00 ,06 ,06 ,06 ,06 ,06 ,06 ,00 ,12 ,06 ,06 ,06 ,06 ,06 ,00 spClTL = 8
Data 12 ,12 ,00 ,00 ,06 ,06 ,06 ,06 ,00 ,12 ,06 ,06 ,06 ,06 ,06 ,00 Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 12 ,06 ,12 ,12 ,00 ,00 ,00 ,00 ,12 ,06 ,06 ,06 ,06 ,06 ,06 ,00 Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 12 ,06 ,06 ,06 ,12 ,12 ,12 ,00 ,12 ,06 ,06 ,06 ,06 ,06 ,06 ,00 Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 12 ,06 ,06 ,06 ,06 ,06 ,06 ,00 ,12 ,06 ,06 ,06 ,06 ,06 ,00 ,00 Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 06 ,00 ,00 ,00 ,00 ,00 ,00 ,06 ,12 ,00 ,00 ,00 ,00 ,00 ,00 ,06 Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
spQuest = 3 Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 09 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,09 Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 06 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,00 Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 06 ,12 ,00 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,00 ,12 ,00 Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,00 ,00 ,00
Data 06 ,12 ,12 ,12 ,12 ,06 ,06 ,06 ,06 ,06 ,12 ,12 ,12 ,12 ,12 ,00 Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,00 ,15 ,15 ,15
Data 06 ,12 ,12 ,12 ,06 ,06 ,00 ,00 ,00 ,06 ,06 ,12 ,12 ,12 ,12 ,00 Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,00 ,15 ,15 ,15 ,15
Data 06 ,12 ,12 ,12 ,06 ,06 ,00 ,12 ,12 ,06 ,06 ,00 ,12 ,12 ,12 ,00 Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,15 ,15 ,15 ,15 ,15
Data 06 ,12 ,12 ,12 ,06 ,06 ,00 ,12 ,12 ,06 ,06 ,00 ,12 ,12 ,12 ,00 Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,00 ,00 ,15 ,15 ,15 ,15 ,15
Data 06 ,12 ,12 ,12 ,12 ,00 ,00 ,12 ,06 ,06 ,06 ,00 ,12 ,12 ,12 ,00 Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,00 ,15 ,15 ,15 ,15 ,15 ,15 ,15
Data 06 ,12 ,12 ,12 ,12 ,12 ,12 ,06 ,06 ,00 ,00 ,00 ,12 ,12 ,12 ,00 Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,00 ,15 ,15 ,15 ,15 ,15 ,15 ,15
Data 06 ,12 ,12 ,12 ,12 ,12 ,12 ,06 ,06 ,00 ,12 ,12 ,12 ,12 ,12 ,00 Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,00 ,15 ,15 ,15 ,15 ,15 ,15
Data 06 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,00 ,00 ,12 ,12 ,12 ,12 ,12 ,00 spClTM = 9
Data 06 ,12 ,12 ,12 ,12 ,12 ,12 ,06 ,06 ,12 ,12 ,12 ,12 ,12 ,12 ,00 Data 09 ,09 ,09 ,09 ,09 ,09 ,00 ,00 ,00 ,00 ,09 ,09 ,09 ,09 ,09 ,09
Data 06 ,12 ,12 ,12 ,12 ,12 ,12 ,06 ,06 ,00 ,12 ,12 ,12 ,12 ,12 ,00 Data 09 ,09 ,09 ,09 ,09 ,00 ,15 ,15 ,15 ,15 ,00 ,09 ,09 ,09 ,09 ,09
Data 06 ,12 ,00 ,12 ,12 ,12 ,12 ,12 ,00 ,00 ,12 ,12 ,12 ,00 ,12 ,00 Data 09 ,09 ,09 ,00 ,00 ,15 ,15 ,15 ,15 ,15 ,15 ,00 ,09 ,09 ,09 ,09
Data 06 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,00 Data 09 ,09 ,00 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,00 ,09 ,00 ,09 ,09
Data 00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 Data 09 ,09 ,00 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,00 ,15 ,00 ,09
spBrick = 4 Data 09 ,09 ,00 ,15 ,15 ,15 ,15 ,15 ,15 ,09 ,15 ,15 ,15 ,15 ,15 ,00
Data 12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 Data 09 ,00 ,15 ,15 ,15 ,09 ,09 ,15 ,15 ,15 ,09 ,15 ,15 ,15 ,15 ,00
Data 06 ,06 ,06 ,06 ,06 ,06 ,06 ,00 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,00 Data 00 ,15 ,15 ,15 ,09 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,00
Data 06 ,06 ,06 ,06 ,06 ,06 ,06 ,00 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,00 Data 15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15
Data 00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 Data 15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15
Data 06 ,06 ,06 ,00 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,00 ,06 ,06 ,06 ,06 Data 15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15
Data 06 ,06 ,06 ,00 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,00 ,06 ,06 ,06 ,06 Data 15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15
Data 06 ,06 ,06 ,00 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,00 ,06 ,06 ,06 ,06 Data 15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15
Data 00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 Data 15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15
Data 06 ,06 ,06 ,06 ,06 ,06 ,06 ,00 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,00 Data 15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15
Data 06 ,06 ,06 ,06 ,06 ,06 ,06 ,00 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,00 Data 15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15
Data 06 ,06 ,06 ,06 ,06 ,06 ,06 ,00 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,00 spClTR = 10
Data 00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 06 ,06 ,06 ,00 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,00 ,06 ,06 ,06 ,06 Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 06 ,06 ,06 ,00 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,00 ,06 ,06 ,06 ,06 Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 06 ,06 ,06 ,00 ,06 ,06 ,06 ,06 ,06 ,06 ,06 ,00 ,06 ,06 ,06 ,06 Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 ,00 Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
spBuTL = 5 Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 Data 00 ,09 ,09 ,00 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 Data 00 ,09 ,00 ,15 ,00 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
66
Data 15 ,00 ,15 ,15 ,00 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 Data 00 ,06 ,14 ,06 ,06 ,14 ,14 ,14 ,06 ,14 ,14 ,14
Data 15 ,15 ,15 ,15 ,00 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 Data 00 ,06 ,06 ,14 ,14 ,14 ,14 ,06 ,06 ,06 ,06 ,00
Data 15 ,15 ,15 ,15 ,15 ,00 ,15 ,00 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 Data 00 ,00 ,00 ,14 ,14 ,14 ,14 ,14 ,14 ,14 ,00 ,00
Data 15 ,15 ,15 ,15 ,15 ,15 ,15 ,00 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 Data 00 ,00 ,06 ,06 ,12 ,06 ,06 ,06 ,00 ,00 ,00 ,00
Data 15 ,15 ,15 ,15 ,15 ,15 ,15 ,00 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 Data 00 ,06 ,06 ,06 ,12 ,06 ,06 ,12 ,06 ,06 ,06 ,00
Data 15 ,15 ,15 ,15 ,15 ,15 ,00 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 Data 06 ,06 ,06 ,06 ,12 ,12 ,12 ,12 ,06 ,06 ,06 ,06
spClBL = 11 Data 14 ,14 ,06 ,12 ,14 ,12 ,12 ,14 ,12 ,06 ,14 ,14
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,00 ,15 ,15 ,09 ,15 ,15 Data 14 ,14 ,14 ,12 ,12 ,12 ,12 ,12 ,12 ,14 ,14 ,14
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,00 ,15 ,15 ,09 ,15 Data 14 ,14 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,14 ,14
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,00 ,15 ,15 ,09 Data 00 ,00 ,12 ,12 ,12 ,00 ,00 ,12 ,12 ,12 ,00 ,00
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,00 ,15 ,15 ,15 Data 00 ,06 ,06 ,06 ,00 ,00 ,00 ,00 ,06 ,06 ,06 ,00
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,00 ,00 ,00 Data 06 ,06 ,06 ,06 ,00 ,00 ,00 ,00 ,06 ,06 ,06 ,06
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 marioW = 12
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 marioH = 16
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 Abaixo está o mapa do cenário. O
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 valor de cada posição representa um
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
spClBM = 12 sprite. O valor 01 corresponde a spSky,
Data 15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,09 ,15 ,15 ,15 ,15 ,15 ,15
Data 15 ,09 ,15 ,15 ,15 ,15 ,15 ,15 ,09 ,15 ,15 ,15 ,15 ,15 ,15 ,15 o valor 02 corresponde a spFloor e as-
Data 09 ,09 ,09 ,15 ,15 ,15 ,09 ,09 ,09 ,09 ,15 ,15 ,15 ,15 ,09 ,15
Data 15 ,15 ,09 ,09 ,09 ,09 ,09 ,09 ,15 ,09 ,09 ,09 ,09 ,09 ,15 ,15 sim por diante. A variável mapW arma-
Data 15 ,15 ,15 ,15 ,09 ,09 ,15 ,15 ,15 ,15 ,09 ,09 ,09 ,15 ,15 ,15
Data 00 ,15 ,15 ,15 ,15 ,15 ,15 ,00 ,15 ,15 ,15 ,15 ,15 ,15 ,15 ,15 zena a largura do cenário e mapH arma-
Data 09 ,00 ,00 ,15 ,15 ,15 ,00 ,09 ,00 ,00 ,15 ,15 ,15 ,15 ,00 ,00
Data 09 ,09 ,09 ,00 ,00 ,00 ,09 ,09 ,09 ,09 ,00 ,00 ,00 ,00 ,09 ,09 zena sua altura.
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 Data 01 ,01 ,01 ,01 ,01 ,08 ,09 ,10 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,01
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 Data 01 ,01 ,01 ,01 ,01 ,11 ,12 ,13 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,01
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 Data 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,08 ,09 ,10 ,01 ,01 ,01 ,01
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 Data 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,11 ,12 ,13 ,01 ,01 ,01 ,01
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 Data 01 ,01 ,01 ,01 ,03 ,04 ,03 ,04 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,01
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 Data 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 ,05 ,06 ,06 ,06 ,07 ,01 ,01
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 Data 02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02
spClBR = 13 Data 02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02 ,02
Data 15 ,15 ,15 ,15 ,15 ,00 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 mapW = 16
Data 15 ,15 ,15 ,15 ,15 ,15 ,00 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 mapH = 8
Data 15 ,15 ,15 ,15 ,15 ,15 ,15 ,00 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 15 ,15 ,15 ,15 ,15 ,15 ,15 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 15 ,15 ,15 ,15 ,15 ,00 ,00 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 00 ,15 ,15 ,00 ,00 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 09 ,00 ,00 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
Data 09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09 ,09
nSprites = spClBR
spW = 16
spH = 16
Dim spOffset As Integer
spOffset = spW * spH / 2 + 4
67
Abaixo estão as declarações dos vetores que armazenarão os dados acima.
O vetor arrSprite armazenará os 13 sprites, marioSprite armazenará os per-
sonagem e matMap armazenará o mapa do cenário.
Dim arrSprite (0 To nSprites * spOffset ) As Integer
Dim marioSprite ( spOffset ) As Integer
Dim matMap (0 To mapW - 1 , 0 To mapH - 1) As Integer
68
A função abaixo calcula o ı́ndice da primeira posição de cada sprite no array.
A função recebe um id maior que zero e spOffset é o número de posições
necessárias no array para armazenar cada sprite.
Function getSpriteIdx ( id , spOffset )
If id <= 0 Then
Print " getSpriteIdx : Error : id <= 0 "
End If
getSpriteIdx = ( id - 1) * spOffset
End Function
69
A função abaixo desenha o personagem na tela. Recebe os mesmos parâmetros
que spDraw. Seu comportamento, porém, é diferente pois considera que os pixels
com valor 00 são transparentes.
Sub marioDraw ( id , spOffset , arrSprite () As Integer ,
X, Y)
bytes = arrSprite (0)
spH = arrSprite (1)
spW = 2 * bytes \ arrSprite (1)
nPix = spH * spW
For p = 0 To nPix - 1
pX = p Mod spW
pY = p \ spW
b = p \ 2
v = arrSprite ( b + 2)
If p Mod 2 = 0 Then
c = v Mod 256
Else
c = v \ 256
End If
If c <> 0 Then
PSet ( X + pX , Y + pY ) , c
End If
Rem Sleep
Next p
End Sub
70
Sub mapDraw ( matMap () As Integer , mapW , mapH ,
spOffset , arrSprite () As Integer , spW , spH )
For Y = 0 To mapH - 1 ’ For each row
For X = 0 To mapW - 1 ’ For each column
spId = matMap (X , Y )
scX = X * spW + 32
scY = Y * spH + 0
Call spDraw ( spId , spOffset , arrSprite () , scX ,
scY )
Next X
Next Y
End Sub
5.3 Exercı́cios
1. Crie um programa que toque arpejos musicais. Use a instrução PLAY com
strings contendo notas musicais definidas por números como em "N24 N28
N31 N36". Toque arpejos
71
(c) menores, com intervalos de 4, 6 e 12 semitons.
(d) menores, subindo e depois descendo.
(e) maiores com sétima, com intervalos de 4, 7 e 11 semitons.
(f) maiores com sétima, subindo e depois descendo.
(g) maiores com sétima menor, com intervalos de 4, 7 e 10 semitons.
(h) maiores com sétima menor, subindo e depois descendo.
2. Crie um programa para visualizar gráficos de funções. Procure desenhar
linhas contı́nuas, de modo que os pontos da função não apareçam isolados.
Desenhe uma função
(a) identidade.
(b) afim.
(c) polinomial de segundo grau.
(d) polinomial de terceiro grau.
(e) exponencial.
(f) logarı́tmica.
(g) senoidal.
(h) 200 exp(−x2 ).
3. Crie um programa para vizualizar funções tridimensionais. Escolha cores
diferentes para diferentes faixas de valores de z. Considere que os eixos x
e y correspondem aos eixos horizontal e vertical respectivamente. Desenhe
a função
(a) paraboloide hiperbólica z = xy.
(b) paraboloide cilı́ndrica z = x2 .
(c) paraboloide cilı́ndrica z = y 2 .
(d) paraboloide de revolução z = x2 + y 2 .
(e) paraboloide elı́ptica z = a−2 x2 + b−2 y 2 .
(f) paraboloide hiperbólica z = a−2 x2 − b−2 y 2 .
72
Capı́tulo 6
1 [Link]
2 [Link]
3 [Link]
73
Print ""
Print " Seja bem vindo a UFS ! Voce eh calouro no curso "
Print " de Engenharia e esta super empolgado com a "
Print " aprovacao . Seus pais estao muito orgulhosos . "
Print " Vamos ver como voce se sai ... "
Print ""
Print " A primeira prova sera em 30 dias . Tente "
Print " equilibrar estudos , diversao e descanso para "
Print " maximizar sua produtividade e nao surtar . "
Print ""
O jogo armazena o status em uma estrutura com quatro variáveis que arma-
zenam o percentual de conhecimento nas disciplinas de Cálculo, Computação,
percentual de stress e de cansaço. Todas começam com zero e podem chegar
até 100.
Type TStatus
estcalc As Integer
estcomp As Integer
stress As Integer
cansaco As Integer
End Type
Status . estcalc = 0
Status . estcomp = 0
Status . stress = 0
Status . stress = 0
O laço principal do jogo conta quantos dias faltam para as provas. Começa
fantando 30 dias. Quando o contador chega em zero, ou seja, no dia da prova,
a nota é sorteada. Quando maior o percentual de conhecimento, maior a nota.
A cada iteração do laço é mostrado o número de dias que faltam para a prova,
o valor das variáveis de status e um menu de ações. Quatro ações são possı́veis:
estudar Cálculo, estudar Computação, sair para beber e descansar. Cada dia
permite uma única ação. O efeito de uma ação de estudar é incrementar o per-
centual de conhecimento na disciplina correspondente, mas também aumenta o
percentual de stress e cansaço em 5 pontos percentuais. O aumento de conheci-
mento é maior quanto menor o percentual de stress e cansaço. O efeito de sair
para beber é diminuir em 20 pontos percentuais o stress e aumentar o cansaço
em 5. O efeito de descansar é diminuir o stress em 5 pontos percentuais e o de
cansaço em 10.
Caso o nı́vel de stress ou cansaço chegue a 100%, o aluno surta e não consegue
mais estudar até o dia da prova.
74
For d = 30 To 1 Step -1
Print " * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * "
Print " Faltam " ; d ; " dias para as provas . "
Print " "
Print " Conhecimento de calculo = ";
Status . estcalc ; " % "
Print " Conhecimento de computacao = " ;
Status . estcomp ; " % "
Print " Nivel de stress = ";
Status . stress ; " % "
Print " Nivel de cansaco = ";
Status . cansaco ; " % "
Print " "
Print " 1 - Estudar calculo "
Print " 2 - Estudar computacao "
Print " 3 - Sair para beber "
Print " 4 - Descansar "
Print " "
Input " O que voce vai fazer hoje ? " , escolha
p = Int (5 - 5 * ( Status . stress / 100) *
( Status . cansaco / 100) )
Select Case escolha
Case 1
Status . estcalc = mudaStatus ( Status . estcalc , p )
Status . stress = mudaStatus ( Status . stress , 5)
Status . cansaco = mudaStatus ( Status . cansaco , 5)
Case 2
Status . estcomp = mudaStatus ( Status . estcomp , p )
Status . stress = mudaStatus ( Status . stress , 5)
Status . cansaco = mudaStatus ( Status . cansaco , 5)
Case 3
Status . stress = mudaStatus ( Status . stress , -20)
Status . cansaco = mudaStatus ( Status . cansaco , 5)
Case 4
Status . stress = mudaStatus ( Status . stress , -5)
Status . cansaco = mudaStatus ( Status . cansaco , -10)
End Select
If Status . stress > 50 Then
Print " Seu nivel de stress esta alto . Tente
descansar ou sair um pouco para nao surtar . "
End If
If Status . stress >= 100 Then
Print " Seu nivel de stress chegou no limite . "
Print " Voce decidiu largar a engenharia para ir
vender coco na praia . "
Exit For
75
End If
If Status . cansaco > 50 Then
Print " Seu nivel de cansaco esta alto . Tente
descansar um pouco para ser mais produtivo . "
End If
If Status . cansaco >= 100 Then
Print " Seu nivel de cansaco chegou no limite . "
Print " Voce decidiu largar a engenharia para
trabalhar de ajudante de pedreiro . "
Exit For
End If
Next d
No dia das provas, as notas são sorteadas, exibidas e é mostrada uma men-
sagem avisando se o aluno foi aprovado ou reprovado em cada disciplina.
Print " * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * "
Print " Chegou o dia da prova de calculo "
NCalculo = sorteiaNota ( Status . estcalc )
Print " Sua nota de calculo foi " ; NCalculo
Print msgNota ( NCalculo )
76
Function msgNota$ ( nota )
If nota < 5 Then
msgNota$ = " Lamentavel ... voce se lascou "
Else
msgNota$ = " Muito bem ! voce foi aprovado ! "
End If
End Function
77
6.2 Animação e ASCII art
O jogo Corrida Aritmética demonstra como fazer uma animação simples com
ASCII art. O objetivo é responder perguntas sobre aritmética. O jogador com
mais acertos vence.
O código abaixo inicializa as variáveis do programa. As variáveis SHARED
são visı́veis dentro do escopo das funções. A variável arr é um array armazena
o status dos dois jogadores, ou seja, pontuação, coordenadas do carro e cor.
Dim Shared car0$
Dim Shared car1$
Dim Shared car2$
car0$ = " _ _ "
car1$ = " \ ‘../ | o_ .. __ "
car2$ = " ‘. ,( _ ) ______ ( _ ) . > "
Type TPlayer
lineP As Integer
columnP As Integer
colorP As Integer
scoreP As Integer
End Type
Dim Shared arr (2) As TPlayer
O código abaixo inicia o jogo com a exibição do tı́tulo, uma pequena animação
dos carros percorrendo a tela e mostra uma bandeira quadriculada na parte in-
ferior da tela. O jogador é consultado quanto ao número de rodadas do jogo. A
Figura 6.1 mostra a tela inicial do jogo.
Locate 10 , 32
Color 0 , 7
Print " Corrida aritmetica "
Call printTrack
78
For col = 1 To 60
Call printCar ( arr (1) . lineP , col , arr (1) . colorP )
Call printCar ( arr (2) . lineP , col , arr (2) . colorP )
_Delay 0.02
Next
Call printFlag
Color 15 , 0
Locate 12 , 1
Input " Digite o numero de rodadas : " , rodadas
Abaixo está o laço principal do jogo. São dois laços encadeados: o primeiro
roda tantas vezes quanto o número de rodadas, o segundo roda uma vez para
cada jogador. O jogo considera que são dois jogadores. A cada iteração é exibido
o score e é pedido a um dos jogadores que calcule o valor de uma soma. Em caso
de acerto, o jogador marca um ponto e o carro se movimenta proporcionalmente
à sua pontuação em direção à direita. Um efeito sonoro diferente é tocado em
caso de acerto ou erro.
For r = 1 To rodadas
For p = 1 To 2
Call printScore
Color 15 , 0
Locate 12 , 1
Print Spc (20)
Print Spc (20)
Print Spc (20)
Print Spc (20)
Locate 12 , 1
Color arr ( p ) . colorP , 0
Print " Rodada " ; r
Print " Player " ; p
v1 = Int ( Rnd * 100)
v2 = Int ( Rnd * 100)
msg$ = Str$ ( v1 ) + " + " + Str$ ( v2 ) + " = "
Print msg$ ;
Input " " , result
79
If result = v1 + v2 Then
arr ( p ) . scoreP = arr ( p ) . scoreP + 1
Print " Correto ! "
Play " l32 O3 cdef "
finalCol = arr ( p ) . scoreP / rodadas * maxCol
Call moveCar ( arr ( p ) . lineP , arr ( p ) . columnP ,
finalCol , arr ( p ) . colorP )
arr ( p ) . columnP = finalCol
Else
Print " Ow peste ... "
Play " l32 O2 c < ge + c "
End If
Sleep 1
Next p
Next r
Ao final da execução dos laços, o jogo atualiza o score na tela, imprime uma
bandeira quadriculada e declara o jogador com maior score como vencedor.
Call printScore
Call printFlag
Locate 21 , 30
If arr (1) . scoreP = arr (2) . scoreP Then
Color 15 , 0
Print " Deu empate !! "
Else
If arr (1) . scoreP > arr (2) . scoreP Then
vencedor = 1
Else
vencedor = 2
End If
Color arr ( vencedor ) . colorP , 0
Print " Vencedor : Player " ; vencedor
End If
80
End Sub
Abaixo está a função que imprime as duas pistas na parte superior da tela.
Sub printTrack ()
Color 0 , colorTrack
Locate 2 , 1
Print Spc (79)
Print Spc (79)
Print Spc (79)
Locate 6 , 1
81
Print Spc (79)
Print Spc (79)
Print Spc (79)
End Sub
6.3 Exercı́cios
1. Incremente o UFS Simulator: A Text Based RPG.
(a) Adicione novas variáveis de status, novas ações e seus efeitos sobre
as variáveis de status.
(b) No inı́cio do jogo, consulte o jogador quanto ao nı́vel de dificuldade,
o que pode influenciar o número de dias e de disciplinas.
(c) Exiba o dia da semana. Considere que o jogo começa na segunda-
feira.
(d) Use arrays para armazenar o histórico dos status e, ao final, exiba-os
em um gráfico.
2. Incremente o Corrida Aritmética.
(a) Adicione novas operações aritméticas.
(b) No inı́cio do jogo, consulte o jogador quanto ao nı́vel de dificuldade,
o que pode influenciar o número de dı́gitos e operações usadas.
82
Capı́tulo 7
Neste capı́tulo veremos como fazer interação com o teclado em tempo real e
como implementar um game loop para jogos de ação.
Operação Função
Captura a última tecla pressionada INKEY$
Verifica se uma tecla está pressionada _KeyDown
Esvazia o buffer do teclado _KeyClear
83
84
Figura 7.1: Códigos de teclas.
O código de teclas de letras, números, caracteres de pontuação e de acen-
tuação são o próprio código ASCII da tecla, mostrado na Tabela A.1 do
Apêndice A. Suas versões maiúsculas são obtidas pressionando-as juntamente
com [Shift] e também estão listadas nesta tabela. Teclas especiais como teclas
de função, [Esc], [Enter], [Insert], [Delete], [Home], [PgUp] etc e teclas quando
pressionadas junto com [Ctrl], [Alt] possuem como código uma string com duas
posições. A primeira é o caractere NUL, com código zero e a segunda é algum
caractere com código menor que 255. A Figura 7.1 mostra os códigos das teclas
especiais e combinações.
O código abaixo é um pequeno exemplo de interação com o teclado. Im-
plementa um piano com uma oitava. Quando o usuário pressiona alguma tecla
entre [q] e [i] no teclado, a nota correspondente é tocada. Observe que somente
as versões minúsculas são testadas, então, o som não sairá se for usado [Shift]
ou [CapsLock]. A tecla [q] corresponde ao C2 do piano. A depender da tecla um
expoente é obtido e a frequência de C2 é multiplicada pelo fator correspondente.
O programa sai do laço quando [Esc] é pressionado.
freqC2 = 65 ’ C2 frequency
b = 2 ^ (1/12) ’ Semitone freq . ratio
Do
k$ = InKey$
Select Case k$
Case " q " : e = 0 ’ C2 : freqDo * b ^ 0
Case " w " : e = 2 ’ D2 : freqDo * b ^ 2
Case " e " : e = 4 ’ E2 : freqDo * b ^ 4
Case " r " : e = 5 ’ F2 : freqDo * b ^ 5
Case " t " : e = 7 ’ G2 : freqDo * b ^ 7
Case " y " : e = 9 ’ A2 : freqDo * b ^ 9
Case " u " : e = 11 ’ B2 : freqDo * b ^ 11
Case " i " : e = 12 ’ C3 : freqDo * b ^ 12
Case Else : e = -1
End Select
Locate 1 , 1
Print k$ ;
If e >= 0 Then
Sound freqC2 * b ^ e , 1
End If
Loop While k$ <> Chr$ (27) ’ [ Esc ] exits
85
Dim arrK (1 To 32) As Integer
freqC2 = 65
b = 2 ^ (1 / 12)
Do
k$ = InKey$
arrK (1) = _KeyDown ( Asc ( " q " ) )
arrK (2) = _KeyDown ( Asc ( " w " ) )
arrK (3) = _KeyDown ( Asc ( " e " ) )
arrK (4) = _KeyDown ( Asc ( " r " ) )
arrK (5) = _KeyDown ( Asc ( " t " ) )
arrK (6) = _KeyDown ( Asc ( " y " ) )
arrK (7) = _KeyDown ( Asc ( " u " ) )
arrK (8) = _KeyDown ( Asc ( " i " ) )
id = -1
Locate 1 , 1
For i = 1 To 8
If arrK ( i ) <> 0 Then
Print " _ " ;
id = i
Else
Print Chr$ (178) ;
End If
Next i
Select Case id
Case 1: e = 0 ’ C2 : freqDo * b ^ 0
Case 2: e = 2 ’ D2 : freqDo * b ^ 2
Case 3: e = 4 ’ E2 : freqDo * b ^ 4
Case 4: e = 5 ’ F2 : freqDo * b ^ 5
Case 5: e = 7 ’ G2 : freqDo * b ^ 7
Case 6: e = 9 ’ A2 : freqDo * b ^ 9
Case 7: e = 11 ’ B2 : freqDo * b ^ 11
Case 8: e = 12 ’ C3 : freqDo * b ^ 12
Case Else : e = -1
End Select
If e >= 0 Then
Sound freqC2 * b ^ e , 0.3
_KeyClear
End If
Loop While k$ <> Chr$ (27) ’ [ Esc ] exits
86
7.2 Game loop
O game loop é um padrão de projeto muito comum em jogos [2]. O piano simples
da seção anterior é um exemplo de game loop. Essencialmente é um laço infinito.
O piano em particular sai do laço quando a tecla [Esc] é pressionada.
Do
k$ = InKey$
...
Loop While k$ <> Chr$ (27) ’ [ Esc ] exits
87
Type TStatus
x As Integer ’ X coordinate
y As Integer ’ Y coordinate
r As Integer ’ Rotation angle . 0 is up .
c As Integer ’ Color
End Type
Dim player (1 To 2) As TStatus
player (1) . x = w / 4 ’ P . 1 starting x coordinate
player (1) . y = h / 3 ’ P . 1 starting y coordinate
player (1) . r = 90 ’ P . 1 starting rotation
player (1) . c = 4 ’ P . 1 color
player (2) . x = ( w / 4) * 3 ’ P . 2 starting x coordinate
player (2) . y = ( h / 3) * 2 ’ P . 2 starting y coordinate
player (2) . r = -90 ’ P . 2 starting rotation
player (2) . c = 2 ’ P . 2 color
Abaixo está o game loop propriamente dito. Pressionar [Esc] encerra o laço.
O vetor arrK é preenchido com o status das teclas [W], [A], [S], [D] e direcionais.
As primeiras quatro controlam o primeiro jogador e as últimas, o segundo. Em
seguida, um laço exibe o status de cada uma das oito teclas. Duas chamadas a
playerUpdate atualizam o status de cada jogador em função das teclas pressio-
nadas. Duas chamadas a playerDraw atualizam a tela. Finalmente, são gerados
efeitos sonoros a depender da tecla pressionada.
Do
k$ = InKey$
arrK (1) = _KeyDown ( Asc ( " w " ) ) Or _KeyDown ( Asc ( " W " ) )
arrK (2) = _KeyDown ( Asc ( " s " ) ) Or _KeyDown ( Asc ( " S " ) )
arrK (3) = _KeyDown ( Asc ( " a " ) ) Or _KeyDown ( Asc ( " A " ) )
arrK (4) = _KeyDown ( Asc ( " d " ) ) Or _KeyDown ( Asc ( " D " ) )
arrK (5) = _KeyDown (256 * 72)
arrK (6) = _KeyDown (256 * 80)
arrK (7) = _KeyDown (256 * 75)
arrK (8) = _KeyDown (256 * 77)
id = -1
Locate 1 , 1
For i = 1 To 8
If arrK ( i ) <> 0 Then
Print " _ " ;
id = i
Else
Print Chr$ (178) ;
End If
Next i
88
Call playerUpdate ( player (1) , arrK (1) , arrK (2) ,
arrK (3) , arrK (4) )
Call playerUpdate ( player (2) , arrK (5) , arrK (6) ,
arrK (7) , arrK (8) )
’ Sound effects
Select Case id
Case 1: e = 0
Case 2: e = 2
Case 3: e = 4
Case 4: e = 5
Case 5: e = 7
Case 6: e = 9
Case 7: e = 11
Case 8: e = 12
Case Else : e = -1
End Select
If e >= 0 Then
For t = 1 To 4
Sound freqC2 * b ^ e , 0.3
Sound freqC2 * b ^ ( e + 10) , 0.3
_KeyClear
Next t
End If
Loop While k$ <> Chr$ (27)
89
End Sub
7.3 Exercı́cios
1. Modifique o piano de exemplo adicionando mais teclas.
2. Modifique o jogo dado como exemplo adicionando teclas para atirar e
desenhe os projéteis na tela.
(a) Teste a colisão do projétil com o adversário.
(b) Adicione a possibilidade das teclas ricochetearem nas extremidades
da tela. Adicione um limite de tempo ou iterações para o projétil
permanecer na tela.
90
Apêndice A
Tabela ASCII
Dec Hex Char Dec Hex Char Dec Hex Char Dec Hex Char
0 0x00 NUL 32 0x20 64 0x40 @ 96 0x60 ‘
1 0x01 STX 33 0x21 ! 65 0x41 A 97 0x61 a
2 0x02 SOT 34 0x22 " 66 0x42 B 98 0x62 b
3 0x03 ETX 35 0x23 # 67 0x43 C 99 0x63 c
4 0x04 EOT 36 0x24 $ 68 0x44 D 100 0x64 d
5 0x05 ENQ 37 0x25 % 69 0x45 E 101 0x65 e
6 0x06 ACK 38 0x26 & 70 0x46 F 102 0x66 f
7 0x07 BEL 39 0x27 ’ 71 0x47 G 103 0x67 g
8 0x08 BS 40 0x28 ( 72 0x48 H 104 0x68 h
9 0x09 HT 41 0x29 ) 73 0x49 I 105 0x69 i
10 0x0A LF 42 0x2A * 74 0x4A J 106 0x6A j
11 0x0B VT 43 0x2B + 75 0x4B K 107 0x6B k
12 0x0C FF 44 0x2C , 76 0x4C L 108 0x6C l
13 0x0D CR 45 0x2D - 77 0x4D M 109 0x6D m
14 0x0E SO 46 0x2E . 78 0x4E N 110 0x6E n
15 0x0F SI 47 0x2F / 79 0x4F O 111 0x6F o
16 0x10 DLE 48 0x30 0 80 0x50 P 112 0x70 p
17 0x11 DC1 49 0x31 1 81 0x51 Q 113 0x71 q
18 0x12 DC2 50 0x32 2 82 0x52 R 114 0x72 r
19 0x13 DC3 51 0x33 3 83 0x53 S 115 0x73 s
20 0x14 DC4 52 0x34 4 84 0x54 T 116 0x74 t
21 0x15 NAK 53 0x35 5 85 0x55 U 117 0x75 u
22 0x16 SYN 54 0x36 6 86 0x56 V 118 0x76 v
23 0x17 ETB 55 0x37 7 87 0x57 W 119 0x77 w
24 0x18 CAN 56 0x38 8 88 0x58 X 120 0x78 x
25 0x19 EM 57 0x39 9 89 0x59 Y 121 0x79 y
26 0x1A SUB 58 0x3A : 90 0x5A Z 122 0x7A z
27 0x1B ESC 59 0x3B ; 91 0x5B [ 123 0x7B {
28 0x1C FS 60 0x3C < 92 0x5C 124 0x7C |
29 0x1D GS 61 0x3D = 93 0x5D ] 125 0x7D }
30 0x1E RS 62 0x3E > 94 0x5E ^ 126 0x7E
31 0x1F US 63 0x3F ? 95 0x5F _ 127 0x7F DEL
91
Tabela A.2: Tabela ASCII estendida, também conhecida como Code Page 437
(CP437). Fora do QBasic atualmente é usado o Unicode ao invés destes códigos.
Sı́mbolos não utilizáveis pelo LATEX foram omitidos1 .
Dec Hex Char Dec Hex Char Dec Hex Char Dec Hex Char
128 0x80 Ç 160 0xA0 á 192 0xC0 224 0xE0 α
129 0x81 ü 161 0xA1 ı́ 193 0xC1 225 0xE1 ß
130 0x82 é 162 0xA2 ó 194 0xC2 226 0xE2 Γ
131 0x83 a
^ 163 0xA3 ú 195 0xC3 227 0xE3 π
132 0x84 ä 164 0xA4 n
~ 196 0xC4 228 0xE4 Σ
133 0x85 à 165 0xA5 ~
N 197 0xC5 229 0xE5 σ
134 0x86 å 166 0xA6 ª 198 0xC6 230 0xE6 µ
135 0x87 ç 167 0xA7 º 199 0xC7 231 0xE7 γ
136 0x88 e
^ 168 0xA8 ¿ 200 0xC8 232 0xE8 Φ
137 0x89 ë 169 0xA9 201 0xC9 233 0xE9 θ
138 0x8A è 170 0xAA ¬ 202 0xCA 234 0xEA Ω
139 0x8B ı̈ 171 0xAB ½ 203 0xCB 235 0xEB δ
140 0x8C ı
^ 172 0xAC ¼ 204 0xCC 236 0xEC ∞
141 0x8D ı̀ 173 0xAD ¡ 205 0xCD 237 0xED ø
142 0x8E Ä 174 0xAE ≪ 206 0xCE 238 0xEE ε
143 0x8F Ǎ 175 0xAF ≫ 207 0xCF 239 0xEF ∩
144 0x90 É 176 0xB0 208 0xD0 240 0xF0 ≡
145 0x91 æ 177 0xB1 209 0xD1 241 0xF1 ±
146 0x92 Æ 178 0xB2 210 0xD2 242 0xF2 ≥
147 0x93 o
^ 179 0xB3 211 0xD3 243 0xF3 ≤
148 0x94 ö 180 0xB4 212 0xD4 244 0xF4
149 0x95 ò 181 0xB5 213 0xD5 245 0xF5
150 0x96 u
^ 182 0xB6 214 0xD6 246 0xF6 ÷
151 0x97 ù 183 0xB7 215 0xD7 247 0xF7 ≈
152 0x98 ÿ 184 0xB8 216 0xD8 248 0xF8 °
153 0x99 Ö 185 0xB9 217 0xD9 249 0xF9 ●
·
√
154 0x9A Ü 186 0xBA 218 0xDA 250 0xFA
155 0x9B ¢ 187 0xBB 219 0xDB 251 0xFB
156 0x9C £ 188 0xBC 220 0xDC 252 0xFC n
[Link]
[Link]
[Link]
92
Figura A.1: Tabela ASCII estendida, também conhecida como Code Page 437
(CP437), usada no QBasic.
93
O código abaixo foi usado para gerar a tabela ASCII estendida mostrada na
Figura A.1.
Width 80 , 43
Cls
vBar$ = Chr$ (179)
For t = 0 To 1
Cls
For j = 0 To 3
Print vBar$ + " Dec Hex Char " ;
Next j
Print vBar$
For i = 0 To 31
For j = 0 To 3
v = 128 * t + 32 * j + i
If v < 32 Then
c$ = " "
Else
c$ = Chr$ ( v )
End If
If v < 16 Then
h$ = " 0 " + Hex$ ( v )
Else
h$ = Hex$ ( v )
End If
Print Using vBar$ + " ### 0 x " ; v ;
Print h$ ; " " ; c$ ; " ";
Next j
Print vBar$
If i = 15 Or i = 31 Then
Sleep
End If
Next i
Next t
94
Referências Bibliográficas
95