बहुत सारे 'अगर' बयान?


263

निम्न कोड काम करता है कि मुझे इसकी आवश्यकता कैसे है, लेकिन यह बदसूरत, अत्यधिक या कई अन्य चीजें हैं। मैंने सूत्रों को देखा है और कुछ समाधान लिखने का प्रयास किया है, लेकिन मैं इसी तरह के बयानों को समाप्त करता हूं।

क्या गणित के एक प्रकार के सूत्र हैं जो मुझे इस उदाहरण में लाभान्वित करेंगे या यदि कथन स्वीकार्य हैं तो 16 हैं?

कोड की व्याख्या करने के लिए, यह एक तरह के युगपत-आधारित-आधारित खेल के लिए है .. दो खिलाड़ियों के पास चार एक्शन बटन होते हैं और परिणाम एक सरणी (0-3) से आते हैं, लेकिन चर 'एक' और 'दो' हो सकते हैं कुछ भी सौंपा अगर यह मदद करता है। परिणाम है, 0 = न तो जीत, 1 = p1 जीत, 2 = P2 जीत, 3 = दोनों जीत।

public int fightMath(int one, int two) {

    if(one == 0 && two == 0) { result = 0; }
    else if(one == 0 && two == 1) { result = 0; }
    else if(one == 0 && two == 2) { result = 1; }
    else if(one == 0 && two == 3) { result = 2; }
    else if(one == 1 && two == 0) { result = 0; }
    else if(one == 1 && two == 1) { result = 0; }
    else if(one == 1 && two == 2) { result = 2; }
    else if(one == 1 && two == 3) { result = 1; }
    else if(one == 2 && two == 0) { result = 2; }
    else if(one == 2 && two == 1) { result = 1; }
    else if(one == 2 && two == 2) { result = 3; }
    else if(one == 2 && two == 3) { result = 3; }
    else if(one == 3 && two == 0) { result = 1; }
    else if(one == 3 && two == 1) { result = 2; }
    else if(one == 3 && two == 2) { result = 3; }
    else if(one == 3 && two == 3) { result = 3; }

    return result;
}


9
निश्चित रूप से यहाँ कुछ तर्क है जिन्हें क्रूरता के बजाय सामान्यीकृत किया जा सकता है? निश्चित रूप से कुछ फ़ंक्शन है f(a, b)जो सामान्य मामले में जवाब देता है? आपने गणना के तर्क की व्याख्या नहीं की है, इसलिए सभी उत्तर केवल एक सुअर पर लिपस्टिक हैं। मैं आपके प्रोग्राम लॉजिक पर गंभीरता से पुनर्विचार करके शुरू करूँगा, intकार्यों के लिए झंडे का उपयोग करना बहुत पुराना है। enums में तर्क हो सकते हैं और वर्णनात्मक हो सकते हैं, इससे आप अपने कोड को और अधिक आधुनिक तरीके से लिख सकेंगे।
बोरिस ने

ऊपर दिए गए अपने वैकल्पिक प्रश्न में दिए गए @Steve बेनेट के जवाबों को पढ़ने के बाद मैं मान सकता हूं कि इसका कोई सीधा फॉरवर्ड फार्मूला उत्तर नहीं है क्योंकि यह अनिवार्य रूप से डेटाबेस के समान है। मैंने मूल प्रश्न में यह समझाने का प्रयास किया कि मैं एक साधारण गेम (फाइटर) बना रहा था और उपयोगकर्ताओं के पास 4 बटनों का चयन है: ब्लॉकहिग (0), ब्लॉकलो (1), अटैक हाई (2) और अटैकलो (3)। इन नंबरों को जरूरत पड़ने तक एक सरणी में रखा जाता है। बाद में इनका उपयोग फंक्शन 'फाइटमैथ ()' द्वारा किया जाता है जो रिजल्ट देने के लिए प्लेयरटाउन के खिलाडियों के चयन का आह्वान करता है। कोई वास्तविक टक्कर का पता लगाने नहीं।
टॉमफिरथ

9
यदि आपके पास कोई उत्तर है, तो कृपया इसे इस तरह पोस्ट करें। टिप्पणियों में विस्तारित चर्चा का पालन करना कठिन है, खासकर जब कोड शामिल हो। यदि आप इस बारे में बात करना चाहते हैं कि क्या इस प्रश्न को कोड रिव्यू में माइग्रेट किया जाना चाहिए था, तो इसके बारे में एक मेटा चर्चा है।
जॉर्ज स्टॉकर

1
"डेटाबेस के समान" से आपका क्या अभिप्राय है? यदि ये मान डेटाबेस में हैं, तो उन्हें वहां से खींचें। अन्यथा, अगर यह वास्तव में यह जटिल है, तो मैं इसे ऐसे ही छोड़ दूंगा जैसे आपके पास है और प्रत्येक पंक्ति के बाद व्यावसायिक तर्क टिप्पणियां जोड़ते हैं ताकि लोग समझें कि क्या चल रहा है। यह बेहतर (मेरे लिए) लंबा और स्पष्ट है - भविष्य में कोई भी समझ सकता है कि क्या चल रहा है। यदि आप इसे एक मानचित्र में रखते हैं या कोड की 8 पंक्तियों को बचाने की कोशिश करते हैं, तो उल्टा वास्तव में छोटा है, और डाउनसाइज़ बड़ा है: आप इसे किसी ऐसे व्यक्ति के लिए अधिक से अधिक भ्रमित करते हैं, जिसे आपके कोड को एक दिन पढ़ने की आवश्यकता है।
स्कैज

जवाबों:


600

यदि आप एक सूत्र के साथ नहीं आ सकते हैं, तो आप इस तरह के परिणामों की एक सीमित संख्या के लिए एक तालिका का उपयोग कर सकते हैं:

final int[][] result = new int[][] {
  { 0, 0, 1, 2 },
  { 0, 0, 2, 1 },
  { 2, 1, 3, 3 },
  { 1, 2, 3, 3 }
};
return result[one][two];

7
यह दिलचस्प है क्योंकि मैंने पहले इस समाधान को नहीं देखा है। मुझे यकीन नहीं है कि मैं रिटर्न रिजल्ट को समझ पाऊंगा, लेकिन परीक्षण में मजा आएगा।
टॉमफिरथ

4
आपको मुखर की जरूरत नहीं है, जावा एक IndexOutOfBoundsExceptionवैसे भी फेंक देगा यदि एक या अधिक सूचकांक सीमा से बाहर हैं।
JAB

43
@JoeHarper यदि आप कुछ आसान पढ़ना चाहते हैं, तो आप पहली बार में जादू की संख्या का उपयोग नहीं करेंगे और आपके पास मैपिंग की व्याख्या करने वाली एक टिप्पणी होगी। जैसा कि यह है, मैं इस संस्करण को मूल के लिए पसंद करता हूं, लेकिन लंबे समय में बनाए रखने योग्य कुछ चीज़ों के लिए, मैं एक ऐसे प्रकार का उपयोग करूंगा जिसमें शामिल प्रकार या कम से कम नामित स्थिरांक शामिल हैं।
JAB

13
@ जोहपर "सैद्धांतिक रूप से" एक बात है, "व्यावहारिक रूप से" एक और है। बेशक मैं वर्णनात्मक नामकरण ( लूप वेरिएबल्स के लिए i/ j/ kसम्मेलन के अपवाद के साथ) का उपयोग करने की कोशिश करता हूं , नाम दिया गया है, स्थिरांक, एक पठनीय फैशन में मेरे कोड की व्यवस्था, आदि, लेकिन जब चर और फ़ंक्शन नाम 20 से अधिक वर्ण लेने लगते हैं प्रत्येक मुझे लगता है कि यह वास्तव में कम पठनीय कोड की ओर जाता है। मेरा सामान्य तरीका है कि आप यहां टिप्पणियों के साथ समझदार लेकिन रसीले कोड के लिए प्रयास करें और यह समझाने के लिए कि कोड को इस तरह से संरचित क्यों किया जाता है (बनाम कैसे)। क्यों नामों में पुट डालकर बस सब कुछ गँवा दिया।
JAB

