How to undo a stack when the struct contains a char ** variable? - c

This code below is something like a candy crush game, where you pop similar letters in a cluster, then they'll disappear and you score. On main, I tried to play it one step ahead and then undo it, and it works since the score managed to undo (from 0 to some score then back to 0 again). However, I just can't figure out why the game board isn't updated?
typedef struct {
int rs;
int cs;
char **board;
int score;
} Instance;
with random letters (a, b ,c or d)
extern Game *create(int nrows, int ncols) {
if (nrows > MAX_ROWS || ncols > MAX_COLS) {
return NULL;
}
Game *b;
b->top = 0;
b->stack[b->top].rs = nrows;
b->stack[b->top].cs = ncols;
b->stack[b->top].board = malloc(sizeof(char *) * nrows);
for (int row = 0; row < nrows; row++) {
b->stack[b->top].board[row] = malloc(sizeof(char) * ncols);
}
srand(time(0));
for (int row = 0; row < nrows; row++) {
for (int column = 0; column < ncols; column++) {
int random = rand() % 4;
if (random == 0) {
b->stack[b->top].board[row][column] = A;
} else if (random == 1) {
b->stack[b->top].board[row][column] = B;
} else if (random == 2) {
b->stack[b->top].board[row][column] = C;
} else {
b->stack[b->top].board[row][column] = D;
}
}
}
return b;
}
// Display the current matrix
extern void display(Game *b) {
/** Prints top border **/
printf(" +-");
for (int top = 0; top < b->stack[b->top].cs; top++) {
printf("--");
}
printf("+\n");
/** Prints the board **/
for (int row = 0; row < b->stack[b->top].rs; row++) {
if (row < 10) {
printf("0%d | ", row);
} else {
printf("%d | ", row);
}
for (int column = 0; column < b->stack[b->top].cs; column++) {
printf("%c ", b->stack[b->top].board[row][column]);
}
printf("|\n");
}
/** Prints bottom border **/
printf(" +-");
for (int bot = 0; bot < b->stack[b->top].cs; bot++) {
printf("--");
}
printf("+\n");
/** Prints vertical column indices **/
printf(" ");
for (int tens = 0; tens < b->stack[b->top].cs; tens++) {
printf("%d ", tens/10);
}
printf("\n");
printf(" ");
int count = 0;
for (int ones = 0; ones < b->stack[b->top].cs; ones++) {
if (count > 9) {
count = 0;
}
printf("%d ", count);
count++;
}
}
extern int select(Game *b, int r, int c) {
char colour = b->stack[b->top].board[r][c];
int n = recursive_helper(b, r, c);
if (n == 1) {
b->stack[b->top].board[r][c] = colour;
return 0;
}
b->stack[b->top].score += n*(n-1);
return n;
}
int main() {
Game *b = create(5, 10);
display(b);
printf("\n");
printf("%d", bp_score(b));
printf("\n");
select(b, 2, 2);
display(b);
printf("\n");
printf("%d", bp_score(b));
printf("\n");
b->top--;
display(b);
printf("\n");
printf("%d", bp_score(b));
printf("\n");
}

As pointed in the comments, your create function doesn't instantiate a Game struct, you need b = malloc(sizeof(Game));
Another error is that your mallocs use sizeof(int*) and sizeof(int) instead of sizeof(char*) and sizeof(char).
Other than that, your problem comes from the fact that b->stack[b->top+1] = b->stack[b->top]; copies a structure, but the board is a pointer and points to the same object! You only have one char** pointer and a single board in memory.
Thus, when you do b->top-- while you do access another struct, it still points to the same fully updated board.
You need to create a function Instance CopyInstance(Instance src) that creates a new board in the new struct and then copies each cell from the source board in the new one. That way each Instance will point to a different board!

Related

Count number of elements in array after placing them in ascending order

