我的程序中需要一些循环。我可以写出伪代码,但我不完全确定如何逻辑地写它们。
我需要 -
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
这是针对蛇和梯子的棋盘游戏,如果它对我的问题更有意义。
我想第一个if语句我需要使用模数,if (num == 100%10)
是否正确?
第二个我不知道。我可以像if (num > 10 && num is < 21 || etc)
一样写出来,但必须有比这更聪明的东西。
答案 0 :(得分:86)
对于第一个,检查一个数字是否是使用倍数:
if (num % 10 == 0) // its divisible by 10
对于第二个:
if(((num - 1) / 10) % 2 == 1 && num <= 100)
但是相当密集,你可能最好只是明确列出选项。
<小时/> 现在您已经更好地了解了自己在做什么,我将第二个写成:
int getRow(int num) {
return (num - 1) / 10;
}
if (getRow(num) % 2 == 0) {
}
它的逻辑相同,但通过使用该功能,我们可以更清楚地了解它的含义。
答案 1 :(得分:40)
if(num是10的倍数){do this}
if (num % 10 == 0) {
// Do something
}
if(num在11-20,31-40,51-60,71-80,91-100之间){do this}
这里的诀窍是寻找范围之间的某种共性。当然,你总是可以使用&#34;蛮力&#34;方法:
if ((num > 10 && num <= 20) ||
(num > 30 && num <= 40) ||
(num > 50 && num <= 60) ||
(num > 70 && num <= 80) ||
(num > 90 && num <= 100)) {
// Do something
}
但您可能会注意到,如果您从1
中减去num
,则您将拥有以下范围:
10-19, 30-39, 50-59, 70-79, 90-99
换句话说,所有2位数字的第一个数字是奇数。接下来,您需要提出一个表达这一点的公式。您可以通过除以10获得第一个数字,并且当您除以2时,可以通过检查剩余的1来测试它是否为奇数。
if ((num > 0) && (num <= 100) && (((num - 1) / 10) % 2 == 1)) {
// Do something
}
考虑到更长但可维护的代码与更短的&#34;聪明的&#34;之间的权衡。代码,我每次都选择更长,更清晰。至少,如果你想要聪明,请包括一个评论,准确解释你正在努力完成的事情。
这有助于假设下一个开发代码的开发人员已经武装起来并知道你住在哪里。 : - )
答案 2 :(得分:30)
如果您使用GCC或任何支持Case Ranges的编译器,您可以执行此操作,但您的代码将不可移植
switch(num)
{
case 11 ... 20:
case 31 ... 40:
case 51 ... 60:
case 71 ... 80:
case 91 ... 100:
// do something
break;
default:
// do something else
break;
}
答案 3 :(得分:15)
这对未来的访客来说比初学者更多。对于更通用的类似算法的解决方案,您可以获取起始值和结束值的列表,并检查传递的值是否在其中一个内:
template<typename It, typename Elem>
bool in_any_interval(It first, It last, const Elem &val) {
return std::any_of(first, last, [&val](const auto &p) {
return p.first <= val && val <= p.second;
});
}
为简单起见,我使用了多态lambda(C ++ 14)而不是显式pair
参数。这也应该坚持使用<
和==
来与标准算法保持一致,但只要Elem
为其定义了<=
,它就会像这样工作。无论如何,它可以像这样使用:
std::pair<int, int> intervals[]{
{11, 20}, {31, 40}, {51, 60}, {71, 80}, {91, 100}
};
const int num = 15;
std::cout << in_any_interval(std::begin(intervals), std::end(intervals), num);
有一个实例here。
答案 4 :(得分:5)
第一个很简单,你只需要将模数运算符应用于你的num值:
if ( ( num % 10 ) == 0)
SInce c ++正在评估每个不为0的数字,你也可以写:
if ( ! ( num % 10 ) ) //does not have a residue when devided by 10
对于第二个,我认为理解这个更清晰:
模式每20次重复一次,因此您可以计算模20。 除了那些可以被20分割的元素之外,你想要的所有元素都会排成一行。
要获得这些,只需使用num-1或更好的num + 19来避免处理负数。
if ( ( ( num + 19 ) % 20 ) > 9 )
这假设模式永远重复,因此对于111-120,它将再次应用,依此类推。否则,您需要将数字限制为100:
if ( ( ( ( num + 19 ) % 20 ) > 9 ) && ( num <= 100 ) )
答案 5 :(得分:5)
在代码中有好几条评论,它可以写得非常简洁和可读。
// Check if it's a multiple of 10
if (num % 10 == 0) { ... }
// Check for whether tens digit is zero or even (1-10, 21-30, ...)
if ((num / 10) % 2 == 0) { ... }
else { ... }
答案 6 :(得分:4)
你基本上是自己解释了答案,但以下是代码。
if((x % 10) == 0) {
//do this
}
if((x > 10 && x < 21) || (x > 30 && x < 41) || (x > 50 && x < 61) || (x > 70 && x < 81) || (x > 90 && x < 101)) {
//do this
}
答案 7 :(得分:3)
你可能会过度思考这个问题。
if (x % 10)
{
.. code for 1..9 ..
} else
{
.. code for 0, 10, 20 etc.
}
第一行if (x % 10)
起作用,因为(a)10的倍数值计算为'0',其他数字导致其自动保留,(b){{1}中的值为0 }被视为if
,其他任何值均为false
。
编辑:
要在二十几岁时来回切换,请使用相同的技巧。这一次,关键数字是true
:
10
if (((x-1)/10) & 1)
{
.. code for 10, 30, ..
} else
{
.. code for 20, 40, etc.
}
返回0到9之间的任何数字x/10
,10到19返回0
,依此类推。对偶数或奇数进行测试 - 1
- 告诉您它是偶数还是奇数。由于您的范围实际上是“11到20”,因此在测试前减去1。
答案 8 :(得分:1)
请求可读性
虽然你已经有了一些很好的答案,但我想推荐一种编程技巧,让你的代码对未来的读者更具可读性 - 可能是你在六个月内,一位同事要求进行代码审查,你的继任者,...
这是将任何“聪明”语句包装到一个函数中,该函数完全显示(及其名称)它正在做什么。虽然对性能产生微不足道的影响(来自“函数调用开销”),但在这样的游戏情况下,这几乎可以忽略不计。
在此过程中,您可以清理输入 - 例如,测试“非法”值。因此,您最终可能会得到这样的代码 - 看看它的可读性有多大? “辅助函数”可以隐藏在某个地方(不需要在主模块中:从他们的名字中可以清楚地知道他们做了什么):
#include <stdio.h>
enum {NO, YES, WINNER};
enum {OUT_OF_RANGE=-1, ODD, EVEN};
int notInRange(int square) {
return(square < 1 || square > 100)?YES:NO;
}
int isEndOfRow(int square) {
if (notInRange(square)) return OUT_OF_RANGE;
if (square == 100) return WINNER; // I am making this up...
return (square % 10 == 0)? YES:NO;
}
int rowType(unsigned int square) {
// return 1 if square is in odd row (going to the right)
// and 0 if square is in even row (going to the left)
if (notInRange(square)) return OUT_OF_RANGE; // trap this error
int rowNum = (square - 1) / 10;
return (rowNum % 2 == 0) ? ODD:EVEN; // return 0 (ODD) for 1-10, 21-30 etc.
// and 1 (EVEN) for 11-20, 31-40, ...
}
int main(void) {
int a = 12;
int rt;
rt = rowType(a); // this replaces your obscure if statement
// and here is how you handle the possible return values:
switch(rt) {
case ODD:
printf("It is an odd row\n");
break;
case EVEN:
printf("It is an even row\n");
break;
case OUT_OF_RANGE:
printf("It is out of range\n");
break;
default:
printf("Unexpected return value from rowType!\n");
}
if(isEndOfRow(10)==YES) printf("10 is at the end of a row\n");
if(isEndOfRow(100)==WINNER) printf("We have a winner!\n");
}
答案 9 :(得分:1)
第一个:
if (x % 10 == 0)
将适用于:
10, 20, 30, .. 100 .. 1000 ...
第二个:
if (((x-1) / 10) % 2 == 1)
将申请:
11-20, 31-40, 51-60, ..
我们基本上先做x-1
来获得:
10-19, 30-39, 50-59, ..
然后我们将它们除以10
以得到:
1, 3, 5, ..
所以我们检查这个结果是否奇怪。
答案 10 :(得分:1)
您可以尝试以下操作:
// multiple of 10
if ((num % 10) == 0)
{
// Do something
}
else if (((num / 10) % 2) != 0)
{
//11-20, 31-40, 51-60, 71-80, 91-100
}
else
{
//other case
}
答案 11 :(得分:0)
正如其他人所指出的那样,使条件更简洁不会加速编译或执行,也不一定有助于提高可读性。
它可以帮助您使程序更加灵活,以防您以后决定在6 x 6板上使用游戏的幼儿版本,或者高级版本(您可以整夜玩) 40 x 50板。
所以我会按如下方式编写代码:
// What is the size of the game board?
#define ROWS 10
#define COLUMNS 10
// The numbers of the squares go from 1 (bottom-left) to (ROWS * COLUMNS)
// (top-left if ROWS is even, or top-right if ROWS is odd)
#define firstSquare 1
#define lastSquare (ROWS * COLUMNS)
// We haven't started until we roll the die and move onto the first square,
// so there is an imaginary 'square zero'
#define notStarted(num) (num == 0)
// and we only win when we land exactly on the last square
#define finished(num) (num == lastSquare)
#define overShot(num) (num > lastSquare)
// We will number our rows from 1 to ROWS, and our columns from 1 to COLUMNS
// (apologies to C fanatics who believe the world should be zero-based, which would
// have simplified these expressions)
#define getRow(num) (((num - 1) / COLUMNS) + 1)
#define getCol(num) (((num - 1) % COLUMNS) + 1)
// What direction are we moving in?
// On rows 1, 3, 5, etc. we go from left to right
#define isLeftToRightRow(num) ((getRow(num) % 2) == 1)
// On rows 2, 4, 6, etc. we go from right to left
#define isRightToLeftRow(num) ((getRow(num) % 2) == 0)
// Are we on the last square in the row?
#define isLastInRow(num) (getCol(num) == COLUMNS)
// And finally we can get onto the code
if (notStarted(mySquare))
{
// Some code for when we haven't got our piece on the board yet
}
else
{
if (isLastInRow(mySquare))
{
// Some code for when we're on the last square in a row
}
if (isRightToLeftRow(mySquare))
{
// Some code for when we're travelling from right to left
}
else
{
// Some code for when we're travelling from left to right
}
}
是的,它很冗长,但它清楚地说明了游戏板上发生了什么。
如果我开发此游戏以在手机或平板电脑上显示,我会制作ROWS和COLUMNS变量而不是常量,因此可以动态设置(在游戏开始时)以匹配屏幕大小和方向。
我还允许在游戏中期随时更改屏幕方向 - 您需要做的就是切换ROWS和COLUMNS的值,同时保留其他所有内容(每个玩家所在的当前方格数,以及所有蛇和梯子的开始/结束方块不变。
那么你只需要很好地绘制板子,并为你的动画编写代码(我认为这是你的if
陈述的目的)......
答案 12 :(得分:0)
我知道这个问题有很多答案,但无论如何我会把我扔到这里......
取自Steve McConnell的Code Complete第2版:
“阶梯式访问表:
另一种表格访问是阶梯式方法。此访问方法不是
直接作为索引结构,但它不会浪费尽可能多的数据空间。
阶梯结构的一般概念,如图18-5所示,是a中的条目
表对数据范围有效,而不是对不同的数据点有效。
图18-5阶梯式方法通过确定等级来对每个条目进行分类 它击中了“阶梯”。它击中的“步骤”决定了它的类别。
例如,如果您正在编写评分程序,则“B”条目范围可能是75 百分比到百分之九十。以下是您可能有一天要编程的一系列成绩:
要使用阶梯方法,请将每个范围的上端放入表格中 然后写一个循环来检查每个范围上端的分数。当你找到 分数首先超过范围的顶部,你知道什么分数 是。使用阶梯技术,你必须小心处理的端点 范围正确。这是Visual Basic中的代码,它将成绩分配给一组学生 基于这个例子的凹痕:
虽然这是一个简单的例子,但您可以轻松地将其概括为处理多个学生,多个评分方案(例如,不同作业中不同分级的不同成绩)以及评分方案中的更改。“
代码完成第2版第426 - 428页(第18章)。 希望这会有所帮助,抱歉我没有用c ++转换代码,但你知道中国古老的说法:“不要给乞丐喂鱼,给他一根钓竿!” :)