टेट्रिस के एक खेल में सर्वश्रेष्ठ चाल का पता लगाएं


10

मुझे टेट्रिस बहुत पसंद है, लेकिन मैं इसमें बहुत अच्छा नहीं हूं। बस एक बार मैं यह देखना चाहूंगा कि अंतरिक्ष यान मेरी आँखों के सामने से उड़ान भरता है! और जब से कंप्यूटर सब कुछ पर ओह-इतना महान हैं, केवल संभव समाधान यह है कि मेरे लिए इसे खेलने के लिए एक कार्यक्रम बनाया जाए ... सिवाय इसके कि आप मेरे लिए ऐसा करने जा रहे हैं!

एक टेट्रोमिनो (चार वर्गों से बनी आकृति) और खेल के मैदान के एक नक्शे को देखते हुए, आप टेट्रोमिनो को ऐसे स्थान पर रखते हैं, जिससे यह सबसे बड़ी संख्या में रेखाएँ बनाता है (बड़ी संख्या में पंक्तियों को पूरी तरह से पूर्ण ब्लॉक बनाता है) और सबसे कम संख्या बनाता है की नई छेद (एक खाली जगह है कि नहीं कर सकते हैं खेल मैदान के शीर्ष "देख" 1 )।

इनपुट

इनपुट में एकल पंक्ति पर एक चरित्र होगा जो ड्रॉपिंग टेट्रोमिनो का प्रतिनिधित्व करता है, इसके बाद रिक्त स्थान के 10 * 18 ग्रिड 2 ( ) और प्लस संकेत ( +)।

यह चरित्र टेट्रिस में पाए गए सात बेस टेट्रोमिनो में से किसी का प्रतिनिधित्व करता है। सभी टुकड़ों को 90 डिग्री तक घुमाया जा सकता है, लेकिन फ़्लिप नहीं। सभी टेट्रोमिनो और उनके रोटेशन निम्नानुसार हैं:

         #
S =  ##  ##
    ##    #

          #
Z = ##   ##
     ##  #

    #   ###  ##
L = #   #     #    #
    ##        #  ###

     #  ###  ##
J =  #    #  #     #
    ##       #   ###

          #   #   #
T = ###  ##  ###  ##
     #    #       #

O = ##
    ##

    #
I = #  ####
    #
    #

ग्रिड टेट्रिस के खेल के क्षेत्र का प्रतिनिधित्व करता है, +पहले से रखे गए ब्लॉक के साथ। तो, एक उदाहरण इनपुट निम्नलिखित हो सकता है:

I











+       ++
+    +++++
++ +++++++
++ +++++++
++ +++++++
++ +++++++
++++++ +++

उत्पादन

आपका आउटपुट इनपुट के समान होगा, लेकिन आदर्श स्थिति में टेट्रोमिनो के साथ। टेट्रोमिनो को #पूर्व-रखे हुए ब्लॉकों से अलग करने के लिए उनका प्रतिनिधित्व किया जाना चाहिए । इसके अतिरिक्त, आपको यह भी आउटपुट करना है कि आपका प्लेसमेंट xL yHनई लाइन में फॉर्म में कितनी लाइनें / छेद बनाता है ।

ऊपर दिए गए उदाहरण के लिए आउटपुट निम्न 3 होगा :

I











+       ++
+    +++++
++#+++++++
++#+++++++
++#+++++++
++#+++++++
++++++ +++
4L 0H

आप केवल सबसे अच्छा परिणाम (ओं) को आउटपुट करने के लिए हैं; एक ही स्कोर देने वाले दो या अधिक मामलों के मामले में, आप उन सभी को आउटपुट करते हैं (एक रिक्त लाइन द्वारा अलग)। सबसे अच्छे परिणाम पहले (नीचे उतरने वाली) रेखाओं की संख्या के आधार पर क्रमबद्ध करके निर्धारित किए जाने हैं, फिर नए छेदों की संख्या (आरोही) बनाई गई है। तो, 1L 1Hसे बेहतर स्कोर है 0L 0H

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

नियम और छूट

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

