15 puzzle help

This is a discussion on 15 puzzle help within the C Programming forums, part of the General Programming Boards category; Hey everyone, I am working on a project (likely the same one someone posted about earlier under arrays) The assignment ...

  1. #1
    Registered User
    Join Date
    Oct 2009
    Posts
    5

    15 puzzle help

    Hey everyone,
    I am working on a project (likely the same one someone posted about earlier under arrays)

    The assignment is to create a 15 - puzzle. At first it is supposed to ask you whether you would like a random puzzle or to create your own. I have gotten this far:

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


    int table[4][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,0}};
    int count = 0;

    void displayTable(void);
    void moveNumbers(void);
    void moveRight(void);
    void moveLeft(void);
    void moveUp(void);
    void moveDown(void);
    void ownsetup (void);
    void randomizer(void);
    int checkForFinish(void);

    main(void)
    {
    int RorY;
    printf("Hello, and welcome to Hunter's 15-puzzle!\n");
    printf("To play a Randomly Generated Puzzle Press r\n");
    printf("To set up your own puzzle press y\n");
    RorY = getchar();
    if(RorY == 'r')
    randomizer();
    if(RorY == 'o')
    ownsetup();


    displayTable();


    //function used to randomize the grid
    void randomizer(){
    srand(time(NULL));
    char unsigned x = rand()%4;
    if ( x = 0 )
    {
    moveUp();
    }
    else if ( x = 1 )
    {
    moveDown();
    }
    else if ( x = 2 )
    {
    moveLeft();
    }
    else if ( x = 3 )
    {
    moveRight();
    }
    }

    //function used to set up your own grid
    void ownsetup();{
    printf("\nPlease enter the numbers for the top row from left to right\n");
    printf("followed by the numbers for the second row from left to right, etc.\n");
    printf("Please do not forget to press enter in between each number.\n");
    scanf("%d", &table[0][0]);
    scanf("%d", &table[0][1]);
    scanf("%d", &table[0][2]);
    scanf("%d", &table[0][3]);
    scanf("%d", &table[1][0]);
    scanf("%d", &table[1][1]);
    scanf("%d", &table[1][2]);
    scanf("%d", &table[1][3]);
    scanf("%d", &table[2][0]);
    scanf("%d", &table[2][1]);
    scanf("%d", &table[2][2]);
    scanf("%d", &table[2][3]);
    scanf("%d", &table[3][0]);
    scanf("%d", &table[3][1]);
    scanf("%d", &table[3][1]);
    scanf("%d", &table[3][1]);
    }

    //function used to move the numbers in the grid
    void moveNumbers(){
    int key;
    printf("\n\nEnter a letter(I, J, K or M): ");
    key = getchar();
    if(key == 'j')
    moveLeft();
    if(key == 'k')
    moveRight();
    if(key == 'i')
    moveUp();
    if(key == 'm')
    moveDown();
    displayTable();
    }

    //moves the number to the right
    void moveRight(){
    int temp,i,j;
    for(i = 0; i < 4; i++){
    for(j = 0; j < 4; j++){
    if(table[i][j] == 0 && j != 0){
    temp = table[i][j-1];
    table[i][j-1] = 0;
    table[i][j] = temp;
    }
    }
    }
    }

    //moves the number to the left
    void moveLeft(){
    int temp,i,j;
    for(i = 3; i >= 0; i--){
    for(j = 3; j >= 0; j--){
    if(table[i][j] == 0 && j != 3){
    temp = table[i][j+1];
    table[i][j+1] = 0;
    table[i][j] = temp;
    }
    }
    }
    }

    //moves the number up
    void moveUp(){
    int temp,i,j;
    for(i = 3; i >= 0; i--){
    for(j = 3; j >= 0; j--){
    if(table[i][j] == 0 && i != 3){
    temp = table[i+1][j];
    table[i+1][j] = 0;
    table[i][j] = temp;
    }
    }
    }
    }

    //moves the number down
    void moveDown(){
    int temp,i,j;
    for(i = 0; i < 4; i++){
    for(j = 0; j < 4; j++){
    if(table[i][j] == 0 && i != 0){
    temp = table[i-1][j];
    table[i-1][j] = 0;
    table[i][j] = temp;
    }
    }
    }
    }

    //function used to display the table
    void displayTable(){
    int i,j;
    for(i = 0; i < 4; i++){
    printf("\n\n");
    for(j = 0; j < 4; j++){
    if(table[i][j] == 0)
    printf(" ");
    else if(table[i][j] < 10)
    printf(" %d ",table[i][j]);
    else
    printf("%d ",table[i][j]);
    }
    }
    printf("\n");
    }

    //function used to spot a winning board
    int checkForFinish(void){
    int i,j,temp,result;
    result = 0;
    temp = 1;
    for(i = 0; i < 4; i++){
    for(j = 0; j < 4; j++){
    if(table[i][j] == temp){
    temp += 1;
    }
    }
    }
    if(temp == 15)
    result = 1;
    return result;
    }
    }


    I am having several problems the first being that I'm in way over my head, but otherwise:
    1. My randomizer needs to be run many times (say 50 - 100) to actually randomize the board. How would I do this?
    2. I'm not sure exactly how to do the build your own puzzle part, so far I just have a scanf set to each 'cell' of the game board. Is there a better way to do this? How can I make it return an error message and ask the user try again if they input a number outside the 0-15 range or put a number in twice?
    3. I'm not really sure how to detect a winning board to end the program

    And advice/suggestions would be greatly appreciated. Thanks!

  2. #2
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Hit edit.
    Find the start of your code.
    Add [code] to it.
    Find the end of your code.
    Add [/code] to it.
    If it still has no indentation, delete the contents and re-paste it in between code tags. If you don't use indentation, do so; no one wants to read that.


    Quzah.
    Hope is the first step on the road to disappointment.

  3. #3
    Registered User
    Join Date
    Oct 2009
    Posts
    5
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    
    int table[4][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,0}};
    int count = 0;
    
    void displayTable(void);
    void moveNumbers(void);
    void moveRight(void);
    void moveLeft(void);
    void moveUp(void);
    void moveDown(void);
    void ownsetup (void);
    void randomizer(void);
    int checkForFinish(void);
    
    main(void)
    {
    int RorY;         
    printf("Hello, and welcome to Hunter's 15-puzzle!\n");
    printf("To play a Randomly Generated Puzzle Press r\n");
    printf("To set up your own puzzle press y\n");
    RorY = getchar();
    if(RorY == 'r')
    randomizer();
    if(RorY == 'o')
    ownsetup();
    
               
    displayTable();
        
    //function used to set up your own grid
    void ownsetup();{
    printf("\nPlease enter the numbers for the top row from left to right\n");
    printf("followed by the numbers for the second row from left to right, etc.\n");
    printf("Please do not forget to press enter in between each number.\n");
    scanf("%d", &table[0][0]);
    scanf("%d", &table[0][1]);
    scanf("%d", &table[0][2]);
    scanf("%d", &table[0][3]);
    scanf("%d", &table[1][0]);
    scanf("%d", &table[1][1]);
    scanf("%d", &table[1][2]);
    scanf("%d", &table[1][3]);
    scanf("%d", &table[2][0]);
    scanf("%d", &table[2][1]);
    scanf("%d", &table[2][2]);
    scanf("%d", &table[2][3]);
    scanf("%d", &table[3][0]);
    scanf("%d", &table[3][1]);
    scanf("%d", &table[3][1]);
    scanf("%d", &table[3][1]); 
    }
    
    //function used to move the numbers in the grid
    void moveNumbers(){
         int key;
         printf("\n\nEnter a letter(I, J, K or M): ");
         key = getchar();
         if(key == 'j')
              moveLeft();
         if(key == 'k')
              moveRight();   
         if(key == 'i')
              moveUp();
         if(key == 'm')
              moveDown(); 
         displayTable();  
    }
    
    //moves the number to the right
    void moveRight(){
        int temp,i,j;
        for(i = 0; i < 4; i++){
            for(j = 0; j < 4; j++){
                if(table[i][j] == 0 && j != 0){
                    temp = table[i][j-1];
                    table[i][j-1] = 0;
                    table[i][j] = temp;
                }
            }
        }
    } 
    
    //moves the number to the left
    void moveLeft(){
        int temp,i,j;
        for(i = 3; i >= 0; i--){
            for(j = 3; j >= 0; j--){
                if(table[i][j] == 0 && j != 3){
                    temp = table[i][j+1];
                    table[i][j+1] = 0;
                    table[i][j] = temp;
                }
            }
        }
    } 
    
    //moves the number up
    void moveUp(){
        int temp,i,j;
        for(i = 3; i >= 0; i--){
            for(j = 3; j >= 0; j--){
                if(table[i][j] == 0 && i != 3){
                    temp = table[i+1][j];
                    table[i+1][j] = 0;
                    table[i][j] = temp;
                }
            }
        }
    }   
    
    //moves the number down
    void moveDown(){
        int temp,i,j;
        for(i = 0; i < 4; i++){
            for(j = 0; j < 4; j++){
                if(table[i][j] == 0 && i != 0){
                    temp = table[i-1][j];
                    table[i-1][j] = 0;
                    table[i][j] = temp;
                }
            }
        }
    }   
    
    //function used to display the table 
    void displayTable(){
        int i,j;
        for(i = 0; i < 4; i++){
            printf("\n\n");
            for(j = 0; j < 4; j++){
                if(table[i][j] == 0)
                    printf("      ");
                else if(table[i][j] < 10)
                    printf(" %d    ",table[i][j]);  
                else
                    printf("%d    ",table[i][j]);
            }
        }
        printf("\n");   
    }
        
        //function used to randomize the grid
    void randomizer(){
         srand(time(NULL));
         char unsigned x = rand()%4;
         if ( x = 0 ) 
    		{
    			moveUp();
    		}
    		else if ( x = 1 ) 
    		{
    			moveDown();
    		}
    		else if ( x = 2 ) 
    		{
    			moveLeft();
    		}
    		else if ( x = 3 ) 
    		{
    			moveRight();
    		}
        }
        
    //function used to spot a winning board
    int checkForFinish(void){
        int i,j,temp,result;
        result = 0;
        temp = 1;
        for(i = 0; i < 4; i++){
            for(j = 0; j < 4; j++){
                if(table[i][j] == temp){
                    temp += 1;
                }
            }
            }
        if(temp == 15)
            result = 1;
        return result;
    }
    }

  4. #4
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Point 1:
    How about a loop?


    Point 2:
    Start with an empty array (put some value in it that you consider 'empty'. For each number blank through 14, ask for coordinates. Check to see if that is not empty. If it isn't empty, don't use it (ask again). If it is, use it.

    Point 3:
    Looking at the actual puzzle, how do you know it's been won? Apply that logic to your program.


    Quzah.
    Hope is the first step on the road to disappointment.

  5. #5
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    I am having several problems the first being that I'm in way over my head, but otherwise:
    1. My randomizer needs to be run many times (say 50 - 100) to actually randomize the board. How would I do this?
    2. I'm not sure exactly how to do the build your own puzzle part, so far I just have a scanf set to each 'cell' of the game board. Is there a better way to do this? How can I make it return an error message and ask the user try again if they input a number outside the 0-15 range or put a number in twice?
    3. I'm not really sure how to detect a winning board to end the program
    1) Don't try to hold your head way above the surface of the water. That just drains your energy. Float, take a breath, and float some more.

    2) You'll use a small array with 16 elements. You'll initialize the array like so:
    Code:
    int uniq[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
    And you'll get a random number, 15 times. Each time that you get one, you'll mark the matching uniq array index, with a 1. Say the first random number is a 4, so you'll mark the uniq[4] element with the value 1:

    Code:
    uniq[16] = {0,0,0,0,1,,0,0,0,0,0,0,0,0,0,0}
    Now, let's say that your 5th random number also happens to be a 4. And you check your uniq array and see that uniq[4] is already a 1, meaning that the number 4 has already been used.

    You do NOT go get another random number!

    You move up in the uniq array (or down if you prefer), until you find the next 0 value in the uniq array, and assign that number, to your puzzle square.

    Since the initial numbers were all chosen at random, and uniq is just a reflection of those random numbers, the randomness of the numbers chosen using this method, are JUST as random as your random number generator.

    Code:
    if(uniq[randomNumber]) {
      do  { 
         randomNumber++;
         if(randomNumber > 15)  //uniq[0] is not used in this example
           randomNumber = 1;
      }while uniq[randomNumber]);
    }
    I put this into (untested) code, because i don't believe I could explain it concisely, in any other way. I'm not trying to do your assignment for you.

    I would use the uniq array again, to determine if the user's number he inputs, is a repeat of another number, or not. Set it up in a while or do while loop.

    To detect a winning board:

    Code:
    int gameWon = 1;
    
    for(i = 0; i < 16; i++) {
      if(board[i-1] != i) {
         gameWon = 0;
         break;
      }
    }
    That's the idea, but this code has not been tested.

  6. #6
    Registered User
    Join Date
    Oct 2009
    Posts
    5
    Ok, I have now worked on it to get this:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    
    int table[4][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,0}};
    int count = 0;
    
    void displayTable(void);
    void moveNumbers(void);
    void moveRight(void);
    void moveLeft(void);
    void moveUp(void);
    void moveDown(void);
    void ownsetup (void);
    void randomizer(void);
    int checkForFinish(void);
    void beginning(void);
    
    main(void)
    {
    beginning();
    void beginning(){         
    int RorY;         
    printf("Hello, and welcome to Hunter's 15-puzzle!\n");
    printf("To play a Randomly Generated Puzzle Press r\n");
    printf("To set up your own puzzle press y\n");
    RorY = getchar();
    if(RorY == 'r')
            randomizer();
    if(RorY == 'o')
            ownsetup();
            }
    
               
    //function used to display the table 
    void displayTable(){
        int i,j;
        for(i = 0; i < 4; i++){
            printf("\n\n");
            for(j = 0; j < 4; j++){
                if(table[i][j] == 0)
                    printf("      ");
                else if(table[i][j] < 10)
                    printf(" %d    ",table[i][j]);  
                else
                    printf("%d    ",table[i][j]);
            }
        }
        printf("\n");   
    }
        
    //function used to set up your own grid
    void ownsetup(){
         int x;
    printf("You will now be asked to place each number.\n");
    printf("When you are given a location please type in the\n");
    printf("number you would like on that piece.\n");
    printf("\nTop Left\n");
    scanf("%d", &x);
    if (0<=x<=15)
    table[0][0] = x;
    else
    printf("Numbers must be from 0 to 15. Please start over and try again.\n");
    printf("\nTop Row 2nd Column\n");
    scanf("%d", &x);
    if (0<=x<=15)
    table[0][1] = x;
    else
    printf("Numbers must be from 0 to 15. Please start over and try again.\n");
    printf("\nTop Row 3rd Column\n");
    scanf("%d", &x);
    if (0<=x<=15)
    table[0][2] = x;
    else
    printf("Numbers must be from 0 to 15. Please start over and try again.\n");
    printf("\nTop Row 4th Column\n");
    scanf("%d", &x);
    if (0<=x<=15)
    table[0][3] = x;
    else
    printf("Numbers must be from 0 to 15. Please start over and try again.\n");
    printf("\nSecond Row First Column\n");
    scanf("%d", &x);
    if (0<=x<=15)
    table[1][0] = x;
    else
    printf("Numbers must be from 0 to 15. Please start over and try again.\n");
    printf("\nSecond Row Second Column\n");
    scanf("%d", &x);
    if (0<=x<=15)
    table[1][1] = x;
    else
    printf("Numbers must be from 0 to 15. Please start over and try again.\n");
    printf("\nSecond Row Third Column\n");
    scanf("%d", &x);
    if (0<=x<=15)
    table[1][2] = x;
    else
    printf("Numbers must be from 0 to 15. Please start over and try again.\n");
    printf("\nSecond Row Fourth Column\n");
    scanf("%d", &x);
    if (0<=x<=15)
    table[1][3] = x;
    else
    printf("Numbers must be from 0 to 15. Please start over and try again.\n");
    printf("\nThird Row First Colum\n");
    scanf("%d", &x);
    if (0<=x<=15)
    table[2][0] = x;
    else
    printf("Numbers must be from 0 to 15. Please start over and try again.\n");
    printf("\nThird Row Second Column\n");
    scanf("%d", &x);
    if (0<=x<=15)
    table[2][1] = x;
    else
    printf("Numbers must be from 0 to 15. Please start over and try again.\n");
    printf("\nThird Row Third Column\n");
    scanf("%d", &x);
    if (0<=x<=15)
    table[2][2] = x;
    else
    printf("Numbers must be from 0 to 15. Please start over and try again.\n");
    printf("\nThird Row Fourth Column\n");
    scanf("%d", &x);
    if (0<=x<=15)
    table[2][3] = x;
    else
    printf("Numbers must be from 0 to 15. Please start over and try again.\n");
    printf("\nLast Row First Column\n");
    scanf("%d", &x);
    if (0<=x<=15)
    table[3][0] = x;
    else
    printf("Numbers must be from 0 to 15. Please start over and try again.\n");
    printf("\nLast Row Second Column\n");
    scanf("%d", &x);
    if (0<=x<=15)
    table[3][1] = x;
    else
    printf("Numbers must be from 0 to 15. Please start over and try again.\n");
    printf("\nLast Row Third Column\n");
    scanf("%d", &x);
    if (0<=x<=15)
    table[3][2] = x;
    else
    printf("Numbers must be from 0 to 15. Please start over and try again.\n");
    printf("\nBottom Right\n");
    scanf("%d", &x);
    if (0<=x<=15)
    table[3][3] = x;
    else
    printf("Numbers must be from 0 to 15. Please start over and try again.\n");
    displayTable();
    }
    
    //moves the number to the right
    void moveRight(){
        int temp,i,j;
        for(i = 0; i < 4; i++){
            for(j = 0; j < 4; j++){
                if(table[i][j] == 0 && j != 0){
                    temp = table[i][j-1];
                    table[i][j-1] = 0;
                    table[i][j] = temp;
                }
            }
        }
    } 
    
    //moves the number to the left
    void moveLeft(){
        int temp,i,j;
        for(i = 3; i >= 0; i--){
            for(j = 3; j >= 0; j--){
                if(table[i][j] == 0 && j != 3){
                    temp = table[i][j+1];
                    table[i][j+1] = 0;
                    table[i][j] = temp;
                }
            }
        }
    } 
    
    //moves the number up
    void moveUp(){
        int temp,i,j;
        for(i = 3; i >= 0; i--){
            for(j = 3; j >= 0; j--){
                if(table[i][j] == 0 && i != 3){
                    temp = table[i+1][j];
                    table[i+1][j] = 0;
                    table[i][j] = temp;
                }
            }
        }
    }   
    
    //moves the number down
    void moveDown(){
        int temp,i,j;
        for(i = 0; i < 4; i++){
            for(j = 0; j < 4; j++){
                if(table[i][j] == 0 && i != 0){
                    temp = table[i-1][j];
                    table[i-1][j] = 0;
                    table[i][j] = temp;
                }
            }
        }
    }   
    
    //function used to move the numbers in the grid
    void moveNumbers(){
         int key;
         printf("\n\nEnter a letter(I, J, K or M): ");
         key = getchar();
         if(key == 'j')
              moveLeft();
         if(key == 'k')
              moveRight();   
         if(key == 'i')
              moveUp();
         if(key == 'm')
              moveDown(); 
         displayTable();  
    }
        
        //function used to randomize the grid
    void randomizer(){
         srand(time(NULL));
         char unsigned x = rand()%4;
         int i = 50;
         while (i>1){
         if ( x = 0 ) 
    		{
    			moveUp();
    		}
    		else if ( x = 1 ) 
    		{
    			moveDown();
    		}
    		else if ( x = 2 ) 
    		{
    			moveLeft();
    		}
    		else if ( x = 3 ) 
    		{
    			moveRight();
    		}
    		i--;
        }
        }
        
    //function used to spot a winning board
    int checkForFinish(void){
        int i,j,temp,result;
        result = 0;
        temp = 1;
        for(i = 0; i < 4; i++){
            for(j = 0; j < 4; j++){
                if(table[i][j] == temp){
                    temp += 1;
                }
            }
            }
        if(temp == 15)
            result = 1;
        return result;
    }
    }
    But I am getting several errors when I compile, such as undefined reference to randomizer, ownsetup, beginning. Any idea what could be wrong?

    Adak, if I understand your suggestion for randomizing correctly it would give me completely random numbers which could lead to an unsolvable board. That is why I am trying to move the pieces around to randomize it. Please correct me if I'm wrong, and thanks for the help!
    Last edited by rhodesianhunter; 10-07-2009 at 09:10 PM.

  7. #7
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Then start with a sorted puzzle, and keep track of where the empty square is, and just start moving around a few thousand moves or so...


    Quzah.
    Hope is the first step on the road to disappointment.

  8. #8
    Registered User
    Join Date
    Oct 2009
    Posts
    5
    I solved all of my compiler errors, but now when I run my program it quits after choosing r or y. Can anyone tell why?

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    
    int table[4][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,0}};
    
    void displayTable(void);
    void moveNumbers(void);
    void moveRight(void);
    void moveLeft(void);
    void moveUp(void);
    void moveDown(void);
    void ownsetup (void);
    void randomizer(void);
    int checkForFinish(void);
    
    
    main(void)
    {
    int RorY;
    printf("Hello, and welcome to Hunter's 15-puzzle!\n");
    printf("To play a Randomly Generated Puzzle Press r\n");
    printf("To set up your own puzzle press y\n");
    RorY = getchar();
    if(RorY == 'r')
            randomizer();
    if(RorY == 'o')
            ownsetup();
            }
    
               
    //function used to display the table 
    void displayTable(){
        int i,j;
        for(i = 0; i < 4; i++){
            printf("\n\n");
            for(j = 0; j < 4; j++){
                if(table[i][j] == 0)
                    printf("      ");
                else if(table[i][j] < 10)
                    printf(" %d    ",table[i][j]);  
                else
                    printf("%d    ",table[i][j]);
            }
        }
        printf("\n");   
    }
        
    //function used to set up your own grid
    void ownsetup(){
         int x;
    printf("You will now be asked to place each number.\n");
    printf("When you are given a location please type in the\n");
    printf("number you would like on that piece.\n");
    printf("\nTop Left\n");
    scanf("%d", &x);
    if (0<=x<=15)
    table[0][0] = x;
    else
    printf("Numbers must be from 0 to 15. Please start over and try again.\n");
    printf("\nTop Row 2nd Column\n");
    scanf("%d", &x);
    if (0<=x<=15)
    table[0][1] = x;
    else
    printf("Numbers must be from 0 to 15. Please start over and try again.\n");
    printf("\nTop Row 3rd Column\n");
    scanf("%d", &x);
    if (0<=x<=15)
    table[0][2] = x;
    else
    printf("Numbers must be from 0 to 15. Please start over and try again.\n");
    printf("\nTop Row 4th Column\n");
    scanf("%d", &x);
    if (0<=x<=15)
    table[0][3] = x;
    else
    printf("Numbers must be from 0 to 15. Please start over and try again.\n");
    printf("\nSecond Row First Column\n");
    scanf("%d", &x);
    if (0<=x<=15)
    table[1][0] = x;
    else
    printf("Numbers must be from 0 to 15. Please start over and try again.\n");
    printf("\nSecond Row Second Column\n");
    scanf("%d", &x);
    if (0<=x<=15)
    table[1][1] = x;
    else
    printf("Numbers must be from 0 to 15. Please start over and try again.\n");
    printf("\nSecond Row Third Column\n");
    scanf("%d", &x);
    if (0<=x<=15)
    table[1][2] = x;
    else
    printf("Numbers must be from 0 to 15. Please start over and try again.\n");
    printf("\nSecond Row Fourth Column\n");
    scanf("%d", &x);
    if (0<=x<=15)
    table[1][3] = x;
    else
    printf("Numbers must be from 0 to 15. Please start over and try again.\n");
    printf("\nThird Row First Colum\n");
    scanf("%d", &x);
    if (0<=x<=15)
    table[2][0] = x;
    else
    printf("Numbers must be from 0 to 15. Please start over and try again.\n");
    printf("\nThird Row Second Column\n");
    scanf("%d", &x);
    if (0<=x<=15)
    table[2][1] = x;
    else
    printf("Numbers must be from 0 to 15. Please start over and try again.\n");
    printf("\nThird Row Third Column\n");
    scanf("%d", &x);
    if (0<=x<=15)
    table[2][2] = x;
    else
    printf("Numbers must be from 0 to 15. Please start over and try again.\n");
    printf("\nThird Row Fourth Column\n");
    scanf("%d", &x);
    if (0<=x<=15)
    table[2][3] = x;
    else
    printf("Numbers must be from 0 to 15. Please start over and try again.\n");
    printf("\nLast Row First Column\n");
    scanf("%d", &x);
    if (0<=x<=15)
    table[3][0] = x;
    else
    printf("Numbers must be from 0 to 15. Please start over and try again.\n");
    printf("\nLast Row Second Column\n");
    scanf("%d", &x);
    if (0<=x<=15)
    table[3][1] = x;
    else
    printf("Numbers must be from 0 to 15. Please start over and try again.\n");
    printf("\nLast Row Third Column\n");
    scanf("%d", &x);
    if (0<=x<=15)
    table[3][2] = x;
    else
    printf("Numbers must be from 0 to 15. Please start over and try again.\n");
    printf("\nBottom Right\n");
    scanf("%d", &x);
    if (0<=x<=15)
    table[3][3] = x;
    else
    printf("Numbers must be from 0 to 15. Please start over and try again.\n");
    displayTable();
    }
    
    //moves the number to the right
    void moveRight(){
        int temp,i,j;
        for(i = 0; i < 4; i++){
            for(j = 0; j < 4; j++){
                if(table[i][j] == 0 && j != 0){
                    temp = table[i][j-1];
                    table[i][j-1] = 0;
                    table[i][j] = temp;
                }
            }
        }
    } 
    
    //moves the number to the left
    void moveLeft(){
        int temp,i,j;
        for(i = 3; i >= 0; i--){
            for(j = 3; j >= 0; j--){
                if(table[i][j] == 0 && j != 3){
                    temp = table[i][j+1];
                    table[i][j+1] = 0;
                    table[i][j] = temp;
                }
            }
        }
    } 
    
    //moves the number up
    void moveUp(){
        int temp,i,j;
        for(i = 3; i >= 0; i--){
            for(j = 3; j >= 0; j--){
                if(table[i][j] == 0 && i != 3){
                    temp = table[i+1][j];
                    table[i+1][j] = 0;
                    table[i][j] = temp;
                }
            }
        }
    }   
    
    //moves the number down
    void moveDown(){
        int temp,i,j;
        for(i = 0; i < 4; i++){
            for(j = 0; j < 4; j++){
                if(table[i][j] == 0 && i != 0){
                    temp = table[i-1][j];
                    table[i-1][j] = 0;
                    table[i][j] = temp;
                }
            }
        }
    }   
    
    //function used to move the numbers in the grid
    void moveNumbers(){
         int key;
         printf("\n\nEnter a letter(I, J, K or M): ");
         key = getchar();
         if(key == 'j')
              moveLeft();
         if(key == 'k')
              moveRight();   
         if(key == 'i')
              moveUp();
         if(key == 'm')
              moveDown(); 
         displayTable();  
    }
        
        //function used to randomize the grid
    void randomizer(){
         srand(time(NULL));
         char unsigned x = rand()%4;
         int i = 50;
         while (i>1){
         if ( x = 0 ) 
    		{
    			moveUp();
    		}
    		else if ( x = 1 ) 
    		{
    			moveDown();
    		}
    		else if ( x = 2 ) 
    		{
    			moveLeft();
    		}
    		else if ( x = 3 ) 
    		{
    			moveRight();
    		}
    		i--;
        }
        displayTable();
        }
        
    //function used to spot a winning board
    int checkForFinish(void){
        int i,j,temp,result;
        result = 0;
        temp = 1;
        for(i = 0; i < 4; i++){
            for(j = 0; j < 4; j++){
                if(table[i][j] == temp){
                    temp += 1;
                }
            }
            }
        if(temp == 15)
            result = 1;
        return result;
    }

  9. #9
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    First off, your indentation sucks.
    Code:
    main(void)
    {
        int RorY;
        printf("Hello, and welcome to Hunter's 15-puzzle!\n");
        printf("To play a Randomly Generated Puzzle Press r\n");
        printf("To set up your own puzzle press y\n");
        RorY = getchar();
        if(RorY == 'r')
            randomizer();
        if(RorY == 'o')
            ownsetup();
    }
    Let's pretend you press r and hit enter. That gets you here:
    Code:
    void randomizer(){
        srand(time(NULL));
        char unsigned x = rand()%4;
        int i = 50;
        while (i>1){
            if ( x = 0 ) 
            {
                moveUp();
            }
            else if ( x = 1 ) 
    	{
    	    moveDown();
            }
            else if ( x = 2 ) 
            {
                moveLeft();
            }
            else if ( x = 3 ) 
            {
                moveRight();
            }
            i--;
        }
        displayTable();
    }
    Ok, all this does is call 'moveDown' over and over... Can you figure out why?

    Quzah.
    Last edited by quzah; 10-07-2009 at 10:27 PM.
    Hope is the first step on the road to disappointment.

  10. #10
    Registered User
    Join Date
    Oct 2009
    Posts
    5
    I know, I'm new. This is my first attempt at programming.

    No, I can't tell why... I'm trying to get it to give a random number between 0 and 3 and then make the corresponding move. How could I change it?

  11. #11
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    = is not ==


    Quzah.
    Hope is the first step on the road to disappointment.

  12. #12
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Adak, if I understand your suggestion for randomizing correctly it would give me completely random numbers which could lead to an unsolvable board. That is why I am trying to move the pieces around to randomize it. Please correct me if I'm wrong, and thanks for the help!
    I thought you wanted completely random numbers for your puzzle, if requested.

    This is a rather ambitious program for a very new programmer to take on.

    There is a 15 piece sliding puzzle applet I found with Google's aid, a few months back. It doesn't show the program, but it does show how it can be solved, step by step. I'd recommend Googling and bookmarking that site. Then you can see if your steps (once you have them), match up with the applet's steps, and also, you can see how to solve a puzzle position that has you baffled.

    Oh, wait! Are you going to have your program solve the puzzle, or is it just going to make the moves that the user enters, and rely on the user to solve the puzzle?

    Either way, you need to have a display of the puzzle in it's current state, and have the program able to correctly make all the legal moves, and none of the illegal moves.

    Kudo's to your ambitious assignment or project. Very nice!

  13. #13
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Firstly, the compiler can do much better that simply check for syntax errors. I recommend turning on warning diagnostics (e.g -Wall with GCC).

    Regarding main:
    [Warning] return type defaults to `int'
    [Warning] control reaches end of non-void function
    This is a technicality but the correct layout of main is
    Code:
    int main(void) 
    {
        //your stuff here
        return 0; //0 means success by convention
    }
    Regarding ownsetup (in many places):
    Code:
    if (0<=x<=15)
    [Warning] comparisons like X<=Y<=Z do not have their mathematical meaning
    Regarding randomizer (following and similar):
    Code:
    if ( x = 0 )
    [Warning] suggest parentheses around assignment used as truth value
    (Of course, first you’d need to make sure that using assignment as a truth value is what you wanted.)

    There is also another logical bug mentioned in an earlier post.

    Next, it has been suggested several times that you simply keep track of the empty slot, which would simplify the logic and allow you to replace all the code reduplication in 4 different move... functions with a single function like this:

    Code:
    /* a convenient helper */
    void swap(int* a, int* b)
    {
        int t = *a;
        *a = *b;
        *b = t;
    }
    
    /*
        swaps table item at [y][x] with the neighbour in direction given by dir_x and dir_y
        returns 1 if successful, and 0 if neighbour is out of bounds
        if swap occurs, *x and *y will contain the coordinates of the target slot
    */
    int moveNumber(int* x, int* y, int dir_x, int dir_y)
    {
        int new_x = *x + dir_x;
        int new_y = *y + dir_y;
        /*check bounds*/
        if (new_x >= 0 && new_x < 4 && new_y >= 0 && new_y < 4) {
            swap(&table[new_y][new_x], &table[*y][*x]);
            *x = new_x;
            *y = new_y;
            return 1;
        }
        return 0;    
    }
    The four directions would be (-1, 0), (1, 0), (0, -1) and (0, 1) - allowing you to reduce code reduplication further by using look-up tables.

    The return value also allows you to check if the move is valid.

    The x and y coordinates are updated by the function. If you store the position of the empty slot once, this function will keep those updated automatically, so you’ll always know where the empty slot is.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  14. #14
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    This is my take on making ownsetup() work. I had to make some changes to get it
    to compile.

    If you don't have conio.h, let me know and I'll post up a version using the Windows
    API, for moving the cursor.

    Code:
    #include <stdio.h>
    #include <conio.h>    //for gotoxy
    #include <dos.h>      //for sleep
    
    int table[4][4];
    int uniq[16] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
    
    void displayTable(void);
    void moveNumbers(void);
    void moveRight(void);
    void moveLeft(void);
    void moveUp(void);
    void moveDown(void);
    void ownsetup (void);
    void randomizer(void);
    int checkForFinish(void);
    void showSqrNum(void);
    
    //?? added int return type for main(). In C, it's always int main.
    int main(void)  
    {
    char choice;
    int r;
    for (r = 0; r < 3; r++)
      printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
    gotoxy(1,2);
    printf("Hello, and welcome to Hunter's 15-puzzle!\n");
    printf("To play a Randomly Generated Puzzle Press r\n");
    printf("To set up your own puzzle press o\n");
    choice = getchar();
    if(choice == 'r')
       randomizer();
    if(choice == 'o')
       ownsetup();
    
    //pulls unwanted strokes off the keyboard buffer
    printf("\n\n\t\t\t     press enter when ready");
    while((choice = getchar()) != '\n'); 
    choice = getchar(); choice++; //holds the text window open
    
    return 0;  //added return 0
    
    }
        
    //function used to display the table 
    void displayTable(){
      int r,c;
      gotoxy(1, 5);
      for(r = 0; r < 4; r++){
        gotoxy(1,r+5);
        for(c = 0; c < 4; c++){
          printf("%4d", table[r][c]);  
        }
      }
    }
        
    //function used to set up your own grid
    void ownsetup(){
      int x, r, c, sqr;
      printf("\n\nYou will now be asked to place each number.\n");
      printf("When you are given a square number, please type in the\n");
      printf("number you want placed there.\n");
      for(r = 0; r < 3; r++)
        printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
      showSqrNum();
    
      for(sqr = 0; sqr < 16; sqr++) {
        do {
          gotoxy(2,12);  //removes error message, if present
          printf("                                               \n");
          printf("                                               \n");
          gotoxy(10,12);
          printf("Square %d: ",sqr+1);
          scanf("%d", &x);
          if(!uniq[x]) {
             x = -1;
          } 
          if (x < 0 || x > 15) { 
            gotoxy(2, 12);
            printf("Numbers must be a unique number, from 0 to 15. \n ");
            printf("Please re-enter a number.");
            sleep(3);
          }
          else {
            r = sqr / 4;
            c = sqr % 4;
            table[r][c] = x;
            uniq[x] = 0;
            displayTable();
          }
       }while(x < 0 || x > 15);
     }
      displayTable();
    
    }
    
    //moves the number to the right
    void moveRight(){
        int temp,i,j;
        for(i = 0; i < 4; i++){
            for(j = 0; j < 4; j++){
                if(table[i][j] == 0 && j != 0){
                    temp = table[i][j-1];
                    table[i][j-1] = 0;
                    table[i][j] = temp;
                }
            }
        }
    } 
    
    //moves the number to the left
    void moveLeft(){
        int temp,i,j;
        for(i = 3; i >= 0; i--){
            for(j = 3; j >= 0; j--){
                if(table[i][j] == 0 && j != 3){
                    temp = table[i][j+1];
                    table[i][j+1] = 0;
                    table[i][j] = temp;
                }
            }
        }
    } 
    
    //moves the number up
    void moveUp(){
        int temp,i,j;
        for(i = 3; i >= 0; i--){
            for(j = 3; j >= 0; j--){
                if(table[i][j] == 0 && i != 3){
                    temp = table[i+1][j];
                    table[i+1][j] = 0;
                    table[i][j] = temp;
                }
            }
        }
    }   
    
    //moves the number down
    void moveDown(){
        int temp,i,j;
        for(i = 0; i < 4; i++){
            for(j = 0; j < 4; j++){
                if(table[i][j] == 0 && i != 0){
                    temp = table[i-1][j];
                    table[i-1][j] = 0;
                    table[i][j] = temp;
                }
            }
        }
    }   
    
    //function used to move the numbers in the grid
    void moveNumbers(){
         int key;
         printf("\n\nEnter a letter(I, J, K or M): ");
         key = getchar();
         if(key == 'j')
              moveLeft();
         if(key == 'k')
              moveRight();   
         if(key == 'i')
              moveUp();
         if(key == 'm')
              moveDown(); 
         displayTable();  
    }
        
        //function used to randomize the grid
    void randomizer(){
    
    //??     keep with int's. You have no need for char's in the puzzle table    
    //     mixing char's with int's when you don't need to, just
    //     complicates things.
    //     char unsigned x = rand()%4;
    
    
         int x;
         int i = 50;
         srand(time(NULL));
         x = rand() % 4;
         while (i>1){
         if ( x == 0 ) 
    		{
    			moveUp();
    		}
    		else if ( x == 1 ) 
    		{
    			moveDown();
    		}
    		else if ( x == 2 ) 
    		{
    			moveLeft();
    		}
    		else if ( x == 3 ) 
    		{
    			moveRight();
    		}
    		i--;
        }
        displayTable();
        }
        
    //function used to spot a winning board
    int checkForFinish(void){
        int i,j,temp,result;
        result = 0;
        temp = 1;
        for(i = 0; i < 4; i++) {
            for(j = 0; j < 4; j++) {
                if(table[i][j] == temp) {
                    temp += 1;
                }
            }
        }
        if(temp == 15)
            result = 1;
        return result;
    
    // mising brace
    }
    //shows the square number of the board, for ownsetup() only
    void showSqrNum(void) {
      int r,c;
        
      for(r = 0; r < 20; r++) {
         gotoxy(30,r+5);
         printf("                          ");
      }
      for(r = 0; r < 4; r++){
        gotoxy(30,r+5);
        for(c = 0; c < 4; c++){
          printf("%4d", (r * 4 + c + 1));  
        }
      }
      printf("\n");   
      r = getchar();
    }
    This doesn't let you move any pieces, it just has an OK way to enter unique and valid numbers, into the puzzle.

  15. #15
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Note for the above post:

    I had no idea this puzzle involved "parity". That is, the puzzle can only be solved from exactly half of the possible set-up positions: Here's one that you can't solve, for instance:

    Code:
    
      1    0    2    3
    
      4    5    6    7
    
      8    9   10   11
    
     12   13   14   15
    The right parity for the solution is shown below, where the 1's indicate a good choice for the empty (marked with a zero here), square:

    Code:
    
      1  0  1  0
      0  1  0  1
      1  0  1  0
      0  1  0  1
    Something new.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. 15 Puzzle
    By jamorg01 in forum C Programming
    Replies: 3
    Last Post: 10-04-2009, 02:42 AM
  2. Replies: 12
    Last Post: 06-06-2008, 06:26 PM
  3. Need some help with C program writing
    By The_PC_Gamer in forum C Programming
    Replies: 9
    Last Post: 02-12-2008, 09:12 PM
  4. Problem with file
    By nevrax in forum C Programming
    Replies: 12
    Last Post: 04-23-2007, 07:18 PM
  5. Crossword Puzzle Program
    By Loctan in forum C++ Programming
    Replies: 2
    Last Post: 08-01-2006, 12:08 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21