Jump to content

Recommended Posts

Posted

yeah the swap works. Just the win bit to sort out and I'm golden.

 

I can't thank you guys enough for all of your help.

@elsiegee40 @witch I'm trying to send big rep to @Steve21 for helping me, but it won't let me! Please could you guys do it for me :)

Posted

Right I'm trying to figure out how to stop the counter at (d*d) - 1.... so currently it checks the first tile is 1, second is 2.. if it isn't it returns false. Then if the last square is 0 returns true....

 

This is the winning combination:

Capture.PNG

 

/**
* Returns true if game is won (i.e., board is in winning configuration), 
* else false.
*/
bool won(void)
{
   int counter;
   counter = 1;
//itterate through numbers, checking them
   for (row = 0; row < d; row++)
   {
      for (col = 0; col < d; col++)
      {    
          if (board[row][col] != counter)
           {
               return false;
               counter++;
           }
           if ((counter == (d*d)) && (board[row][col] == 0))
           {
               return true;
           }
           
      }
   }
   return true;
}

Posted
Right I'm trying to figure out how to stop the counter at (d*d) - 1.... so currently it checks the first tile is 1, second is 2.. if it isn't it returns false. Then if the last square is 0 returns true....

 

This is the winning combination:

[ATTACH=CONFIG]39304[/ATTACH]

 

          if (board[row][col] != counter)
           {
               return false;
               counter++;
           }
           if ((counter == (d*d)) && (board[row][col] == 0))
           {
               return true;
           }

 

That

counter++

will never be reached because it's immediately after a return instruction. Put it outside the if clause, like this:

 

 

          if (board[row][col] != counter)
           {
               return false;
           }
           counter++;

 

John

  • Thanks 1
Posted

Actually, having thought about it a bit further, the logic in that section is quite out of order. (As in, wrongly ordered, not the other meaning.) The test which returns false is being done too soon, meaning you never get far enough to return true.

 

bool won(void)
{
   int counter;
   counter = 1;
   //  Iterate through numbers, checking them
   for (row = 0; row < d; row++)
   {
       for (col = 0; col < d; col++)
       {
           if ((counter == (d*d)) && (board[row][col] == 0))
           {
               return true;
           }
           if (board[row][col] != counter)
           {
               return false;
           }
           counter++;
       }
   }
   return true;
}

 

John

  • Thanks 1
Posted
Woot woot :D

 

One thing to check, does your 1/2 swap work on your version now? As wasn't working when I tried it so changed few bits for that.

 

Steve

 

 

And your "swap 1/2" function isn't working at all currently.

 

So things are working now... (thanks @jwinters !) but this swap function, continuously swaps the values on a 4x4 grid... so I think I need to put a do while loop in there, so it only does the swap once at the beginning. Would you agree with that? Or is there a better solution?

Posted
So things are working now... (thanks @jwinters !) but this swap function, continuously swaps the values on a 4x4 grid... so I think I need to put a do while loop in there, so it only does the swap once at the beginning. Would you agree with that? Or is there a better solution?

 

I think it's time for you to show us your code as it currently stands again. Difficult to give advice without knowing the current state of play.

 

Cheers,

John

Posted

I've been playing with the do while loops. They don't work...

/**
* fifteen.c
*
* Computer Science 50
* Problem Set 3
*
* Implements Game of Fifteen (generalized to d x d).
*
* Usage: fifteen d
*
* whereby the board's dimensions are to be d x d,
* where d must be in [DIM_MIN,DIM_MAX]
*
* Note that usleep is obsolete, but it offers more granularity than
* sleep and is simpler to use than nanosleep; `man usleep` for more.
*/

#define _XOPEN_SOURCE 500

#include 
#include 
#include 
#include 

// constants
#define DIM_MIN 3
#define DIM_MAX 9

// board
int board[DIM_MAX][DIM_MAX];

// dimensions
int d;

//global declarations
int row, col, val, blankTile, blankTileCol, blankTileRow;
int drawTrue = 0;
int initTrue = 0;

// prototypes
void clear(void);
void greet(void);
void init(void);
void draw(void);
bool move(int tile);
bool won(void);

