1

This 2048 program can work,but often there are catons happening(it runs to slow,need to wait for some seconds to get on), and i sincerely hope to receive some advice on how to promote the speed of my program. I am the beginner of C language, and this 2048 game is my first program. I appreciate it if you can give me some help.

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>
#include<conio.h>

int a[4][4] = { 0 };
int a[4][4] = { 0 };
int* p = &a[0][0];
int gameover = 0;

void input(int a[4][4], int* score);
void init(int a[4][4]);
void game_over(void);
void operate(int a[4][4], int* empty, int* score);

int main(void) {
    int empty = 2;
    int score = 0;

    init(a);
    input(a, &score);

    while (gameover != 1) {
        operate(a, &empty, &score);
        input(a, &score);
    }

    fflush(stdin);
    getchar();
    return 0;
}


void input(int a[4][4], int* score)
{
    int i = 0, j = 0;
    for (j = 3; j >= 0; j--) {
        printf("-------------------------\n");
        printf("|");
        fflush(stdout);
        fflush(stdin);
        for (i = 0; i < 4; i++) {
            if (a[j][i] == 0)
                printf("     |");
            else
                printf("  %d  |", a[j][i]);
            fflush(stdout);
        }
        putchar('\n');
    }

    printf("-------------------------\n");
    printf("up↑  down↓  left←  right→\n");
    fflush(stdout);
    fflush(stdin);
    printf("-----score:%d -----\n", *score);
}



void init(int a[4][4]) {
    int x, y;

    srand((unsigned)time(NULL));
    x = rand() % 4;
    y = rand() % 4;

    a[y][x] = 2;
    while (a[y][x] != 0) {
        x = rand() % 4;
        y = rand() % 4;
    }
    a[y][x] = 2;

}

void operate(int a[4][4], int* empty, int* score) {
    int in = 0;
    int x = 0, y = 0, check = 0;

    getch();
    in = getch();
    fflush(stdin);
    switch (in)
    {
    case 72:
        for (x = 0;x < 4; x++)
        {
            for (y = 3; y >= 0; y--)
            {
                if (a[y][x] != 0 && y != 3)
                {
                    check = y + 1;

                    for (; check < 4; check++)
                    {
                        if (a[check][x] != 0)
                        {
                            if (a[y][x] == a[check][x])
                            {
                                a[check][x] = 2 * a[check][x];
                                a[y][x] = 0;
                                *empty -= 1;
                                *score += a[check][x];
                                break;
                            }
                            else
                            {
                                if (check - 1 != y)
                                {
                                    a[check - 1][x] = a[y][x];
                                    a[y][x] = 0;
                                }
                                break;
                            }
                        }
                        if (check == 3 && a[check][x] == 0)
                        {
                            a[3][x] = a[y][x];
                            a[y][x] = 0;
                            break;
                        }

                    }

                }

            }
        }
        break;

    case 80:
        for (x = 0;x < 4; x++)
        {
            for (y = 0; y < 4; y++)
            {
                if (a[y][x] != 0 && y != 0)
                {
                    check = y - 1;

                    for (; check >= 0; check--)
                    {
                        if (a[check][x] != 0)
                        {
                            if (a[y][x] == a[check][x])
                            {
                                a[check][x] = 2 * a[check][x];
                                a[y][x] = 0;
                                *empty -= 1;
                                *score += a[check][x];
                                break;
                            }
                            else
                            {
                                if (check + 1 != y)
                                {
                                    a[check + 1][x] = a[y][x];
                                    a[y][x] = 0;
                                }
                                break;
                            }
                        }
                        if (check == 0 && a[check][x] == 0)
                        {
                            a[0][x] = a[y][x];
                            a[y][x] = 0;
                            break;
                        }

                    }

                }

            }
        }
        break;

    case 75:
        for (y = 0;y < 4; y++)
        {
            for (x = 0; x < 4; x++)
            {
                if (a[y][x] != 0 && x != 0)
                {
                    check = x - 1;

                    for (; check >= 0; check--)
                    {
                        if (a[y][check] != 0)
                        {
                            if (a[y][x] == a[y][check])
                            {
                                a[y][check] = 2 * a[y][check];
                                a[y][x] = 0;
                                *empty -= 1;
                                *score += a[y][check];
                                break;
                            }
                            else
                            {
                                if (check + 1 != x)
                                {
                                    a[y][check + 1] = a[y][x];
                                    a[y][x] = 0;
                                }
                                break;
                            }
                        }
                        if (check == 0 && a[y][check] == 0)
                        {
                            a[y][0] = a[y][x];
                            a[y][x] = 0;
                            break;
                        }

                    }

                }

            }
        }
        break;

    case 77:
        for (y = 0;y < 4; y++)
        {
            for (x = 3; x >= 0; x--)
            {
                if (a[y][x] != 0 && x != 3)
                {
                    check = x + 1;

                    for (; check < 4; check++)
                    {
                        if (a[y][check] != 0)
                        {
                            if (a[y][x] == a[y][check])
                            {
                                a[y][check] = 2 * a[y][check];
                                a[y][x] = 0;
                                *empty -= 1;
                                *score += a[y][check];
                                break;
                            }
                            else
                            {
                                if (check - 1 != x)
                                {
                                    a[y][check - 1] = a[y][x];
                                    a[y][x] = 0;
                                }
                                break;
                            }
                        }
                        if (check == 3 && a[y][check] == 0)
                        {
                            a[y][3] = a[y][x];
                            a[y][x] = 0;
                            break;
                        }

                    }

                }

            }
        }
        break;
    }
    *empty += 1;
    if (*empty <= 16)
    {
        do
        {
            srand((unsigned)time(NULL));
            x = rand() % 4;
            y = rand() % 4;
        } while (a[y][x] != 0);
        a[y][x] = 2;
        system("cls");
        fflush(stdout);
        fflush(stdin);
    }
    else
    {
        game_over();
    }


}

