Conditional Sequence of Events - c

Im trying to write a function that scans in IP addresses on user input and has three main conditions:
If the IP address is valid, valid_addresses += 1
If the IP address is precisely -1.-1.-1.-1 then stop scanning for any further IP addresses and return valid_addresses (should contain the number of valid addresses).
If the IP address contains any value that is either below 0 or above 255, printf("Invalid input.\n") but continue scanning for further IP addresses (don't terminate the loop).
My current attempt is simply printing "Invalid input":
Main:
#include <stdio.h>
int LENGTH = 5; /* Tells the function how many IP addresses the user needs to provide on input */
char dot; /* Stores the points between digits */
struct ipaddr{ /* Making the ip address struct */
int octet1;
int octet2;
int octet3;
int octet4;
}; typedef struct ipaddr ipaddr_t;
int get_valid_ip_addrs(ipaddr_t addr_array[], int addr_array_len); /* Function prototype */
int main(){
struct ipaddr addr_array[LENGTH]; /* Variable declaration */
get_valid_ip_addrs(addr_array, LENGTH); /* Function call */
}
Function definition
int get_valid_ip_addrs(ipaddr_t addr_array[], int addr_array_len){
int valid_inputs = 0, i, k;
for(i = 0; i < addr_array_len; i++){
scanf("%i%c%i%c%i%c%i", &addr_array[i].octet1, &dot, &addr_array[i].octet2, &dot,
&addr_array[i].octet3, &dot, &addr_array[i].octet4);
/* Condition 1. (if the address is valid) */
for(k = 0; k < addr_array_len; k++){
if(addr_array[k].octet1 > 0 && addr_array[k].octet1 < 256 &&
addr_array[k].octet2 > 0 && addr_array[k].octet2 < 256 &&
addr_array[k].octet3 > 0 && addr_array[k].octet3 < 256 &&
addr_array[k].octet4 > 0 && addr_array[k].octet4 < 256){
valid_inputs = valid_inputs + 1;
}
/* Condition 2 (if the address is -1.-1.-1.-1) */
else if(addr_array[k].octet1 == -1 &&
addr_array[k].octet2 == -1 &&
addr_array[k].octet3 == -1 &&
addr_array[k].octet4 == -1){
return valid_inputs;
}
/* Condition 3 - if the address is invalid */
else if(addr_array[k].octet1 < 0 || addr_array[k].octet1 > 255 ||
addr_array[k].octet2 < 0 || addr_array[k].octet2 > 255 ||
addr_array[k].octet3 < 0 || addr_array[k].octet3 > 255 ||
addr_array[k].octet4 < 0 || addr_array[k].octet4 > 255){
printf("Invalid input.\n");
}
}
}
return valid_inputs;
}
I cant seem to figure out why my program doesn't do what i'm expecting it to do, any help for a beginner is greatly appreciated!

Try this :
typedef enum
{
IP_GET_OK,
IP_GET_ERROR,
IP_GET_END,
}IP_STATUS_t;
IP_STATUS_t getIP4(char *buff, int *ip4)
{
IP_STATUS_t result = IP_GET_ERROR;
if(buff && ip4 && fgets(buff, 32, stdin))
{
if(sscanf(buff, "%d.%d.%d.%d", &ip4[0], &ip4[1], &ip4[2], &ip4[3]) == 4)
{
int allminusone = 1;
for(size_t index = 0; index < 4; index++)
{
allminusone = allminusone && (ip4[index] == -1);
}
if(allminusone)
{
result = IP_GET_END;
}
else
{
result = IP_GET_OK;
for(size_t index = 0; index < 4; index++)
{
if(ip4[index] < 0 || ip4[index] > 0xff )
{
result = IP_GET_ERROR;
break;
}
}
}
}
}
return result;
}

You have an extra inner k loop. in which in the first case you only have one input but you still iterate over all the elements for which the behavior may be undefined.
int get_valid_ip_addrs(ipaddr_t addr_array[], int addr_array_len){
int valid_inputs = 0, i, k;
for(i = 0; i < addr_array_len; i++){
scanf("%d%c%d%c%d%c%d", &addr_array[i].octet1, &dot,
&addr_array[i].octet2, &dot,&addr_array[i].octet3, &dot, &addr_array[i].octet4);
/* Condition 1. (if the address is valid) */
if(addr_array[i].octet1 > 0 && addr_array[i].octet1 < 256 &&
addr_array[i].octet2 > 0 && addr_array[i].octet2 < 256 &&
addr_array[i].octet3 > 0 && addr_array[i].octet3 < 256 &&
addr_array[i].octet4 > 0 && addr_array[i].octet4 < 256){
valid_inputs = valid_inputs + 1;
}
/* Condition 2 (if the address is -1.-1.-1.-1) */
else if(addr_array[i].octet1 == -1 &&
addr_array[i].octet2 == -1 &&
addr_array[i].octet3 == -1 &&
addr_array[i].octet4 == -1){
return valid_inputs;
}
/* Condition 3 - if the address is invalid */
else if(addr_array[i].octet1 < 0 || addr_array[i].octet1 > 255 ||
addr_array[i].octet2 < 0 || addr_array[i].octet2 > 255 ||
addr_array[i].octet3 < 0 || addr_array[i].octet3 > 255 ||
addr_array[i].octet4 < 0 || addr_array[i].octet4 > 255){
printf("Invalid input.\n");
}
}
return valid_inputs;
}

Related

Segmentation fault when there is just one value as input

My code seems to be working fine, but I get a Segmentation fault when there is just one value as input. It should print a square shape based on a number as character input.
test case : ["2", "2"]
"oo\noo\n"
test case: ["", ""]
""
test case : ["2"]
SIGSEGV (signal 11)
#include <string.h>
#include <stdlib.h>
void my_square(int *x, int *y)
{
int i , j;
if (*x == 0 || *y == 0) {
printf("");
}
else{
for(i = 0; i < *x; i++){
for(j = 0; j < *y; j++){
if(*x<=2 && j == 0){
printf("o");
}else if(*x<=2 && j == 1){
printf("o\n");
}else if(*y<=2 && i == 0){
printf("o");
}else if(*y<=2 && i == 1){
printf("o\n");
}else{
//printf(" i: %d, j: %d ", i, j);
if(i == 0 && j == 0 || i == *y-1 && j == 0 || i == 0 && j == *x-1 || i == *y-1 && j == *x-1){
printf("o");
}
if(i >= 1 && j == 0 && i != *y-1) {
printf("|");
}
if(i >= 1 && j == *x-1 && i != *y-1) {
printf("|");
}
if(i == 0 && j >= 1 && j != *y-1|| i == *x-1 && j >= 1 && j != *y-1){
printf("-");
}
if(i >= 1 && j >= 1 && i < *x-1 && j < *y-1){
printf(" ");
}
if(j == *x-1){
printf("\n");
}
}
//printf("> %d, %d", i, j);
}
}
}
}
int main(int ac, char **av)
{
int x = atoi(av[1]);
int y = atoi(av[2]);
my_square(&x, &y);
return 0;
}```
You should always check ac before accessing av, otherwise it may lead to undefined behaviour (and cause a segmentation fault).
That's how you could do it (the first value is always the program file name):
int main(int ac, char **av)
{
int x, y;
if (ac <= 3)
{
x = atoi(av[1]);
y = x; // if there's only one argument, we use it for both x and y
if (ac == 3)
{
y = atoi(av[2]);
}
my_square(&x, &y);
}
return 0;
}

Seg Fault when using pthread_create

I am having difficulty creating thread when using pthread_create, I have tried changing functions to void* and such but it keeps throwing a segmentation fault.
Any help towards fixing this problem would be appreciated, I have tried researching this problem but to no avail I have yet to find a solution
Here is my code below:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <ctype.h>
#include <getopt.h>
#include <stdbool.h>
void readSudoku(int x[][9], FILE *in);
void printSudoku(int x[][9]);
int validateRows(int x[9][9]);
int validateCols(int x[9][9]);
int validateSubGrids(int x[9][9]);
void *vr(int x[9][9]);
void *vc(int x[9][9]);
void *vs(int x[9][9]);
bool validSudokuGrid(int x[][9]);
/* These are the only two global variables allowed in your program */
static int verbose = 0;
static int use_fork = 0;
// This is a simple function to parse the --fork argument.
// It also supports --verbose, -v
void parse_args(int argc, char *argv[])
{
int c;
while (1)
{
static struct option long_options[] =
{
{"verbose", no_argument, 0, 'v'},
{"fork", no_argument, 0, 'f'},
{0, 0, 0, 0}};
int option_index = 0;
c = getopt_long(argc, argv, "vf", long_options, &option_index);
if (c == -1)
break;
switch (c)
{
case 'f':
use_fork = 1;
break;
case 'v':
verbose = 1;
break;
default:
exit(1);
}
}
}
int main(int argc, char *argv[])
{
// Commented this out because this will be used later
// parse_args(argc, argv);
// if (verbose && use_fork) {
// printf("We are forking child processes as workers.\n");
// } else if (verbose) {
// printf("We are using worker threads.\n");
// }
// printf("Test");
// Initializing sudoku grid to parse file grid
int sudoku_grid[9][9];
if (argc == 1)
{
printf("File successfully opened!\n");
}
readSudoku(sudoku_grid, stdin);
printSudoku(sudoku_grid);
// validateRows(sudoku_grid);
// validateCols(sudoku_grid);
if (validSudokuGrid(sudoku_grid))
{
printf("The input is a valid Sudoku. \n");
}
else
{
printf("The input is not a valid Sudoku. \n");
}
return 0;
}
void readSudoku(int x[][9], FILE *in)
{
fseek(in, -1, SEEK_CUR); // Seek to start off the current position of the file ptr
char entry;
int i, j, totalVals = 0;
while ((fread(&entry, 1, 1, in)) > 0 && totalVals < 81)
{ // Read 81 digits from stdin file
if (entry != '\n')
{ // Ignore newline
if (isdigit(entry))
{
++totalVals;
x[i][j] = entry - '0'; // Store integer representation
++j;
if (j == 9)
{
j = 0;
++i;
}
}
}
}
}
void printSudoku(int x[][9])
{
int i = 0, j = 0; // i = rows, j = cols
for (i = 0; i < 9; i++)
{
for (j = 0; j < 9; j++)
{
// if we are on the third or fifth number of sub-grid
// we make a space between nums
if (2 == j || 5 == j)
{
printf("%d ", x[i][j]);
}
// if we are on the last num of row we make a space
else if (8 == j)
{
printf("%d\n", x[i][j]);
}
// anything else we make a space
else
{
printf("%d ", x[i][j]);
}
}
// if we are on row 3 or row 5 we make a space
if (2 == i || 5 == i)
{
printf("\n");
}
}
}
// Used to validate rows per 3x3 grid
int validateRows(int x[9][9])
{
for (int i = 0; i < 9; i += 3)
{
for (int j = 0; j < 9; j += 3)
{
int subgridValidate[9] = {0};
for (int k = i; k < i + 3; k++)
{
for (int m = j; m < j + 3; m++)
{
int currVal = x[k][m];
if (subgridValidate[currVal - 1] == 0)
{
subgridValidate[currVal - 1] = 1;
}
// else
// {
// // printf("row: %d, col: %d", k+1, m+1);
// // printf("Row: %d does not have required values \n", k + 1);
// // printf("Column: %d does not have required values \n", m + 1);
// return 0;
// }
else if((subgridValidate[currVal - 1] == 1) && (k >= 0 && k <=2)) { // checks for dupes, segfaults if num > 9
if( m >= 0 && m <= 2 ){
printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
return 0;
}
else if ( m >= 3 && m <= 5 ){
printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
return 0;
}
else if ( m >= 6 && m <= 8 ){
printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
return 0;
}
}
else if((subgridValidate[currVal - 1] == 1) && (k >= 3 && k <=5) ) { // checks for dupes, segfaults if num > 9
if( m >= 0 && m <= 2 ){
printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
return 0;
}
else if( m >= 3 && m <= 5 ){
printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
return 0;
}
else if( m >= 6 && m <= 8 ){
printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
return 0;
}
}
else if((subgridValidate[currVal - 1] == 1) && (k >= 6 && k <=8)) { // checks for dupes, segfaults if num > 9
if( m >= 0 && m <= 2 ){
printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
return 0;
}
else if( m >= 3 && m <= 5 ){
printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
return 0;
}
else if( m >= 6 && m <= 8 ){
printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
return 0;
}
}
else //all subgrid have correct values.
{
return 1; // true
}
}
}
}
}
}
// Validating columns in the 3x3 grid *BACK UP*
// Fixing column tracking
// int validateCols(int x[9][9]) {
// int col = 0;
// // Traversing Rows
// for(int i = 0; i < 9; i++) {
// // Initialzing array to detect for duplicate values
// int colValidate[9] = {0};
// // Traversing columns
// for(int j = 0; j < 9; j++) {
// // Holds current value depending on row / col
// int currVal = x[i][j];
// // If the index is filled with a zero
// // that means the index is not taken
// if(colValidate[currVal - 1] == 0) {
// colValidate[currVal - 1] = 1; // fill index with 1 (true)
// } else { // Checks if dupllicate or out of bounds
// printf("Column: %d does not have the required values\n", j + 1);
// return 0;
// }
// } col ++;
// }
// }
// Function to check 3x3 Sub-Grids
int validateCols(int x[9][9])
{
for (int i = 0; i < 9; i += 3)
{
for (int j = 0; j < 9; j += 3)
{
int subgridValidate[9] = {0};
for (int k = i; k < i + 3; k++)
{
for (int m = j; m < j + 3; m++)
{
int currVal = x[k][m];
if (subgridValidate[currVal - 1] == 0)
{
subgridValidate[currVal - 1] = 1;
}
// else
// {
// // printf("row: %d, col: %d", k+1, m+1);
// // printf("Row: %d does not have required values \n", k + 1);
// // printf("Column: %d does not have required values \n", m + 1);
// return 0;
// }
else if((subgridValidate[currVal - 1] == 1) && (k >= 0 && k <=2)) { // checks for dupes, segfaults if num > 9
if( m >= 0 && m <= 2 ){
printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
return 0;
}
else if ( m >= 3 && m <= 5 ){
printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
return 0;
}
else if ( m >= 6 && m <= 8 ){
printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
return 0;
}
}
else if((subgridValidate[currVal - 1] == 1) && (k >= 3 && k <=5) ) { // checks for dupes, segfaults if num > 9
if( m >= 0 && m <= 2 ){
printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
return 0;
}
else if( m >= 3 && m <= 5 ){
printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
return 0;
}
else if( m >= 6 && m <= 8 ){
printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
return 0;
}
}
else if((subgridValidate[currVal - 1] == 1) && (k >= 6 && k <=8)) { // checks for dupes, segfaults if num > 9
if( m >= 0 && m <= 2 ){
printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
return 0;
}
else if( m >= 3 && m <= 5 ){
printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
return 0;
}
else if( m >= 6 && m <= 8 ){
printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
return 0;
}
}
else //all subgrid have correct values.
{
return 1; // true
}
}
}
}
}
}
// Needs intense fixing
int validateSubGrids(int x[9][9])
{
for (int i = 0; i < 9; i += 3)
{
for (int j = 0; j < 9; j += 3)
{
int subgridValidate[9] = {0};
for (int k = i; k < i + 3; k++)
{
for (int m = j; m < j + 3; m++)
{
int currVal = x[k][m];
if (subgridValidate[currVal - 1] == 0)
{
subgridValidate[currVal - 1] = 1;
}
// else
// {
// // printf("row: %d, col: %d", k+1, m+1);
// // printf("Row: %d does not have required values \n", k + 1);
// // printf("Column: %d does not have required values \n", m + 1);
// return 0;
// }
else if((subgridValidate[currVal - 1] == 1) && (k >= 0 && k <=2)) { // checks for dupes, segfaults if num > 9
if( m >= 0 && m <= 2 ){
printf("The top left subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
return 0;
}
else if ( m >= 3 && m <= 5 ){
printf("The top mid subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
return 0;
}
else if ( m >= 6 && m <= 8 ){
printf("The top right subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
return 0;
}
}
else if((subgridValidate[currVal - 1] == 1) && (k >= 3 && k <=5) ) { // checks for dupes, segfaults if num > 9
if( m >= 0 && m <= 2 ){
printf("The left subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
return 0;
}
else if( m >= 3 && m <= 5 ){
printf("The left mid subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
return 0;
}
else if( m >= 6 && m <= 8 ){
printf("The left right subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
return 0;
}
}
else if((subgridValidate[currVal - 1] == 1) && (k >= 6 && k <=8)) { // checks for dupes, segfaults if num > 9
if( m >= 0 && m <= 2 ){
printf("The bottom left subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
return 0;
}
else if( m >= 3 && m <= 5 ){
printf("The bottom mid subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
return 0;
}
else if( m >= 6 && m <= 8 ){
printf("The bottom right subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
return 0;
}
}
else //all subgrid have correct values.
{
return 1; // true
}
}
}
}
}
}
void *vr(int x[9][9]) {
validateRows(x);
}
void *vc(int x[9][9]) {
validateCols(x);
}
void *vs(int x[9][9]) {
validateSubGrids(x);
}
bool validSudokuGrid(int x[][9])
{
int numThreads = 2;
pthread_t tid [2];
for(int i = 0; i < 1; i++) {
if(i == 0) {
pthread_create(&tid[i], NULL, vr(x), NULL);
} else if(i == 1) {
pthread_create(&tid[i], NULL, vc(x), NULL);
} else {
pthread_create(&tid[i], NULL, vc(x), NULL);
}
printf("OOOGA BOOGA");
}
printf("OOOGA BOOGA");
for (int i = 0; i < numThreads; i++) {
pthread_join(tid[i], NULL);
printf("Thread %10x joined\n", tid[i]);
fflush(stdout);
}
printf("All Four Threads have exited using join(), exiting program....\n");
fflush(stdout);
exit(EXIT_SUCCESS);
return validateRows(x) + validateCols(x) + validateSubGrids(x); // if all true = valid 9x9, else = not valid 9x9
// return validateSubGrids(x);
}
Pthreads expect a callback function of the form void* func (void*), period. You cannot invent your own function format and expect it to work.
Furthermore the vr(x) etc parameters are function calls - you call the function once then use the result of that to tell pthread_create that it's a pointer to a callback function, which it isn't - it's just nonsense.
Also a function with a return type must always return something.
All of these problems could be avoided early on by configuring the compiler correctly, so that it gives errors upon encountering blatant bugs and invalid C, see What compiler options are recommended for beginners learning C? Correct use of functions is very fundamental stuff and something you need to grasp before moving on to more advanced topics like multi-threading.
Correct use, as was told in the friendly man:
void* vr (void* x) {
validateRows(x);
return NULL;
}
...
pthread_create(&tid[i], NULL, vr, x);
I am not sure if your code compiles but if it does then what will happen is this: When the program runs, then in pthread_create() function, it will call your function vr() and use the return value of vr() as the pointer to the function that should be called when the thread is created.
But vr() does not return any value but it is not of significance here.
The return value of any function is stored somewhere (register, etc.) according to the system. Let's assume that the return value is stored in a register called A. So, vr(x) will be called and then the value in register A will be read and the code will then assume that this value is the pointer to the function that should be called. But A can have any value (because the function vr(x) doesn't return any value and hence it didn't update A) - 0x0, 0x1, 0x75745, etc. And mostly this will be an invalid address (may be it will point to a restricted memory area, or to read only memory, etc.) and so the hardware will raise a memory access violation interrupt/signal which then results in segmentation fault.
Run the following code and you will understand what I am saying.
#include <stdio.h>
#include <pthread.h>
void *f(void *g)
{
printf("Called f().\n");
}
void *x(void *v)
{
printf("Called x().\n");
return (void *)(f);
}
int main(void)
{
pthread_t pt;
pthread_create(&pt, NULL, x((void *)5), NULL);
// join pthread.
pthread_join(pt, NULL);
return 0;
}
Both functions x() and f() will get called when you run the above code.
The output will be:
Called x().
Called f().

An error is generated regarding 'lvalue'.what is the reason?

I want to make a program to check if there are any numbers, uppercase and lowercase letters in my password.But,an error about 'lvalue' will occur when this code is executed. What is the reason?
#include <stdio.h>
#include <string.h>
int main(void)
{
char passwd[99];
printf("make a password:");
gets_s(passwd,99);
int num_count = 0, up_count = 0, down_count = 0;
while(1)
{
for (int i = 0; passwd[i] != NULL; i++)
{
if ('0' <= passwd[i] && passwd[i] <= '9')
num_count++;
else if ('a' <= passwd[i] && passwd[i] <= 'z')
{
down_count++;
}
else if ('A' <= passwd[i] && passwd[i] <= 'Z')
{
up_count++;
}
}
if (num_count == 0 || up_count == 0 || down_count = 0)
printf("make the password again!");
else
{
break;
}
}
getch();
return 0;
}
num_count == 0 || up_count == 0 || down_count = 0
should be
num_count == 0 || up_count == 0 || down_count == 0
To explain the error, the statement you have is equivalent to the following:
( num_count == 0 || up_count == 0 || down_count ) = 0
An expression that can be found on the left-hand side of an assignment is called an lvalue, and the expression in parens is not a valid lvalue.

How to extend my multiple loop conditions?

My code
#include <stdlib.h>
#include <stdio.h>
int main()
{
int i=0;
int j=0;
size_t count=0;
float numbers[20][100];
float velocity[21][101];
char *line = NULL;
FILE *myFile;
myFile = fopen("vel.txt", "r");
if (myFile == NULL)
{
printf("Error Reading File\n");
exit (0);
}
while(i < 20 && getline(&line, &count, myFile)!=-1) {
int len = 0, pos = 0;
j = 0;
while(j < 100 && 1 == sscanf(line + pos, "%f%n", &numbers[i][j++], &len))
pos += len;
i++;
}
free(line);
fclose(myFile);
i=1;
for( j = 0; j < 101; j++ )
{
if( j == 1 )
{
velocity[i][j]=numbers[i][j];
}
else if ( j == 101 )
{
velocity[i][j]=numbers[i][j];
}
else
{
velocity[i][j]=(numbers[i][j-1]+numbers[i][j])/2;
}
}
for (j=0 ; j<101 ; j++) {
printf("\n%f", velocity[i][j]);
}
}
I need to calculate velocities for 21,101 two dimensional mesh.If i==1 ,that is my code above and works fine.The sam conditions apply if i==21.But for all other values (2 to 20) calculations are different.How should I change
if( i== from 2 to 20 &&j == 1 )
{
do something
}
else if (i== from to to 20 && j == 101 )
{
do something 2
}
else(means i goes from 2,20 j goes from 2,100)
{
do something 3
}
Do you want something like this: if(i >= 2 %% i <= 20)? Means: 2 <= i <= 20 or if i is greater or the same as 2 and i is lower or the same as 20 it is true.
If your example:
if(i >= 2 && i <= 20 && j == 1)
{
//do something
}
else if(i >= 2 && i <= 20 && j == 101)
{
//do something 2
}
else if(i >= 2 && i <= 20 && j >= 2 && j <= 100) //means i goes from 2,20 j goes from 2,100
{
//do something 3
}
or is there anything I missed?

Trouble with moving tiles in Game of Fifteen

Below is a function in the game of fifteen which should search for the "0" tile and once found, allow adjacent tiles to move into its place. It works for the first few moves but then doesn't allow moves that it should permit when the zero tile is at the top row (it starts on the bottom right). Note below the "0" tile is drawn as an underscore. For example:
8 7 6
5 4 3
2 1 _
Tile to move: 3
8 7 6
5 4 _
2 1 3
Tile to move: 6
8 7 _
5 4 6
2 1 3
Tile to move: 7
Illegal move.
Here is the code:
bool move(int tile)
{
int blankrow;
int blankcol;
for (int i = 0; i < d; i++)
{
for (int j = 0; j < d; j++)
{
if (board[i][j] == 0)
{
blankrow = i;
blankcol = j;
}
}
}
for (int i = 0; i < d; i++)
{
for (int j = 0; j < d; j++)
{
if ((board[i][j] == tile) && ((board[i+1][j] == 0 || board[i-1][j] == 0) &&
(board[i][j+1] == 0 || board[i][j-1] == 0)))
{
int swapped = board[i][j];
board[blankrow][blankcol] = swapped;
board[i][j] = 0;
return true;
}
}
}
return false;
}
Just by looking, I'm pretty sure you need to change:
((board[i+1][j] == 0 || board[i-1][j] == 0) &&
(board[i][j+1] == 0 || board[i][j-1] == 0))
To:
(board[i+1][j] == 0 || board[i-1][j] == 0 ||
board[i][j+1] == 0 || board[i][j-1] == 0)
EDIT: I agree with the user comment below. Better code would look something like:
bool move(int tile)
{
int blankrow, blankcol, tilerow, tilecol;
for (int i = 0; i < d; i++) {
for (int j = 0; j < d; j++) {
if (board[i][j] == 0) {
blankrow = i;
blankcol = j;
}
else if (board[i][j] == tile) {
tilerow = i;
tilecol = j;
}
}
}
if( (blankrow == tilerow && abs(blankcol - tilecol) == 1) ||
(blankcol == tilecol && abs(blankrow - tilerow) == 1) ) {
board[blankrow][blankcol] = board[tilerow][tilecol];
board[tilerow][tilecol] = 0;
return true;
}
return false;
}
You found the blankrow and blankcol. Do the same thing to find the tilerow and tilecol. Then verify either
((blankrow == tilerow) && (abs(blankcol - tilecol) == 1))
or
((blankcol == tilecol) && (abs(blankrow - tilerow) == 1))
Swap if either of those conditions is met. The problem with the existing code is that you can have array accesses out-of-bounds. For example, if i is 0, then board[i-1][j] is an out-of-bounds access.
I think you should change the if statement in the second loop from
if ((board[i][j] == tile) &&
((board[i+1][j] == 0 || board[i-1][j] == 0) &&
(board[i][j+1] == 0 || board[i][j-1] == 0)))
to
if ((board[i][j] == tile) &&
((i+1==blankrow && j==blankcol) ||
(i-1==blankrow && j==blankcol) ||
(i==blankrow && j+1==blankcol) ||
(i==blankrow && j-1==blankcol)))
In the original you are requiring a row offset of one and a column offset of zero and a row offset of zero and a column offset of one simultaneously. Also you're potentially taking a negative index into the array or reading past its end.

Resources