13
मुझे इस विशिष्ट समस्या के लिए यह समाधान पसंद है क्योंकि परिणाम वास्तव में एक परिणाम मैट्रिक्स द्वारा तय किए जाते हैं।
कोशिश कर रहा है

201

चूंकि आपका डेटा सेट इतना छोटा है, आप सब कुछ 1 लंबे पूर्णांक में संपीड़ित कर सकते हैं और इसे एक सूत्र में बदल सकते हैं

public int fightMath(int one,int two)
{
   return (int)(0xF9F66090L >> (2*(one*4 + two)))%4;
}

अधिक बिटवार प्रकार:

यह इस तथ्य का उपयोग करता है कि सब कुछ 2 का एक बहु है

public int fightMath(int one,int two)
{
   return (0xF9F66090 >> ((one << 3) | (two << 1))) & 0x3;
}

जादू की उत्पत्ति की उत्पत्ति

मैं क्या कह सकता हूँ? दुनिया को जादू की जरूरत है, कभी-कभी इसके निर्माण के लिए किसी चीज की संभावना होती है।

ओपी की समस्या को हल करने वाले फ़ंक्शन का सार 2 नंबरों (एक, दो), डोमेन {0,1,2,3} से सीमा {0,1,2,3} तक का नक्शा है। प्रत्येक उत्तर में यह बताया गया है कि उस नक्शे को कैसे लागू किया जाए।

इसके अलावा, आप कई सवालों के जवाब में देख सकते हैं 1 2-अंकों के आधार 4 नंबर एन (एक, दो) के नक्शे के रूप में समस्या का एक प्रतिबंध जहां एक अंक 1 है, दो अंक 2 है, और एन = 4 * एक + दो; एन = {0,1,2, ..., 15} - सोलह विभिन्न मूल्य, यह महत्वपूर्ण है। फ़ंक्शन का आउटपुट एक 1-अंकों का आधार 4 नंबर {0,1,2,3} - 4 विभिन्न मान भी महत्वपूर्ण है।

अब, 1-अंकों के आधार 4 नंबर को 2-अंकों के आधार 2 नंबर के रूप में व्यक्त किया जा सकता है; {[1,1,2,3} = {00,01,10,11}, और इसलिए प्रत्येक आउटपुट को केवल 2 बिट्स के साथ एन्कोड किया जा सकता है। ऊपर से, केवल 16 अलग-अलग आउटपुट संभव हैं, इसलिए 16 * 2 = 32 बिट्स पूरे नक्शे को एन्कोड करने के लिए आवश्यक है; यह सब 1 पूर्णांक में फिट हो सकता है।

निरंतर M मानचित्र m की एन्कोडिंग है जहाँ m (0) बिट्स में एनकोडेड है [0: 1], m (1) बिट्स में एन्कोडेड है [2: 3], और m (n) बिट्स में एन्कोडेड है एम [n * 2: n * 2 + 1]।

जो कुछ भी रहता है वह अनुक्रमणित होता है और निरंतर के दाहिने हिस्से को वापस करता है, इस स्थिति में आप M दाएं 2 * N बार शिफ्ट कर सकते हैं और 2 कम से कम महत्वपूर्ण बिट्स ले सकते हैं, वह है (M >> 2 * N) & 0x3। भाव (एक << 3) और (दो << 1) केवल 2 * x = x << 1 और 8 * x = x << 3 को ध्यान में रखते हुए चीजों को गुणा कर रहे हैं।


79
स्मार्ट, लेकिन कोड पढ़ने वाले किसी और के पास इसे समझने का मौका नहीं होगा।
अरन मुल्होलैंड

106
मुझे लगता है कि यह बहुत बुरा अभ्यास है। लेखक के अलावा किसी और को यह समझ में नहीं आएगा। आप कोड के एक टुकड़े को देखना चाहते हैं और इसे जल्दी से समझना चाहते हैं। लेकिन यह सिर्फ समय की बर्बादी है।
बाल्ज़ नेमेथ

14
मैं इस पर @ BalázsMáriaNémeth के साथ हूं। हालांकि बहुत प्रभावशाली है, आपको हिंसक मनोरोगियों के लिए कोडिंग होना चाहिए!
OrhanC1

90
सभी डाउनवोटर्स सोचते हैं कि यह एक छिपी हुई कोड गंध है। सभी upvoters एक ही सोचते हैं, लेकिन इसके पीछे की चतुराई की प्रशंसा करते हैं। +1 (कभी भी इस कोड का उपयोग न करें।)
usr

4
केवल कोड लिखने का कितना सुंदर उदाहरण है !
लीलैंड

98

मुझे JAB को छोड़कर प्रस्तुत कोई भी समाधान पसंद नहीं है। दूसरों में से कोई भी कोड पढ़ना और समझना नहीं चाहता है कि क्या गणना की जा रही है

यहां बताया गया है कि मैं इस कोड को कैसे लिखूंगा - मुझे केवल C # पता है, जावा नहीं, लेकिन आपको चित्र मिलता है:

const bool t = true;
const bool f = false;
static readonly bool[,] attackResult = {
    { f, f, t, f }, 
    { f, f, f, t },
    { f, t, t, t },
    { t, f, t, t }
};
[Flags] enum HitResult 
{ 
    Neither = 0,
    PlayerOne = 1,
    PlayerTwo = 2,
    Both = PlayerOne | PlayerTwo
}
static HitResult ResolveAttack(int one, int two)
{
    return 
        (attackResult[one, two] ? HitResult.PlayerOne : HitResult.Neither) | 
        (attackResult[two, one] ? HitResult.PlayerTwo : HitResult.Neither);
}    

अब यह अधिक स्पष्ट है कि यहां क्या गणना की जा रही है: यह इस बात पर जोर देता है कि हम गणना कर रहे हैं कि कौन किस हमले से प्रभावित होता है, और दोनों परिणामों को वापस करता है।

हालाँकि यह और भी बेहतर हो सकता है; कि बूलियन सरणी कुछ हद तक अपारदर्शी है। मुझे टेबल लुकअप दृष्टिकोण पसंद है लेकिन मैं इसे इस तरह से लिखना चाहूंगा जिससे यह स्पष्ट हो सके कि इच्छित गेम शब्दार्थ क्या थे। यही है, "शून्य के हमले और एक हिट में एक परिणाम की रक्षा" के बजाय, कोड को अधिक स्पष्ट रूप से "कम किक हमले और बिना किसी हिट में कम ब्लॉक रक्षा परिणाम" बनाने का एक तरीका ढूंढें। कोड को खेल के व्यावसायिक तर्क को प्रतिबिंबित करें।


66
बकवास। अधिकांश हल्के अनुभव वाले कार्यक्रम यहां दी जा रही सलाह की सराहना करने में सक्षम होंगे, और कोडिंग शैली को अपने स्वयं के लैंग गेज पर लागू करेंगे। सवाल यह था कि अगर एक तार से बचा जाए। इससे पता चलता है कि कैसे।
ग्रीनएजजडे

6
@ user3414693: मैं अच्छी तरह से जानता हूं कि यह एक जावा प्रश्न है। यदि आप उत्तर को ध्यान से पढ़ते हैं जो स्पष्ट हो जाता है। यदि आप मानते हैं कि मेरा उत्तर नासमझी है तो मैं आपको अपना स्वयं का उत्तर लिखने के लिए प्रोत्साहित करता हूं जो आपको बेहतर लगता है।
एरिक लिपर्ट

1
@ EricLippert मुझे JAB का समाधान भी पसंद है। IMHO, सी # में एनम प्रकार वांछित होने के लिए बहुत कुछ छोड़ देता है। यह सफलता के दर्शन के गड्ढे का पालन नहीं करता है जो बाकी सुविधाएँ करते हैं। उदाहरण के लिए stackoverflow.com/a/847353/92414 क्या c # टीम के पास कोई नया एनम टाइप बनाने की योजना है (ताकि मौजूदा कोड को तोड़ने से बचा जा सके) जो बेहतर तरीके से बनाया गया है?
SolutionYogi

@SolutionYogi: मुझे सी # में एनम बहुत पसंद नहीं है, हालांकि वे वैसे हैं जैसे वे अच्छे ऐतिहासिक कारणों से हैं। (मौजूदा COM enums के साथ संगतता के लिए ज्यादातर।) मैं किसी भी योजनाओं के बारे में पता करने के लिए नहीं जानता हूँ कि सी # 6 में enums के लिए नया गियर जोड़ने के लिए
एरिक लिपर्ट

3
@Listist नहीं, टिप्पणियां नहीं चलती हैं। ओपी ने ठीक वही किया जो किया जाना चाहिए; टिप्पणियों को स्पष्ट कोड में बदलें। उदाहरण के लिए देखें स्टीव मैककोनेल कोड पूरा stevemcconnell.com/cccntnt.htm
djechlin

87

आप मैट्रिक्स बना सकते हैं जिसमें परिणाम होते हैं

int[][] results = {{0, 0, 1, 2}, {0, 0, 2, 1},{2, 1, 3, 3},{2, 1, 3, 3}};

जब आप मूल्य प्राप्त करना चाहते हैं तो आप उपयोग करेंगे

public int fightMath(int one, int two) {
  return this.results[one][two]; 
}

69

अन्य लोगों ने पहले से ही मेरे प्रारंभिक विचार, मैट्रिक्स विधि का सुझाव दिया है, लेकिन अगर बयानों को समेकित करने के अलावा, आप कुछ सुनिश्चित करने से बच सकते हैं कि आपूर्ति की गई तर्क अपेक्षित सीमा में हैं और इन-प्लेस रिटर्न का उपयोग करके (कुछ कोडिंग) मानकों को मैंने फ़ंक्शंस के लिए एक-पॉइंट-आउट-आउट लागू करने के लिए देखा है, लेकिन मैंने पाया है कि तीर कोडिंग से बचने के लिए कई रिटर्न बहुत उपयोगी हैं और जावा में अपवादों के प्रसार के साथ वैसे भी इस तरह के नियम को सख्ती से लागू करने के लिए बहुत अधिक बिंदु नहीं हैं। विधि के अंदर फेंका गया कोई भी अनकहा अपवाद वैसे भी बाहर निकलने का एक संभावित बिंदु है)। नेस्टिंग स्विच स्टेटमेंट एक संभावना है, लेकिन आपके द्वारा जांचे जा रहे मानों की छोटी सी श्रेणी के लिए मैं यह पाता हूं कि क्या स्टेटमेंट्स अधिक कॉम्पैक्ट हैं और प्रदर्शन के अंतर के परिणामस्वरूप अधिक होने की संभावना नहीं है,