I'm creating a program that reads input from an array and orders it in an ascending order. However, I also wanted to count the number of times each element appears in the array, but I'm struggling to to this. This is the code I have so far:
#include <stdlib.h>
#include <locale.h>
typedef enum _ordem {
Crescente=1
} ordem;
void troca(int *x, int *y){
int wk;
wk=*x;*x=*y;*y=wk;
}
int trocar(int x, int y, ordem dir){
if(dir == Crescente)
return x > y;
return 0;
}
void bubbleSort(int *array, int top, int fim, ordem dir){
int i, j, trocado;
for(i = top; i < fim; ++i){
trocado = 0;
for(j = top + 1; j <= fim - i; ++j)
if(trocar(array[j-1], array[j], dir)){
troca(&array[j-1], &array[j]);
trocado = 1;
}
if(trocado == 0)break;
}
}
int main(){
int vetor[100], index, ordem=1;
index=0;
setlocale(LC_ALL,"Portuguese");
printf("Introduza os nĂºmeros. Escreva -00 para parar. \n");
do{
scanf("%d", &vetor[index++]);
}while(vetor[index-1] != -00 && index < 100);
--index;
bubbleSort(vetor, 0, index-1, ordem);
{
int i;
for(i=0;i<index;++i)
printf("%d ", vetor[i]);
printf("\n");
}
return 0;
}
After the numbers have been sorted, equal numbers will be next to each other in the array. This makes it easy to count the number of times each number occurs using a single loop that iterates through the sorted array, with an extra variable that is incremented when the next element has the same number as the current element, or is reset when the next element has a different number.
The following block of code will do that:
{
int i, c;
c = 1;
for (i = 0; i < index; ++i) {
if (i < index - 1 && vetor[i] == vetor[i + 1]) {
c++;
} else {
printf("%d(x%d) ", vetor[i], c);
c = 1;
}
}
printf("\n");
}
You could create another array to store a table of the unique values with their frequency of occurrance:
struct freq {
int val;
int freq;
};
struct freq freq[100];
int nfreq = 0;
Fill the table using a loop similar to the earlier code:
{
int i, c;
c = 1;
for (i = 0; i < index; ++i) {
if (i < index - 1 && vetor[i] == vetor[i + 1]) {
c++;
} else {
freq[nfreq].val = vetor[i];
freq[nfreq].freq = c;
nfreq++;
c = 1;
}
}
}
Print the out the table with another simple loop:
{
int i;
for (i = 0; i < nfreq; i++) {
printf("%d(x%d) ", freq[i].val, freq[i].freq);
}
printf("\n");
}

Check diagonally winner in Connect N using C

