如何减少相似代码块的检查量?
How to reduce the amount of checks of similar code blocks?
我似乎无法改进以下代码:
if(state[SDL_SCANCODE_M]){
if(_ball.velocity.x < 0)
_ball.velocity.x -= 20;
else
_ball.velocity.x += 20;
if(_ball.velocity.y < 0)
_ball.velocity.y -= 20;
else
_ball.velocity.y += 20;
}
if(state[SDL_SCANCODE_L]){
if(_ball.velocity.x < 0)
_ball.velocity.x += 20;
else
_ball.velocity.x -= 20;
if(_ball.velocity.y < 0)
_ball.velocity.y += 20;
else
_ball.velocity.y -= 20;
}
它们很相似,但操作相反。
是否有任何最佳实践或技术可以改善此类情况?
这很简单:
// lambda or function it does not matter
auto upgradeVelocity = [](auto& velocity, auto deltaIfGreaterZero, auto deltaIfLessZero){
velocity += velocity < 0 ? deltaIfLessZero : deltaIfGreaterZero;
};
if(state[SDL_SCANCODE_M]){
upgradeVelocity(_ball.velocity.x, -20, 20);
upgradeVelocity(_ball.velocity.y, -20, 20);
}
if(state[SDL_SCANCODE_L]){
upgradeVelocity(_ball.velocity.x, 20, -20);
upgradeVelocity(_ball.velocity.y, 20, -20);
}
你可以看到,L 状态和 M 状态是相互的,你可以这样做:
auto delta = (state[SDL_SCANCODE_L] ? 20 : 0) - (state[SDL_SCANCODE_M] ? 20 : 0);
upgradeVelocity(_ball.velocity.x, delta, -delta);
upgradeVelocity(_ball.velocity.y, delta, -delta);
这段代码可能没有上一段那么清晰,但是很短
你可以pre-compute一些因素来反转条件的符号。
这是一个例子:
int xCoef = (_ball.velocity.x < 0) ? -1 : 1;
int yCoef = (_ball.velocity.y < 0) ? -1 : 1;
if(state[SDL_SCANCODE_M]){
_ball.velocity.x += xCoef * 20;
_ball.velocity.y += yCoef * 20;
}
if(state[SDL_SCANCODE_L]){
_ball.velocity.x -= xCoef * 20;
_ball.velocity.y -= yCoef * 20;
}
更紧凑的 (branch-less) 版本不太清楚(但可能更有效)如下:
int xCoef = (_ball.velocity.x < 0) ? -1 : 1;
int yCoef = (_ball.velocity.y < 0) ? -1 : 1;
int mPressed = state[SDL_SCANCODE_M] ? 1 : 0;
int lPressed = state[SDL_SCANCODE_L] ? 1 : 0;
_ball.velocity.x += (mPressed - lPressed) * xCoef * 20;
_ball.velocity.y += (mPressed - lPressed) * yCoef * 20;
请注意,如果 state
是一个布尔数组,您甚至不需要使用三元数组,因为布尔值可以直接转换为 0-1 整数值。
我似乎无法改进以下代码:
if(state[SDL_SCANCODE_M]){
if(_ball.velocity.x < 0)
_ball.velocity.x -= 20;
else
_ball.velocity.x += 20;
if(_ball.velocity.y < 0)
_ball.velocity.y -= 20;
else
_ball.velocity.y += 20;
}
if(state[SDL_SCANCODE_L]){
if(_ball.velocity.x < 0)
_ball.velocity.x += 20;
else
_ball.velocity.x -= 20;
if(_ball.velocity.y < 0)
_ball.velocity.y += 20;
else
_ball.velocity.y -= 20;
}
它们很相似,但操作相反。
是否有任何最佳实践或技术可以改善此类情况?
这很简单:
// lambda or function it does not matter
auto upgradeVelocity = [](auto& velocity, auto deltaIfGreaterZero, auto deltaIfLessZero){
velocity += velocity < 0 ? deltaIfLessZero : deltaIfGreaterZero;
};
if(state[SDL_SCANCODE_M]){
upgradeVelocity(_ball.velocity.x, -20, 20);
upgradeVelocity(_ball.velocity.y, -20, 20);
}
if(state[SDL_SCANCODE_L]){
upgradeVelocity(_ball.velocity.x, 20, -20);
upgradeVelocity(_ball.velocity.y, 20, -20);
}
你可以看到,L 状态和 M 状态是相互的,你可以这样做:
auto delta = (state[SDL_SCANCODE_L] ? 20 : 0) - (state[SDL_SCANCODE_M] ? 20 : 0);
upgradeVelocity(_ball.velocity.x, delta, -delta);
upgradeVelocity(_ball.velocity.y, delta, -delta);
这段代码可能没有上一段那么清晰,但是很短
你可以pre-compute一些因素来反转条件的符号。
这是一个例子:
int xCoef = (_ball.velocity.x < 0) ? -1 : 1;
int yCoef = (_ball.velocity.y < 0) ? -1 : 1;
if(state[SDL_SCANCODE_M]){
_ball.velocity.x += xCoef * 20;
_ball.velocity.y += yCoef * 20;
}
if(state[SDL_SCANCODE_L]){
_ball.velocity.x -= xCoef * 20;
_ball.velocity.y -= yCoef * 20;
}
更紧凑的 (branch-less) 版本不太清楚(但可能更有效)如下:
int xCoef = (_ball.velocity.x < 0) ? -1 : 1;
int yCoef = (_ball.velocity.y < 0) ? -1 : 1;
int mPressed = state[SDL_SCANCODE_M] ? 1 : 0;
int lPressed = state[SDL_SCANCODE_L] ? 1 : 0;
_ball.velocity.x += (mPressed - lPressed) * xCoef * 20;
_ball.velocity.y += (mPressed - lPressed) * yCoef * 20;
请注意,如果 state
是一个布尔数组,您甚至不需要使用三元数组,因为布尔值可以直接转换为 0-1 整数值。