1 मैं जानता हूं कि यह कुछ गलत सकारात्मकताएं पैदा करेगा, लेकिन यह एक सरलीकरण है।

2 यह ग्रिड आकार है जिसका उपयोग गेम बॉय संस्करण में किया जाता है।

3 हाँ, 0Hसही है। फिर से जाँच करें, मैंने कहा कि नए छेद; ^)


क्या होगा अगर एक टुकड़ा 1 नया छेद का कारण बनेगा, लेकिन 2 लाइनों को स्कोर करेगा, बनाम केवल 1 लाइन स्कोरिंग?
नाथन मेरिल

पहले लाइनों की संख्या के आधार पर छाँटें। 2 पंक्ति> 1 पंक्ति, इसलिए यह कोई फर्क नहीं पड़ता कि छेद की संख्या क्या है।
सीन लाथम

2
यदि आप एक छेद को मुक्त करते हैं, तो क्या यह आपको -1 एच देता है?
ओवरएक्टर

हम्म, मैंने ऐसा नहीं सोचा था - यह भोले छेद की परिभाषा के परिणामस्वरूप हो सकता है। हां, मुझे लगता है कि यह होगा।
सीन लाथम

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

जवाबों:


3

C 1009 बाइट्स

#include <stdio.h>
#define L for(n=0;n<18;++n)
int T[19]={54,561,99,306,785,23,547,116,802,71,275,116,39,562,114,305,51,4369,15},W[19]={3,2,3,2,2,3,2,3,2,3,2,3,3,2,3,2,2,1,4},O[7]={0,2,4,8,12,16,17},R[7]={2,2,4,4,4,1,2},G[18],F[24],t=0,I,x,y,S[99],X[99],Y[99],N[99],s,M=0,i,j,k,l,m,n,h,c;char B[99],*C="SZLJTOI";void A(){for(m=0;m<24;++m)F[m]=0;for(m=0;m<4;++m)F[y+m]=(T[I]>>(m*4)&15)<<x;}void D(){S[s]=0;L S[s]+=(G[n]|F[n])==1023;S[s]=200*(S[s])+199;for(m=0;m<10;++m){l=0;L{h=(G[n]|F[n])&1<<m;l|=h;S[s]-=l&&!h;}}}int E(){A();c=0;L c|=G[n]&F[n];return !c;}int main(){S[0]=0;gets(B);while(C[t]!=B[0])++t;I=O[t];L{G[n]=0;gets(B);for(m=0;m<10;++m)G[n]|=(B[m]=='+')?(1<<m):0;}s=0;D();for(i=0;i<R[t];++i){for(x=0;x<10-W[I];x++){y=0;while(E())y++;--y;++s;A();D();if(S[s]>M)M=S[s];X[s]=x;Y[s]=y;N[s]=I;}I++;}for(i=1;i<s;++i)if(S[i]==M){j=i;x=X[i];y=Y[i];I=N[i];A();for(n=1;n<18;++n){for(m=0;m<10;++m)printf((G[n]&1<<m)!=0?"+":((F[n]&1<<m)!=0?"#":" "));printf("\n");}}printf("%dL %dH\n",S[j]/200,S[0]%200-S[j]%200);}

यहाँ ungolfed संस्करण है

#include <stdio.h>

int tiles[19] = {54,561,99,306,785,23,547,116,802,71,275,116,39,562,114,305,51,4369,15};
int widths[19] = {3,2,3,2,2,3,2,3,2,3,2,3,3,2,3,2,2,1,4};
char *codes = "SZLJTOI";
int offsets[7] = {0,2,4,8,12,16,17};
int transformations[7] = {2,2,4,4,4,1,2};
int gameField[18], tileField[24];

int i,j,k,l,m,n,h;
char buffer[99];
int tile=0, tileIndex;
int xpos, ypos;
int scores[99], xplacements[99], yplacements[99], tindex[99];
int scoreIndex, maxScore=0;

void readGame()
{
  gets(buffer);
  while (codes[tile]!=buffer[0]) ++tile;
  tileIndex = offsets[tile];
  for (n=0;n<18;++n)
  {
    gameField[n] = 0;
    gets(buffer);
    for (m=0; m<10;++m)
      gameField[n] |= (buffer[m]=='+')?(1<<m):0;
  }
}

