簡體   English   中英

如果聲明被黑客入侵,是否有更好的方法編寫此代碼?

[英]If statement hack, is there is better way to write this?

我正在嘗試編寫一個簡單的橫向卷軸游戲,這是實驗性的第一步。 如果播放器在某個方向上移得太遠,我有這段代碼可以重新居中屏幕。

有更好的書寫方式嗎? 我覺得我在濫用這種語言,但是效果很好,我認為可能還不錯。

public void adjustFrameIfNecessary()
{
    int dx, dy;
    if ((dx = (GAME_WIDTH - GAME_WIDTH / 3) - player.x) < 0 || (dx = GAME_WIDTH / 3 - player.x) > 0 || (dx = 0) == 0);
    if ((dy = (GAME_HEIGHT - GAME_HEIGHT / 3) - player.y) < 0 || (dy = GAME_HEIGHT / 3 - player.y) > 0 || (dy = 0) == 0);

    if(dx != 0 || dy != 0)
    {
        for (Drawable shiftMe : drawables)
        {
            shiftMe.unconditionalShift(dx, dy);
        }
    }

}

編輯

關於每個人的輸入,為了使其更具可讀性,我將其更改為

public void adjustFrameIfNecessary()
{
    int dx, dy;

    assignX:
    {
        dx = (GAME_WIDTH - GAME_WIDTH / 3) - player.x;
        if(dx < 0) break assignX;
        dx = GAME_WIDTH / 3 - player.x;
        if(dx > 0) break assignX;
        dx = 0;
    }

    assignY:
    {
        dy = (GAME_HEIGHT - GAME_HEIGHT / 3) - player.y;
        if(dy < 0) break assignY;
        dy = GAME_HEIGHT / 3 - player.y;
        if(dy > 0) break assignY;
        dy = 0;
    }

    if (dx != 0 || dy != 0)
    {
        for (Drawable shiftMe : drawables)
        {
            shiftMe.unconditionalShift(dx, dy);
        }
    }

}

這是否更好?

編輯2

public void adjustFrameIfNecessary()
{
    int dx = calculateShift(GAME_WIDTH, frameReference.x);
    int dy = calculateShift(GAME_HEIGHT, frameReference.y);

    if (dx != 0 || dy != 0)
    {
        for (Drawable shiftMe : drawables)
        {
            shiftMe.unconditionalShift(dx, dy);
        }
    }
}

我認為現在很清楚。 感謝大家。

我不確定我為什么會在頂部使用if語句。 初始化變量時,只需分配變量即可。

dx = (GAME_WIDTH - GAME_WIDTH / 3) - player.x)
dy = (GAME_HEIGHT - GAME_HEIGHT / 3) - player.y)

無論您在if語句中如何,它們都將被分配給該對象。 如果rearches第三個條件,那么它已經零,因此沒有理由為它分配。 丟棄兩個if語句,而只堅持直接變量分配。 將條件保持在for循環之上,這是您需要進行的唯一檢查。

您的if語句難以讀取。 如果您(或其他任何人)以后需要進行更改,則可能會非常困難且容易出錯。

編寫不僅有效而且可維護的代碼是一個好習慣。 既然您可以使用它,則應使其更易於維護。

將if語句分成有意義的變量並使用多行。 你不是在寫高爾夫比賽嗎?

待會兒你會謝謝你的。

這個怎么樣?

/* calculate offset to center */
dx = X_current_center - player.x;
dy = Y_current_center - player.y;

if (abs(dx) > MARGIN || abs(dy) > MARGIN)
    /* recenter */

不可讀,但我明白你的意思。 但是,有一件事:為什么不對x和y重用相同的檢查? 通過使用三元運算符,您可以減少一分駭客。

static int toBounds(int max, int curr) {
  int ret;
  return ((ret = (max - max/3) - curr) < 0 || (ret = max/3 - curr) > 0)? ret : 0;
}

改進此類代碼的想法通常是使用數學:)

首先,對於冗長的帖子,我們深表歉意。 如果您親自遇到我,不要問我這個話題,我將不會停止講話。

簡潔版本