int main(int argc, string argv[])
{
   // ensure proper usage
   if (argc != 2)
   {
       printf("Usage: fifteen d\n");
       return 1;
   }

   // ensure valid dimensions
   d = atoi(argv[1]);
   if (d < DIM_MIN || d > DIM_MAX)
   {
       printf("Board must be between %i x %i and %i x %i, inclusive.\n",
           DIM_MIN, DIM_MIN, DIM_MAX, DIM_MAX);
       return 2;
   }
   
   //Set blank tile location
   blankTileRow = (d - 1);
   blankTileCol = (d - 1);
   blankTile = board[blankTileRow][blankTileCol];

   // open log
   FILE* file = fopen("log.txt", "w");
   if (file == NULL)
   {
       return 3;
   }

   // greet user with instructions
   greet();

   // initialize the board
   init();


   // accept moves until game is won
   while (true)
   {
       // clear the screen
       clear();

       // draw the current state of the board
       draw();

       // log the current state of the board (for testing)
       for (int i = 0; i < d; i++)
       {
           for (int j = 0; j < d; j++)
           {
               fprintf(file, "%i", board[i][j]);
               if (j < d - 1)
               {
                   fprintf(file, "|");
               }
           }
           fprintf(file, "\n");
       }
       fflush(file);

       // check for win
       if (won())
       {
           printf("ftw!\n");
           break;
       }

       // prompt for move
       printf("Tile to move: ");
       int tile = GetInt();
       
       // quit if user inputs 0 (for testing)
       if (tile == 0)
       {
           break;
       }

       // log move (for testing)
       fprintf(file, "%i\n", tile);
       fflush(file);

       // move if possible, else report illegality
       if (!move(tile))
       {
           printf("\nIllegal move.\n");
           usleep(500000);
       }

       // sleep thread for animation's sake
       usleep(500000);
   }
   
   // close log
   fclose(file);

   // success
   return 0;
}

/**
* Clears screen using ANSI escape sequences.
*/
void clear(void)
{
   printf("\033[2J");
   printf("\033[%d;%dH", 0, 0);
}

/**
* Greets player.
*/
void greet(void)
{
   clear();
   printf("WELCOME TO GAME OF FIFTEEN\n");
   usleep(2000000);
}

/**
* Initializes the game's board with tiles numbered 1 through d*d - 1
* (i.e., fills 2D array with values but does not actually print them).  
*/
void init(void)
{
 
   val = 1;
   //populate board by row, move along columns
   for (row = 0; row < d; row++)
   {
      for (col = 0; col < d; col++)
       {
       board[row][col] = (d * d) - val;
       val = val + 1;
       }
   }
       board[d-1][d-1] = 0;
       
   //switch 1 and 2 for odd number of tiles
   do
   {
       if ((d %2 == 0) && board[row][col] == 2)
       {
       board[row][col] = 1;
       }
       else 
           if ((d %2 == 0) && board[row][col] == 1)
           {
               board[row][col] = 2;
           }
           initTrue = 1;
   }
   while (initTrue == 0);
}

/**
* Prints the board in its current state.
*/
void draw(void)
{

   val = 1;
   //populate board by row, move along columns

   for (row = 0; row < d; row++)
   {
       
      for (col = 0; col < d; col++)
       {
       
       do
       {
       if ((d %2 == 0) && board[row][col] == 2)
       {
       board[row][col] = 1;
       }
       else 
           if ((d %2 == 0) && board[row][col] == 1)
           {
               board[row][col] = 2;
               
           }
           drawTrue = 1;
       }
       while (drawTrue == 0);
           
       if (board[row][col] == 0)
       {
           printf("  _");
       }
       else 
       {
       printf(" %2d", board[row][col]);
       } 
       
       }
       printf("\n");
   }
}

/**
* If tile borders empty space, moves tile and returns true, else
* returns false. 
*/
bool move(int tile)
{

   //search for tile
   for (row = 0; row < d; row++)
   {
       //printf("Working on column %d\n", col);
      for (col = 0; col < d; col++)
      {    
          //printf("Working on row %d\n", row);
      if (tile == board[row][col])
      {
       blankTile = 0;
          //check it is next to 0
          if (((blankTileRow == (row - 1)) && (col == blankTileCol)) || (( blankTileRow == (row +1)) && (col == blankTileCol)) || 
          ((row == blankTileRow) && (blankTileCol == (col - 1))) || ((row == blankTileRow) && (blankTileCol == (col + 1))))
           {
           //swap locations of tile and 0
               board[blankTileRow][blankTileCol] = tile;
               board[row][col] = blankTile;
               blankTileRow = row;
               blankTileCol = col;
               
               return true;
           }
      }
      }
   }
   return false;
}

