Tic-Tac-Toe user input looping endlessly when alphabetical character entered - c

So I am making a tic tac toe game in C and I am having a problem where I am asking the user to undo their move by pressing 2. Each time it is their turn, they can either undo a move or continue to select there next turn by selecting another key.
It works how it should but I have a problem where if the user enters an alphabetical character, the program just repeatedly loops through saying that this is not a number when it checks my GetHumanMove function. Does anyone know how to make it stop doing this and just say this is not a number once without it looping the program?
Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <windows.h>
//Tic-Tac-Toe game in C
//20/03/2019
//5x5 Board with 4 in a row to win. Also has playable AI that randomly blocks human moves.
//Also has replay function using a doubly linked list
/*
int board[49] = {
;,;, ;, ;, ;, ;, ;,
;,1, 2, 3, 4, 5 ,;,
;,6, 7, 8, 9, 10,;,
;,11,12,13,14,15,;,
;,16,17,18,19,20,;,
;,21,22,23,24,25,;,
;,;, ;, ;, ;, ;, ;,
}
*/
struct node
{
int side;
int move;
int place;
struct node * prev;
struct node * next;
};
void append(struct node **, int, int, int);
void display(struct node *);
void delete(struct node **, int);
//Constants of pieces, border and empty places
enum { NOUGHTS, CROSSES, BORDER, EMPTY };
//Constants for human/computer win or draw
enum { HUMANWIN, COMPWIN, DRAW };
const int directions[4] = { 1, 7, 6, 8 };
int moveCount = 0;
//Values of original places to play
const int ConvertTo49[25] = {
8, 9, 10,11,12,
15,16,17,18,19,
22,23,24,25,26,
29,30,31,32,33,
36,37,38,39,40
};
void append(struct node ** list, int side, int move, int place)
{
struct node *temp , *current = *list;
if(*list == NULL)
{
*list = (struct node *) malloc(sizeof(struct node));
(*list) -> prev = NULL;
(*list) -> side = side;
(*list) -> move = move;
(*list) -> place = place;
(*list) -> next = NULL;
}
else
{
while(current -> next != NULL)
current = current -> next;
temp = (struct node *) malloc(sizeof(struct node));
temp -> side = side;
temp -> move = move;
temp -> place = place;
temp -> next = NULL;
temp -> prev = current;
current -> next = temp;
}
}
void delete(struct node ** list, int num)
{
struct node *temp = *list;
while(temp != NULL)
{
if(temp -> move == num)
{
if(temp == *list)
{
*list = (*list) -> next;
(*list) -> prev = NULL;
}
else
{
if(temp -> next == NULL)
temp -> prev -> next = NULL;
else
{
temp -> prev -> next = temp -> next;
temp -> next -> prev = temp -> prev;
}
free(temp);
}
return ;
}
temp = temp -> next;
}
printf("Element %d not found in the supplied list \n\n", num);
}
//Loop through a direction until a border square is hit
int GetNumForDir(int startSq, const int dir, const int *board, const int us)
{
int found = 0;
while(board[startSq] != BORDER)
{
if(board[startSq] != us)
{
break;
}
found++;
startSq += dir;
}
return found;
}
//Loop through directions and find four in a row
int FindFourInARow(const int *board, const int ourIndex, const int us)
{
int dirIndex = 0;
int dir = 0;
int countFour = 1;
for(dirIndex = 0; dirIndex < 4; ++dirIndex)
{
dir = directions[dirIndex];
countFour += GetNumForDir(ourIndex + dir, dir, board, us);
countFour += GetNumForDir(ourIndex + dir * -1, dir * -1, board, us);
if(countFour == 4)
{
break;
}
countFour = 1;
}
return countFour;
}
//Set up board structure
void InitialiseBoard(int *board)
{
//index variable
int index;
//set whole board to border squares initially
for(index = 0; index < 49; ++index)
{
board[index] = BORDER;
}
//Set up empty squares for placing pieces
for(index = 0; index < 25; ++index)
{
board[ConvertTo49[index]] = EMPTY;
}
}
//Print the board
void PrintBoard(const int *board)
{
//index variable
int index;
//Set pieces and places
char pceChars[] = "OX| ";
printf("\n\n\n");
//Loop through and only draw the actual playable squares, leaving out the border squares
for(index = 0; index < 25; ++index)
{
//Put lines inbetween places
if(index==1 || index==2 || index==3 || index==4 ||
index==6 || index==7 || index==8 || index==9 ||
index==11 || index==12 || index==13 || index==14 ||
index==16 || index==17 || index==18 || index==19 ||
index==21 || index==22 || index==23 || index==24)
{
printf(" |");
}
//Put space at start to space out board from edge of screen
if(index==0)
{
printf(" ");
}
//Print new line every 5 places
if(index!= 0 && index==5 || index==10 || index==15 || index==20)
{
printf("\n");
printf(" -------------------");
printf("\n");
printf(" ");
}
//Print each playable piece
printf(" %c", pceChars[board[ConvertTo49[index]]]);
}
printf("\n\n");
}
//Check if board has empty spaces
int HasEmpty(const int *board)
{
int index;
for(index = 0; index < 25; ++index)
{
if(board[ConvertTo49[index]] == EMPTY) return 1;
}
return 0;
}
//Function for making move of current player
void MakeMove(int *board, const int sq, const side)
{
//set board place that either player decides
board[sq] = side;
}
void UndoMove(int *board, int sq, int side)
{
//set board place that either player decides
board[sq] = side;
}
//Help the computer find a winning move
int GetWinningMove(int *board, const int side)
{
int ourMove = -1;
int winFound = 0;
int index = 0;
for(index = 0; index < 25; ++index)
{
if(board[ConvertTo49[index]] == EMPTY)
{
ourMove = ConvertTo49[index];
board[ourMove] = side;
if(FindFourInARow(board, ourMove, side) == 4)
{
winFound = 1;
}
board[ourMove] = EMPTY;
if(winFound == 1)
{
return ourMove;
}
ourMove = -1;
};
}
return ourMove;
}
//Get computer player move
int GetComputerMove(int *board, const int side)
{
int index;
int numFree = 0;
int availableMoves[25];
int randMove = 0;
//Set random number to randomly run a function
int randFunction = 0;
randFunction = (rand() % 2);
//Go for the winning move
randMove = GetWinningMove(board, side);
if(randMove != -1)
{
return randMove;
}
//If random function is 1, stop any winning move from the human
if(randFunction == 1)
{
randMove = GetWinningMove(board, side ^ 1);
if(randMove != -1)
{
return randMove;
}
}
randMove = 0;
//Loop through all squares and put piece in random place
for(index = 0; index < 25; ++index)
{
if(board[ConvertTo49[index]] == EMPTY)
{
availableMoves[numFree++] = ConvertTo49[index];
};
}
randMove = (rand() % numFree);
return availableMoves[randMove];
}
//Get human player move
int GetHumanMove(const int *board)
{
//Array for user input
int userInput;
char term;
//Start moveOK at 0
int moveOK = 0;
int move = -1;
//Loop through until move being made is valid
while(moveOK == 0)
{
printf("\n");
//Ask user for input of 1-9
printf("Please enter a place on the board to make your move, from 1 to 25: ");
//Make sure that user doesnt enter long string with number on the end that eventaully passes tests in the while loop
scanf("%d%c", &userInput, &term);
if(term != '\n')
{
move = -1;
printf("This is not a number\n");
continue;
}
//Check if input is in proper range
if(userInput < 1 || userInput > 25)
{
move = -1;
printf("Invalid Range\n");
continue;
}
//decrement move to get the array location of the playable places
userInput--;
//Check if place selected is already taken
if(board[ConvertTo49[userInput]] != EMPTY)
{
move = -1;
printf("Square not available\n");
continue;
}
//Set move ok to 1 after passing all the tests
moveOK = 1;
}
//Print move being made and return it
printf("\nHuman making Move at square: %d\n",(userInput+1));
return ConvertTo49[userInput];
}
//Run Game function
void RunGame()
{
struct node *list;
list = NULL;
//Display
printf("\n\n Noughts And Crosses Game:");
printf("\n =========================");
//game over variable
int gameOver = 0;
//Start on noughts side
int side = NOUGHTS;
//Record last move
int lastMoveMade = 0;
//Create new board
int board[49];
//Count of first move
int initialMove = 0;
//Initialise the Board
InitialiseBoard(&board[0]);
//Print the board to screen
PrintBoard(&board[0]);
//While game isn't over
while(!gameOver)
{
initialMove++;
//Human
if(side==NOUGHTS)
{
//Ask to undo move after first move played
if(initialMove > 1)
{
while(list -> prev != NULL)
list = list -> prev;
int undo;
printf("\n\nWould you like to undo your move? \nEnter 2 to undo or any other key/s to continue: ");
scanf("%d", &undo);
if( undo == 2)
{
while(list -> next != NULL)
list = list -> next;
char pceChars[] = "OX| ";
//printf(" %c", pceChars[board[ConvertTo49[index]]]);
int count = 2;
while(count != 0)
{
UndoMove(&board[0], list -> place, EMPTY);
list = list -> prev;
delete(&list, list -> next -> move);
moveCount--;
count--;
}
PrintBoard(&board[0]);
}
}
//Make new move for human
lastMoveMade = GetHumanMove(&board[0]);
MakeMove(&board[0], lastMoveMade, side);
moveCount++;
int humanMove;
//Find the position the computer is making on the 5x5 board
for(humanMove = 0; humanMove < 25; ++humanMove)
{
if(ConvertTo49[humanMove] == lastMoveMade)
{
break;
}
}
append(&list, 0, moveCount, lastMoveMade);
side = CROSSES;
}
//Computer
else
{
//Make move for computer
lastMoveMade = GetComputerMove(&board[0], side);
MakeMove(&board[0], lastMoveMade, side);
int compMove;
//Find the position the computer is making on the 5x5 board
for(compMove = 0; compMove < 25; ++compMove)
{
if(ConvertTo49[compMove] == lastMoveMade)
{
break;
}
}
printf("\nComputer making move at square: %d", compMove+1);
moveCount++;
append(&list, 1, moveCount, lastMoveMade);
side = NOUGHTS;
PrintBoard(&board[0]);
}
//If three in a row exists, game over
if(FindFourInARow(board, lastMoveMade, side ^ 1) == 4)
{
gameOver = 1;
if(side == NOUGHTS)
{
printf("\nGame Over!\n");
printf("Computer Wins! :(\n");
}
else
{
PrintBoard(&board[0]);
printf("\nGame Over!\n");
printf("Human Wins! :D\n");
}
}
//If no more moves, game is a draw
if(!HasEmpty(board))
{
PrintBoard(&board[0]);
printf("\n\nGame Over!\n");
gameOver = 1;
printf("It's a draw! :/\n");
}
}
/*
*
* Match Replay
*
*/
int answer;
printf("\n\nWould you like to replay the match? \nEnter 1 to replay or any other key/s to quit: ");
scanf("%d", &answer);
if(answer == 1)
{
InitialiseBoard(&board[0]);
while ( list != NULL )
{
MakeMove(&board[0], list -> place, list -> side);
PrintBoard(&board[0]);
char who[7];
if(list -> side == 0)
{
strcpy(who, "NOUGHTS");
//who = "NOUGHTS";
}
else
{
strcpy(who, "CROSSES");
//who = "CROSSES";
}
int moveMade;
//Find the position the computer is making on the 5x5 board
for(moveMade = 0; moveMade < 25; ++moveMade)
{
if(ConvertTo49[moveMade] == list -> place)
{
break;
}
}
printf ("\nMove:%2d Side:%8s Place: %d\n", list -> move, who, moveMade+1);
Sleep(2000);
list = list -> next ;
}
}
else
{
printf("\nGood Game! See ya!\n");
getch();
}
}
int main()
{
//Create random number
srand(time(NULL));
//Call Run Game to play
RunGame();
return 0;
}