public int fightMath(int one, int two) {
    if (one > 3 || one < 0 || two > 3 || two < 0) {
        throw new IllegalArgumentException("Result is undefined for arguments outside the range [0, 3]");
    }

    if (one <= 1) {
        if (two <= 1) return 0;
        if (two - one == 2) return 1;
        return 2; // two can only be 3 here, no need for an explicit conditional
    }

    // one >= 2
    if (two >= 2) return 3;
    if (two == 1) return 1;
    return 2; // two can only be 0 here
}

यह अंत में कम पठनीय होता है क्योंकि यह इनपुट-> परिणाम मानचित्रण के कुछ हिस्सों की अनियमितता के कारण हो सकता है। मैं इसकी सरलता के कारण मैट्रिक्स शैली का पक्ष लेता हूं और आप दृष्टिगोचर बनाने के लिए मैट्रिक्स कैसे सेट कर सकते हैं (हालांकि वह कर्णघट मानचित्रों की मेरी यादों से प्रभावित है):

int[][] results = {{0, 0, 1, 2},
                   {0, 0, 2, 1},
                   {2, 1, 3, 3},
                   {2, 1, 3, 3}};

अद्यतन: ब्लॉकिंग / हिटिंग के अपने उल्लेख को देखते हुए, यहाँ फ़ंक्शन के लिए एक अधिक क्रांतिकारी परिवर्तन है जो इनपुट और परिणाम के लिए उचित / विशेषता-धारण किए हुए प्रकारों का उपयोग करता है और अवरुद्ध करने के लिए परिणाम को थोड़ा संशोधित करता है, जिसके परिणामस्वरूप परिणाम अधिक होना चाहिए पठनीय कार्य।

enum MoveType {
    ATTACK,
    BLOCK;
}

enum MoveHeight {
    HIGH,
    LOW;
}

enum Move {
    // Enum members can have properties/attributes/data members of their own
    ATTACK_HIGH(MoveType.ATTACK, MoveHeight.HIGH),
    ATTACK_LOW(MoveType.ATTACK, MoveHeight.LOW),
    BLOCK_HIGH(MoveType.BLOCK, MoveHeight.HIGH),
    BLOCK_LOW(MoveType.BLOCK, MoveHeight.LOW);

    public final MoveType type;
    public final MoveHeight height;

    private Move(MoveType type, MoveHeight height) {
        this.type = type;
        this.height = height;
    }

    /** Makes the attack checks later on simpler. */
    public boolean isAttack() {
        return this.type == MoveType.ATTACK;
    }
}

enum LandedHit {
    NEITHER,
    PLAYER_ONE,
    PLAYER_TWO,
    BOTH;
}

LandedHit fightMath(Move one, Move two) {
    // One is an attack, the other is a block
    if (one.type != two.type) {
        // attack at some height gets blocked by block at same height
        if (one.height == two.height) return LandedHit.NEITHER;

        // Either player 1 attacked or player 2 attacked; whoever did
        // lands a hit
        if (one.isAttack()) return LandedHit.PLAYER_ONE;
        return LandedHit.PLAYER_TWO;
    }

    // both attack
    if (one.isAttack()) return LandedHit.BOTH;

    // both block
    return LandedHit.NEITHER;
}

यदि आप अधिक ऊंचाइयों के ब्लॉक / हमलों को जोड़ना चाहते हैं, तो आपको केवल फ़ंक्शन को बदलना नहीं है; अतिरिक्त प्रकार की चालों को जोड़ने पर संभवतः फ़ंक्शन के संशोधन की आवश्यकता होगी, हालांकि। इसके अलावा, EnumSetरों अधिक मुख्य enum के गुणों, जैसे के रूप में अतिरिक्त enums का उपयोग करने से एक्स्टेंसिबल हो सकता है EnumSet<Move> attacks = EnumSet.of(Move.ATTACK_HIGH, Move.ATTACK_LOW, ...);और उसके बाद attacks.contains(move)के बजाय move.type == MoveType.ATTACK, हालांकि का उपयोग कर EnumSetरों शायद प्रत्यक्ष बराबरी चेकों की तुलना में थोड़ा धीमी हो जाएगा।


उस मामले के लिए जहां एक सफल ब्लॉक एक काउंटर में परिणाम देता है, आप के if (one.height == two.height) return LandedHit.NEITHER;साथ बदल सकते हैं

if (one.height == two.height) {
    // Successful block results in a counter against the attacker
    if (one.isAttack()) return LandedHit.PLAYER_TWO;
    return LandedHit.PLAYER_ONE;
}

इसके अलावा, ifटर्नरी ऑपरेटर के उपयोग के साथ कुछ कथनों को बदलने से ( boolean_expression ? result_if_true : result_if_false) कोड को अधिक कॉम्पैक्ट बना सकता है (उदाहरण के लिए, पूर्ववर्ती ब्लॉक में कोड बन जाएगा return one.isAttack() ? LandedHit.PLAYER_TWO : LandedHit.PLAYER_ONE;), लेकिन इससे हार्ड-टू-रीड ओनलिनर्स हो सकते हैं, इसलिए मैं ' टी इसे और अधिक जटिल शाखाओं में बँटाने की सलाह देते हैं।