/**
* Returns true if game is won (i.e., board is in winning configuration), 
* else false.
*/
bool won(void)
{
   int counter;
   counter = 1;
   //  Iterate through numbers, checking them
   for (row = 0; row < d; row++)
   {
       for (col = 0; col < d; col++)
       {
           if ((counter == (d*d)) && (board[row][col] == 0))
           {
               return true;
           }
           if (board[row][col] != counter)
           {
               return false;
           }
           counter++;
       }
   }
   return true;
}

 

Bear in mind I'll get to the formatting bit when I'm finished messing :p

Posted

You need to get rid of most your draw function.

 

Draw should only be posting to the board, and not modifying anything on the array.

 

Your 1/2 swap isn't working in your init function which is why I mentioned it before, so fix the one in the init and then just use draw to draw :)

 

Steve

Posted
I've been playing with the do while loops. They don't work...

 

Honestly, they do... :)

 

/**
* Initializes the game's board with tiles numbered 1 through d*d - 1
* (i.e., fills 2D array with values but does not actually print them).  
*/
void init(void)
{
 
   val = 1;
   //populate board by row, move along columns
   for (row = 0; row < d; row++)
   {
      for (col = 0; col < d; col++)
       {
       board[row][col] = (d * d) - val;
       val = val + 1;
       }
   }
       board[d-1][d-1] = 0;
       
   //switch 1 and 2 for odd number of tiles
   do
   {
       if ((d %2 == 0) && board[row][col] == 2)
       {
       board[row][col] = 1;
       }
       else 
           if ((d %2 == 0) && board[row][col] == 1)
           {
               board[row][col] = 2;
           }
           initTrue = 1;
   }
   while (initTrue == 0);
}

 

Bear in mind I'll get to the formatting bit when I'm finished messing :p

 

As a bit of general advice, it will help a lot if you get into the habit of getting the formatting right first. It is an active aid to helping you see what is wrong with your program. I'm reminded of advice which I once saw in a "Beginning Programming" book somewhere, which advocated switching off compiler warnings until later in the development process. Said advice was quite insane.

 

I think your problem in the above quoted code is that you are expecting the initTrue = 1; bit to be conditional on the preceding else. At least, you've indented it as if it were. Unfortunately it isn't and will be executed unconditionally, which is probably why the result is surprising you.

 

Cheers,

John

Posted
I've been playing with the do while loops. They don't work...

 

You don't need any addiitonal ones for it in regards to the swapping. Just put in an additional check in your initiate one.

 

void init(void)
{
   val = 1;
   //populate board by row, move along columns
   for (row = 0; row < d; row++)
   {
      for (col = 0; col < d; col++)
       {

       if (((d*d)%2) == 0 && ((d * d) - val) == 2) {
               board[row][col] = 1;
       }  else if (((d*d)%2) == 0 && ((d * d) - val) == 1) {
               board[row][col] = 2;
       }  else
       {
               board[row][col] = (d * d) - val;
       }
         val = val + 1;
       }
   }
       board[d-1][d-1] = 0;

}

/**
* Prints the board in its current state.
*/
void draw(void)
{
   for (row = 0; row < d; row++)
   {
       for (col = 0; col < d; col++)
       {
           printf(" %2d", board[row][col]);
       }
       printf("\n");
   }
}

 

Steve

  • Thanks 1
Posted

All is working dandy now!! If anyone cares, my final code is this:

/**
* fifteen.c
*
* Computer Science 50
* Problem Set 3
*
* Implements Game of Fifteen (generalized to d x d).
*
* Usage: fifteen d
*
* whereby the board's dimensions are to be d x d,
* where d must be in [DIM_MIN,DIM_MAX]
*
* Note that usleep is obsolete, but it offers more granularity than
* sleep and is simpler to use than nanosleep; `man usleep` for more.
*/

#define _XOPEN_SOURCE 500

#include 
#include 
#include 
#include 

// constants
#define DIM_MIN 3
#define DIM_MAX 9

// board
int board[DIM_MAX][DIM_MAX];

// dimensions
int d;

//global declarations
int row, col, val, blankTile, blankTileCol, blankTileRow;

// prototypes
void clear(void);
void greet(void);
void init(void);
void draw(void);
bool move(int tile);
bool won(void);