Input that doesn't match your format doesn't get consumed by scanf. It remains in the input stream. So when you type a letter it fails to match the number you wanted %d and stays in the input stream.
scanf("%d%c", &userInput, &term);
Instead of scanf, it would be simpler to use getline to consume the entire line of input. And then parse the result with sscanf (the string-based version of the function) or another method.
char *line = NULL;
size_t len = 0;
while ((read = getline(&line, &len, stdin)) != -1) {
// Do something with line
int scanned = sscanf(line, "%d%c", &userInput);
if (scanned == EOF || scanned != 2) {
printf("Line failed to match\n");
}
}

Just read the manual page:
The format string consists of a sequence of directives which describe
how to process the sequence of input characters. If processing of a
directive fails, no further input is read, and scanf() returns. A
"failure" can be either of the following: input failure, meaning that
input characters were unavailable, or matching failure, meaning that
the input was inappropriate (see below).
You do not check the return value of scanf(). So you try to scan the same non-digit as digit all the time.

Related

Kruskal Algorithm, exited with code=code=3221225477

#define MAX_VERTICES 10000
#define MAX_EDGES 50000000
#define HEAP_EMPTY(n) (!n)
#define LINE_SIZE 100
#define HEAP_FULL(n) (n == MAX_EDGES-1)
typedef struct {
int weight;
int node1;
int node2;
} element;
element min_heap[MAX_EDGES];
int parent_array[MAX_VERTICES];
element delete_min_heap(int *n) {
/* delete element with the highest key from the heap */
int parent, child;
element item, temp;
if(HEAP_EMPTY(*n)) {
fprintf(stderr, "The heap is empty");
exit(1);
}
/* save value of the element with the largest key */
item = min_heap[1];
/* use the last element in the heap to adjust heap */
temp = min_heap[(*n)--];
parent = 1;
child = 2;
while(child <= *n) {
/* find the larger child of the current parent */
if((child < *n) && (min_heap[child].weight > min_heap[child+1].weight)) child++;
if(temp.weight <= min_heap[child].weight) break;
/* move to the next lower level */
min_heap[parent] = min_heap[child];
parent = child;
child *= 2;
}
min_heap[parent] = temp;
return item;
}
void insert_min_heap(element item, int *n) {
int i;
if(HEAP_FULL(*n)) {
fprintf(stderr, "The heap is full.\n");
exit(1);
}
i = ++(*n);
while((i != 1) && (item.weight < min_heap[i/2].weight)) {
min_heap[i] = min_heap[i/2];
i /= 2;
}
min_heap[i] = item;
}
int simpleFind(int i) {
for( ; parent_array[i] >= 0; i = parent_array[i])
;
return i;
}
void weightedUnion(int i, int j) {
int temp = parent_array[i] + parent_array[j];
if(parent_array[i] > parent_array[j]) {
parent_array[i] = j;
parent_array[j] = temp;
} else {
parent_array[j] = i;
parent_array[i] = temp;
}
}
void main(int argc, char **argv) { //argc = argument 개수 argv argument list
//if(argc != 2) {
//printf("No input file is given or Two many input files are given.\n");
//exit(0);
//}
clock_t start = clock();
FILE *fp1 = fopen("input_large.txt", "r"); //replace to argv[1]
if(fp1 == NULL) {
printf("The input file does not exist.\n");
exit(0);
}
char *command_line;
char buffer[LINE_SIZE];
int cost;
int n_connected;
start = clock();
FILE *f = fopen("hw3_result.txt", "w+");
int line_num= 0;
int num_edges;
int num_vertices;
int n_heap = 0;
while (!feof(fp1)) { //한줄 씩 입력받기
element edge;
command_line = fgets(buffer, sizeof(buffer), fp1);
if(line_num == 0) {num_vertices = atoi(command_line);}
else if(line_num == 1) {num_edges = atoi(command_line);}
else {
int vertex_from = atoi(strtok(command_line, " "));
int vertex_to = atoi(strtok(NULL, " "));
int weigth = atoi(strtok(NULL, " "));
edge.node1 = vertex_from;
edge.node2 = vertex_to;
edge.weight = weigth;
insert_min_heap(edge, &n_heap);
}
line_num++;
}
fclose(fp1);
int i = 0;
for(i = 0; i< num_vertices; i++) { parent_array[i]=-1;}
element edge = delete_min_heap(&n_heap);
int j = 0;
cost = 0;
n_connected =0;
while((n_heap >= 0) && (n_connected != num_vertices)) {
int node1 = edge.node1;
int node2 = edge.node2;
if(j == 0) {
weightedUnion(node1, node2);
cost += edge.weight;
//printf("%d %d %d\n",node1, node2, edge.weight);
n_connected += 2;
j++;
}
else if ( simpleFind(node1) != simpleFind(node2)) {
weightedUnion(node1, node2);
cost += edge.weight;
//printf("%d %d %d\n",node1, node2, edge.weight);
n_connected++;
}
edge = delete_min_heap(&n_heap);
printf("%d %d\n", n_connected, n_heap);
}
printf("END\n");
printf("COST%d\n", cost);
printf("num vertices %d connected %d\n", num_vertices, n_connected);
if(n_connected < num_vertices) printf("DISCONNECTED\n");
if(n_connected == num_vertices) printf("CONNECTED\n");
fclose(f);
clock_t end = clock();
double time_spent = (double)(end - start) / CLOCKS_PER_SEC;
printf("output written to hw3_result.txt\n");
printf("running time :%lf\n", time_spent);
}
I tried to implement Kruskal's Algorithm, but I faced some problems. The format of the input file is like this.
7
9
0 1 28
0 5 10
1 2 16
1 6 14
2 3 12 //source vertex destination vertex weight
3 4 22
3 6 18
4 5 25
4 6 24
The first line is the number of vertices and the second is number of edges. There is no problem when running small input file, but when the input file is very large, the program is exited with code=3221225477.
This code is to find where the code is exited
while((n_heap >= 0) && (n_connected != num_vertices)) {
int node1 = edge.node1;
int node2 = edge.node2;
if(j == 0) {
weightedUnion(node1, node2);
cost += edge.weight;
//printf("%d %d %d\n",node1, node2, edge.weight);
n_connected += 2;
j++;
}
else if ( simpleFind(node1) != simpleFind(node2)) {
weightedUnion(node1, node2);
cost += edge.weight;
//printf("%d %d %d\n",node1, node2, edge.weight);
n_connected++;
}
edge = delete_min_heap(&n_heap);
**printf("%d %d\n", n_connected, n_heap);** //here
}
The result is like this.
...
1657 4998343 //num of connected vertices num of heap's remaining element
1658 4998342
1659 4998341
1660 4998340
1661 4998339
1662
After deleting 1661 element in heap, for some reasons, program doesn't work any more.