做這個:

/**
 * Computes the distance from a point x to an interval [a,b]
 */
public static int distanceToInterval( int x, int a, int b ){
   return x<a? (a-x): ( x>b? (b-x):0 ); 
   // alternative: 
   // return Math.max( a - x, 0 ) + Math.min( b - x, 0 ); 
}

// then use as 
int dx = distanceToInterval( player.x, GAME_WIDTH/3, GAME_WIDTH*2/3 ); 
int dy = distanceToInterval( player.y, GAME_HEIGHT/3, GAME_HEIGHT*2/3 ); 

長版

您的初始聲明

if ((dx = (GAME_WIDTH - GAME_WIDTH / 3) - player.x) < 0 || 
    (dx = GAME_WIDTH / 3 - player.x) > 0 || 
    (dx = 0) == 0);

可以通過將它變成...來清理一點

...更長的版本

dx1 = GAME_WIDTH*2/3 - player.x; 
dx2 = GAME_WIDTH*1/3 - player.x; 
dx3 = 0; 

if( dx1 < 0 ) dx = dx1; 
else if( dx2 > 0 ) dx = dx2; 
else dx = dx3; 

恕我直言,這很清楚。 現在,我可以看到您要執行的操作,並用簡潔的句子表達出來: 如果播放器不在屏幕中間三分之一處,我們想移動屏幕

使其更加清晰

if( player.x < GAME_WIDTH/3 ) dx = GAME_WIDTH/3 - player.x;  // positive num
else if( player.x > GAME_WIDTH*2/3 ) dx = GAME_WIDTH*2/3 - player.x; // negative num
else dx = 0; // no shift

您可以看到我對您的陳述進行了重新排序,我先檢查了左邊界,然后是右邊界。 如果您是一個從右到左閱讀的國家,您可能會發現另一個方向更加直觀:)

是我會選擇的解決方案。 它很短,很可讀,很完美:)

但是,如果您想要更簡潔,則可以更進一步

做數學技巧

您需要了解這三種情況是完全排斥的,它們不可能同時發生。 讓我們回到使用更多的變量:

// on the left side we shift a positive number, or not at all 
dx1 = Math.max( GAME_WIDTH/3 - player.x, 0 ); 
// on the right side we shift a negative amount, or not at all 
dx2 = Math.min( GAME_WIDTH*2/3 - player.x, 0 ); 

現在來看一下這個美麗:

  • 如果GAME_WIDTH/3-player.x > 0 ,則GAME_WIDTH*2/3 - player.x > 0因此Math.min(...,0) = 0
  • 如果GAME_WIDTH*2/3 - player.x < 0 ,則GAME_WIDTH*1/3 - player.x < 0因此Math.max(...,0) = 0

這意味着您可以簡單地將兩者相加來計算總位移。 這是您的代碼將如下所示:

int dx = 
     Math.max( GAME_WIDTH/3 - player.x, 0 ) + // too far to the left? 
     Math.min( GAME_WIDTH*2/3 - player.x, 0 ); // or too far to the right? 

多一點抽象

無論您選擇哪種變體,現在都可以輕松地將其放入方法中。 但是讓我們使其比這種特殊情況更有意義。 我會建議

/**
 * Computes the distance from a point x to an interval [a,b]
 */
public static int distanceToInterval( int x, int a, int b ){
   return 
       Math.max( a - x, 0 ) + // too far to the left? 
       Math.min( b - x, 0 ); // or too far to the right? 
}

// now use as 
int dx = distanceToInterval( player.x, GAME_WIDTH/3, GAME_WIDTH*2/3 ); 
int dy = distanceToInterval( player.y, GAME_HEIGHT/3, GAME_HEIGHT*2/3 ); 

ps,請注意,在GAME_WIDTH - GAME_WIDTH/3 ,我已將GAME_WIDTH - GAME_WIDTH/3替換為GAME_WIDTH*2/3 這兩個整數運算的結果略有不同,但是我更喜歡短版本,因為我發現它更直觀(“三分之二的屏幕”與“整個屏幕,然后三分之一的屏幕”)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM