C - check matrix[x][y] positions around - c

I've a matrix with size 7x7 that represents a game board. When a player makes a move, the program has to check the positions around the coordinates where the piece is, in order to detect another piece aside.
I use this function:
int check_position(COORDINATES coordinates, char board[7][7]) {
int result = -1;
if (board[coordinates.x][coordinates.y] != 'O' && board[coordinates.x-1][coordinates.y] != 'O' && board[coordinates.x][coordinates.y-1] != 'O' && board[coordinates.x+1][coordinates.y] != 'O' && board[coordinates.x][coordinates.y+1] != 'O' && board[coordinates.x-1][coordinates.y-1] != 'O' && board[coordinates.x+1][coordinates.y+1] != 'O' && board[coordinates.x-1][coordinates.y+1] != 'O' && board[coordinates.x+1][coordinates.y-1] != 'O') {
result = 1;
}
return result;
}
The first parameter are the coordinates of the player's piece as a struct, with members x and y. The second parameter is the board array.
The if statement doesn't work to well, and I don't know which alternative can I take.
Can you help me? Thanks!

You forgot about your coordinates overflowing at the borders. You can either test for this, or:
Hint: Make the array two rows and columns larger than the board and fill the border with "empty" marker. The active board will the have coordinates 1...7 This way your coordinates cannot wrap (1 - 1 and 7 + 1 are still within the array) and you do not have to care about the borders.
Note: If you just want to return a boolean value, it would be better to use stdbool.h and return a bool result. That way, the caller can directly use that function as a condition:
#include <stdbool.h>
...
bool check_position(COORDINATES coordinates, const char board[9][9]) {
int x = coordinates.x - 1
for ( int xc = 0 ; xc < 3 ; xc++ ) {
int y = coodinates.y - 1;
for ( int yc = 0 ; yc < 3 ; yc++ ) {
if ( board[x][y] != '0' )
return true;
y++;
}
x++;
}
return false;
}
Note: as you only need one one non-empty field, you can terminate instantly if you found one. That is identical to the multiple conditions. Of course, that also works for your original int result.
Note2: I modified the type of board to being const, as it is not changed inside the function.

You could also solve the edge overflow like this. Edit improved after discussion with #Olaf
#define BOARD 7
int check_position(COORDINATES coordinates, char board[BOARD][BOARD]) {
int result = -1;
int left = coordinates.x == 0 ? 0 : coordinates.x - 1;
int top = coordinates.y == 0 ? 0 : coordinates.y - 1;
int right = coordinates.x == BOARD-1 ? coordinates.x : coordinates.x + 1;
int bottom = coordinates.y == BOARD-1 ? coordinates.y : coordinates.y + 1;
if (board[left] [top] != 'O' &&
board[coordinates.x][top] != 'O' &&
board[right] [top] != 'O' &&
board[left] [coordinates.y] != 'O' &&
board[coordinates.x][coordinates.y] != 'O' &&
board[right] [coordinates.y] != 'O' &&
board[left] [bottom] != 'O' &&
board[coordinates.x][bottom] != 'O' &&
board[right] [bottom] != 'O' && )
{
result = 1;
}
return result;
}

Related

Can I compare an array with 2 more arrays and see if it will meet the condition

I wanted to ask if its possible to have 1 array with two conditions for it to meet?
lets just say the arrays are
//gi.move2[10] = 1,1,1,1,1,1,1,0,1,1
//gi.move3[10] = 1,1,1,1,1,1,1,0,1,1
//pi.move1 [10] = 2,3,4,5,6,7,0,8,1,8
scanf("%d",&pi.move1[k]); // user will input 8 thus resulting a &pi.move[7] = 8
for (i = 0; i <= 10; i++)
{
if (pi.move1[7] = (gi.move2[7] == '0' || gi.move3[7] == '0'))
{
printf("x");
}
else
{
printf("-");
}
}
I tied the code above, but
I have the structure of gi.move2, gi. move3 and pi.move 1// I have no problems with those.
I am not sure how to show that this statement is true
(pi.move1[7] = (gi.move2[7] == '0' || gi.move3[7] == '0'))
I tried this also didnt work.
if (pi.move1[7] = (gi.move2[7] == 0 || gi.move3[7] == 0))
it gave me xxxx-xxxxx-xx
**
The outcome I'm looking for is
--------X--
and also once 8 has been input it cant be used again.
**
the outcome i get is ----------
Thank you
if (pi.move1[7] = (gi.move2[7] == '0' || gi.move3[7] == '0'))
the single '=' is the first problem i see
try fixing the if logic