मैं निश्चित रूप से इस पर गौर करूंगा लेकिन मेरा वर्तमान कोड मुझे अपनी स्प्रिटशीट पर आरंभ बिंदुओं के रूप में उपयोग करने oneऔर twoपुन: उपयोग करने की अनुमति देता है । हालाँकि इसके लिए अनुमति देने के लिए बहुत अतिरिक्त कोड की आवश्यकता नहीं होती है।
टॉमफिरथ

2
@ TomFirth84 एक ऐसा EnumMapवर्ग है जिसका उपयोग आप एनमों को अपने पूर्णांक ऑफ़सेट्स में मैप करने के लिए कर सकते हैं (आप सीधे एनम सदस्यों के क्रमिक मूल्यों का भी उपयोग कर सकते हैं, उदाहरण के Move.ATTACK_HIGH.ordinal()लिए 0, Move.ATTACK_LOW.ordinal()होगा 1, आदि, लेकिन यह स्पष्ट रूप से अधिक नाजुक या कम लचीला है) प्रत्येक सदस्य को मौजूदा मान के बीच में मानों को जोड़ने के रूप में मान के साथ जोड़ना, गिनती को फेंक देगा, जो कि मामला नहीं होगाEnumMap ।)
JAB

7
यह सबसे पठनीय समाधान है क्योंकि यह कोड को उस चीज़ में अनुवादित करता है जो कोड पढ़ने वाले व्यक्ति के लिए सार्थक है।
डेविड स्टैनली

आपका कोड, कम से कम एनमों का उपयोग करने वाला, गलत है। यदि ओपी में एक आत्महत्या ब्लॉक में बयानों की रिकॉर्डिंग हमलावर पर हिट होती है। लेकिन अर्थपूर्ण कोड के लिए +1।
तैमिर

2
तुम भी एनम के attack(against)लिए एक विधि जोड़ सकते हैं Move, वापस आ रहा है जब कदम एक सफल हमला है, वापस जाएँ जब कदम एक अवरुद्ध हमला है, और जब यह हमला नहीं है तब कुछ भी नहीं। इस तरह से आप इसे सामान्य रूप से लागू कर सकते हैं ( public boolean attack(Move other) { if this.isAttack() return (other.isAttack() || other.height != this.height) ? HIT : BACKFIRE; return NOTHING; }), और जरूरत पड़ने पर इसे विशिष्ट चालों पर ओवरराइड कर सकते हैं (कमजोर चालें जो किसी भी ब्लॉक को ब्लॉक कर सकती हैं, हमले जो कभी भी पीछे नहीं हटते आदि)
फिर से लिखना

50

क्यों नहीं एक सरणी का उपयोग करें?

मैं शुरू से शुरू करूंगा। मैं एक पैटर्न देखता हूं, मान 0 से 3 तक जाते हैं और आप सभी संभावित मूल्यों को पकड़ना चाहते हैं। यह आपकी टेबल है:

0 & 0 = 0
0 & 1 = 0
0 & 2 = 1
0 & 3 = 2
1 & 0 = 0
1 & 1 = 0
1 & 2 = 2
1 & 3 = 1
2 & 0 = 2
2 & 1 = 1
2 & 2 = 3
2 & 3 = 3
3 & 0 = 2
3 & 1 = 1
3 & 2 = 3
3 & 3 = 3

जब हम इसी टेबल बाइनरी को देखते हैं तो हमें निम्न परिणाम दिखाई देते हैं:

00 & 00 = 00
00 & 01 = 00
00 & 10 = 01
00 & 11 = 10
01 & 00 = 00
01 & 01 = 00
01 & 10 = 10
01 & 11 = 01
10 & 00 = 10
10 & 01 = 01
10 & 10 = 11
10 & 11 = 11
11 & 00 = 10
11 & 01 = 01
11 & 10 = 11
11 & 11 = 11

अब शायद आप पहले से ही कुछ पैटर्न देख सकते हैं, लेकिन जब मैं एक और दो को संयोजित करता हूं, तो मैं देखता हूं कि आप सभी मानों 0000, 0001, 0010, ..... 1110 और 1111 का उपयोग कर रहे हैं। अब एक बनाने के लिए मान एक और दो को मिलाएं। 4 बिट पूर्णांक।

0000 = 00
0001 = 00
0010 = 01
0011 = 10
0100 = 00
0101 = 00
0110 = 10
0111 = 01
1000 = 10
1001 = 01
1010 = 11
1011 = 11
1100 = 10
1101 = 01
1110 = 11
1111 = 11

जब हम इसे वापस दशमलव मानों में अनुवाद करते हैं, तो हम उन मूल्यों की एक बहुत ही संभावित सारणी देखते हैं, जहाँ एक और दो को सूचकांक के रूप में इस्तेमाल किया जा सकता है:

0 = 0
1 = 0
2 = 1
3 = 2
4 = 0
5 = 0
6 = 2
7 = 1
8 = 2
9 = 1
10 = 3
11 = 3
12 = 2
13 = 1
14 = 3
15 = 3

सरणी तब है {0, 0, 1, 2, 0, 0, 2, 1, 2, 1, 3, 3, 2, 1, 3, 3}, जहां यह सूचकांक केवल एक और दो संयुक्त है।

मैं जावा प्रोग्रामर नहीं हूं, लेकिन आप सभी से छुटकारा पा सकते हैं यदि कथन और बस इसे कुछ इस तरह लिखें:

int[] myIntArray = {0, 0, 1, 2, 0, 0, 2, 1, 2, 1, 3, 3, 2, 1, 3, 3};
result = myIntArray[one * 4 + two]; 

मैं नहीं जानता कि क्या 2 से एक बिटशिफ्ट गुणा से अधिक तेज है। लेकिन यह एक कोशिश के काबिल हो सकता है।


2
2 की एक बिट-शिफ्ट लगभग निश्चित रूप से 4 के गुणन की तुलना में अधिक तेज है। सबसे अच्छा, 4 से गुणा, यह पहचानता है कि 4 2 ^ 2 है और खुद को थोड़ा बदलाव करते हैं (संकलक द्वारा संभावित रूप से अनुवादित)। सच कहूँ तो, मेरे लिए, शिफ्ट अधिक पठनीय है।
क्रंचर

मुझे आपका तरीका पसंद है! यह अनिवार्य रूप से एक 4x4 मैट्रिक्स को 16 तत्व सरणी में समतल करता है।
कैमरन टिंकर

6
आजकल, अगर मैं गलत नहीं हूँ, तो संकलक निस्संदेह पहचान लेगा कि आप दो की शक्ति से गुणा कर रहे हैं और उसके अनुसार इसे अनुकूलित करें। तो आपके लिए, प्रोग्रामर, बिट शिफ्ट और गुणा में समान प्रदर्शन होना चाहिए।
टान्नर स्विट

24

यह बिटकॉइन का एक छोटा सा उपयोग करता है (आप एक ही पूर्णांक में दो बिट सूचना (कम / उच्च और हमला / ब्लॉक) पकड़कर कर रहे हैं):

मैंने इसे नहीं चलाया है, केवल इसे यहाँ टाइप किया है, कृपया डबलचेक करें। विचार निश्चित रूप से काम करता है। संपादित करें: यह अब हर इनपुट के लिए परीक्षण किया जाता है, ठीक काम करता है।

public int fightMath(int one, int two) {
    if(one<2 && two<2){ //both players blocking
        return 0; // nobody hits
    }else if(one>1 && two>1){ //both players attacking
        return 3; // both hit
    }else{ // some of them attack, other one blocks
        int different_height = (one ^ two) & 1; // is 0 if they are both going for the same height - i.e. blocker wins, and 1 if height is different, thus attacker wins
        int attacker = one>1?1:0; // is 1 if one is the attacker, two is the blocker, and 0 if one is the blocker, two is the attacker
        return (attacker ^ different_height) + 1;
    }
}

या क्या मुझे जानकारी के दो बिट्स को अलग-अलग चर में अलग करने का सुझाव देना चाहिए? ऊपर दिए गए बिट ऑपरेशंस के आधार पर कोड आमतौर पर बनाए रखने के लिए वास्तव में कठिन होता है।


