Tengo algunos bucles que necesito en mi programa. Puedo escribir el pseudocódigo, pero no estoy completamente seguro de cómo escribirlo de forma lógica.
Necesito -
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
Esto es para un juego de mesa de serpientes y escaleras, si tiene más sentido para mi pregunta.
Me imagino que la primera declaración if necesitaré usar módulo, ¿ if (num == 100%10)
sería correcta?
El segundo no tengo ni idea. Puedo escribirlo como, if (num > 10 && num is < 21 || etc)
pero tiene que haber algo más inteligente que eso.
c++
comparison
conditional-statements
integer-arithmetic
user3419168
fuente
fuente
Respuestas:
Para el primero, para verificar si un número es un múltiplo de uso:
Para el segundo:
Pero eso es bastante denso, y es mejor que enumere las opciones explícitamente.
Ahora que ha dado una mejor idea de lo que está haciendo, escribiría el segundo como:
Es la misma lógica, pero al usar la función obtenemos una idea más clara de lo que significa.
fuente
if((num - 1) / 10) % 2 == 1 && num < 100)
- Lloraría si lo viera.num >= 11
como (1) que el límite inferior está proscrito, y (2)%
en un número negativo también devuelve un número negativo. (Debo admitir que usar& 1
aquí es "más seguro", pero también asume conocimientos adicionales).getRow(num) % 2 == 0
una función para dejar en claro cuál es la intención.bool inEvenRow(int num){ return getRow(num) % 2 ==0;}
El truco aquí es buscar algún tipo de concordancia entre los rangos. Por supuesto, siempre puede utilizar el método de "fuerza bruta":
Pero puede notar que, si resta
1
denum
, tendrá los rangos:En otras palabras, todos los números de dos dígitos cuyo primer dígito es impar. A continuación, debe crear una fórmula que exprese esto. Puede obtener el primer dígito dividiendo por 10, y puede probar que es impar al verificar el resto de 1 cuando divide por 2. Poniendo todo eso junto:
Dada la compensación entre un código más largo pero que se puede mantener y un código "inteligente" más corto, elegiría más y más claro cada vez. Por lo menos, si intenta ser inteligente, incluya un comentario que explique exactamente lo que está tratando de lograr.
Es útil asumir que el próximo desarrollador que trabajará en el código está armado y sabe dónde vive. :-)
fuente
&& isTensDigitOdd(num)
, tal vez con un comentario antes de la definición de la función que explique lo que hace. Si tal patrón existe, un comentario que explique el razonamiento del patrón es esclarecedor para la mantenibilidad imo.Si está utilizando GCC o cualquier compilador que admita rangos de casos , puede hacer esto, pero su código no será portátil .
fuente
Esto es para futuros visitantes más que para principiantes. Para una solución más general, similar a un algoritmo, puede tomar una lista de valores iniciales y finales y verificar si un valor pasado está dentro de uno de ellos:
Para simplificar, utilicé una lambda polimórfica (C ++ 14) en lugar de un
pair
argumento explícito . Esto probablemente también debería ceñirse al uso<
y==
ser coherente con los algoritmos estándar, pero funciona así siempre que seElem
haya<=
definido para ello. De todos modos, se puede usar así:Hay un ejemplo vivo aquí .
fuente
El primero es facil. Solo necesita aplicar el operador de módulo a su valor num:
Dado que C ++ está evaluando cada número que no es 0 como verdadero, también podría escribir:
Para el segundo, creo que esto es más claro de entender:
El patrón se repite cada 20, por lo que puede calcular el módulo 20. Todos los elementos que desee estarán en una fila excepto los que se pueden dividir entre 20.
Para obtenerlos también, simplemente use num-1 o mejor num + 19 para evitar lidiar con números negativos.
Esto supone que el patrón se repite para siempre, por lo que para 111-120 se aplicaría nuevamente, y así sucesivamente. De lo contrario, debe limitar los números a 100:
fuente
Con un par de buenos comentarios en el código, se puede escribir de forma bastante concisa y legible.
fuente
num % 10 == 0
es lo mismo quenum
un múltiplo de 10.if (num % 10 == 0)
significa lo mismo que// Check if it's a multiple of 10
no debería mantener su código. Este es un anti-patrón bien conocido.%
sea un anti-patrón; obviamente no lo es. Realmente, asumiendo que muchos de los lectores de este post serán principiantes, enseñarles este estilo de escribir comentarios está haciendo una contribución negativa a su desarrollo como programadores.Básicamente, usted mismo explicó la respuesta, pero aquí está el código por si acaso.
fuente
x < 41 x > 50
y ponga paréntesis.operator&&
tiene una precedencia más alta queoperator||
, por lo que está bien, pero estoy bastante seguro de que GCC advierte de todos modos.10 < x < 21
como en10 < x && x < 21
lugar dex > 10 && x < 21
. Es más fácil leer la desigualdad cuando está en el mismo orden en que la escribirías matemáticamente.Puede que estés pensando demasiado en esto.
La primera línea
if (x % 10)
funciona porque (a) un valor que es un múltiplo de 10 calcula como '0', otros números dan como resultado su remainer, (b) un valor de 0 en unaif
se considerafalse
, cualquier otro valor estrue
.Editar:
Para alternar hacia adelante y hacia atrás en veinte, use el mismo truco. Esta vez, el número fundamental es
10
:x/10
devuelve cualquier número de 0 a 9 como0
, 10 a 19 como1
y así sucesivamente. Probar en pares o impares (el& 1
) te dice si es par o impar. Dado que sus rangos son en realidad "11 a 20", reste 1 antes de realizar la prueba.fuente
Una petición de legibilidad
Si bien ya tiene algunas buenas respuestas, me gustaría recomendar una técnica de programación que hará que su código sea más legible para algún lector futuro, que puede ser usted en seis meses, un colega pidió realizar una revisión del código, su sucesor, ... .
Esto es para envolver cualquier declaración "inteligente" en una función que muestre exactamente (con su nombre) lo que está haciendo. Si bien hay un impacto minúsculo en el rendimiento (debido a la "sobrecarga de llamadas a funciones"), esto es realmente insignificante en una situación de juego como esta.
A lo largo del camino, puede desinfectar sus entradas, por ejemplo, probar valores "ilegales". Por lo tanto, podría terminar con un código como este: ¿ve cuánto más legible es? Las "funciones auxiliares" se pueden ocultar en algún lugar (no es necesario que estén en el módulo principal: se desprende de su nombre lo que hacen):
fuente
YES
yNO
?TRUE
,True
otrue
? ¿Y qué archivos de encabezado, si los hubiera, debería incluir en C ordinario? Así que rodé el mío. Me pregunto si eso es lo que recibió un voto negativo ...Para el primero:
se aplicará a:
Para el segundo:
solicitará:
Básicamente, primero lo hacemos
x-1
para obtener:Luego los dividimos entre
10
para obtener:Entonces comprobamos si este resultado es extraño.
fuente
Puedes probar lo siguiente:
fuente
Sé que esta pregunta tiene tantas respuestas, pero de todos modos arrojaré la mía aquí ...
Tomado de Código completo de Steve McConnell , 2da edición: "Tablas de acceso de escalones:
Otro tipo de acceso a la mesa es el método escalonado. Este método de acceso no es tan directo como una estructura de índice, pero no desperdicia tanto espacio de datos. La idea general de las estructuras escalonadas, ilustrada en la Figura 18-5, es que las entradas en una tabla son válidas para rangos de datos más que para puntos de datos distintos.
Figura 18-5 El enfoque escalonado clasifica cada entrada determinando el nivel en el que llega a una "escalera". El "paso" que da determina su categoría.
Por ejemplo, si está escribiendo un programa de calificación, el rango de entrada "B" puede ser del 75 al 90 por ciento. Aquí hay una variedad de calificaciones que quizás tenga que programar algún día:
Para usar el método escalonado, coloque el extremo superior de cada rango en una tabla y luego escriba un bucle para comparar una puntuación con el extremo superior de cada rango. Cuando encuentre el punto en el que la puntuación excede por primera vez el límite superior de un rango, sabrá cuál es la calificación. Con la técnica de escalones, debe tener cuidado de manipular correctamente los puntos finales de los rangos. Aquí está el código en Visual Basic que asigna calificaciones a un grupo de estudiantes según este ejemplo:
Aunque este es un ejemplo simple, puede generalizarlo fácilmente para manejar varios estudiantes, múltiples esquemas de calificación (por ejemplo, diferentes calificaciones para diferentes niveles de puntos en diferentes asignaciones) y cambios en el esquema de calificación ".
Code Complete , 2da edición, páginas 426 - 428 (Capítulo 18).
fuente
Como han señalado otros, hacer que las condiciones sean más concisas no acelerará la compilación o la ejecución, y tampoco ayuda necesariamente con la legibilidad.
Puede ayudar a hacer su programa más flexible, en caso de que más tarde decida que quiere una versión del juego para niños pequeños en un tablero de 6 x 6, o una versión avanzada (que puede jugar toda la noche) en un tablero de 40 x 50 .
Entonces lo codificaría de la siguiente manera:
Sí, es detallado, pero deja claro exactamente lo que está sucediendo en el tablero de juego.
Si estuviera desarrollando este juego para mostrarlo en un teléfono o tableta, haría variables FILAS y COLUMNAS en lugar de constantes, para que puedan configurarse dinámicamente (al comienzo de un juego) para que coincidan con el tamaño y la orientación de la pantalla.
También permitiría que la orientación de la pantalla se cambiara en cualquier momento, a mitad del juego; todo lo que necesitas hacer es cambiar los valores de FILAS y COLUMNAS, dejando todo lo demás (el número de casilla actual en el que está cada jugador y el cuadrados de inicio / final de todas las serpientes y escaleras) sin cambios. Luego, 'solo' tiene que dibujar bien el tablero y escribir código para sus animaciones (supongo que ese era el propósito de sus
if
declaraciones) ...fuente
#define
#define
instrucciones similares a funciones , poner paréntesis alrededor de los argumentos, donde aparecen en la expansión. Entonces, en lugar de hacerlo#define finished(num) (num == lastSquare)
, debería escribir#define finished(num) ((num) == lastSquare)
. La razón es que si usa una instrucción de este tipo con una expresión que contiene un operador con una precedencia lo suficientemente baja, no obtendrá la respuesta que espera. En este caso, si no usa los paréntesis adicionales, entonces sefinished(a & b)
expande en lo(a & b == lastSquare)
que es casi seguro que no es lo que desea.