i hope there will be no caton or less. And sorry for so much code. Because so much catons , i added many fflush() hoping that the situation can getting better, but it is totoally invalid.

blacksadnb
  • 11
  • 2
  • 3
    What do you mean by carton/caton? What exactly is the issue? That it runs too slow? – Joachim Sauer Oct 08 '19 at 10:39
  • yes,it runs too slow,i using google translation ,and it tell me caton==sorry for that – blacksadnb Oct 08 '19 at 10:43
  • 1
    Remove the `fflush(stdout)` and remove the invalid `fflush(stdin)`. Only `fflush(stdout)` after everything is printed out you want to show this loop. Also you could try `setvbuf` full buffering. – KamilCuk Oct 08 '19 at 10:54
  • 4
    In this loop `do { srand((unsigned)time(NULL)); x = rand() % 4; y = rand() % 4; } while (a[y][x] != 0);` if it has to repeat it will do so for *up to one second*. **Don't keep re-seeding the PRNG.** – Weather Vane Oct 08 '19 at 10:54
  • ... anyway, a better strategy for repeating until a place is found, can be to make a list of available places, and pick one at ramdom. – Weather Vane Oct 08 '19 at 10:56
  • As for performance, it's very likely related to whatever strange MS DOS emulator you need in order to run this code. Or are you actually running it on a genuine DOS computer? – Lundin Oct 08 '19 at 10:57
  • 1
    `for (y = 3; y >= 0; y--) { if (a[y][x] != 0 && y != 3)` looks odd, why are you starting the loop at `3`, when the loop should not do anything for `3`? – mch Oct 08 '19 at 10:57
  • 1
    after removing srand from do-while, it runs much faster. – blacksadnb Oct 08 '19 at 11:07

1 Answers1

-1

There's a couple of subtle things I notice like maybe call pre-decrement, pre-increment instead of post-. Only seed srand((unsigned)time(NULL)) once (maybe in main()), or somewhere else rather than in a loop. But these may not make a significant difference.

Here is a quote:

"The First Rule of Program Optimization: Don't do it. The Second Rule of Program Optimization (for experts only!): Don't do it yet." — Michael A. Jackson

If there is a part that is noticeably slow, go for it. The first step would be to profile the code, to see which part is slow and then concentrate on optimizing that. Because even the micro things I mentioned may not make a significant difference.

ericcurtin
  • 1,499
  • 17
  • 20
  • 2
    "maybe call pre-decrement, pre-increment instead of post" That's just nonsense when the ++ operator is placed in a statement of its own, as in this code. – Lundin Oct 08 '19 at 10:55
  • 1
    @Lundin several books promote this https://stackoverflow.com/questions/2030189/general-c-performance-improvement-tips mostly written by Scott Meyers, although it may not make a difference here as the optimizer may nullify the benefit in this case, it is at worst equal performance and at best better performing, so it's certainly a good best practice for the case where you have a choice between the two. – ericcurtin Oct 08 '19 at 13:17
  • 2
    *like maybe*? In my experience, things such as "like maybe" when dealing with performance and optimization really means "you wasted your time even thinking about that". If you really want to optimize code, **profile** the actual executable and fix the performance bottlenecks such profiling reveals. Anything else is a waste of time and effort - even code that looks blindingly-obviously-bad performance-wise quite often isn't. – Andrew Henle Oct 08 '19 at 13:29
  • @ericcurtin C++ is not C. Relevant reading here: https://stackoverflow.com/questions/24886/is-there-a-performance-difference-between-i-and-i-in-c – Lundin Oct 08 '19 at 13:32
  • Thanks @Lundin a more relevant link, these answers still come to the same conclusion as the C++ link "++i will sometimes be faster but never slower". – ericcurtin Oct 08 '19 at 13:39
  • @AndrewHenle sounds like you are just repeating what I wrote in the answer "The first step would be to profile the code, to see which part is slow and then concentrate on optimizing that. Because even the micro things I mentioned may not make a significant difference." – ericcurtin Oct 08 '19 at 13:40
  • @ericcurtin Relevant answer [here](https://stackoverflow.com/a/26482954/584518). – Lundin Oct 08 '19 at 14:20
  • As is written underneath your answer, I don't know where you got this quote "Prefix ++ is always faster", I certainly never claimed this. It is good practice to use prefix because postfix ++ is never faster. – ericcurtin Oct 08 '19 at 14:34
  • Prefix ++ is never faster either, it is all just hogwash. You are telling the OP that they should switch to prefix ++ to optimize the code, but that will achieve nothing, since all ++ in their code are properly sequenced. Spreading optimization myths isn't helping anyone. Now the real best practice programming rule to adhere to is "never mix ++ with other operands in the same expression". Only people who don't use that best practice, but write bad code instead, need to worry their heads about prefix vs postfix performance. – Lundin Oct 09 '19 at 06:56
  • Is it not still good practice to use prefix ++ over postfix ++? What if you are using a compiler suite that doesn't optimize this out? When you are relying on an optimization to change your code, I'm not sure how you can make this statement "Prefix ++ is never faster either". Or someday your codebase turns into a mix of C and C++? Postfix also can mislead a reader on intent. – ericcurtin Oct 09 '19 at 08:14