我目前正在使用SFML for c ++并尝试调整窗口大小但是我发现问题的解决方案并不是很正确,而且我在寻找是否有更好的方法。
我有一个可以多次调整大小的对象,因此它可能适合窗口内部,如果它更大,我必须扩展窗口,如果它更小,我必须缩小窗口。但是我有一个窗口的最小大小,如果对象适合我要将窗口重置为该大小。
这是我现在正在使用的伪代码:
if (Object.getSize().x > window.getSize().x || Object.getSize().y > window.getSize.y){
if(Object.getSize().x > windowMinSize.x){
window.resize(Object.getSize().x, window.getSize().y)
}
if(Object.getSize().y > windowMinSize.y){
window.resize(window.getSize().x, Object.getSize().y)
}
}
else{
window.resize(windowMinSize);
}
我已经查看了switch
和其他选项,但我还没有找到我正在寻找的内容。
答案 0 :(得分:2)
这里使用的正确模式是限制调用外部方法的代码路径的数量,以便只有一个使用点:
你的伪代码变成这样:
auto new_win_size = windowMinSize;
if (Object.getSize().x > window.getSize().x || Object.getSize().y > window.getSize.y){
if(Object.getSize().x > windowMinSize.x){
new_win_size.x = Object.getSize().x;
new_win_size.y = window.getSize().y;
}
if(Object.getSize().y > windowMinSize.y){
new_win_size.x = window.getSize().x;
new_win_size.y = Object.getSize().y;
}
}
window.resize(new_win_size );
但我怀疑你真正想要的是:
auto new_win_size = windowMinSize;
if(Object.getSize().x > windowMinSize.x){
new_win_size.x = Object.getSize().x;
}
if(Object.getSize().y > windowMinSize.y){
new_win_size.y = Object.getSize().y;
}
window.resize(new_win_size );
答案 1 :(得分:1)
我有点困惑,因为最后听起来你只想简单地将窗口调整到对象大小,同时保持特定的最小尺寸。
因此,您只需要简单调用std::max()
来确定两个输入值的较大值:
unsigned int width = std::max(min_width, object_width);
unsigned int height = std::max(min_height, object_height);
使用新尺寸时,它基本上会调整窗口大小以匹配您的对象,除非该对象小于您的最小尺寸。
您可以使用相同的模式,使用std::min()
作为附加图层添加最大尺寸:
unsigned int width = std::min(max_width, std::max(min_width, object_width));
unsigned int height = std::min(max_height, std::max(min_height, object_height));
编辑:正如bolov正确建议的那样,使用新std::clamp
的现代编译器可以进一步简化:
unsigned int width = std::clamp(object_width, min_width, max_width);
unsigned int height = std::clamp(object_height, min_height, max_height);
答案 2 :(得分:1)
您可以使用可变参数template
来获得您想要的效果。我的版本在这里采用else
函数(第一个参数),然后是函数对(谓词,块,谓词,块,......)。如果没有任何谓词计算为true
,则将执行else
函数。这应该适用于C ++ 11或更高版本。
这里可能存在一些错误(我还没有做过多少测试),但你可以踢掉轮胎。如果您将#if 0
更改为#if 1
,则可以发现else
函数无法被调用。
#include <iostream>
template <typename PRED, typename EXEC>
bool multi_branch_detail(PRED pred, EXEC exec) {
if(pred()) {
exec();
return true;
}
return false;
}
template <typename PRED, typename EXEC, typename ...REM>
bool multi_branch_detail(PRED pred, EXEC exec, REM ...rem) {
auto result = false;
if(pred()) {
exec();
result = true;
}
return multi_branch_detail(std::forward<REM>(rem)...) || result;
}
template <typename ELSE, typename ...FNS>
void multi_branch(ELSE el, FNS ...fns) {
if(!multi_branch_detail(std::forward<FNS>(fns)...)) {
el();
}
}
int main() {
multi_branch(
[]() { std::cout << "No cases\n"; },
#if 0
[]() { return 1 < 2; }, []() { std::cout << "first case\n"; },
[]() { return 10 < 20; }, []() { std::cout << "second case\n"; },
#endif
[]() { return 1 > 2; }, []() { std::cout << "bug\n"; }
);
return 0;
}
使用#if 0
输出:
No cases
使用#if 1
输出:
first case
second case
答案 3 :(得分:1)
我将您的问题解释为询问如何重构以下代码:
if ( A )
{
if ( B ) { X } else { Y }
if ( C ) { Z } else { Y }
}
else { Y }
避免重复Y
。
一种方法是:
bool A = ....;
bool B = ....;
bool C = ....;
if ( A && B ) { X }
else if ( A && C ) { Z }
else { Y }
虽然与原始代码的短路行为相比,这可能涉及不必要的函数调用。
最“明显”的解决方案是存储变量:
bool updated = false;
if ( A )
{
if ( B ) { X; updated = true; }
if ( C ) { Z; updated = true; }
}
if ( !updated ) { Y }
另一种方法是使用一个可以突破的控制结构:
do
{
if ( A )
{
if ( B ) { X; break; }
if ( C ) { Z; break; }
}
Y;
} while (0);
有些人不喜欢这个,因为如果你正在阅读代码,看起来我们正在进入一个循环,但后来证明它不是一个循环。就个人而言,我会创建一个函数(break
替换为return
);但如果使用do...while(0)
,你应该在开头添加一个代码注释,指出这不是一个循环。