Tenho alguns loops de que preciso no meu programa. Posso escrever o pseudocódigo, mas não tenho certeza de como escrevê-los logicamente.
Eu preciso -
if (num is a multiple of 10) { do this }
if (num is within 11-20, 31-40, 51-60, 71-80, 91-100) { do this }
else { do this } //this part is for 1-10, 21-30, 41-50, 61-70, 81-90
Este é um jogo de tabuleiro de cobras e escadas, se fizer mais sentido para a minha pergunta.
Imagino a primeira instrução if que vou precisar usar modulus, estaria if (num == 100%10)
correta?
O segundo eu não tenho ideia. Posso escrever assim, if (num > 10 && num is < 21 || etc)
mas tem que haver algo mais inteligente do que isso.
c++
comparison
conditional-statements
integer-arithmetic
user3419168
fonte
fonte
Respostas:
Para o primeiro, para verificar se um número é múltiplo de uso:
Para o segundo:
Mas isso é bastante denso, e talvez seja melhor listar as opções explicitamente.
Agora que você deu uma ideia melhor do que está fazendo, eu escreveria o segundo como:
É a mesma lógica, mas usando a função temos uma ideia mais clara do que ela significa.
fonte
if((num - 1) / 10) % 2 == 1 && num < 100)
- Eu choraria se visse isso.num >= 11
como (1) que o limite inferior é proscrito e (2)%
em um número negativo retorna um número negativo também. (Devo admitir que usar& 1
aqui é "mais seguro", mas também pressupõe conhecimento adicional.)getRow(num) % 2 == 0
em uma função também para deixar bem claro qual é a intenção.bool inEvenRow(int num){ return getRow(num) % 2 ==0;}
O truque aqui é procurar algum tipo de semelhança entre os intervalos. Claro, você sempre pode usar o método de "força bruta":
Mas você pode notar que, se subtrair
1
denum
, terá os intervalos:Em outras palavras, todos os números de dois dígitos cujo primeiro dígito seja ímpar. Em seguida, você precisa criar uma fórmula que expresse isso. Você pode obter o primeiro dígito dividindo por 10 e pode testar se ele é estranho verificando o resto de 1 ao dividir por 2. Juntando tudo:
Dada a compensação entre um código mais longo, mas passível de manutenção, e um código "inteligente" mais curto, sempre escolheria mais e mais claro. No mínimo, se você tentar ser inteligente, por favor, inclua um comentário que explique exatamente o que você está tentando realizar.
Ajuda supor que o próximo desenvolvedor a trabalhar no código está armado e sabe onde você mora. :-)
fonte
&& isTensDigitOdd(num)
fosse dita , talvez com um comentário antes da definição da função explicando o que ela faz. Se tal padrão existir, um comentário explicando o raciocínio para o padrão é esclarecedor para a manutenibilidade.Se você estiver usando GCC ou qualquer compilador que ofereça suporte a intervalos de caso, você pode fazer isso, mas seu código não será portátil .
fonte
Isso é mais para futuros visitantes do que para um iniciante. Para uma solução mais geral, semelhante a um algoritmo, você pode pegar uma lista de valores iniciais e finais e verificar se um valor passado está dentro de um deles:
Para simplificar, usei um lambda polimórfico (C ++ 14) em vez de um
pair
argumento explícito . Isso provavelmente também deve se limitar a usar<
e==
ser consistente com os algoritmos padrão, mas funciona assim, contanto queElem
seja<=
definido para ele. De qualquer forma, pode ser usado assim:Há um exemplo ao vivo aqui .
fonte
O primeiro é fácil. Você só precisa aplicar o operador de módulo ao seu valor num:
Como o C ++ avalia cada número que não seja 0 como verdadeiro, você também pode escrever:
Para o segundo, acho mais fácil entender:
O padrão se repete a cada 20, então você pode calcular o módulo 20. Todos os elementos que você deseja estarão em uma linha, exceto aqueles que são divisíveis por 20.
Para obtê-los também, use num-1 ou melhor, num + 19, para evitar lidar com números negativos.
Isso supõe que o padrão se repita para sempre, portanto, para 111-120 ele se aplicaria novamente e assim por diante. Caso contrário, você precisa limitar os números a 100:
fonte
Com alguns bons comentários no código, ele pode ser escrito de forma bastante concisa e legível.
fonte
num % 10 == 0
é a mesma coisa quenum
um múltiplo de 10.if (num % 10 == 0)
significa o mesmo// Check if it's a multiple of 10
que não deveria manter seu código. Este é um antipadrão bem conhecido.%
seja um antipadrão; obviamente não é. Realmente, supondo que muitos dos leitores deste post sejam iniciantes, ensiná-los esse estilo de escrever comentários é uma contribuição negativa para seu desenvolvimento como programadores.Você basicamente explicou a resposta sozinho, mas aqui está o código para garantir.
fonte
x < 41 x > 50
e coloque parênteses.operator&&
tem uma precedência maior do queoperator||
, então está bem, mas tenho certeza que o GCC avisa sobre isso de qualquer maneira.10 < x < 21
como em10 < x && x < 21
vez dex > 10 && x < 21
. É mais fácil ler a desigualdade quando ela está na mesma ordem em que você a escreveria matematicamente.Você pode estar pensando demais nisso.
A primeira linha
if (x % 10)
funciona porque (a) um valor que é um múltiplo de 10 calcula como '0', outros números resultam em seu restante, (b) um valor de 0 em umif
é consideradofalse
, qualquer outro valor étrue
.Editar:
Para alternar entre os anos 20, use o mesmo truque. Desta vez, o número principal é
10
:x/10
retorna qualquer número de 0 a 9 como0
, 10 a 19 como1
e assim por diante. Testar em pares ou ímpares - o& 1
- informa se é par ou ímpar. Como seus intervalos são, na verdade, "11 a 20", subtraia 1 antes de testar.fonte
Um apelo à legibilidade
Embora você já tenha algumas boas respostas, gostaria de recomendar uma técnica de programação que tornará seu código mais legível para algum leitor futuro - que pode ser você em seis meses, um colega pediu para fazer uma revisão de código, seu sucessor .. .
Isso envolve qualquer instrução "inteligente" em uma função que mostra exatamente (com seu nome) o que está fazendo. Embora haja um impacto minúsculo no desempenho (de "sobrecarga de chamada de função"), isso é realmente insignificante em uma situação de jogo como essa.
Ao longo do caminho, você pode higienizar suas entradas - por exemplo, teste os valores "ilegais". Assim, você pode acabar com um código como este - vê o quanto ele é mais legível? As "funções auxiliares" podem estar escondidas em algum lugar (não precisam estar no módulo principal: é claro pelo nome o que fazem):
fonte
YES
eNO
?TRUE
,True
outrue
? E quais arquivos de cabeçalho, se houver, eu precisaria incluir no C comum? Então eu rolei meu próprio. Imagino se foi isso que teve um downvote ...Para o primeiro:
se aplicará a:
Para o segundo:
irá candidatar-se a:
Basicamente, primeiro fazemos
x-1
para obter:Em seguida, os dividimos por
10
para obter:Portanto, verificamos se esse resultado é estranho.
fonte
Você pode tentar o seguinte:
fonte
Eu sei que essa pergunta tem tantas respostas, mas vou jogar a minha aqui mesmo assim ...
Retirado do código completo de Steve McConnell , 2ª edição: "Tabelas de acesso em escada:
Ainda outro tipo de acesso à mesa é o método de escada. Este método de acesso não é tão direto quanto uma estrutura de índice, mas não desperdiça muito espaço para dados. A ideia geral das estruturas em degraus, ilustrada na Figura 18-5, é que as entradas em uma tabela são válidas para intervalos de dados, e não para pontos de dados distintos.
Figura 18-5 A abordagem em degraus categoriza cada entrada, determinando o nível em que ela atinge uma "escada". O “passo” que atinge determina sua categoria.
Por exemplo, se você está escrevendo um programa de avaliação, o intervalo de entrada “B” pode ser de 75 por cento a 90 por cento. Aqui está uma série de notas que você pode ter que programar algum dia:
Para usar o método da escada, você coloca a extremidade superior de cada faixa em uma tabela e, em seguida, escreve um loop para comparar a pontuação com a extremidade superior de cada faixa. Quando você encontra o ponto em que a pontuação excede o topo de uma faixa, você sabe qual é a nota. Com a técnica de degraus, você deve ter cuidado para lidar com os pontos finais dos intervalos de maneira adequada. Este é o código em Visual Basic que atribui notas a um grupo de alunos com base neste exemplo:
Embora este seja um exemplo simples, você pode facilmente generalizá-lo para lidar com vários alunos, vários esquemas de notas (por exemplo, diferentes notas para diferentes níveis de pontuação em diferentes tarefas) e mudanças no esquema de notas. "
Code Complete , 2ª edição, páginas 426-428 (Capítulo 18).
fonte
Como outros apontaram, tornar as condições mais concisas não acelera a compilação ou a execução e não necessariamente ajuda na legibilidade.
Isso pode ajudar a tornar seu programa mais flexível, caso você decida posteriormente que deseja uma versão infantil do jogo em um tabuleiro de 6 x 6 ou uma versão avançada (que você pode jogar a noite toda) em um tabuleiro de 40 x 50 .
Então, eu iria codificá-lo da seguinte maneira:
Sim, é prolixo, mas deixa claro exatamente o que está acontecendo no tabuleiro.
Se eu estivesse desenvolvendo este jogo para ser exibido em um telefone ou tablet, faria variáveis ROWS e COLUMNS em vez de constantes, para que pudessem ser definidas dinamicamente (no início de um jogo) para corresponder ao tamanho da tela e orientação.
Eu também permitiria que a orientação da tela fosse alterada a qualquer momento, no meio do jogo - tudo que você precisa fazer é mudar os valores de LINHAS e COLUNAS, deixando todo o resto (o número do quadrado atual em que cada jogador está, e o quadrados inicial / final de todas as cobras e escadas) inalterados. Então você 'apenas' tem que desenhar bem o quadro e escrever o código para suas animações (presumo que seja esse o propósito de suas
if
declarações) ...fonte
#define
#define
instruções semelhantes a funções , colocar parênteses em torno dos argumentos, onde eles aparecem na expansão. Então, ao invés de#define finished(num) (num == lastSquare)
você deve escrever#define finished(num) ((num) == lastSquare)
. O motivo é que, se você usar essa instrução com uma expressão contendo um operador com precedência baixa o suficiente, não obterá a resposta que espera. Neste caso, se você não usar os parênteses extras, entãofinished(a & b)
expande o(a & b == lastSquare)
que quase certamente não é o que você deseja.