2
मैं इस समाधान से सहमत हूं, मुख्य प्रश्न पर मेरी टिप्पणी में मेरे मन में जो कुछ था, वह बहुत कुछ दिखता है। मैं इसे अलग-अलग चर में विभाजित करना पसंद करूंगा, जिससे भविष्य में उदाहरण के लिए मध्य हमले को जोड़ना आसान होगा।
योह

2
मैंने इसे परीक्षण करने के बाद ऊपर दिए गए कोड में कुछ कीड़े तय किए, अब यह अच्छी तरह से काम करता है। बिट-मैनिपुलेटर के रास्ते पर आगे बढ़ते हुए, मैं एक लाइन समाधान के साथ भी आया, जो अभी भी अन्य उत्तरों में बिटमैक्स की तरह रहस्यमय नहीं है, लेकिन अभी भी आपके दिमाग को पेंच करने के लिए काफी मुश्किल है:return ((one ^ two) & 2) == 0 ? (one & 2) / 2 * 3 : ((one & 2) / 2 ^ ((one ^ two) & 1)) + 1;
एलियास

1
यह किसी भी नए प्रोग्रामर को पढ़ने के लिए सबसे अच्छा जवाब है क्योंकि यह वास्तव में उन सभी जादू नंबरों के पीछे हो रहे जादू को समझेगा।
बीज़मैक्स

20

काफी ईमानदार होने के लिए, हर किसी के पास कोड की अपनी शैली है। मुझे नहीं लगता था कि प्रदर्शन बहुत अधिक प्रभावित होगा। यदि आप स्विच केस संस्करण का उपयोग करने से बेहतर समझते हैं, तो इस का उपयोग करें।

यदि आप जांच कर सकते हैं, तो संभावित रूप से आपके अंतिम के लिए थोड़ी सी प्रदर्शन वृद्धि होगी अगर जाँच के रूप में कई बयानों के माध्यम से नहीं गया होता। लेकिन एक बुनियादी जावा पाठ्यक्रम के संदर्भ में यह शायद लाभ नहीं होगा।

else if(one == 3 && two == 3) { result = 3; }

इसलिए, इसके बजाय ...

if(one == 0 && two == 0) { result = 0; }
else if(one == 0 && two == 1) { result = 0; }
else if(one == 0 && two == 2) { result = 1; }
else if(one == 0 && two == 3) { result = 2; }

आप करेंगे ...

if(one == 0) 
{ 
    if(two == 0) { result = 0; }
    else if(two == 1) { result = 0; }
    else if(two == 2) { result = 1; }
    else if(two == 3) { result = 2; }
}

और जैसा आप चाहें, वैसा ही सुधार करें।

यह कोड को बेहतर नहीं बनाता है, लेकिन संभावित रूप से इसे थोड़ा मैं मानता हूं।


3
पता नहीं अगर यह वास्तव में अच्छा अभ्यास है, लेकिन इस मामले के लिए, मैं शायद नेस्टेड स्विच स्टेटमेंट का उपयोग करूंगा। यह अधिक जगह लेगा, लेकिन यह वास्तव में स्पष्ट होगा।
डाइसेडिस

यह भी काम करेगा, लेकिन मुझे लगता है कि यह वरीयता की बात है। मैं वास्तव में पसंद करता हूं अगर बयानों के रूप में यह वास्तव में कह रहा है कि कोड क्या कर रहा है। अपनी राय रखने से नहीं, जो भी आपके लिए काम करता है :)। हालांकि वैकल्पिक सुझाव के लिए अपवोट करें!
जो हार्पर

12

आइए देखें कि हम क्या जानते हैं

1: आपके उत्तर P1 (खिलाड़ी एक) और P2 (खिलाड़ी दो) के लिए सममित हैं। यह एक लड़ खेल के लिए समझ में आता है, लेकिन यह भी कुछ है जो आप अपने तर्क को बेहतर बनाने के लिए लाभ उठा सकते हैं।

2: 3 बीट्स 0 बीट्स 2 बीट्स 1 बीट्स 3। इन मामलों द्वारा कवर नहीं किए जाने वाले एकमात्र मामले 0 बनाम 1 और 2 बनाम 3 के संयोजन हैं। इसे एक और तरीके से रखने के लिए अद्वितीय जीत तालिका इस तरह दिखती है: 0 बीट्स 2, 1 बीट्स। 3, 2 बीट्स 1, 3 बीट्स 0।

3: यदि 0/1 एक दूसरे के खिलाफ जाते हैं तो एक हिट रहित ड्रॉ होता है लेकिन यदि 2/3 प्रत्येक के खिलाफ जाते हैं तो दोनों हिट होते हैं

यदि हम जीत गए तो सबसे पहले, हमें एक-तरफ़ा कार्य करने के लिए कहें:

// returns whether we beat our opponent
public boolean doesBeat(int attacker, int defender) {
  int[] beats = {2, 3, 1, 0};
  return defender == beats[attacker];
}

हम अंतिम परिणाम की रचना करने के लिए इस फ़ंक्शन का उपयोग कर सकते हैं:

// returns the overall fight result
// bit 0 = one hits
// bit 1 = two hits
public int fightMath(int one, int two)
{
  // Check to see whether either has an outright winning combo
  if (doesBeat(one, two))
    return 1;

  if (doesBeat(two, one))
    return 2;

  // If both have 0/1 then its hitless draw but if both have 2/3 then they both hit.
  // We can check this by seeing whether the second bit is set and we need only check
  // one's value as combinations where they don't both have 0/1 or 2/3 have already
  // been dealt with 
  return (one & 2) ? 3 : 0;
}

हालांकि यह यकीनन अधिक जटिल है और संभवतः कई उत्तरों में पेश किए गए टेबल लुकअप की तुलना में धीमा है, मेरा मानना ​​है कि यह एक बेहतर तरीका है क्योंकि यह वास्तव में आपके कोड के तर्क को अतिक्रमण करता है और इसका वर्णन वह करता है जो आपका कोड पढ़ रहा है। मुझे लगता है कि यह इसे बेहतर कार्यान्वयन बनाता है।

(यह कुछ समय हो गया है क्योंकि मैंने किसी भी जावा को माफी दी है यदि सिंटैक्स बंद है, तो उम्मीद है कि यह अभी भी समझदार है अगर मैंने इसे थोड़ा गलत पाया है)

वैसे, 0-3 का स्पष्ट अर्थ कुछ है; वे मनमाने ढंग से मान नहीं रहे हैं तो इससे उन्हें नाम रखने में मदद मिलेगी।


11

मुझे उम्मीद है कि मैं तर्क को सही ढंग से समझ पाऊंगा। कैसे कुछ के बारे में:

public int fightMath (int one, int two)
{
    int oneHit = ((one == 3 && two != 1) || (one == 2 && two != 0)) ? 1 : 0;
    int twoHit = ((two == 3 && one != 1) || (two == 2 && one != 0)) ? 2 : 0;

    return oneHit+twoHit;
}

एक हिट उच्च या एक हिट कम की जाँच अवरुद्ध नहीं है और खिलाड़ी दो के लिए समान है।

संपादित करें: एल्गोरिथ्म को पूरी तरह से समझा नहीं गया था, "हिट" को अवरुद्ध होने पर सम्मानित किया गया था जो मुझे एहसास नहीं था (Thx elias):

public int fightMath (int one, int two)
{
    int oneAttack = ((one == 3 && two != 1) || (one == 2 && two != 0)) ? 1 : (one >= 2) ? 2 : 0;
    int twoAttack = ((two == 3 && one != 1) || (two == 2 && one != 0)) ? 2 : (two >= 2) ? 1 : 0;

    return oneAttack | twoAttack;
}

पेटेंट महान परिणाम खोजने के लिए रास्ता!
चाड