void writeGame()
{
  for (n=1;n<18;++n)
  {
    for (m=0; m<10;++m)
      printf( (tileField[n] & 1<<m) != 0 ? "#" :((gameField[n] & 1<<m) != 0 ? "+" :" "));
    printf("\n");
  }
}

void placeTile()
{
  for (m=0;m<24;++m) tileField[m] = 0;
  for (m=0;m<4;++m) 
    tileField[ypos+m] = (tiles[tileIndex]>>(m*4) & 15) << xpos;
}

void score()
{
  scores[scoreIndex] = 0;
  for (n=0;n<18;++n) 
    if ((gameField[n] | tileField[n])==1023) scores[scoreIndex]++;

  scores[scoreIndex] = 200*(scores[scoreIndex]) + 199;

  for (m=0;m<10;++m)
  {
    l=0;
    for (n=0;n<18;++n)
    {
      h = (gameField[n] | tileField[n]) & 1<<m;
      l |= h;
      scores[scoreIndex] -= l && !h;
    }
  }
}

int noCollision()
{
  placeTile();
  int coll = 0;
  for (n=0;n<18;++n) coll |= gameField[n] & tileField[n];
  return !coll;
}

int main()
{ scores[0] = 0;
  readGame();
  scoreIndex = 0;
  score();
  for (i=0; i<transformations[tile]; ++i)
  {
    for (xpos=0; xpos<10-widths[tileIndex]; xpos++)
    {
      ypos = 0;
      while (noCollision()) ypos++;
      --ypos;
      ++scoreIndex;
      placeTile();
      score();
      if (scores[scoreIndex]>maxScore) maxScore=scores[scoreIndex];
      xplacements[scoreIndex] = xpos;
      yplacements[scoreIndex] = ypos;
      tindex[scoreIndex] = tileIndex;
    }
    tileIndex++;
  }

  for (i=1;i<scoreIndex; ++i) 
    if (scores[i]==maxScore)
    {
      j=i;
      xpos = xplacements[i];
      ypos = yplacements[i];
      tileIndex = tindex[i];
      placeTile();
      writeGame();
    }

  printf("%dL %dH\n", scores[j]/200, scores[0]%200-scores[j]%200);
}

मैंने देखा कि लम्बे कोड का मुख्य स्रोत शायद टाइल्स की परिभाषा होगी। इसलिए मैंने उन्हें 4x4 बिट सरणी में बिट पैटर्न के रूप में प्रतिनिधित्व करने का निर्णय लिया। इसके परिणामस्वरूप 16 बिट्स होते हैं जो आसानी से एकल में फिट हो जाते हैं inttilesसरणी 7 टाइल्स की 19 संभव रोटेशन के लिए सभी पैटर्न रखती है।

संकलित करते समय, उस चेतावनी को अनदेखा करें जो getsपदावनत है। मुझे पता है कि यह है, लेकिन यह इनपुट से एक पंक्ति को पढ़ने का सबसे छोटा तरीका है।


वैश्विक स्तर पर, आप intमान सकते हैं कि यह मान लिया गया है। आपके printfsकेवल एक ही चरित्र के कई आउटपुट। आप putcharवर्णों के एक जोड़े को बचाने के लिए उन्हें समकक्ष के साथ बदलने में सक्षम हो सकते हैं । उदाहरण के लिए, printf("\n")putchar(10)
जोश

यदि आप केवल एक नई पंक्ति चाहते हैं तो ("") और भी कम है। इसके अलावा, आप रिटर्न का उपयोग कर सकते हैं! C (कोई स्थान नहीं)। पहली बार जब आप लूप के लिए एक इंडेक्स का उपयोग करते हैं, तो आप प्रारंभिक को 0 पर छोड़ सकते हैं क्योंकि चर विश्व स्तर पर घोषित किए जाते हैं। इसके अलावा, मुझे लगता है कि आप फ़ंक्शन ई का उपयोग केवल एक बार करते हैं, इसलिए इसे केवल इनलाइन करना संभव होना चाहिए।
अल्काइमर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.