Joanne Posted October 18, 2016 Author Posted October 18, 2016 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
Steve21 Posted October 18, 2016 Posted October 18, 2016 Sweet, Let us know if you get stuck And look forward to being able to test it at end Steve 1
elsiegee40 Posted October 18, 2016 Posted October 18, 2016 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 Done it 1
Joanne Posted October 18, 2016 Author Posted October 18, 2016 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: /** * 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; }
jwinters Posted October 18, 2016 Posted October 18, 2016 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 1
jwinters Posted October 18, 2016 Posted October 18, 2016 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 1
Joanne Posted October 19, 2016 Author Posted October 19, 2016 Woot woot 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?
jwinters Posted October 19, 2016 Posted October 19, 2016 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
Joanne Posted October 19, 2016 Author Posted October 19, 2016 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
Steve21 Posted October 19, 2016 Posted October 19, 2016 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
jwinters Posted October 19, 2016 Posted October 19, 2016 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 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
Steve21 Posted October 19, 2016 Posted October 19, 2016 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 1
Joanne Posted October 19, 2016 Author Posted October 19, 2016 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; }
jwinters Posted October 19, 2016 Posted October 19, 2016 Excellent news! Congratulations on your persistence. Cheers, John 1
mavhc Posted October 19, 2016 Posted October 19, 2016 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
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now