1
मुझे दृष्टिकोण पसंद है, लेकिन मुझे डर है कि यह समाधान पूरी तरह से एक हमले को अवरुद्ध करके मारने की संभावना का अभाव है (उदाहरण के लिए यदि एक = 0 और दो = 2 यह 0 देता है, लेकिन विनिर्देश के अनुसार 1 की उम्मीद है)। हो सकता है कि आप इसे ठीक करने के लिए इस पर काम कर सकते हैं, लेकिन मुझे यकीन नहीं है कि परिणामी कोड अभी भी यह सुरुचिपूर्ण होगा, क्योंकि इसका मतलब है कि लाइनें कुछ हद तक बढ़ेंगी।
एलियास

यह महसूस नहीं किया कि ब्लॉक के लिए "हिट" से सम्मानित किया गया था। इस पर ध्यान दिलाने के लिए धन्यवाद। बहुत सरल फिक्स के साथ समायोजित किया गया।
क्रिस

10

मेरे पास जावा के साथ अनुभव नहीं है इसलिए कुछ टाइपोस हो सकते हैं। कृपया कोड को छद्म कोड मानें।

मैं एक साधारण स्विच के साथ जाऊँगा। उसके लिए, आपको एक एकल संख्या मूल्यांकन की आवश्यकता होगी। हालांकि, इस मामले के लिए, चूंकि 0 <= one < 4 <= 9और 0 <= two < 4 <= 9, हम दोनों को one10 इंच जोड़कर और एक सरल इंट में बदल सकते हैं two। फिर इस तरह परिणामी संख्या में एक स्विच का उपयोग करें:

public int fightMath(int one, int two) {
    // Convert one and two to a single variable in base 10
    int evaluate = one * 10 + two;

    switch(evaluate) {
        // I'd consider a comment in each line here and in the original code
        // for clarity
        case 0: result = 0; break;
        case 1: result = 0; break;
        case 1: result = 0; break;
        case 2: result = 1; break;
        case 3: result = 2; break;
        case 10: result = 0; break;
        case 11: result = 0; break;
        case 12: result = 2; break;
        case 13: result = 1; break;
        case 20: result = 2; break;
        case 21: result = 1; break;
        case 22: result = 3; break;
        case 23: result = 3; break;
        case 30: result = 1; break;
        case 31: result = 2; break;
        case 32: result = 3; break;
        case 33: result = 3; break;
    }

    return result;
}

एक और छोटी विधि है जिसे मैं केवल एक सैद्धांतिक कोड के रूप में इंगित करना चाहता हूं। हालाँकि, मैं इसका उपयोग नहीं करूंगा क्योंकि इसमें कुछ अतिरिक्त जटिलताएं हैं जो आप सामान्य रूप से नहीं चाहते हैं। अतिरिक्त जटिलता आधार 4 से आती है , क्योंकि गिनती 0, 1, 2, 3, 10, 11, 12, 13, 20, ... है।

public int fightMath(int one, int two) {
    // Convert one and two to a single variable in base 4
    int evaluate = one * 4 + two;

    allresults = new int[] { 0, 0, 1, 2, 0, 0, 2, 1, 2, 1, 3, 3, 1, 2, 3, 3 };

    return allresults[evaluate];
}

वास्तव में सिर्फ अतिरिक्त नोट, मामले में मैं जावा से कुछ याद कर रहा हूं। PHP में मैं करूँगा:

function fightMath($one, $two) {
    // Convert one and two to a single variable in base 4
    $evaluate = $one * 10 + $two;

    $allresults = array(
         0 => 0,  1 => 0,  2 => 1,  3 => 2,
        10 => 0, 11 => 0, 12 => 2, 13 => 1,
        20 => 2, 21 => 1, 22 => 3, 23 => 3,
        30 => 1, 31 => 2, 32 => 3, 33 => 3 );

    return $allresults[$evaluate];
}

8 वें संस्करण से पहले जावा का कोई लामा नहीं है
किरिल गमाज़कोव

1
यह। इतनी कम संख्या में इनपुट के लिए, मैं एक समग्र मूल्य के साथ एक स्विच का उपयोग करूंगा (हालांकि यह 10 से अधिक गुणक के साथ अधिक पठनीय हो सकता है, जैसे कि 100 या 1000)।
मेडिनोक

7

चूंकि आप नेस्टेड ifकंडीशन पसंद करते हैं, इसलिए यहां एक और तरीका है।
ध्यान दें कि यह resultसदस्य का उपयोग नहीं करता है और यह किसी भी राज्य को नहीं बदलता है।

public int fightMath(int one, int two) {
    if (one == 0) {
      if (two == 0) { return 0; }
      if (two == 1) { return 0; }
      if (two == 2) { return 1; }
      if (two == 3) { return 2; }
    }   
    if (one == 1) {
      if (two == 0) { return 0; }
      if (two == 1) { return 0; }
      if (two == 2) { return 2; }
      if (two == 3) { return 1; }
    }
    if (one == 2) {
      if (two == 0) { return 2; }
      if (two == 1) { return 1; }
      if (two == 2) { return 3; }
      if (two == 3) { return 3; }
    }
    if (one == 3) {
      if (two == 0) { return 1; }
      if (two == 1) { return 2; }
      if (two == 2) { return 3; }
      if (two == 3) { return 3; }
    }
    return DEFAULT_RESULT;
}

आपके पास कोई और क्यों नहीं है?
एफडिनॉफ

3
@Finoff मैं elseजंजीरों का इस्तेमाल कर सकता था, लेकिन इससे कोई फर्क नहीं पड़ता था।
निक डंडौलकिस

1
मुझे पता है कि यह तुच्छ है, लेकिन अन्य श्रृंखलाओं को तेजी से निष्पादित नहीं करेगा? 4 में से 3 मामलों में? मैं हमेशा कोड लिखने की आदत बनाता हूं ताकि जितनी जल्दी हो सके निष्पादित कर सकें, भले ही यह केवल कुछ चक्र हो।
ब्रैंडन बेयरडेन

2
@BrandonBearden यहाँ वे कोई फर्क नहीं पड़ता (यह मानते हुए कि इनपुट हमेशा 0..3 रेंज में है)। कंपाइलर शायद वैसे भी कोड को माइक्रो-ऑप्टिमाइज़ करेगा। यदि हमारे पास else ifबयानों की लंबी श्रृंखला है तो हम कोड को switchलुक-अप टेबल के साथ बढ़ा सकते हैं ।
निक डंडौलकिस