(C) Write doubles outside the stack

I am trying to write numbers from type double outside of the stack but I can't quite work it out how to do it. I have tried doing it with while loop and if statements, sometimes I get only zeros but most of the time I get nothing displayed. Thanks for helping in advance.
#include <stdio.h>
struct element
{
double data;
element * next;
};
element *top = NULL;
void Get(double &x)
{
element *p;
if(top == NULL)
{
printf("\nThe stack is empty!");
return;
}
x = top -> data;
p = top;
top = top -> next;
delete(p);
}
void Put(double x)
{
element *p;
p = new(element);
if(p == NULL)
{
printf("\nNOT enough memory!");
return;
}
p -> data = x;
p -> next = top;
top = p;
}
int main()
{
printf("Enter integers in stack. Enter 0 to end!\n");
double val;
double m;
do
{
printf("Enter number: ");
scanf("%lf", &val);
if(val >= 3697 && val <= 3698)
{
Put(val);
}
}
while(val != 0);
printf("\nStack contains: ");
while(top != NULL)
{
Get(val);
printf("%lf ", val);
}
return 0;
}

Present Matrix in tabular form C Programming

Currently, I am trying to use the linked node to represent the matrix. My codes are working fine, while I not sure it is possible to represent my matrix in tabular form instead of (x,y) = value I want to represent it like(consists of zero element and non-zero elements.)
1 2 3
0 5 0
7 8 9
Below is my codes with the linked node in the matrix, my program will read the row,column and value from user and print it out.
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int column;
int value;
int row;
struct node *next;
} element;
void Init(element *x[])
{
int i;
for (i = 0; i < 3; i++) x[i] = NULL;
}
void Insert(element *x[], int row, int column, int value)
{
int r = row;
element *p;
element *new = malloc(sizeof(element));
new->row = row;
new->column = column;
new->value = value;
if (x[r] == NULL)
{
x[r] = new;
new->next = NULL;
}
else
{
p = x[r];
if (new->column < p->column)
{
new->next = p;
x[r] = new;
}
else if (new->column > p->column)
{
while (p->next != NULL && p->next->column < new->column)
{
p = p->next;
}
new->next = p->next;
p->next = new;
}
else printf("An element already exists there!!\n");
}
}
void Printout(element *x[])
{
int i, test = 0;
element *temp;
for (i = 0; i < 3; i++)
{
temp = x[i];
while (temp != NULL)
{
printf("Element position (%d,%d) = %d\n", i, temp->column, temp->value);
test = 1;
temp = temp->next;
}
}
if (test == 0) printf("This matrix is empty!!\n");
}
int main(int argc, const char * argv[])
{
int choice, column, row, value, number;
element *a[3], *b[3], *sum[3];
Init(a); Init(b); Init(sum);
do
{
printf("\n***\tADDING SPARSE MATRICES\t***\n");
printf("\n 1.) Insert in A");
printf("\n 2.) Insert in B");
printf("\n 3.) Printout both");
printf("\n 0.) EXIT");
printf("\nChoose ---------> ");
scanf("%d", &choice);
switch (choice)
{
case 1: /*Insert in A */
do
{
printf("Enter row -> ");
scanf("%d", &row);
} while (row < 0 || row > 3);
do
{
printf("Enter column -> ");
scanf("%d", &column);
} while (column < 0);
printf("Enter value -> ");
scanf("%d", &value);
Insert(a, row, column, value);
break;
case 2: /*Insert in B */
do
{
printf("Enter row -> ");
scanf("%d", &row);
} while (row < 0 || row > 2);
do
{
printf("Enter column -> ");
scanf("%d", &column);
} while (column < 0);
printf("Enter value -> ");
scanf("%d", &value);
Insert(b, row, column, value);
break;
case 3: /* Printout A & B */
printf("\n::::::: MATRIX A :> \n\n");
Printout(a);
printf("\n::::::: MATRIX B :> \n\n");
Printout(b);
break;
default:
printf("\nWRONG CHOICE");
}
} while (choice != 0);
return 0;
}
I need someone to enlighten me.
First, the code needs to figure out the width of the matrix. This can be done by scanning all of the elements to find the element with the largest column. The matrix width is the largest column plus one.
Then, to print each row in the matrix, print zeros until the correct column is reached. Then print the value in the element, and move to the next element. When all of the elements have been printed, print additional zeros until the width is reached.
void Printout(element *x[])
{
// find the width of the matrix
int width = -1;
for (int row = 0; row < 3; row++)
{
for (element *node = x[row]; node != NULL; node = node->next)
if (node->column > width)
width = node->column;
}
width++; // width is max column plus one
// print each row of the matrix
for (int row = 0; row < 3; row++)
{
int col = 0;
for (element *node = x[row]; node != NULL; node = node->next)
{
for (; col < node->column; col++) // print zeros until the column is reached
printf("0 ");
printf("%d ", node->value); // print the value for the current element
col = node->column + 1;
}
for (; col < width; col++) // print zeros until the width is reached
printf("0 ");
printf("\n");
}
}