I'm doing the game Connect N using C and I'm having a hard time trying to code an algorithm to check if there is a winner diagonally.
char **BASE;
int piecesToWin, ROWS, COLS;
printf("Enter how many connected pieces to win?: ");
scanf("%d", &piecesToWin);
ROWS = 2 + piecesToWin;
COLS = 3 + piecesToWin;
BASE = (char **) malloc(ROWS * sizeof(char *)); // Allocate the row pointers
for (int i = 0; i < ROWS; i++) // Allocate each row separately
BASE[i] = (char *) malloc(COLS * sizeof(char));
// Fill all with space to start
for (int i = 0; i < ROWS; i++)
for (int j = 0; j < COLS; j++)
BASE[i][j] = ' ';
After this, I insert a piece to the board and then, I check if there is a winner diagonally.
if (diagAscWin(ROWS, COLS, BASE, piecesToWin, 'X')) {
printf("X has won!.");
}
if (diagDescWin(ROWS, COLS, BASE, piecesToWin, 'X')) {
printf("X has won!.");
}
What I have tried to check diagonally:
bool diagAscWin(int ROWS, int COLS, char **BASE, int numToWin, char letter) {
bool isWinner = false;
for (int i=3; i<ROWS; i++){
for (int j=0; j<COLS-3; j++){
if (BASE[i][j] == letter && BASE[i-1][j+1] == letter && BASE[i-2][j+2] == letter && BASE[i-3][j+3] == letter)
isWinner = true;
}
}
return isWinner;
}
bool diagDescWin(int ROWS, int COLS, char **BASE, int numToWin, char letter) {
bool isWinner = false;
for (int i=3; i<ROWS; i++){
for (int j=3; j<COLS; j++){
if (BASE[i][j] == letter && BASE[i-1][j-1] == letter && BASE[i-2][j-2] == letter && BASE[i-3][j-3] == letter)
isWinner = true;
}
}
return isWinner;
}
These functions are not working. When I have N pieces diagonally, diagAscWin and diagDescWin don't see them and always return false. Also, I'm not sure if I need to initialize i or j with 3 or j<COLS-3. I was trying to replicate a solution from another thread.
Also, I have tried this:
bool diagRightWin(int ROWS, int COLS, char **BASE, int numToWin, char letter) {
bool isWinner = false;
int count;
for (int rowStart = 0; rowStart < ROWS - 4; rowStart++) {
count = 0;
int row, col;
for (row = rowStart, col = 0; row < ROWS && col < COLS; row++, col++) {
if (BASE[row][col] == letter) {
count++;
if (count >= numToWin) isWinner = true;
} else {
count = 0;
}
}
}
return isWinner;
}
bool diagLeftWin(int ROWS, int COLS, char **BASE, int numToWin, char letter) {
bool isWinner = false;
int count;
for (int rowStart = 0; rowStart < ROWS - 4; rowStart++) {
count = 0;
int row, col;
for (row = rowStart, col = 0; row < ROWS && col < COLS; row++, col++) {
if (BASE[row][col] == letter) {
count++;
if (count >= numToWin) isWinner = true;
} else {
count = 0;
}
}
}
return isWinner;
}
These two functions also always return false.
I have tried different logics with no luck. The correct thing is to check how many numToWin pieces are diagonally to say if there is a winner.
I have tried to replicate:
Connect 4 check for a win algorithm
Java: How to check diagonal Connect Four win in 2D array
Javascript - Connect Four game validation
Checking for a line of four (Connect Four in Java)
My goal is to check if there is a winner diagonally (on any direction), having in mind that the board can be big or small, we don't know the size. What we know for sure is the piecesToWin which is the number of pieces that needs to be together to say there is a winner.
The main problem is that you are not exiting the function when you find a match of 4 elements. Also the function looping needs to be modified as shown.
You need two functions to check left diagonal and right diagonal
/ <-- left diagonal right diagonal --> \
/ \
/ \
/ \
I have modified the check functions and also added the functionality to check for variable number of elements in a diagonal.
// this function checks diagnonal sloping left "/"
//
bool diagLeftWin(int ROWS, int COLS, char **BASE, int numToWin, char letter) {
for (int i=0; i<ROWS-numToWin; i++){
for (int j=0; j<COLS-numToWin; j++){
char curr = BASE[i][j];
if (curr == letter) {
int k;
for (k=1; k<numToWin; k++) {
if (curr != BASE[i+k][j+k]) {
break;
}
}
if (k == numToWin) {
// match found
return true;
}
}
}
}
return false;
}
// this function checks diagnonal sloping right "\"
//
bool diagLeftWin(int ROWS, int COLS, char **BASE, int numToWin, char letter) {
for (int i=ROWS-numToWin; i>=0; i--){
for (int j=0; j<COLS-numToWin; j++){
char curr = BASE[i][j];
if (curr == letter) {
int k;
for (k=1; k<numToWin; k++) {
if (curr != BASE[i-k][j+k]) {
break;
}
}
if (k == numToWin) {
// match found
return true;
}
}
}
}
return false;
}
These functions check the entire board every time. You can optimise it to only check around newly added pieces to the board.

sort function won't print sorted array?