ऐसा कैसे है? यदि one==0यह कोड चलाएगा, तो उसे यह जांचना होगा कि one==1अगर one==2और अंत में अगर one==3- अगर वहाँ और अगर वहाँ थे, तो यह अंतिम तीन चेक नहीं करेगा क्योंकि यह पहले मैच के बाद बयान से बाहर निकल जाएगा। और हाँ, आप बयानों के स्थान पर एक स्विच स्टेटमेंट का if (one...उपयोग करके और फिर आगे के मामले में एक और स्विच का उपयोग करके अनुकूलित कर सकते हैं one's। हालाँकि, यह मेरा सवाल नहीं है।
ब्रैंडन बेयरडेन

6

इसे स्विच केसिंग के साथ आज़माएँ ..

एक नजर डालें यहाँ या यहाँ इसके बारे में अधिक जानकारी के लिए

switch (expression)
{ 
  case constant:
        statements;
        break;
  [ case constant-2:
        statements;
        break;  ] ...
  [ default:
        statements;
        break;  ] ...
}

आप इसमें कई शर्तें (एक साथ नहीं) जोड़ सकते हैं और यहां तक कि एक डिफ़ॉल्ट विकल्प भी हो सकता है जहां कोई अन्य मामले संतुष्ट नहीं हुए हैं।

पुनश्च: केवल अगर एक शर्त को पूरा करना है ..

अगर 2 स्थितियां एक साथ उत्पन्न होती हैं .. मुझे नहीं लगता कि स्विच का उपयोग किया जा सकता है। लेकिन आप यहां अपना कोड कम कर सकते हैं।

जावा स्विच स्टेटमेंट कई मामले


6

पहली बात जो मेरे साथ हुई, वह अनिवार्य रूप से फ्रांसिस्को प्रेसेनिया द्वारा दिया गया उत्तर था, लेकिन कुछ हद तक अनुकूलित:

public int fightMath(int one, int two)
{
    switch (one*10 + two)
    {
    case  0:
    case  1:
    case 10:
    case 11:
        return 0;
    case  2:
    case 13:
    case 21:
    case 30:
        return 1;
    case  3:
    case 12:
    case 20:
    case 31:
        return 2;
    case 22:
    case 23:
    case 32:
    case 33:
        return 3;
    }
}

आप अंतिम मामले (3 के लिए) को डिफ़ॉल्ट केस बनाकर इसे और अनुकूलित कर सकते हैं:

    //case 22:
    //case 23:
    //case 32:
    //case 33:
    default:
        return 3;

इस पद्धति का लाभ यह है कि यह देखना आसान है कि कौन से मूल्यों के लिए कौन सा oneऔर twoकिस प्रकार के अन्य सुझाए गए तरीकों से मूल्यों को लौटाता है।


यह यहाँ मेरे एक और जवाब का रूपांतर है
डेविड आर ट्रिब्बल

6
((two&2)*(1+((one^two)&1))+(one&2)*(2-((one^two)&1)))/2

4
आपको इस पर पहुंचने में कितना समय लगा?
mbatchkarov

2
@mbatchkarov अन्य उत्तरों को पढ़ने के बारे में 10 मिनट, फिर पेंसिल और कागज के साथ स्क्रिब्लिंग के 10 मिनट।
दाऊद इब्न करीम

7
अगर मुझे इसे बनाए रखना है तो मुझे वास्तव में दुख होगा।
मेरियोवी

uhmmm ... एक बग है: आप गायब हैं; --unicorns
अल्बर्टो

मैं @Meryovi के साथ सहमत हूँ, संक्षिप्त होने के लिए सहारा, फिर भी एपीएल कोड की तरह भयानक
एड

4

आप म्यूटेंट के बजाय स्विच केस का उपयोग कर सकते हैंif

यह भी उल्लेख करने के लिए कि चूंकि आपके पास दो चर हैं तो आपको स्विच में उनका उपयोग करने के लिए दो चर को मिलाना होगा

दो चर को संभालने के लिए इस जावा स्विच स्टेटमेंट की जाँच करें ?


3

जैसे ही मैं एक / दो और परिणाम के बीच एक तालिका खींचता हूं, मुझे एक पैटर्न दिखाई देता है,

if(one<2 && two <2) result=0; return;

यदि कथनों में उपरोक्त कम से कम 3 कट जाएगा। मुझे एक सेट पैटर्न नहीं दिखता है और न ही मैं दिए गए कोड से बहुत अधिक चमकने में सक्षम हूं - लेकिन अगर इस तरह के तर्क को प्राप्त किया जा सकता है, तो यह कई बयानों को काट देगा।

उम्मीद है की यह मदद करेगा।


3

नियमों को पाठ के रूप में परिभाषित करने के लिए एक अच्छा बिंदु होगा, आप आसानी से फिर सही सूत्र प्राप्त कर सकते हैं। इसे लालाटो के अच्छे सरणी प्रतिनिधित्व से निकाला गया है:

{ 0, 0, 1, 2 },
{ 0, 0, 2, 1 },
{ 2, 1, 3, 3 },
{ 1, 2, 3, 3 }

और यहां हम कुछ सामान्य टिप्पणियों के साथ जाते हैं, लेकिन आपको उन्हें नियम के रूप में वर्णित करना चाहिए:

if(one<2) // left half
{
    if(two<2) // upper left half
    {
        result = 0; //neither hits
    }
    else // lower left half
    {
        result = 1+(one+two)%2; //p2 hits if sum is even
    }
}
else // right half
{
    if(two<2) // upper right half
    {
        result = 1+(one+two+1)%2; //p1 hits if sum is even
    }
    else // lower right half
    {
        return 3; //both hit
    }
}

आप बेशक इसे कम कोड में क्रंच कर सकते हैं, लेकिन आमतौर पर यह समझने के लिए एक अच्छा विचार है कि आप कॉम्पैक्ट समाधान खोजने के बजाय क्या कोड बनाते हैं।

if((one<2)&&(two<2)) result = 0; //top left
else if((one>1)&&(two>1)) result = 3; //bottom right
else result = 1+(one+two+((one>1)?1:0))%2; //no idea what that means

जटिल p1 / p2 हिट पर कुछ स्पष्टीकरण बहुत अच्छा होगा, दिलचस्प लग रहा है!


3

सबसे छोटा और अभी भी पठनीय हल:

static public int fightMath(int one, int two)
{
    if (one < 2 && two < 2) return 0;
    if (one > 1 && two > 1) return 3;
    int n = (one + two) % 2;
    return one < two ? 1 + n : 2 - n;
}

या इससे भी कम:

static public int fightMath(int one, int two)
{
    if (one / 2 == two / 2) return (one / 2) * 3;
    return 1 + (one + two + one / 2) % 2;
}

किसी भी "जादू" संख्या में शामिल नहीं है;) आशा है कि यह मदद करता है।


2
इन जैसे सूत्र बाद की तारीख में संयोजन के परिणाम को बदलना (अपडेट) करना असंभव बना देंगे। एकमात्र तरीका पूरे फॉर्मूले को फिर से तैयार करना होगा।
8

2
@ शेष: मैं इससे सहमत हूं। सबसे लचीला समाधान 2D सरणी का उपयोग कर रहा है। लेकिन इस पोस्ट का ऑटोरेटर एक सूत्र चाहता था और यह सबसे अच्छा है जिसे आप केवल सरल इफ्स और गणित के साथ प्राप्त कर सकते हैं।
पीडब्लू

2

static int val(int i, int u){ int q = (i & 1) ^ (u & 1); return ((i >> 1) << (1 ^ q))|((u >> 1) << q); }


1

मैं व्यक्तिगत रूप से टर्नरी ऑपरेटरों को कैस्केड करना पसंद करता हूं:

int result = condition1
    ? result1
    : condition2
    ? result2
    : condition3
    ? result3
    : resultElse;

लेकिन आपके मामले में, आप इसका उपयोग कर सकते हैं:

final int[] result = new int[/*16*/] {
    0, 0, 1, 2,
    0, 0, 2, 1,
    2, 1, 3, 3,
    1, 2, 3, 3
};

public int fightMath(int one, int two) {
    return result[one*4 + two];
}

या, आप बिट्स में एक पैटर्न देख सकते हैं:

one   two   result

section 1: higher bits are equals =>
both result bits are equals to that higher bits

00    00    00
00    01    00
01    00    00
01    01    00
10    10    11
10    11    11
11    10    11
11    11    11

section 2: higher bits are different =>
lower result bit is inverse of lower bit of 'two'
higher result bit is lower bit of 'two'

00    10    01
00    11    10
01    10    10
01    11    01
10    00    10
10    01    01
11    00    01
11    01    10

तो आप जादू का उपयोग कर सकते हैं:

int fightMath(int one, int two) {
    int b1 = one & 2, b2 = two & 2;
    if (b1 == b2)
        return b1 | (b1 >> 1);

    b1 = two & 1;

    return (b1 << 1) | (~b1);
}

1

यहाँ एक संक्षिप्त संक्षिप्त संस्करण है, JAB की प्रतिक्रिया के समान । यह स्टोर करने के लिए एक मानचित्र का उपयोग करता है जो दूसरों पर विजय प्राप्त करता है।

public enum Result {
  P1Win, P2Win, BothWin, NeitherWin;
}

public enum Move {
  BLOCK_HIGH, BLOCK_LOW, ATTACK_HIGH, ATTACK_LOW;

  static final Map<Move, List<Move>> beats = new EnumMap<Move, List<Move>>(
      Move.class);

  static {
    beats.put(BLOCK_HIGH, new ArrayList<Move>());
    beats.put(BLOCK_LOW, new ArrayList<Move>());
    beats.put(ATTACK_HIGH, Arrays.asList(ATTACK_LOW, BLOCK_LOW));
    beats.put(ATTACK_LOW, Arrays.asList(ATTACK_HIGH, BLOCK_HIGH));
  }