int main(int argc, string argv[])
{
   // ensure proper usage
   if (argc != 2)
   {
       printf("Usage: fifteen d\n");
       return 1;
   }

   // ensure valid dimensions
   d = atoi(argv[1]);
   if (d < DIM_MIN || d > DIM_MAX)
   {
       printf("Board must be between %i x %i and %i x %i, inclusive.\n",
           DIM_MIN, DIM_MIN, DIM_MAX, DIM_MAX);
       return 2;
   }
   
   //Set blank tile location
   blankTileRow = (d - 1);
   blankTileCol = (d - 1);
   blankTile = board[blankTileRow][blankTileCol];

   // open log
   FILE* file = fopen("log.txt", "w");
   if (file == NULL)
   {
       return 3;
   }

   // greet user with instructions
   greet();

   // initialize the board
   init();


   // accept moves until game is won
   while (true)
   {
       // clear the screen
       clear();

       // draw the current state of the board
       draw();

       // log the current state of the board (for testing)
       for (int i = 0; i < d; i++)
       {
           for (int j = 0; j < d; j++)
           {
               fprintf(file, "%i", board[i][j]);
               if (j < d - 1)
               {
                   fprintf(file, "|");
               }
           }
           fprintf(file, "\n");
       }
       fflush(file);

       // check for win
       if (won())
       {
           printf("ftw!\n");
           break;
       }

       // prompt for move
       printf("Tile to move: ");
       int tile = GetInt();
       
       // quit if user inputs 0 (for testing)
       if (tile == 0)
       {
           break;
       }

       // log move (for testing)
       fprintf(file, "%i\n", tile);
       fflush(file);

       // move if possible, else report illegality
       if (!move(tile))
       {
           printf("\nIllegal move.\n");
           usleep(500000);
       }

       // sleep thread for animation's sake
       usleep(500000);
   }
   
   // close log
   fclose(file);

   // success
   return 0;
}

/**
* Clears screen using ANSI escape sequences.
*/
void clear(void)
{
   printf("\033[2J");
   printf("\033[%d;%dH", 0, 0);
}

/**
* Greets player.
*/
void greet(void)
{
   clear();
   printf("WELCOME TO GAME OF FIFTEEN\n");
   usleep(2000000);
}

/**
* Initializes the game's board with tiles numbered 1 through d*d - 1
* (i.e., fills 2D array with values but does not actually print them).  
*/
void init(void)
{
   val = 1;
   //populate board by row, move along columns
   for (row = 0; row < d; row++)
   {
      for (col = 0; col < d; col++)
       {
   //swaps values if board has odd number of tiles (but even d number)
           if (((d*d)%2) == 0 && ((d * d) - val) == 2) 
               {
                   board[row][col] = 1;
               }  
           else if (((d*d)%2) == 0 && ((d * d) - val) == 1) 
               {
                   board[row][col] = 2;
               }  
           else
               {
                   board[row][col] = (d * d) - val;
               }
         val = val + 1;
       }
   }
       board[d-1][d-1] = 0;
}

/**
* Prints the board in its current state.
*/
void draw(void)
{
   for (row = 0; row < d; row++)
   {
       for (col = 0; col < d; col++)
       {
           if (board[row][col] == 0)
               {
                   printf("  _");
               }
           else 
               {
                   printf(" %2d", board[row][col]);
               }
           }
       printf("\n");
   }
}

/**
* If tile borders empty space, moves tile and returns true, else
* returns false. 
*/
bool move(int tile)
{

   //search for tile
   for (row = 0; row < d; row++)
   {
       //printf("Working on column %d\n", col);
      for (col = 0; col < d; col++)
      {    
          //printf("Working on row %d\n", row);
           if (tile == board[row][col])
               {
                   blankTile = 0;
          //check it is next to 0
               if (((blankTileRow == (row - 1)) && (col == blankTileCol)) || (( blankTileRow == (row +1)) && (col == blankTileCol)) || 
          ((row == blankTileRow) && (blankTileCol == (col - 1))) || ((row == blankTileRow) && (blankTileCol == (col + 1))))
                   {
           //swap locations of tile and 0
               board[blankTileRow][blankTileCol] = tile;
               board[row][col] = blankTile;
               blankTileRow = row;
               blankTileCol = col;
               
               return true;
                   }
               }
      }
   }
   return false;
}

/**
* Returns true if game is won (i.e., board is in winning configuration), 
* else false.
*/
bool won(void)
{
   int counter;
   counter = 1;
   //  Iterate through numbers, checking them
   for (row = 0; row < d; row++)
   {
       for (col = 0; col < d; col++)
       {
           if ((counter == (d*d)) && (board[row][col] == 0))
           {
               return true;
           }
           if (board[row][col] != counter)
           {
               return false;
           }
           counter++;
       }
   }
   return true;
}

Posted
Congrats. Also useful to put your reasoning/intentions into comments of how you expect the code to work, so others don't have to infer how it's supposed to work

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now



×
×
  • Create New...