Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Reformatted Tiny 2048.c
M[16],X=16,W,k;
main(){
T(system("stty cbreak"));
puts(W&1?"WIN":"LOSE");
}
K[]={2,3,1};
s(f,d,i,j,l,P){
for(i=4;i--;)
for(j=k=l=0;k<4;)
j<4?P=M[w(d,i,j++)],W|=P>>11,l*P&&(f?M[w(d,i,k)]=l<<(l==P):0,k++),l=l?P?l-P?P:0:l:P:(f?M[w(d,i,k)]=l:0,++k,W|=2*!l,l=0);
}
w(d,i,j){
return d?w(d-1,j,3-i):4*i+j;
}
T(i){
for(i=X+rand()%X;M[i%X]*i;i--);
i?M[i%X]=2<<rand()%2:0;
for(W=i=0;i<4;)s(0,i++);
for(i=X,puts("\e[2J\e[H");i--;i%4||puts(""))
printf(M[i]?"%4d|":" |",M[i]);
W-2||read(0,&k,3)|T(s (1,K[(k>>X)%4]));
}
//[2048] reformated
Original Version : https://gist.github.com/justecorruptio/9967738
by : Jay Chan
@anirudh-chhangani

This comment has been minimized.

Copy link
Owner Author

anirudh-chhangani commented Apr 5, 2014

Original version : https://gist.github.com/justecorruptio/9967738
By : Jay Chan

@auroranil

This comment has been minimized.

Copy link

auroranil commented Apr 5, 2014

I've reformatted the code a bit more, and added a few comments to explain some of the code. Please correct me if I'm wrong. (Unfortunately I don't know much about gist, so for now I'll leave the code here)

// Original file by Jay Chan:
// https://gist.github.com/justecorruptio/9967738

#include <stdio.h>
#define GRID_LEN 16

int M[GRID_LEN];
int X = GRID_LEN;
int W;
int k;

int K[] = {2, 3, 1};

s(f, d, i, j, l, P) {
    for(i = 4; i--;) {
        for(j = k = l = 0; k < 4;) {
            if(j < 4) {
                P = M[w(d, i, j++)];
                W |= P >> 11;
                l * P && (f ? M[w(d, i, k)] = l << (l == P) : 0, k++);
                l = l ? (P ? (l-P ? P : 0) : l) : P;
            }
            else {
                f ? M[ w(d, i, k) ] = l : 0;
                ++k;
                W |= 2 * !l;
                l = 0;
            }
        }
    }        
}

int w(d, i, j) {
    // Decrements until d reaches 0
    // Recursive function

    if(d <= 0) {
        return 4 * i + j;
    }

    return w(d - 1, j, 3 - i);
}

T(i) {
    for(i = X + rand() % X; M[i % X] * i; i--);
        i ? M[i % X] = 2 << rand() % 2: 0;

    for(W = i = 0; i < 4; i++) {
        s(0, i);
    }

    // Prints the tiles onto the terminal
    for(i = X, puts("\e[2J\e[H"); i--; i % 4 || puts("")) {
        printf(M[i] ? "%4d|":"    |", M[i]);
    }


    // Read input from keyboard
    W - 2 || read(0, &k, 3) | T(s (1, K[(k >> X) % 4]));
}

int main() {
    // Uses stty to clear the screen in preparation for the game
    T(system("stty cbreak"));

    // Game has finished by this point
    // If win, display "WIN". Otherwise, display "LOSE".
    puts(W & 1 ? "WIN" : "LOSE");
    return 0;
}

//[2048]
@catull

This comment has been minimized.

Copy link

catull commented Apr 5, 2014

This passes gcc and clang without a warning.

Simplified the three functions T(), w() and s(); the arguments weren't passed in from outside, but were later initialised.
Unrolled the for-loops, sticking to the "1 statement per line" rule.

Added random seed.

// Original file by Jay Chan:
// https://gist.github.com/justecorruptio/9967738

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>

#define GRID_LEN 16

int M[GRID_LEN];
int X = GRID_LEN;
int W;
int k;
int K[] = { 2, 3, 1 };


int
w (int d, int i, int j)
{
  if (d <= 0) {
    return 4 * i + j;
  }

  return w (d - 1, j, 3 - i);
}

void
s (int f, int d)
{
  int i = 4, j, l, P;

  for (; i--;) {
    j = k = l = 0;

    for (; k < 4;) {
      if (j < 4) {
        P = M[w (d, i, j++)];
        W |= P >> 11;
        l *P && (f ? M[w (d, i, k)] = l << (l == P) : 0, k++);
        l = l ? (P ? (l - P ? P : 0) : l) : P;
      }
      else {
        f ? M[w (d, i, k)] = l : 0;
        ++k;
        W |= 2 * !l;
        l = 0;
      }
    }
  }
}

void
T ()
{
  int i = X + rand () % X;

  for (; M[i % X] * i; i--);

  i ? M[i % X] = 2 << rand () % 2 : 0;
  W = i = 0;

  for (; i < 4; i++) {
    s (0, i);
  }

  // Prints the tiles onto the terminal
  i = X;
  puts ("\e[2J\e[H");

  for (; i--;) {
    if (M[i]) {
      printf ("%4d|", M[i]);
    } else {
      printf ("%s", "    |");
    }

    // every 4th cell is followed by a line-break
    if (0 == (i & 3)) {
      putchar ('\n');
    }
  }

  // read input from keyboard
  if (!(W - 2)) {
    read (0, &k, 3);
    s (1, K[(k >> X) % 4]);
    T ();
  }
}

int
main (void)
{
  // Uses stty to clear the screen in preparation for the game
  system ("stty cbreak");

  /* Intializes random number generator */
  srand ((unsigned) time (NULL));

  T ();

  // Game has finished by this point
  // If win, display "WIN". Otherwise, display "LOSE".
  puts (W & 1 ? "WIN" : "LOSE");

  return 0;
}
@dazhao

This comment has been minimized.

Copy link

dazhao commented Apr 6, 2014

I don't understand, why read(0,&k,3), the arrow keys only need 2 bytes.

@catull

This comment has been minimized.

Copy link

catull commented Apr 6, 2014

The reason why 3 characters are read is that arrow keys generate 3-byte sequences.

Key bytes Hex value
arrow left 0x1b, '[', 'D' 0x1b5b44
arrow right 0x1b, '[', 'C' 0x1b5b43
arrow up 0x1b, '[', 'A' 0x1b5b41
arrow down 0x1b, '[', 'B' 0x1b5b42

When the characters are read, the 3-byte sequence actually is reversed.
So for instance, in the last case ('arrow down'), k is assigned 0x425b1b.

k is then used to decide which of the K-array value to use.
k is right-shifted by 16 bits, reducing it to 0x42, so we have K [ 0x042 % 4 ], which is equivalent to K[2], the 3rd element of K[].

Thus, the statement after the read (0, &k, 3) evaluates to calling s (1, 1).
I wonder why K[] does not have 4 values, one for each arrow key.

@altanhaligur

This comment has been minimized.

Copy link

altanhaligur commented Dec 24, 2017

What is this mate i dont understand this code can u pls help me? I think w,a,s,d doesnt work for example i put w but numbers doesnt went up why?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.