  public static Result compare(Move p1Move, Move p2Move) {
    boolean p1Wins = beats.get(p1Move).contains(p2Move);
    boolean p2Wins = beats.get(p2Move).contains(p1Move);

    if (p1Wins) {
      return (p2Wins) ? Result.BothWin : Result.P1Win;
    }
    if (p2Wins) {
      return (p1Wins) ? Result.BothWin : Result.P2Win;
    }

    return Result.NeitherWin;
  }
} 

उदाहरण:

System.out.println(Move.compare(Move.ATTACK_HIGH, Move.BLOCK_LOW));

प्रिंटों:

P1Win

मैं static final Map<Move, List<Move>> beats = new java.util.EnumMap<>();इसके बजाय सिफारिश करूंगा , यह थोड़ा अधिक कुशल होना चाहिए।
JAB

@ जेएबी हां, अच्छा विचार है। मैं हमेशा यह भूल जाता हूं कि टाइप मौजूद है। और ... एक निर्माण करना कितना अजीब है!
डंकन जोन्स

1

मैं एक मानचित्र का उपयोग करता हूं, या तो एक HashMap या एक TreeMap

खासकर अगर पैरामीटर फॉर्म पर नहीं हैं 0 <= X < N

यादृच्छिक सकारात्मक पूर्णांकों के सेट की तरह ।।

कोड

public class MyMap
{
    private TreeMap<String,Integer> map;

    public MyMap ()
    {
        map = new TreeMap<String,Integer> ();
    }

    public void put (int key1, int key2, Integer value)
    {
        String key = (key1+":"+key2);

        map.put(key, new Integer(value));
    }

    public Integer get (int key1, int key2)
    {
        String key = (key1+":"+key2);

        return map.get(key);
    }
}

1

@Joe हार्पर के लिए धन्यवाद, क्योंकि मैं उनके उत्तर की भिन्नता का उपयोग करके समाप्त हुआ। इसे नीचे पतला करने के लिए प्रति 4 परिणाम के रूप में 2 थे वही मैंने इसे और नीचे पतला कर दिया।

मैं कुछ बिंदु पर इस पर वापस आ सकता हूं, लेकिन अगर कई- ifस्थापनों के कारण कोई प्रमुख प्रतिरोध नहीं है, तो मैं इसे अभी के लिए रखूंगा। मैं तालिका मैट्रिक्स और स्विच स्टेटमेंट समाधान को आगे देखूंगा।

public int fightMath(int one, int two) {
  if (one === 0) {
    if (two === 2) { return 1; }
    else if(two === 3) { return 2; }
    else { return 0; }
  } else if (one === 1) {
    if (two === 2) { return 2; }
    else if (two === 3) { return 1; }
    else { return 0; }
  } else if (one === 2) {
    if (two === 0) { return 2; }
    else if (two === 1) { return 1; }
    else { return 3; }
  } else if (one === 3) {
    if (two === 0) { return 1; }
    else if (two === 1) { return 2; }
    else { return 3; }
  }
}

13
यह वास्तव में मूल की तुलना में कम पठनीय है और यदि कथनों की संख्या को कम नहीं करता है ...
चाड

@ क्या यह विचार प्रक्रिया की गति को बढ़ाने के लिए था और हालांकि यह भयावह लग रहा है कि यह आसानी से अपडेट हो गया है, मुझे भविष्य में और अधिक कार्यों को जोड़ना चाहिए। यह कहना कि मैं अब एक पिछले उत्तर का उपयोग कर रहा हूं, जिसे मैं पहले पूरी तरह से समझ नहीं पाया था।
टॉमफिरथ

3
@ TomFirth84 क्या कोई कारण है कि आप अपने बयानों के लिए उचित कोडिंग सम्मेलनों का पालन नहीं कर रहे हैं?
ylun.ca

@ सिलुन: मैंने एसओ पर चिपकाने से पहले लाइनों को कम कर दिया था, पठनीयता के लिए नहीं बल्कि सरासर स्पैम स्पेस के लिए। इस पृष्ठ पर अभ्यास के रूपांतर हैं और दुख की बात यह है कि मैंने जिस तरह से सीखा है और उसी के साथ सहज हूं।
टॉमफिरथ

2
@ TomFirth84 मुझे नहीं लगता कि यह आसानी से अपडेट किया गया है, लाइनों की संख्या अनुमत मूल्यों की संख्या के उत्पाद की तरह कुछ बढ़ती है।
एंड्रयू लाजर

0
  1. कोड को अधिक पठनीय बनाने के लिए स्थिरांक या एनम का उपयोग करें
  2. कोड को और अधिक कार्यों में विभाजित करने का प्रयास करें
  3. समस्या की समरूपता का उपयोग करने का प्रयास करें

यहाँ एक सुझाव है कि यह कैसे दिख सकता है, लेकिन यहाँ एक चींटियों का उपयोग करना अभी भी बदसूरत है:

static final int BLOCK_HIGH = 0;
static final int BLOCK_LOW = 1;
static final int ATTACK_HIGH = 2;
static final int ATTACK_LOW = 3;

public static int fightMath(int one, int two) {
    boolean player1Wins = handleAttack(one, two);
    boolean player2Wins = handleAttack(two, one);
    return encodeResult(player1Wins, player2Wins); 
}



private static boolean handleAttack(int one, int two) {
     return one == ATTACK_HIGH && two != BLOCK_HIGH
        || one == ATTACK_LOW && two != BLOCK_LOW
        || one == BLOCK_HIGH && two == ATTACK_HIGH
        || one == BLOCK_LOW && two == ATTACK_LOW;

}

private static int encodeResult(boolean player1Wins, boolean player2Wins) {
    return (player1Wins ? 1 : 0) + (player2Wins ? 2 : 0);
}

यह इनपुट और आउटपुट के लिए एक संरचित प्रकार का उपयोग करने के लिए अच्छा होगा। इनपुट में वास्तव में दो फ़ील्ड हैं: स्थिति और प्रकार (ब्लॉक या हमला)। आउटपुट में दो फ़ील्ड भी होते हैं: player1Wins और player2Wins। इसे एक पूर्णांक में एन्कोड करने से कोड को पढ़ना कठिन हो जाता है।

class PlayerMove {
    PlayerMovePosition pos;
    PlayerMoveType type;
}

enum PlayerMovePosition {
    HIGH,LOW
}

enum PlayerMoveType {
    BLOCK,ATTACK
}

class AttackResult {
    boolean player1Wins;
    boolean player2Wins;

    public AttackResult(boolean player1Wins, boolean player2Wins) {
        this.player1Wins = player1Wins;
        this.player2Wins = player2Wins;
    }
}

AttackResult fightMath(PlayerMove a, PlayerMove b) {
    return new AttackResult(isWinningMove(a, b), isWinningMove(b, a));
}

boolean isWinningMove(PlayerMove a, PlayerMove b) {
    return a.type == PlayerMoveType.ATTACK && !successfulBlock(b, a)
            || successfulBlock(a, b);
}

boolean successfulBlock(PlayerMove a, PlayerMove b) {
    return a.type == PlayerMoveType.BLOCK 
            && b.type == PlayerMoveType.ATTACK 
            && a.pos == b.pos;
}

दुर्भाग्य से, जावा उन प्रकार के डेटा-प्रकारों को व्यक्त करने में बहुत अच्छा नहीं है।


-2

इसके बजाय कुछ ऐसा करें

   public int fightMath(int one, int two) {
    return Calculate(one,two)

    }


    private int Calculate(int one,int two){

    if (one==0){
        if(two==0){
     //return value}
    }else if (one==1){
   // return value as per condtiion
    }

    }

4
आपने बस एक निजी समारोह बनाया है जो जनता द्वारा लिपटा हुआ है। सार्वजनिक समारोह में इसे लागू क्यों नहीं किया?
मार्टिन उडिंग

5
और अगर आपने स्टेटमेंट्स की संख्या कम नहीं की है।
चाड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.