0

I took some days to code 2048 game. And now I made most of the functions but one, testing whether the game is over. To code this game, my idea is to merge the same numbers first with the function up(down, left or right)_merge and make all the numbers go to the arrow direction that user presses with the function all_go_up(down, left or right). And then add a new number with the add_new_number function.

Here are some piece of those code I mentioned above:

void up_merge()
{
    for(int i = 1; i < 4; i++) {
        for(int j = 0; j < 4; j++) {
            if(grid[i][j] > 0 && grid[i - 1][j] == grid[i][j]) {
                while(grid[i - 1][j] == grid[i][j]) {
                    grid[i - 1][j] *= 2;
                    grid[i][j] = 0;
                }

            }
            else if(grid[i][j] > 0 && grid[i - 1][j] == 0 && grid[i - 2][j] == grid[i][j]) {
                while(grid[i - 2][j] == grid[i][j]) {
                    grid[i - 2][j] *= 2;
                    grid[i][j] = 0;
                }

            }
            else if(grid[i][j] > 0 && grid[i - 1][j] == 0 && grid[i - 2][j] == 0 && grid[i - 3][j] == grid[i][j]) {
                while(grid[i - 3][j] == grid[i][j]) {
                    grid[i - 3][j] *= 2;
                    grid[i][j] = 0;
                }

            }
        }
    }
}

void all_go_up()
{
    for(int i = 3; i > 0; i--) {
        for(int j = 0; j < 4; j++) {
            if(grid[i][j] > 0 && grid[i - 1][j] == 0) {
                grid[i - 1][j] = grid[i][j];
                grid[i][j] = 0;
            }
            for(int k = 3; k > 0; k--) { 
                if(grid[k][j] > 0 && grid[k - 1][j] == 0) {
                    grid[k - 1][j] = grid[k][j];
                    grid[k][j] = 0;
                }
            }
        }
    }
}

bool add_new_number(int num)
{
    int n = rand() % 2 + 1; 
    int newnumber = 1 << n; 
    int r, c;
    switch(num) {
    case 1: //up
        r = rand() % 2 + 2;
        c = rand() % 4;
        break;
    case 2: //down
        r = rand() % 2;
        c = rand() % 4;
        break;
    case 3: //left
        r = rand() % 4;
        c = rand() % 2 + 2;
        break;
    case 4: //right
        r = rand() % 4;
        c = rand() % 2;
        break;
    }
    do {
        if(check_empty() == 1) {
            if(grid[r][c] == 0) {
                grid[r][c] = newnumber;
                return false;
            }
            if(grid[r][c] != 0) {
                switch(num) {
                case 1: //up
                    r = rand() % 2 + 2;
                    c = rand() % 4;
                    break;
                case 2: //down
                    r = rand() % 2;
                    c = rand() % 4;
                    break;
                case 3: //left
                    r = rand() % 4;
                    c = rand() % 2 + 2;
                    break;
                case 4: //right
                    r = rand() % 4;
                    c = rand() % 2;
                    break;
                }
            }
        }
        else {
            return false;
        }

    } while(true);
}

I have some other functions to check whether the grid is full and so on. I also tried use some while() and for() to do this, too. But I do not know where I get wrong to code the function to test whether the game is over.

I hope I express my problem well. Hoping to get some suggestions to code the test_fail function without changing too much of my code. Thanks.

roshan_nazareth
  • 311
  • 5
  • 16
Theodore Tang
  • 831
  • 2
  • 21
  • 42
  • Well you can check if the grid is full right? Isn't the game over when the grid is full and no adjacent numbers are the same? a function moveExist maybe could check if a move can be made or can't (game over) – Tyler Sep 07 '17 at 15:15
  • You could write a `gameIsOver()` function in which you treat the case the 2048 tile is reached (you can decide what this function does, will it let continue or whatsoever) and which is called at the end of each `merge...`- function –  Sep 07 '17 at 15:16
  • @Tyler I thought about adding a function like moveExist, I think if I want to do this, I may need do some changement in my all_go_... functions, which i do not really want to. Do you have some ideas of how to do this? – Theodore Tang Sep 07 '17 at 15:20
  • 2
    "A function about checking whether the game is over in 2048 game". Start with giving it a name, like `gameOver()`. Then try to code it up. If there's a problem with the function, post your question about the problem, together with the code of the function. It isn't quite clear what is your specific problem, and what all this irrelevant code is doing here. – n. m. could be an AI Sep 07 '17 at 15:27
  • @LeonBreidt which merge function is called is determined by which arrow user presses. Now I even have difficulty coding the basic testing whether the game is over function, After what I asked is solved, i will add the function to play again. – Theodore Tang Sep 07 '17 at 15:30
  • @TheodoreTang You can put the check in a separated function as well and call this new function, maybe named `checkIfTileIsReached`, at the end of EACH merge function... –  Sep 07 '17 at 15:33
  • 1
    @TheodoreTang Wasn't checking for the completion of the game part of your design from the beginning? It is strange why you wrote all of this code, and suddenly you can't code part of what should have been in the design from the beginning. – PaulMcKenzie Sep 07 '17 at 15:34
  • @n.m. I just tried many ways to do this gameOver function then I do not even know which problem functions to post. Instead I just decided to ask some suggestions to do this. – Theodore Tang Sep 07 '17 at 15:35
  • @PaulMcKenzie In the beginning I do this, I just put all the functions into a infinite loop. That is why I did not code gameOver function in the beginning. – Theodore Tang Sep 07 '17 at 15:39
  • Can't decide? Show your last attempt. – n. m. could be an AI Sep 07 '17 at 15:40
  • @TheodoreTang 1) start game 2) play game 3) ask if want to play again -- yes, then go to step 1), no then done. – PaulMcKenzie Sep 07 '17 at 15:40
  • @PaulMcKenzie But I do need a function to test whether the game is over and then ask whether to play it again. Now I feel like I really stuck there. – Theodore Tang Sep 07 '17 at 15:43

1 Answers1

0

With all the respect, your code looks totally unreadable. Consider functional approach where you compose few smaller function to break down more complex problem. I am going to demonstrate this in Typescript but it would be very similar in C++. In this way the code is I believe self-explanatory.

type Board = number[][]

function isGameOver(board: Board) {
  if (hasEmptySpace(board)) return false
  return checkHorizontalGameOver(board) && checkVerticalGameOver(board)
}

function hasEmptySpace(board: Board) {
  for (let r = 0; r < NUM_ROWS; r++) {
    for (let c = 0; c < NUM_COLS; c++) {
      if (board[r][c] === 0) return true
    }
  }
  return false
}

function checkHorizontalGameOver(board: Board) {
  for (let i = 0; i < NUM_ROWS; i++) {
    for (let j = 0; j < NUM_COLS - 1; j++) {
      if (board[i][j] === board[i][j + 1]) return false
    }
  }
  return true
}

function checkVerticalGameOver(board: Board) {
  for (let i = 0; i < NUM_ROWS - 1; i++) {
    for (let j = 0; j < NUM_COLS; j++) {
      if (board[i][j] === board[i + 1][j]) return false
    }
  }
  return true
}

I understand it's 5 years ago as I am reading now and your skills in programming are far far better, but still - I will post it here for people who might come across this so it can possibly help them.

Sebastian Voráč MSc.
  • 3,256
  • 1
  • 18
  • 25