How do I fix a Segmentation Fault error in my C code

I am working on writing a code for the game, Mancala, and testing along the way. So far, I am getting an error that says:
Segmentation Fault (core dumped)
I'm not sure how to fix it and keep it running.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void move_clockwise(int board[], int pos, int player_1);
void move_count_clock(int board[], int pos, int player_1);
void mancala_board(int board[]);
int *current1;
int *current2;
int board[30], player_1, sum, position, direction, i, n, play, initPos, curPos, pos;
//======================================================================
int main(void)
{
int board[30];
board[0] = 4;
board[1] = 4;
board[2] = 4;
board[3] = 4;
board[4] = 4;
board[5] = 4;
board[6] = 0;
board[7] = 4;
board[8] = 4;
board[9] = 4;
board[10] = 4;
board[11] = 4;
board[12] = 4;
board[13] = 0;
printf("Welcome to Mancala\n");
printf("\n\n 5 4 3 2 1 0 \n");
printf("BLUE\n");
printf("=====[%d] [%d] [%d] [%d] [%d] [%d]-----\n", board[5], board[4], board[3], board[2], board[1], board[0]);
printf("|%d| |%d|\n", board[6], board[13]);
printf("-----[%d] [%d] [%d] [%d] [%d] [%d]=====\n", board[7], board[8], board[9], board[10], board[11], board[12]);
printf(" RED\n");
printf(" 6 7 8 9 10 11 \n\n");
sum=board[6]+board[13];
player_1=first_player();
while(sum!=48)
{
while (player_1 == 1)
{
printf("Player RED\n");
printf("Pick a position corresponding to the integer: ");
scanf("%d", position);
while (position!=6 || position!=7 || position!=8 || position!=9 || position!=10 || position!=11)
{
printf("\nInvalid input, you have to select a bowl from your side.\nPlease select another position");
scanf("%d",&position);
}
printf("Would you like to move clockwise or counter-clockwise?");
printf("\n1. Clockwise \n2. Counter-Clockwise");
scanf("%d",&direction);
while(direction!=1 && direction!=2)
{
printf("\nInvalid input, you have to select an integer corresponding to the given options.\n");
printf("\n1. Clockwise \n2. Counter-Clockwise");
scanf("%d",&direction);
}
if (direction==1)
{
position+=1;
move_clockwise(board, position, player_1);
}
if(direction==2)
{
position=+1;
move_count_clock(board, position, player_1);
}
player_1-=1;
mancala_board(board);
}
if (player_1 == 0)
{
printf("Player BLUE\n");
printf("Pick a position corresponding to the integer: ");
scanf("%d", position);
while (position!=0 || position!=1 || position!=2 || position!=3 || position!=4 || position!=5)
{
printf("\nInvalid input, you have to select a bowl from your side.\nPlease select another position");
scanf("%d",&position);
}
printf("Would you like to move clockwise or counter-clockwise?");
printf("\n1. Clockwise \n2. Counter-Clockwise");
scanf("%d",&direction);
while(direction!=1 && direction!=2)
{
printf("\nInvalid input, you have to select an integer corresponding to the given options.\n");
printf("\n1. Clockwise \n2. Counter-Clockwise");
scanf("%d",&direction);
}
if (direction==1)
{
position+=1;
move_clockwise(board, position, player_1);
}
if(direction==2)
{
position=+1;
move_count_clock(board, position, player_1);
}
player_1+=1;
mancala_board(board);
}
sum=board[6]+board[13];
}
}
//======================================================================
int first_player(void)
{
//to determine who will be player 1
play=rand()%2;
return (play);
}
//======================================================================
//Display current board
void mancala_board(int board[])
{
printf("\n\n 5 4 3 2 1 0 \n");
printf("BLUE\n");
printf("=====[%d] [%d] [%d] [%d] [%d] [%d]-----\n", board[5], board[4], board[3], board[2], board[1], board[0]);
printf("|%d| |%d|\n", board[6], board[13]);
printf("-----[%d] [%d] [%d] [%d] [%d] [%d]=====\n", board[7], board[8], board[9], board[10], board[11], board[12]);
printf(" RED\n");
printf(" 6 7 8 9 10 11 \n\n");
}
//======================================================================
//allow player to move again if late marble lands in mancala
//void move_again(int board[], int pos, int player_1)
//{
//}
//======================================================================
//captures the marbles across the current position if player's
//last marble lands on their own bowl with no marbles in
//void capture()
//{
//}
//======================================================================
void move_clockwise(int board[], int pos, int player_1)
{
initPos = pos;
n=board[pos];
pos+=1;
for (i = 0; i < n ; i++)
{
curPos +=1;
board[curPos]+=1;
if (curPos == 14)
curPos -=14;
else if (curPos >= 28)
curPos -= 28;
if (player_1 == 0)
{
current1 = &(board[curPos]);
if (current1 == &(board[6]))
{
current1 = &(board[7]);
current1 += 1;
}
}
if (player_1 == 1)
{
current2 = &(board[curPos]);
if (current2 == &(board[13]))
{
current2 = &(board[0]);
current2 += 1;
}
}
}
board[initPos] = 0;
}
//======================================================================
void move_count_clock(int board[], int pos, int player_1)
{
initPos = pos;
n=board[pos];
pos+=1;
for (i = 0; i < n ; i++)
{
curPos +=1;
board[curPos]+=1;
if (curPos == 14)
curPos -=14;
else if (curPos >= 28)
curPos -= 28;
if (player_1 == 0)
{
current1 = &(board[curPos]);
if (current1 == &(board[6]))
{
current1 = &(board[7]);
current1 += 1;
}
}
if (player_1 == 1)
{
current2 = &(board[curPos]);
if (current2 == &(board[13]))
{
current2 = &(board[0]);
current2 += 1;
}
}
}
board[initPos] = 0;
}
Maybe you want to separate the code in smaller pieces and test each piece. Or maybe this can help you: http://ericlippert.com/2014/03/05/how-to-debug-small-programs/
To put & inside scanf is correct suggestion, I think that was meant in the comment.
Anyway, this is also weird:
while (position!=6 || position!=7 || position!=8 || position!=9 || position!=10 || position!=11)
{
scanf("%d",&position);
}
what do you expect above? It will always enter that loop, and never come out, since
if position is 6 it can't be 7 hence due to OR the statement will be true.