Problem in reading data from a var and pass it to other one in C

I'm trying to create a 3D Game Using C.
but I have a problem in The following Code
explain The Code
I have a file named 1.cub (lock down the code), this file has The map.
using The function read_cf_color I read The color of The floor and The sky from The 1.cub file and store The floor color in var named mlx->floor_color, and The ceiling in var named mlx->sky_color.
P.S: using some other functions I read all The data from 1.cub and store it in var named mlx->lines.
parse_parameters : scan all The data in mlx->lines (1.cub file) and send every line to choose_param.
choose_param: get The line from parse_parameters and tey to match every c with the right function.
read_cf_color: This function gets the color of the floor/ceiling. and cast it from char * to long int.
ft_isfloor: get the color from the previous function and give it to the right var (mlx->floor_color/mlx->sky->color).
for example:
parse_parameters pass this line F 100 , 100 , 214 to choose_param.
Then choose_param pass The F To char c in read_cf_color and the rest 100 , 100 , 214 to char *s.
the function try to make this 100 , 100 , 214 look like this 100100214 and store it in long int color
int choose_param(char c, char *str, t_mlx *mlx)
{
while (*str == ' ')
str++;
if (c == 'R' && *(str + 1) == ' ')
read_resolution(str + 1, mlx);
else if (c == 'N' && *(str + 1) == 'O' && *(str + 2) == ' ')
read_txt(1, str + 2, mlx);
else if (c == 'S' && *(str + 1) == 'O' && *(str + 2) == ' ')
read_txt(2, str + 2, mlx);
else if (c == 'W' && *(str + 1) == 'E' && *(str + 2) == ' ')
read_txt(4, str + 2, mlx);
else if (c == 'E' && *(str + 1) == 'A' && *(str + 2) == ' ')
read_txt(3, str + 2, mlx);
else if (c == 'F' && *(str + 1) == ' ')
read_cf_color(str + 1, mlx, 'f');
else if (c == 'C' && *(str + 1) == ' ')
read_cf_color(str + 1, mlx, 'c');
else if (c == 'S' && *(str + 1) == ' ')
read_txt(5, str + 1, mlx);
else if (c == '1' || c == '0' || c == '2')
return (0);
else if (c)
ft_put_error("NON-EMPTY LINE WITH WRONG IDENTIFIER\n", mlx);
return (1);
}
char **parse_parameters(t_mlx *mlx, char **lines)
{
int i;
int j;
int map;
i = 0;
map = 0;
while (lines[i])
{
j = 0;
while (lines[i][j] == ' ')
j++;
if (!choose_param(lines[i][j], lines[i], mlx))
{
return (&lines[i]);
}
i++;
}
ft_put_error("NO MAP FOUND\n", mlx);
return (lines);
}
void ft_isfloor(char *s, t_mlx *mlx, char type, char *stor)
{
if (type == 'f')
{
ft_printf("The rest of The floor:\t|%s|\n",s);
extra_param(s, mlx, "Too many Floor rgb inputs");
mlx->floor_color = ft_atoi(stor);
ft_printf("The floor Value: |%d|\n",mlx->floor_color);
if (mlx->floor_color < 0)
ft_put_error("Wrong values for floor color\n", mlx);
mlx->floor_done = 1;
}
else if (type == 'c')
{
ft_printf("The rest of The ceiling\t\n|%s|\n",s);
extra_param(s, mlx, "Too many ceiling rgb inputs");
mlx->sky_color = ft_atoi(stor);
ft_printf("The ceiling Value: |%d|\n",mlx->sky_color);
if (mlx->floor_color < 0)
ft_put_error("Wrong values for ceiling color\n", mlx);
mlx->sky_done = 1;
}
}
void read_cf_color(char *s, t_mlx *mlx, char type)
{
long int color;
char *stor;
int i;
i = 3;
color = 0;
if (mlx->floor_done && type == 'f')
ft_put_error("Multiple floor color inputs\n", mlx);
if (mlx->sky_done && type == 'c')
ft_put_error("Multiple ceiling color inputs\n", mlx);
stor = (char *)malloc(sizeof(char) * 10);
while (i > 0)
{
ft_printf("s = |%s|\n",s);
while (*s == ' ')
s++;
ft_printf("s = |%s|\n",s);
color = ft_atoi(s);
s += ft_intsize(color);
stor = ft_strjoin(stor, ft_itoa(color));
ft_printf("color = |%d|\nstor = |%s|\n---------\n",color, stor);
while (*s == ' ')
s++;
ft_printf("s = |%s|\n",s);
if (*(s++) != ',' && i > 1)
ft_put_error("Wrong floor color input\n", mlx);
i--;
}
ft_printf("\tThe final color |%s|\n",stor);
ft_isfloor(s, mlx, type, stor);
free(stor);
}
file 1.cub:
R 1000 750
F 100 , 100 , 214
C 135, 197 ,214
EA ./textures/cat4.xpm
NO ./textures/cat1.xpm
SO ./textures/cat2.xpm
WE ./textures/cat3.xpm
S ./textures/barrel.xpm
1000000001
11111111111 100000000100000010111
10000000010000
1111101111
1111101111111111111111111111111111111111111
010000000100000110000000000000000000000001
01000000010000011000000000000000001001000111111111111111111111111111111
1111110100000001100000000000000000110000000000000000000000010000001
1000000000000001100000000001111110101111111111111111111110000111101
1111110000000001100000010000000000100001100000100000000000000000001
10000010000000011000000000000100001011000000001111111111111111111111
10000000000 0000000000010000000000010110000000001
100000100000000110000000000000000010110000000111
111111000000000110000000000000010010000000001
100011100000W00000000001111110000010000000001
1000000000000001100000000 000000000100000000001
1000000000000001100000000000000000100000000001
100000000000000110000000002000000010010000001
10000000000000011000000000000000001000000001
10000000000000011000000000000000001000000001
1111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111
when I compile all this I get this:
In The image :
--> after the floor color is stored and free(stor) when starting store the ceiling color the old value in var stor stays and add the new data :
--> after store all the data in s and s = || it's get a new data like in the image:
I hope you understand what I'm trying to say
The problem was in the Last if statement:
if (*(s++) != ',' && i > 1)
ft_put_error("Wrong floor color input\n", mlx);
I was reading beyond \0, so That way all This happened.
for stor I was allocated it 2 time:
The first time in stor = (char *)malloc(sizeof(char) * 10);
The second time when I call ft_strjoin.

