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!
So I have to scan a maze number of rows and columns for a file, bit I got that part.
File have a form like this
3
4
....
.#.#
....
Where the first number is a number of rows and the second is the number of columns. Character '#' is a wall and I can't go there but I can go through '.'
Now I have to, using structures and pointers, find a shortest path to any point in a maze. Example structure is in my code (Cell).
I have no idea how to do this. I've created a array 'visited' to track which cell I've been to and function to check if a point is valid.
Somehow I have to point to other points in NORTH, WEST, EAST, SOUTH directions.
#include "stdafx.h"
#include "stdlib.h"
//Starting point
#define START_X 0
#define START_Y 0
//example structure I have to use
struct Cell
{
struct Cell *north;
struct Cell *east;
struct Cell *south;
struct Cell *west;
char value;
int distance;
};
//function that prints a maze
void printMap(char **charMaze, int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
printf_s("%c", charMaze[i][j]);
}
printf_s("\n");
}
}
// functions that check if a point is valid
bool isValid(int x, int y, int row, int col)
{
if (x < row && y < col && x >= 0 && y >= 0)
return true;
return false;
}
bool isSafe(char **charMaze, int **visited, int x, int y)
{
if (charMaze[x][y] == '#' || visited[x][y]==true)
return false;
return true;
}
//My attempt at solving this
int BFS(char **maze,int END_X, int END_Y,int row, int col, bool **visited)
{
isValid(END_X, END_Y, row, col);
}
int main()
{
FILE *map;
int row, col;
// I open a file with a maze
fopen_s(&map, "test1.txt", "r");
// I scan a row number and column number
fscanf_s(map, "%d", &row);
fscanf_s(map, "\n%d\n", &col);
char** charMaze;
charMaze = (char**)malloc(row * sizeof(char*));
for (int i = 0; i < row; i++)
charMaze[i] =(char*)malloc(col * sizeof(char));
bool** visited;
visited = (bool**)malloc(row * sizeof(bool*));
for (int i = 0; i < row; i++)
visited[i] = (bool*)malloc(col * sizeof(bool));
//set staring point as true and other points as false
visited[START_X][START_Y] = true;
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
visited[i][j] = false;
}
}
// I scan a maze and I put it in a array
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
fscanf_s(map, "%c", &charMaze[i][j],1);
}
fscanf_s(map, "\n");
}
fclose(map);
//printMap(charMaze, row, col);
return 0;
}
You could use the Dijkstra algorithm to find the shortest path.
As result, suppose you have to return a path from the starting point to every dot in the maze.
You have here an implementation of the Dijkstra algorithm.
You would need to adapt it your maze map.
You could use a matrix of structs where each struct contains the x,y coordinate of the previous node, the distance to the starting node, and the flag done.
Edit
If fact you don’t even need to implement the Dijkstra algorithm. A simple flooding algorithm will do because the weight of all vertex of the graph is one.
Here is how I would do it.
#include <stdbool.h>
#include <stdlib.h>
enum State { Wall, Unvisited, WaveBorder, NewWaveBorder, Done };
// define the structure holding coordinates of previous cell in path and state
typedef struct Cell {
int i,j; // coordinates of predecessor in path
enum State state;
} Cell;
// visit cell (vi,vj) from neighbor cell (i,j)
void visitCell(Cell **m, int vi, int vj, int i, int j) {
if m[vi][vj].state == Unvisited {
m[vi][vj].state = NewWaveBorder;
m[vi][vj].i = i;
m[vi][vj].j = j;
}
}
Cell** findShortestPath(char **maze, int row, int col, int iStart, int jStart) {
Cell **m = malloc(sizeof(Cell*)*row);
for (int i = 0; i < row; i++)
m[i] = malloc(sizeof(Cell)*col);
for (int i = 0; i < row; i++)
for (int j = 0; j < col; j++)
if (maze[i][j] == '.') {
m[i][j].state = Unvisited;
m[i][j].i = m[i][j].j = -1;
} else {
m[i][j].state = Wall;
m[i][j].i = m[i][j].j = -2;
}
m[iStart][jStart].state = WaveBorder;
bool done = false;
while (!done) {
for (int i = 0; i < row; i++)
for (int j = 0; j < col; j++) {
if (m[i][j].state != waveBorder)
continue;
if (i > 0)
visitCell(m, i-1, j, i, j);
if (j > 0)
visitCell(m, i, j-1, i, j);
if (i < row)
visitCell(m, i+1, j, i, j);
if (j < col)
visitCell(m, i, j+1, i, j);
m[i][j].state = Done;
}
done = true;
for (int i = 0; i < row; i++)
for (int j = 0; j < col; j++)
if (m[i][j].state == Unvisited)
done = false;
else if (m[i][j].state == NewWaveBorder)
m[i][j].state == WaveBorder;
}
return m;
}
The path from cell (i,j) is stored in the matrix of Cell structures. Each cell has the coordinates of the predecessor in the path toward (iStart, jStart). The cell (iStart,jStart) will have (-1,-1) as predecessor in the path. Walls will have (-2,-2) as predecessors.
Okay I did something like this. But it doesn't work for some reason.
#include "stdafx.h"
#include "stdlib.h"
//Starting point
#define START_X 0
#define START_Y 0
#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
//example structure I have to use
struct Cell
{
struct Cell *north;
struct Cell *east;
struct Cell *south;
struct Cell *west;
char value;
int distance;
};
//function that prints a maze
void printMap(char **charMaze, int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
printf_s("%c", charMaze[i][j]);
}
printf_s("\n");
}
}
void printMap2(int **intMaze, int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
printf_s("%d", intMaze[i][j]);
}
printf_s("\n");
}
}
// functions that check if a point is valid
bool isValid(int x, int y, int row, int col)
{
if (x < row && y < col && x >= 0 && y >= 0)
{
printf("Dobry punkt");
return true;
}
else
{
printf("Nieprawidlowy");
}
return false;
}
bool isSafe(char **charMaze, int **visited, int x, int y)
{
//char wall = '#';
//char character = charMaze[x][y];
if (charMaze[x][y] =='#' || visited[x][y])
{
printf("unsafe");
return false;
}
else
{
printf("safe");
}
return true;
}
bool canGo(Cell *cell, int d)
{
if (cell == NULL)
{
return 0;
}
if (cell->value == '#')
return 0;
if (cell->value == '.')
return 1;
if (cell->distance > d)
return 1;
return 0;
}
void findShortestPath(char **maze, int start_X, int start__Y, int i, int j, int row, int col, int **visited, int minDist, int dist)
{
if (j = start__Y && i == start_X)
{
minDist = MIN(dist, minDist);
return;
}
visited[start_X][start__Y] = 1;
//bottom
if (isValid(start_X + 1, start__Y, row, col) && isSafe(maze, visited, start_X + 1, start__Y))
findShortestPath(maze, start_X + 1, start__Y, i, j, row, col, visited, minDist, dist + 1);
//right
if (isValid(start_X, start__Y + 1, row, col) && isSafe(maze, visited, start_X, start__Y + 1))
findShortestPath(maze, start_X, start__Y + 1, i, j, row, col, visited, minDist, dist + 1);
//top
if (isValid(start_X - 1, start__Y, row, col) && isSafe(maze, visited, start_X + 1, start__Y))
findShortestPath(maze, start_X + 1, start__Y, i, j, row, col, visited, minDist, dist + 1);
//left
if (isValid(start_X, start__Y - 1, row, col) && isSafe(maze, visited, start_X, start__Y - 1))
findShortestPath(maze, start_X, start__Y - 1, i, j, row, col, visited, minDist, dist + 1);
visited[start_X, start__Y] = 0;
}
int main()
{
FILE *map;
int start_X = 0;
int start_Y = 0;
int row, col;
struct Cell cell;
// I open a file with a maze
fopen_s(&map, "test1.txt", "r");
// I scan a row number and column number
fscanf_s(map, "%d", &row);
fscanf_s(map, "\n%d\n", &col);
char** charMaze;
charMaze = (char**)malloc(row * sizeof(char*));
for (int i = 0; i < row; i++)
charMaze[i] = (char*)malloc(col * sizeof(char));
int** visited;
visited = (int**)malloc(row * sizeof(int*));
for (int i = 0; i < row; i++)
visited[i] = (int*)malloc(col * sizeof(int));
memset(visited, 0, sizeof visited);
int minDist = INT_MAX;
// I scan a maze and I put it in a array
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
fscanf_s(map, "%c", &charMaze[i][j], 1);
}
fscanf_s(map, "\n");
}
findShortestPath(charMaze, start_X, start_Y, 2, 3, row, col, visited, minDist, 0);
if (minDist != INT_MAX)
{
printf("Najkrotsza droga z poczatku do konca to %d", minDist);
}
else
{
printf("Can't get to the point");
}
printMap(charMaze, row, col);
fclose(map);
return 0;
}
i try to create dynamic matrix and enter values with scanf.
Its work only for 1 row, when i increase the error begins.
Can not make progress from the first line and thus can not get values.
int main()
{
int **matrix1;
BuildMatrix(&matrix1, 3, 3);
}
void BuildMatrix(int*** matrix, int row, int column)
{
int i, j, flag = 1, num;
*matrix = (int**)malloc(row * sizeof(int*));
if (*matrix == NULL)
{
printf("Not enough memory!\n");
}
else
{
for (i = 0; i < row && flag; i++)
{
*matrix[i] = (int* )malloc(column * sizeof(int));
if (*matrix[i] == NULL)
{
printf("Not enough memory!\n");
for (j = 0; j < i; j++)
{
free(*matrix[j]);
flag = 0;
}
free(*matrix);
}
}
if (flag)
{
for (i = 0; i < row; i++)
{
for (j = 0; j < column; j++)
{
scanf("%d", &*matrix[i][j]);
}
}
}
}
}
Due to operator precedence, the expression *matrix[i] is equal to *(matrix[i]). That is, it dereferences matrix[i] and not matrix.
You need to use (*matrix)[i] instead.
int main() {
struct matrix m;
m.rows = 20;
m.columns = 20;
m.grid = create_grid(m.rows,m.columns,'&');
/* Example animation */
printf("\033[H\033[2J");
for (int i = 0; i < m.columns; i++) {
update_matrix(m.grid,10,i,'x');
if ( i > 0) {
update_matrix(m.grid,10,i-1,'&');
}
printf("\033[H\033[2J");
sleep(1);
printMatrix(m.grid,m.rows,m.columns);
}
for (int i = 0; i < m.rows; i++) {
free(m.grid[i]);
}
free(m.grid);
return 0;
}
void update_matrix(char** grid, int row,int column,char symbol) {
grid[row][column] = symbol;
}
char** create_grid(int rows, int columns, char symbol) {
int i,j;
char **grid = malloc(rows * sizeof(char *));
for (i = 0; i < rows; i++) {
grid[i] = malloc(columns * sizeof(char));
}
for (i = 0; i < rows; i++) {
for(j = 0; j < columns; j++) {
grid[i][j] = symbol;
}
}
return grid;
}
void printMatrix(char** array, int rows, int columns) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
printf("%c",array[i][j]);
}
printf("\n");
}
}
my method of animation is essentially to...
print the matrix
update the matrix
pause
clear the screen
reprint the matrix
The problem with this method of animation is that it creates a flickering effect and i'm sure is very inefficient. What can I do so that I do not have to clear the screen and reprint the entire matrix each time.
I run linux.
Apart from using ncurses, you could do
printf("\033%d;%df", row, column);
to set the cursor to the required row and column (note that in here, first row is 1 and not 0) instead of
printf("\033[H\033[2J");
Print the matrix once after setting it up and then change the displayed matrix when modifications are made.
You might want to position the cursor to the first row and column before printing the initial matrix like
printf("\033[%d;%df", 1, 1);
m.grid = create_grid(m.rows,m.columns,'&');
printMatrix(m.grid, m.rows, m.columns);
/* Example animation */
for (int i = 0; i < m.columns; i++) {
update_matrix(m.grid,10,i,'x');
printf("%c[%d;%df", 0x1B, 10+1, i+1);
printf("%c", 'x');
if ( i > 0) {
update_matrix(m.grid,10,i-1,'&');
printf("%c[%d;%df", 0x1B, 10+1, i-1+1);
printf("%c", '&');
}
sleep(1);
fflush(stdout);
}
fflush(stdout); may be needed to flush the output stream. Otherwise the changes written to stdout may not come on screen the moment they are changed.
But for such uses ncurses is better.
Have a look here and at this wikipedia page as well.
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;
}