junk output in the array of structs

This is my project in the sortstudents() function I try to read from file the data is on one row or one line contentiously when I try to print the array I got junk data
this is example about how data look like in the file (2 records):
1 mohamed talaat €#A
2 ahmed mohamed #A
#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <stdlib.h>
#include <windows.h>
///////////////////////////////////////////////////////////////////////////
struct student
{
char id[5];
char name[30];
int term;
float gpa;
char grade;
};
struct student stu;
typedef struct student stud;
//////////////////////////////////////////////////////////////////////////
//set the cordinate to 0, 0 (top-left corner of window)
//<windows.h> is needed
COORD coord = {0,0};
//////////////////////////////////////////////////////////////////////////
//need cordinate struct to use it
//gotoxy to set coordinate x,y
void gotoxy(int x, int y)
{
//X and Y coordinates
coord.X = x; coord.Y = y;
// ew3a tensa Microsoft
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
//////////////////////////////////////////////////////////////////////////
//print regtangle shape Ascii table www.asciitable.com
// window width = 80 character window hight = 25 character
void drawRectangle()
{
int i, j;
//print the corner rear top left
gotoxy(0,0);
printf("%c",201);
// print 78 line shape = starts from rear top left ended at the top rear right
for(i = 1; i < 78; i++)
{
gotoxy(i, 0);
printf("%c",205);
}
//print the corner rear top right
gotoxy(78,0);
printf("%c",187);
//print the corner rear right side with width = 25
for(i = 1; i < 25; i++)
{
gotoxy(78, i);
//print T-shape at width 6 and after 6 proceed until 25 printing right side
if(i == 6)
{
printf("%c",185);
}
else
{
printf("%c",186);
}
}
//print the corner rear bottom right
gotoxy(78, 25);
printf("%c",188);
// -i- already = 78
// print bottom side pf the regtangle
for(i = 77; i > 0; i--)
{
gotoxy(i,25);
// print T-shape at width 35 and after that proceed until 78 printing rgt base side
if(i == 35)
{
printf("%c",202);
}
else
{
printf("%c",205);
}
}
//print the corner rear bottom left
gotoxy(0,25);
printf("%c",200);
// print T-shape at width 6 and after 6 proceed until 25 printing left side
for(i = 24; i > 0; i--)
{
gotoxy(0,i);
if(i == 6)
{
printf("%c",204);
}
else
{
printf("%c",186);
}
}
// print T-shape at width 36 and connect left side to right side
for(i = 1; i < 78; i++)
{
gotoxy(i,6);
if(i == 35)
{
printf("%c",203);
}
else
{
printf("%c",205);
}
}
// connect middle T-shape at the middle of the regtangle to the base
for(i = 7; i < 25; i++)
{
gotoxy(35,i);
printf("%c",186);
}
}
//////////////////////////////////////////////////////////////////////////
// Build Program window interface using functions --drawRectangle
// with color 1 = Blue & Font color 7 = White
void swindow()
{
int i;
drawRectangle();
gotoxy(28,1);
system("color 17");
printf("STUDENT GRADE SYSTEM");
gotoxy(28,2);
for(i=1;i<21;i++)
{
printf("%c",205);
}
gotoxy(15,3);
printf("College of Computing and Information Technology");
gotoxy(10,4);
printf(" ");
gotoxy(10,5);
printf("Arab Academy for Science, Technology & Maritime Transport");
gotoxy(25,24);
}
//////////////////////////////////////////////////////////////////////////
void print_heading(const char st[])
{
gotoxy(50,8);
printf("%s",st);
}
//////////////////////////////////////////////////////////////////////////
void clearWindow()
{
int i,j;
for(i = 37; i < 78; i++)
{
for(j = 7; j < 25; j++)
{
gotoxy(i,j);
printf(" ");
}
}
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
void add()
{
clearWindow();
print_heading("Add Record");
int print = 37;
char ans;
int i;
FILE *fp;
fp = fopen("record.txt","ab+");
if(fp == NULL)
{
MessageBox(0,"Error in Opening file\nMake sure your file is not write protected","Warning",0);
}
else
{
fflush(stdin);
//here i can Add Records ...
////////////////////////////////////////////////////////////////////////////////
gotoxy(print,10);printf("ID: ");gets(stu.id);
gotoxy(print,12);printf("Name: ");gets(stu.name);
gotoxy(print,14);printf("Term: ");scanf("%d",&stu.term);
gotoxy(print,16);printf("Score % : ");scanf("%f",&stu.gpa);
if (stu.gpa>=3.40)
{
stu.grade='A';
}
else {
if (stu.gpa>=2.80)
{stu.grade='B';}
else
{
if (stu.gpa>=2.20)
{stu.grade='C';}
else
{
if (stu.gpa>=2.00)
{stu.grade='D';}
else
{stu.grade='F';}
}
}
}
gotoxy(print,18);printf("GPA: %c",stu.grade);printf("\n");
gotoxy(print,20);printf("Press(Y) to Save (N) for Cancel... ");//scanf("%c",&ans);
ans = getche();
if (ans=='y' || ans=='Y')
{
fwrite(&stu, sizeof(stu), 1, fp);
gotoxy(40,22); printf("The record is sucessfully added");
}
else
{
gotoxy(40,22); printf("Entry process cancelled");
}
}
fclose(fp);
}
//////////////////////////////////////////////////////////////////////////
void search(){
clearWindow();
print_heading("Search Record");
char s_id[5];
int isFound = 0;
gotoxy(37,10);
printf("Enter ID to Search: ");
fflush(stdin);
gets(s_id);
//Read the record file from File
FILE *fp;
fp = fopen("record.txt","ab+");
while(fread(&stu,sizeof(stu),1,fp) == 1)
{
if(strcmp(s_id,stu.id) == 0)
{
isFound = 1;
break;
}
}
if(isFound == 1){
gotoxy(37,12);printf("The record is Found");
gotoxy(37,13);printf("--------------------");
gotoxy(37,14);printf("ID: %s",stu.id);
gotoxy(37,16);printf("Name: %s",stu.name);
gotoxy(37,18);printf("Term: %d",stu.term);
gotoxy(37,20);printf("Score %: %0.1f",stu.gpa);
gotoxy(37,22);printf("GPA: %c",stu.grade);
}else
{
gotoxy(37,12);printf("Sory, No record found in the database");
}
fclose(fp);
}
//////////////////////////////////////////////////////////////////////////
void sortstudents()
{
clearWindow();
FILE *fp;
fp = fopen("record.txt","r");
//////// detect number of characters ////////
char nextChar = getc(fp);
int numCharacters = 0;
while (nextChar != EOF)
{
//Do something else, like collect statistics
numCharacters++;
nextChar = getc(fp);
}
//////// detect number of characters ////////
int chunck = numCharacters/sizeof(stu);
//stud *arr = (stud *)malloc(chunck);
stud starray[25];
int d;
int numStudents = 0;
while( fscanf(fp,"%s%s%d%f%c",stu.id,stu.name,&stu.term,&stu.gpa,&stu.grade) > 0)
{
starray[numStudents++] = stu;
}
gotoxy(37,12);printf("The record is Found");
gotoxy(37,13);printf("--------------------");
gotoxy(37,14);printf("ID: %s",starray[0].id);
gotoxy(37,16);printf("Name: %s",starray[0].name);
gotoxy(37,18);printf("Term: %d",starray[0].term);
gotoxy(37,20);printf("Score %: %0.1f",starray[0].gpa);
gotoxy(37,22);printf("GPA: %c",starray[0].grade);
/*"ID: %s",stu.id);
"Name: %s",stu.name);
"Term: %d",stu.term);
Score %: %0.1f",stu.gpa);
"GPA: %c",stu.grade);*/
fclose(fp);
}
//////////////////////////////////////////////////////////////////////////
void menu(){
int choice;
int x = 2;
while(1)
{
gotoxy(x,10);
printf("1. Add Student");
gotoxy(x,12);
printf("2. Search Student");
gotoxy(x,14);
printf("3. Statistics");
gotoxy(x,16);
printf("4. Close");
gotoxy(x,20);
printf("Please enter your choice :");
scanf("%d",&choice);
switch(choice)
{
case 1:
add();
break;
case 2:
search();
break;
case 3:
sortstudents();
break;
case 4:
exit(0);
break;
default:
break;
}
}
}
//////////////////////////////////////////////////////////////////////////
int main()
{
// draw entry window
//drawRectangle();
swindow();
menu();
//clearWindow();
system("PAUSE");
return 0;
}
In the sortStudents you have a loop in the beginning that will read all characters in the file. Then you attempt to read the files as a kind of records. This usage of fscanf will return EOF as you are attempting to read beyond the end of the file.
And even when you don't read any records into your starray array, you still print values from starray[0] which will be all uninitialized (and therefore contain indeterminate (e.g. seemingly random) values).

Resources