Booleans in C language

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdbool.h>
_Bool check_domain(char *domain) {
int str_count = 0, x = strlen(domain), y = 0;
if (domain[x-1] == '.' || domain[0] == '.'){
return false; //if there is a period at start or end
}
else{
while (domain[y]){
if (str_count==2){
return false; //if 2 consecutive periods
}
if (domain[y] == 46 || 65<=domain[y]<=90 || 97<=domain[y]<=122){ //if character is period or alphanumeric
if (domain[y] == '.'){
str_count += 1;
}
else{
str_count = 0;
}
}
else{ // if character is non period non alphanumeric
return false;
}
y += 1;
}
}
return true;
}
int main(void){
char domain[] = "nus#edu.sg";
printf("%d",check_domain(domain));
}
EDIT:
Thank you for your responses, have a little more clarity on the subject now.
In addition to not having a period at the end or beginning, nor two consecutive periods, there should be no non-period, non-alphanumeric character inside the string.
For reasons I can't figure out, this code fails to return false for cases wherein there are non-period, non-alphanumeric characters inside the string.
Start here
if (domain[y] == 46 || 65<=domain[y]<=90 || 97<=domain[y]<=122){
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^
C can't handle statement like n <= X <= m in the way you expect.
C treats this as:
(65<=domain[y]) <= 90
^^^^^^^^^^^^^^^ ^^
bool <= number
So first C will calculate a bool result from 65<=domain[y] and then it will compare that bool to a number. The bool is converted to either 0 or 1 so when comparing with 90, the result is always true.
If you had checked the compiler warnings, you would have seen something like:
main.cpp:18:49: warning: comparison of constant '90' with boolean expression is always true [-Wbool-compare]
18 | if (domain[y] == 46 || 65<=domain[y]<=90 || 97<=domain[y]<=122){
| ^~
which tells you that something is wrong.
You need to write
if (domain[y] == 46 || (65<=domain[y] && domain[y]<=90) || (97<=domain[y] && domain[y]<=122)){
BTW:
Don't use magic numbers like 65, 90 and so on. Use the character instead. Like:
(65<=domain[y] && domain[y]<=90) --> ('A' <= domain[y] && domain[y] <= 'Z')
It makes the code much easier to understand.
Further - consider using the function isalpha(domain[y]) for such checks.
Finally - Your text (and function name) says that that you want to check for a domain name. However, your input is more like an e-mail address.

Tic-Tac-Toe without AI

I'm doing homework for UNI and I got to do a Tic-Tac-Toe without any decision taken by player, the moves are all chosen randomly. So if the character on matrix is ' ' it means it's free, while if it's 'X' or 'O' it should generate another move. This is the code (language C):
if (playerTurn == 1){
playerSymb = 'X';
}
else if (playerTurn == 2){
playerSymb = 'O';
}
if (matrix[rand1][rand2] == ' '){
matrix[rand1][rand2] = playerSymb;
} else if(matrix[rand1][rand2] == 'X' || matrix[rand1][rand2] == 'O'){
do{
randAlt1 = MINRND + rand()%(MAXRND - MINRND +1);
randAlt2 = MINRND + rand()%(MAXRND - MINRND +1);
}while (matrix[randAlt1][randAlt2] != 'X' && matrix[randAlt1][randAlt2] != 'O');
matrix[randAlt1][randAlt2] = playerSymb;
}
I did not copied the whole code because it's not finished at all, i just need help solving this. But if I try to run this, the Symbols can be overwritten, like if I have a 'X' at matrix[1][2], it's possible that it will be a 'O' after some turns. So how can I make moves do not overwrite? (sorry for bad english).
Just put correct condition:
while (matrix[randAlt1][randAlt2] == 'X' || matrix[randAlt1][randAlt2] == 'O')
(i.e. try again if this cell is not empty)
Also it is easy to simplify your code without loosing of anything:
randAlt1 = rand1;
randAlt2 = rand2;
while (matrix[randAlt1][randAlt2] != ' ') {
randAlt1 = MINRND + rand()%(MAXRND - MINRND +1);
randAlt2 = MINRND + rand()%(MAXRND - MINRND +1);
}
matrix[randAlt1][randAlt2] = (playerTurn == 1) ? 'X' : 'O';
And it is better to add loop guard to prevent infinite loop (or to add special checks for this case):
randAlt1 = rand1;
randAlt2 = rand2;
int nbAttempts = 0;
while (matrix[randAlt1][randAlt2] != ' ' && nbAttempts < 100) {
randAlt1 = MINRND + rand()%(MAXRND - MINRND +1);
randAlt2 = MINRND + rand()%(MAXRND - MINRND +1);
nbAttempts++;
}
if (matrix[randAlt1][randAlt2] != ' ') {
// show error message and stop the game
}
matrix[randAlt1][randAlt2] = (playerTurn == 1) ? 'X' : 'O';
You choose an arbitrary position and then test if it is free – possibly multiple times. But you can also choose a number of a free position and then find it.
First set up a turn counter
int turnNo = 0;
then make a loop for alternate moves, which chooses one of 9-turnNo unused positions, finds it, marks is with a player mark and tests if the move made a line of three:
while(turnNo < 9)
{
char currPlayerMark = ...choose 'X' or 'O';
int freePos = 9 - turnNo;
int currPos = rand() % freePos; // 0 .. freePos-1
for(x=0; x<3; x++)
{
for(y=0; y<3; y++)
{
if(matrix[x][y] == ' ') // a free position
if(--currPos < 0) // the sought one
break; // break the inner loop
}
if(currPos < 0)
break; // break the outer loop
}
matrix[x][y] = currPlayerMark;
if(test_for_win_position(x,y))
{
message_a_win_of_player(currPlayerMark);
break; // turnNo < 9 here
}
turnNo ++;
}
Finally test if the loop terminated with no 'win':
if(turnNo == 9)
message_its_a_draw(); // no-one wins
A function to test the win position might look like this:
int test_for_win_position(int x, int y)
{
char mark = matrix[x][y];
// check a column
if(matrix[x][0] == mark && matrix[x][1] == mark && matrix[x][2] == mark)
return 1;
// check a row
if(matrix[0][y] == mark && matrix[1][y] == mark && matrix[2][y] == mark)
return 1;
// check one diagonal
if(x==y)
if(matrix[0][0] == mark && matrix[1][1] == mark && matrix[2][2] == mark)
return 1;
// check another diagonal
if(x+y==2)
if(matrix[0][2] == mark && matrix[1][1] == mark && matrix[2][0] == mark)
return 1;
// current player has not won (yet)
return 0;
}

segmentation fault because of character changement

I'm writing a board game detailed information. I get segmentation fault just changing problem_ch from ' '(space) to '.'. When I play by the moves and with ' ', I don't get but when I play by the moves and with '.'I get. I really and really don't understand what happening.
Solved: Because of negative index, I get the segmentation fault. By
handling, It is solved.
Following moves:
3d
2d
5f
2e
1e
4b
4c
4a
3b
at 4b segmentation fault
Code:
void make_move(char board[][SIZE], size_t row, size_t col, char player)
{
int rowdelta = 0; // Row increment
int coldelta = 0; // Column increment
size_t x = 0; // Row index for searching
size_t y = 0; // Column index for searching
// Identify opponent
char opponent = (player == player_ch) ? computer_ch : player_ch;
board[row][col] = player; // Place the player counter
// Check all squares around this square for opponents counter
for(rowdelta = -1 ; rowdelta <= 1 ; ++rowdelta)
for(coldelta = -1; coldelta <= 1; ++coldelta)
{
// Don’t check off the board, or the current square
if((row == 0 && rowdelta == -1) || row + rowdelta >= SIZE ||
(col == 0 && coldelta == -1) || col + coldelta >= SIZE ||
(rowdelta == 0 && coldelta == 0))
continue;
// Now check the square
if(board[row + rowdelta][col + coldelta] == opponent)
{ // Found opponent so search in same direction for player counter
x = row + rowdelta; // Move to opponent
y = col + coldelta; // square
for(;;)
{
x += rowdelta; // Move to the
y += coldelta; // next square
if(board[x][y] == problem_ch) // If square is blank...
break; // ...give up
// If we find the player counter, go backward from here
// changing all the opponents counters to player
if(board[x][y] == player)
{
while(board[x -= rowdelta][y -= coldelta] == opponent) // Opponent?
board[x][y] = player; // Yes, change it
break; // We are done
}
}
}
}
}

Resources