My sort function won't print the sorted array?
I'm trying to write a program that gathers array elements, sorts the array, then prints the factorial of each element. I don't want to get ahead of myself and write the recursive function if the array isn't being sorted correctly. The sort seems fine to me; people have criticized me using while loop but I don't know another way yet. Any input is appreciated.
#include <stdio.h>
int sorter(int numbList[]);
int getData(int numList[]);
//int recursive(int numList[]);
int main(void) {
int x;
int numberList[x];
getData(&numberList[x]);
sorter(&numberList[x]);
//recursive(&numberList[x]);
return 0;
}
//gets user input-data
int getData(int numbList[]) {
int i;
int x;
printf("Enter number of Elements:\n");
scanf("%d", &x);
printf("Enter the values for each element starting from first
element:\n");
for (i = 0; i < x; i++) {
scanf("%d", &numbList[i]);
}
printf("\nYou have filled the array list with\n");
for (i = 0; i < x; i++) {
printf("%d\n", numbList[i]);
}
return numbList[x];
}
//sorter function
int sorter(int numbList[]) {
int x;
int temp;
int swapped;
while (1) {
swapped = 0;
for (int i = 0; i < x; i++) {
if (i > numbList[i + 1]) {
temp = numbList[x];
numbList[x] = numbList[x + 1];
numbList[x + 1] = numbList[x];
swapped = 1;
}
if (swapped == 0) {
break;
}
}
printf("Array as sorted:\n");
for (int i = 0; i < x; i++) {
printf("%d\t", numbList[x]);
}
return(numbList[x]);
}
}
//recursive factorial function
/* int recursive(int numbList[]) {
int b = 0;
numbList[b] *= numbList[b - 1];
return 0;
} */
Some hints as comments in your code:
It still won't do the job, but get you in better shape...
int main(void)
{
//uninitialized x!
int x;
//Even if you get a value for x, VLAs are depreciated
int numberList[x];
//Both calls get the adress of last value + 1 in numberList.
//So you a) go out of the array bounds, and b) why would you want
//the last element's address??
//Just use it like getData(numberList);
getData(&numberList[x]);
sorter(&numberList[x]);
return 0;
}
//gets user input-data
//What is the return value for?
int getData(int numbList[])
{
int i;
int x;
printf("Enter number of Elements:\n");
scanf("%d",&x);
printf("Enter the values for each element starting from first element:\n");
for(i=0;i<x;i++){
scanf("%d",&numbList[i]);
}
printf("\nYou have filled the array list with\n");
for(i=0;i<x;i++){
printf("%d\n",numbList[i]);
}
//see above
return numbList[x];
}
//sorter function
//Again, what and why return?
int sorter(int numbList[])
{
//uninitialized x!
int x;
int temp;
int swapped;
while(1)
{
swapped=0;
for(int i=0;i<x;i++)
{
//What do you compare here? Think.
if(i>numbList[i+1])
{
temp=numbList[x];
numbList[x]=numbList[x+1];
//What do you have temp for??
numbList[x+1]=numbList[x];
swapped=1;
}
//Pretty sure you want an else clause here
if(swapped==0)
{
break;
}
}
printf("Array as sorted:\n");
for(int i=0;i<x;i++)
{
printf("%d\t",numbList[x]);
}
return(numbList[x]);
}
}
There are multiple problems in your code:
the number of elements x is uninitialized when you define the array numbList[x]. This has undefined behavior. You should pass a pointer to the count to getData and this function should update this value, allocate the array, read the values and return a pointer to the array.
You should not break strings on multiple lines without a \
The swap code is broken: the test if (i > numbList[i + 1]) is incorrect, it should be
if (numbList[i] > numbList[i + 1])
the swap code should use i instead of x as an index and the last assignment in the swap code should store temp into numbList[i + 1].
the inner loop should stop at x - 1 to avoid reading past the end of the array.
you should let the inner loop run to the end and break from the outer loop if swapped == 0.
Here is a corrected version:
#include <stdio.h>
#include <stdlib.h>
int *getData(int *count);
void sorter(int numList[], int count);
int main(void) {
int x;
int *numberList;
numberList = getData(&x);
if (numberList != NULL) {
printf("Elements entered:");
for (int i = 0; i < x; i++) {
printf(" %d", numberList[i]);
}
printf("\n");
sorter(numberList, x);
printf("Sorted array:");
for (int i = 0; i < x; i++) {
printf(" %d", numberList[i]);
}
printf("\n");
free(numberList);
}
return 0;
}
//gets user input-data
int *getData(int *countp) {
int i, x;
int *numbList;
printf("Enter the number of elements: ");
if (scanf("%d", &x) != 1 || x <= 0) {
printf("Invalid size:");
return NULL;
}
numbList = calloc(sizeof *numbList, x);
if (numbList == NULL) {
printf("Memory allocation error:");
return NULL;
}
printf("Enter the element values: ");
for (i = 0; i < x; i++) {
if (scanf("%d", &numbList[i]) != 1) {
free(numbList);
return NULL;
}
}
*countp = x;
return numbList;
}
//sorter function
void sorter(int numbList[], int x) {
for (;;) {
int swapped = 0;
for (int i = 0; i < x - 1; i++) {
if (numbList[i] > numbList[i + 1]) {
int temp = numbList[i];
numbList[i] = numbList[i + 1];
numbList[i + 1] = temp;
swapped = 1;
}
}
if (swapped == 0) {
break;
}
}
}
You can use bubble sort algorithm technique which is fast sorting algorithm and it uses for loop instead of while loop
int bubbleSorter(int numbList[])
{
int temp;
int i, x;
bool swapped = false;
for (i = 0; i < x - 1; i++)
{
swapped = false;
for (j = 0; j < x - 1 - i; j++)
{
if (list[j] > list[j + 1])
{
temp = list[j];
list[j] = list[j + 1];
list[j + 1] = temp;
swapped = true;
}
else {
swapped = false;
}
}
// if no number was swapped that means
// array is sorted now, break the loop.
if (!swapped) {
break;
}
printf("Array as sorted:\n");
for (int i = 0; i<x; i++)
{
printf("%d\t", numbList[x]);
}
return(numbList[x]);
}
}

Splitting array into two parts, sorting each part, and recombining into single array

I've been working on a program that generates an array of random numbers, splits the array into two equal parts, sorts each part, and then recombines the two parts back into a singular sorted array. When attempting an insert sort I get the following:
http://i.imgur.com/70J4eLG.png
Can you guys see a reason why the first half array is sorted correctly but the second half is not?
int cmpfunc (const void *a, const void *b) {
return ( *(int*)a - *(int*)b );
}
void insertion_sort (int ar[], int size) {
int c, d, t;
for (c = 1; c <= size - 1; c++){
d = c;
while(d > 0 && ar[d] < ar[d - 1]) {
t = ar[d];
ar[d] = ar[d - 1];
ar[d - 1] = t;
d--;
}
}
}
void check_sort (int ara[], int size_t) {
int b;
int c_i;
c_i = 0;
for (b = 1; b < size_t; b++) {
if (ara[b - 1] > ara[b]) {
printf("Array is not sorted correctly\n");
break;
} else {
c_i++;
}
}
if (c_i == size_t - 1) {
printf("Array is sorted correctly\n");
}
}
void combine_array(int a_ar[], int b_ar[], int c_ar[], int size_1, int size_2) {
int i, j, k;
i, j, k = 0;
while (i < size_1 && j < size_2) {
if (a_ar[i] < b_ar[j]) {
c_ar[k] = a_ar[i];
i++;
} else {
c_ar[k] = b_ar[j];
j++;
}
k++;
}
if (i >= size_1) {
while (j < size_2) {
c_ar[k] = b_ar[j];
j++;
k++;
}
}
if (j >= size_2) {
while (i < size_1) {
c_ar[k] = a_ar[i];
i++;
k++;
}
}
}
int main (int argc, char *argv[]) {
int a_size, t_num;
char s_type;
int i, j, k;
int two_s[1];
a_size = atoi(argv[1]);
t_num = atoi(argv[2]);
s_type = argv[3][0];
int array_m[a_size];
for (i = 0; i < a_size; i++) {
array_m[i] = rand();
}
for (i = 0; i < a_size; i++) {
printf("%d \n", array_m[i]);
}
printf("\n");
if (t_num == 2) {
two_s[0] = ((a_size/2));
two_s[1] = (a_size);
int array_s1[two_s[0]];
int array_s2[two_s[0]];
printf("First half \n");
for (j = 0; j < two_s[0]; j ++) {
array_s1[j] = array_m[j];
printf("%d \n", array_s1[j]);
}
printf("Second half \n");
for (k = two_s[0]; k < two_s[1]; k++) {
array_s2[k] = array_m[k];
printf("%d \n", array_s2[k]);
}
printf("Size of second array: %d", (two_s[1] - two_s[0]));
printf("\n");
check_sort(array_m, a_size);
if (s_type == 'I') { //Insertion sort
insertion_sort(array_s1, two_s[0]);
insertion_sort(array_s2, two_s[0]);
printf("Sorted first half \n");
for (i = 0; i < two_s[0]; i++) {
printf("%d \n", array_s1[i]);
}
printf("Sorted second half \n");
for (i = 0; i < two_s[0]; i++) {
printf("%d \n", array_s2[i]);
}
//combine_array(array_s1, array_s2, array_m, two_s[0], two_s[0]);
printf("\n");
printf("Combined and sorted \n");
for (i = 0; i < a_size; i++) {
printf("%d \n", array_m[i]);
}
check_sort(array_m, a_size);
}
if (s_type == 'Q') { //Quick sort
qsort(array_m, a_size, sizeof(int), cmpfunc);
printf("\n");
for (i = 0; i < a_size; i++) {
printf("%d \n", array_m[i]);
}
}
}
}
In your example, array_s2 is an array with 5 elements. In the following for loop, you're writing to memory outside the bounds of the array:
for (k = two_s[0]; k < two_s[1]; k++) {
array_s2[k] = array_m[k];
printf("%d \n", array_s2[k]);
}
k has an initial value of 5 and a final value of 9, which is outside the bounds of array_s2. Try the following to correctly index the array:
for (k = two_s[0]; k < two_s[1]; k++) {
array_s2[k - two_s[0]] = array_m[k];
printf("%d \n", array_s2[k - two_s[0]]);
}

C - Chomp questions

I'm trying to create the game Chomp. I am halfway through but pretty stuck.
The game will have 5 different functions. Pointers and structs are not allowed.
a) initialize() Initialize every position in the matrix to 'O'. No parameters or return value.
b) print_board() Prints the matrix. No parameters or return value.
c) get_move() Scan a move from the player (row and col) and "return" it with an array. Parameters: Information about whos turn it is (Player 1 or Player 2), and an array with two elements where the move coordinates will be stored. No return value.
d) check_move() Controls if a move is legal (not outside the matrix and not a position that has already been eaten). Parameters: The move that is going to be checked (row and col). Return value: Result of the control. <------ ???????
e) update_board() Updates the matrix. Parameters: The new move (row and col). No return value.
This is how far I have come and I am stuck at the check_move() function. I don't understand what I am going to return from that function.
#include <stdio.h>
int height = 4;
int width = 10;
char matrix[4][10];
void initialize()
{
for(int row = 0; row < height; row++)
for(int col = 0; col < width; col++)
matrix[row][col] = 'O';
}
void print_board()
{
for(int row = 0; row < height; row++)
{
for(int col = 0; col < width; col++)
{
printf("%c", matrix[row][col]);
}
printf("\n");
}
printf("\n");
}
void get_move(int player, int input[])
{
printf("Player %d, make your move: ", player);
scanf("%d %d", &input[0], &input[1]);
}
int check_move(int position[])
{
int row = position[0];
int col = position[1];
if(row <= height && col <= width)
{
for(row; row <= height; row++)
{
for(col; col <= width; col++)
{
if(matrix[row][col] == ' ');
printf("Invalid move! \n");
}
}
}
}
void update_board(int x, int y)
{
for(int xi = x; xi <= 10; ++xi)
{
for(int yi = y; yi <= 10; ++yi)
matrix[xi-1][yi-1] = ' ';
}
}
int main(void)
{
int player = 1;
int position[2];
initialize();
print_board();
get_move(player, position);
check_move(position);
update_board(position[0], position[1]);
print_board();
getchar();
getchar();
getchar();
return 0;
}
You should return a value from check_move, because it is prototyped that way, I assume you want to use the exit status somewhere? :
int check_move(int position[])
and you have an unnecessary ; at the end of your if:
int check_move(int position[])
{
int row = position[0];
int col = position[1];
int status = 1;
if(row <= height && col <= width)
{
for(row; row <= height; row++)
{
for(col; col <= width; col++)
{
if(matrix[row][col] == ' ') //removed ";" from end of line, otherwise,
{ //printf will always be called
printf("Invalid move! \n");
return 0;
}//also added brackets to force return if error (only need one error to return)
}
}
}
return status; //added return status
}
So, now in the main, you would do something like this to call check_move():
int main(void)
{
int player = 1;
int position[2];
initialize();
print_board();
get_move(player, position);
while(check_move(position) != 1)
{
printf("Try again!\n\n");
print_board();
get_move(player, position);
}
update_board(position[0], position[1]);
print_board();
getchar();
getchar();
getchar();
return 0;
}

Resources