How to validate a move in a checkerboard C? - c

Hi im a newbie at programming and this task is frustrating me rn because I still can't get the piece to move on the board. I am guessing this has to do on my while loop function but still can't get it right. The 1st user input should detect the coordinate of the character to move and show what are the available spots to where it can send the piece using validateMove(). Here's my code, Been onto this for weeks now.
#include <stdio.h>
char board[8][8] = {
{' ', 'B', ' ', 'B', ' ', 'B', ' ', 'B'},
{'B', ' ', 'B', ' ', 'B', ' ', 'B', ' '},
{' ', 'B', ' ', 'B', ' ', 'B', ' ', 'B'},
{'*', ' ', '*', ' ', '*', ' ', '*', ' '},
{' ', '*', ' ', '*', ' ', '*', ' ', '*'},
{'W', ' ', 'W', ' ', 'W', ' ', 'W', ' '},
{' ', 'W', ' ', 'W', ' ', 'W', ' ', 'W'},
{'W', ' ', 'W', ' ', 'W', ' ', 'W', ' '}};
void printBoard()
{
int i , j , k ;
printf("\n ");
for(i=0;i<8;i++)
printf(" %d", i+1 );
printf(" \n");
for(k=0;k<8;k++)
{
printf(" ");
for(i=0;i<42;i++)
{
printf("-");
}
printf(" \n");
printf(" %d ", k+1);
for(j=0;j<8;j++)
{
printf("|| %c ", board[k][j]);
}
printf("|| \n");
}
printf(" ");
for(i=0;i<42;i++)
{
printf("-");
}
printf(" \n");
}
void validateMoveChecker(int x1, int y1, int af, int bf, int v)
{
int a, b;
for(a=1, b=1; board[x1+ af * a][y1+ bf * b] == '*'; a++, b++)
{
if((x1+af*a) == -1 || (y1+bf*b)==v)
return;
printf("%d%d , ", x1+af*a , y1+bf*b);
}
}
int validateMove(int x1 , int y1)
{
printf( "Available coordinates to send the piece are: \n" );
validateMoveChecker(x1, y1, -1, 1, 8);
validateMoveChecker(x1, y1, 1, -1, -1);
validateMoveChecker(x1, y1, 1, 1, 8);
validateMoveChecker(x1, y1, -1, -1, -1);
}
int getChange(int x1 ,int y1 ,int x2 ,int y2 )
{
char temp;
temp = board[x1][y1];
board[x1][y1] = board[x2][y2];
board[x2][y2] = temp;
}
int check(int x, int y)
{
switch(board[x][y])
{
case 'B':
return 1;
break;
default:
return 0;
}
}
int main(){
int x1, y1, x2, y2, pos1, pos2, x, y;
char board[8][8];
printBoard();
do
{
printf("\nEnter the position of the piece [X,Y]: ");
scanf("%d", &pos1);
y1 = pos1%10;
x1 = pos1/10;
switch(board[x1][y1])
{
case 'B': validateMove(x1, y1);
break;
default: printf("Invalid Position. Please enter again!");
}
}while(x1!=0 && y1!=0);
printf("\nEnter the position on where to send the piece [X,Y]: ");
scanf("%d", &pos2);
y2 = pos2%10;
x2 = pos2/10;
getChange(x1 ,y1 ,x2 ,y2);
if((x2-x1==y2-y1)!=0)
{
getChange(x1 ,y1 ,x2 ,y2);
check(x,y);
}
}

I changed printBoard() to show index starting with 0 (1 is fine too, but then you need to adjust indexes):
void printBoard() {
int i , j , k ;
printf("\n ");
for(i=0;i<8;i++)
printf(" %d", i );
printf(" \n");
for(k=0;k<8;k++) {
printf(" ");
for(i=0;i<42;i++) {
printf("-");
}
printf(" \n");
printf(" %d ", k);
for(j=0;j<8;j++) {
printf("|| %c ", board[k][j]);
}
printf("|| \n");
}
printf(" ");
for(i=0;i<42;i++) {
printf("-");
}
printf(" \n");
}
and then in main() I made the following changes:
removed the local variable board; your code relies on a global variable of the same name. It would, however, be a better design to pass board to the functions that need it instead of using a global variable.
changed the two scanf() to just read the coordinates directly.
added a printBoard() after getChange() to verify the move worked.
(not fixed) the variables x and y are uninitialized.
int main(void) {
int x1, y1, x2, y2, x, y;
printBoard();
do {
printf("\nEnter the position of the piece [X,Y]: ");
scanf("%d,%d", &x1, &y1);
switch(board[x1][y1]) {
case 'B':
validateMove(x1, y1);
break;
default:
printf("Invalid Position. Please enter again!");
}
} while(x1 && y1);
printf("\nEnter the position on where to send the piece [X,Y]: ");
scanf("%d,%d", &x2, &y2);
getChange(x1, y1 ,x2 ,y2);
printBoard();
if((x2-x1==y2-y1)!=0) {
getChange(x1 ,y1 ,x2 ,y2);
check(x, y);
}
}
and example session:
0 1 2 3 4 5 6 7
------------------------------------------
0 || || B || || B || || B || || B ||
------------------------------------------
1 || B || || B || || B || || B || ||
------------------------------------------
2 || || B || || B || || B || || B ||
------------------------------------------
3 || * || || * || || * || || * || ||
------------------------------------------
4 || || * || || * || || * || || * ||
------------------------------------------
5 || W || || W || || W || || W || ||
------------------------------------------
6 || || W || || W || || W || || W ||
------------------------------------------
7 || W || || W || || W || || W || ||
------------------------------------------
Enter the position of the piece [X,Y]: 0,1
Available coordinates to send the piece are:
Enter the position on where to send the piece [X,Y]: 0,0
0 1 2 3 4 5 6 7
------------------------------------------
0 || B || || || B || || B || || B ||
------------------------------------------
1 || B || || B || || B || || B || ||
------------------------------------------
2 || || B || || B || || B || || B ||
------------------------------------------
3 || * || || * || || * || || * || ||
------------------------------------------
4 || || * || || * || || * || || * ||
------------------------------------------
5 || W || || W || || W || || W || ||
------------------------------------------
6 || || W || || W || || W || || W ||
------------------------------------------
7 || W || || W || || W || || W || ||
------------------------------------------

Related

Implement a function to recursively return a valid win-condition - C

Issue: I'm trying to utilize recTest to check and return the winner of a simple Tic-Tac-Toe game.
I'm just unsure of what I need to pass in the call (line I've highlighted), and how to integrate my public square array.
I apologize if this is overly simple, I'm just having a rough time connecting the dots.
#include<stdio.h>
#include<conio.h>
char square[10] = {'o', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
// returns -1 if no v[i] satisfies p
// returns i if v[i] satisfies p (picks largest i)
// (i>=0) and (i<n)
const int numwinpos = 8;
const int winpos[8][3] = {{1,2,3},
{4,5,6},
{7,8,9},
{1,4,7},
{2,5,8},
{3,6,9},
{1,5,9},
{3,5,7}};
//Function below, and variables above<--------------------------------------
int recTest(const int v[], const int n){
if( (n>0) && (!p(v[n-1])) )
return recTest(v,n-1);
else
return n-1;
}
/*int winnerCheck() {
//not even hard-coded tho...
if (square[1] == square[2] && square[2] == square[3])
return 1;
else if (square[4] == square[5] && square[5] == square[6])
return 1;
else if (square[7] == square[8] && square[8] == square[9])
return 1; //above 3 check across
else if (square[1] == square[4] && square[4] == square[7])
return 1;
else if (square[2] == square[5] && square[5] == square[8])
return 1;
else if (square[3] == square[6] && square[6] == square[9])
return 1; //above 3 check down
else if (square[1] == square[5] && square[5] == square[9])
return 1;
else if (square[3] == square[5] && square[5] == square[7])
return 1; //above 2 check diagonal
else if (square[1] != '1' && square[2] != '2' && square[3] != '3' && square[4]
!= '4' && square[5] != '5' &&
square[6] != '6' && square[7] != '7' && square[8]
!= '8' && square[9] != '9')
return 0;
else
//exit
return -1;
}
*/
void board() {
printf("\n\n\tTic Tac Toe\n\n");
printf("Player 1 (X) - Player 2 (O)\n\n\n");
//prints the board after every input
printf(" | | \n");
printf(" %c | %c | %c \n", square[1], square[2],square[3]);
printf("____|_____|____\n");
printf(" | | \n");
printf(" %c | %c | %c \n", square[4], square[5],square[6]);
printf("____|_____|____\n");
printf(" | | \n");
printf(" %c | %c | %c \n", square[7], square[8],square[9]);
printf(" | | \n");
}
int main() {
/*
char board[3][3] = {
};
printf("\t|\t|\t\n");
printf("\t|\t|\t\n");
printf("________|_______|________\n");
printf("\t|\t|\t\n");
printf("\t|\t|\t\n");
printf("________|_______|________\n");
printf("\t|\t|\t\n");
printf("\t|\t|\t\n");
printf("\t|\t|\t\n");
*/
int player = 1, i, choice;
char mark;
do {
board();
player = player % 2 ? 1 : 2;
printf("Player %d, enter a number: ", player);
scanf("%d", &choice);
//mark = (player == 1) ? 'X' : 'O';
if (player == 1) {
mark = 'X';
} else {
mark = 'O';
}
if (choice == 1)
square[1] = mark;
else if (choice == 2)
square[2] = mark;
else if (choice == 3)
square[3] = mark;
else if (choice == 4)
square[4] = mark;
else if (choice == 5)
square[5] = mark;
else if (choice == 6)
square[6] = mark;
else if (choice == 7)
square[7] = mark;
else if (choice == 8)
square[8] = mark;
else if (choice == 9)
square[9] = mark;
i = recTest(square, numwinpos); //HERE <--------------------------------------
player++;
} while (i == -1);
board();//call board
if (i == 1)
printf("----->\aPlayer %d WINS!<-----", --player);//nice alert sound when printed
else
printf("----->\aC-could it be...? Game draw!<-----");//nice alert sound when printed
//getch();//waits for user input before ending
return 0;
}
A quick and dirty way to use recursion would be to do something like below... and yes this can be optimized..
int winnerCheck(int x)
{
if(x < numwinpos)
{
if((square[winpos[x][0]] == 'x') && (square[winpos[x][1]] == 'x') && (square[winpos[x][2]] == 'x') ||
(square[winpos[x][0]] == 'o') && (square[winpos[x][1]] == 'o') && (square[winpos[x][2]] == 'o'))
return 1;
else
{
return winnerCheck(++x);
}
}
return 0;
}

Counting work days between two dates in C

I am writing a code in C with two functions.
The first (WorkDay) takes a date and says if it is a working day (return 1) or not (return 0). I think the first function is OK, although it could be better, but it is working. It includes weekends and public holidays in my country.
The problem comes with the second function (CountWorkDays). It should take two dates and say if they are correct (return 1) and in that case also say how many working days is among them, including the entered dates (cnt=). If the dates aren't correct (first is bigger than second etc.), there is return 0. I've tried to make a helping function next_day(), but I am pretty sure it is wrong. Can you help me with the second function please?
I cannot use <time.h> and I put there some asserts, which I am testing the function with.
#include <stdio.h>
#include <math.h>
#include <assert.h>
int WorkDay ( int y, int m, int d )
{
int h, day;
h= (d + floor(((m+1)*26)/10) + y + floor(y/4) + 6*floor(y/100) + floor(y/400));
day=h%7;
if ((y%4!=0) && m==2 && d==29)
return 0;
else if (((y%4==0 || y%400==0) && (y%100!=0 || y%4000!=0)) && m==2 && d==29)
{
if (day==2 || day==3 || day==4 || day==1 || day==0)
return 1;
else
return 0;
}
else if ((d==1 && m==1) || (d==1 && m==5) || (d==8 && m==5) || (d==5 && m==7) || (d==6 && m==7) || (d==28 && m==9) || (d==28 && m==10) || (d==17 && m==11) || (d==24 && m==12) || (d==25 && m==12) || (d==26 && m==12) || day==0 || day==1 || (m==1 && (d>31 || d<1)) || (m==2 && (d>29 || d<1)) || (m==3 && (d>31 || d<1)) || (m==4 && (d>30 || d<1)) || (m==5 && (d>31 || d<1)) || (m==6 && (d>30 || d<1)) || (m==7 && (d>31 || d<1)) || (m==8 && (d>31 || d<1)) || (m==9 && (d>30 || d<1)) || (m==10 && (d>31 || d<1)) || (m==11 && (d>30 || d<1)) || (m==12 && (d>31 || d<1)) || y<2000 || m>12 || m<1)
return 0;
else if (day==2 || day==3 || day==4 || day==5 || day==6)
return 1;
else
return 0;
}
int next_day()
{
int y1, m1, d1;
static int days_in_month[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
unsigned short day_counter;
d1 += 1; day_counter++;
if (d1 > days_in_month[m1])
{
d1 = 1;
m1 += 1;
if (m1 > 12)
{
m1 = 1;
y1 += 1;
if (((y1%4==0 || y1%400==0) && (y1%100!=0 || y1%4000!=0)))
{
days_in_month[2] = 29;
}
else
{
days_in_month[2] = 28;
}
}
}
return 0;
}
int CountWorkDays ( int y1, int m1, int d1,
int y2, int m2, int d2,
int * cnt )
{
int i,x;
if ( (m1==1 && (d1>31 || d1<1)) || (m1==2 && (d1>29 || d1<1)) || (m1==3 && (d1>31 || d1<1)) || (m1==4 && (d1>30 || d1<1)) || (m1==5 && (d1>31 || d1<1)) || (m1==6 && (d1>30 || d1<1)) || (m1==7 && (d1>31 || d1<1)) || (m1==8 && (d1>31 || d1<1)) || (m1==9 && (d1>30 || d1<1)) || (m1==10 && (d1>31 || d1<1)) || (m1==11 && (d1>30 || d1<1)) || (m1==12 && (d1>31 || d1<1)) || y1<2000 || m1>12 || m1<1 ||(m2==1 && (d2>31 || d2<1)) || (m2==2 && (d2>29 || d2<1)) || (m2==3 && (d2>31 || d2<1)) || (m2==4 && (d2>30 || d2<1)) || (m2==5 && (d2>31 || d2<1)) || (m2==6 && (d2>30 || d2<1)) || (m2==7 && (d2>31 || d2<1)) || (m2==8 && (d2>31 || d2<1)) || (m2==9 && (d2>30 || d2<1)) || (m2==10 && (d2>31 || d2<1)) || (m2==11 && (d2>30 || d2<1)) || (m2==12 && (d2>31 || d2<1)) || y2<2000 || m2>12 || m2<1 || y2>y1 || (y1==y2 && m2>m1) || (y1==y2 && m1==m2 && d2>d1) )
return 0;
else
{
while (y1!=y2 && m1!=m2 && d1!=d2)
{
while (next_day())
{
if (WorkDay( y1, m1, d1 ) == 1)
i=0;
x=i++;
}
}
*cnt=x;
return 1;
}
}
int main ( int argc, char * argv [] )
{
int cnt;
assert ( WorkDay ( 2016, 11, 11 ) );
assert ( ! WorkDay ( 2016, 11, 12 ) );
assert ( CountWorkDays ( 2016, 11, 1,
2016, 11, 30, &cnt ) == 1
&& cnt == 21 );
assert ( CountWorkDays ( 2001, 1, 1,
2015, 2, 29, &cnt ) == 0 );
return 0;
}
The problem is in next_day() and CountWorkDays().
next_day() is using local variables d1, m1 and y1. It is calculating next day of some random day.
In CountWorkDays(), you are not incrementing d1, m1, y1.
Solution:
Modify next_day() to receive a day as input and return next day as output.
int next_day(int *d, int *m, int *y)
{
/* Use current day to start. */
int y1 = *y;
int m1 = *m;
int d1 = *d;
/* Your code to find next day. Remove day_counter here as it is unnecessary.*/
/* Return next day. */
*y = y1;
*m = m1;
*d = d1;
return 0;
}
In CountWorkDays() call next_day with d1, m1, y1 as below.
else
{
while (1)
{
if (y1!=y2 && m1!=m2 && d1!=d2) //Check if end day is reached.
{
if (WorkDay( y1, m1, d1 ) == 1)
x++; //At the beginning initialize x to 0.
}
else
{
break;
}
next_day(&d1, &m1, &y1); //Get the next day.
}
}
int CountWorkDays(int y1, int m1, int d1, int y2, int m2, int d2, int * cnt)
{
int i, x;
if( (m1 == 1 && (d1>31 || d1<1)) || (m1 == 2 && (d1>29 || d1<1)) || (m1 == 3 && (d1>31 || d1<1)) || (m1 == 4 && (d1>30 || d1<1)) || (m1 == 5 && (d1>31 || d1<1)) || (m1 == 6 && (d1>30 || d1<1)) || (m1 == 7 && (d1>31 || d1<1)) || (m1 == 8 && (d1>31 || d1<1)) || (m1 == 9 && (d1>30 || d1<1)) || (m1 == 10 && (d1>31 || d1<1)) || (m1 == 11 && (d1>30 || d1<1)) || (m1 == 12 && (d1>31 || d1<1)) || y1<2000 || m1>12 || m1<1 ||
(m2 == 1 && (d2>31 || d2<1)) || (m2 == 2 && (d2>29 || d2<1)) || (m2 == 3 && (d2>31 || d2<1)) || (m2 == 4 && (d2>30 || d2<1)) || (m2 == 5 && (d2>31 || d2<1)) || (m2 == 6 && (d2>30 || d2<1)) || (m2 == 7 && (d2>31 || d2<1)) || (m2 == 8 && (d2>31 || d2<1)) || (m2 == 9 && (d2>30 || d2<1)) || (m2 == 10 && (d2>31 || d2<1)) || (m2 == 11 && (d2>30 || d2<1)) || (m2 == 12 && (d2>31 || d2<1)) || y2<2000 || m2>12 || m2<1 ||
y2>y1 || (y1 == y2 && m2>m1) || (y1 == y2 && m1 == m2 && d2>d1))
...
x++;
Your logic is wrong and redundant. You need to check only once if day is less than 1. You are checking at least 20 times. Then you check it again another 20 times in another function. You repeat that for d2. This makes your code unreadable and prone to errors.
Also you are not initializing variables. The starting value of x is undefined. Put int x = 0; and i = 0;
Later you have:
i=0;
x=i++;
You could rewrite this as x = 1. But you probably mean to write x++
Here it seems you are checking for holidays:
else if((
d == 1 && m == 1) ||
(d == 1 && m == 5) ||
(d == 8 && m == 5) ||
(d == 5 && m == 7) ||
(d == 6 && m == 7) ||
(d == 28 && m == 9) ||
(d == 28 && m == 10) ||
(d == 17 && m == 11) ||
(d == 24 && m == 12) ||
(d == 25 && m == 12) ||
(d == 26 && m == 12) ||
This type of coding is not wrong, but it's not practical either. I would put the holidays in a structure:
struct holidays_t
{
int day, month;
};
struct holidays_t holidays[] = {
{ 1 , 1 },
{ 1 , 5 },
...
};
Then loop through holidays array to see if the dates match. If you have not learned structures yet, then put the days and months in two different arrays. Example:
int holiday_days[]={1,1,...};
int holiday_months[]={1,5,...};
Your formula for weekday is wrong. You need to fix that.
#include <stdio.h>
#include <math.h>
int is_leap_year(int y)
{
return (y % 4) == 0 && y % 100 != 0 || (y % 400 == 0 && y != 4000);
}
int get_days_in_month(int year, int month)
{
const int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if(month >= 1 && month <= 12)
{
int days = days_in_month[month - 1];
if(month == 2 && is_leap_year(year))
days++;
return days;
}
return 0;
}
int is_date_valid(int year, int month, int day)
{
if(get_days_in_month(year, month) == 0) return 0;
return day >= 1 && day <= get_days_in_month(year, month);
}
//this is wrong: ***************************************************
int get_weekday(int y, int m, int d)
{
int h = (d + floor(((m + 1) * 26) / 10) + y + floor(y / 4) + 6 * floor(y / 100) + floor(y / 400));
int weekday = h % 7;
return weekday;
}
struct holidays_t
{
int day, month;
};
int is_holiday(int m, int d)
{
const struct holidays_t holidays[] = {
{ 1 , 1 },
{ 1 , 5 },
{ 8 , 5 },
{ 5 , 7 },
{ 6 , 7 },
{ 28, 9 },
{ 28, 10 },
{ 17, 11 },
{ 24, 12 },
{ 25, 12 },
{ 26, 12 },
};
int count = sizeof(holidays) / sizeof(holidays[0]);
int i;
for(i = 0; i < count; i++)
if(holidays[i].month == m && holidays[i].day == d)
return 1;
return 0;
}
int CountWorkDays(int y1, int m1, int d1, int y2, int m2, int d2, int *ptr)
{
int count = 0;
*ptr = 0;
if(!is_date_valid(y1, m1, d1)) return 0;
if(!is_date_valid(y2, m2, d2)) return 0;
int y, m, d;
for(y = y1; y <= y2; y++)
{
int month_start = 1;
int month_end = 12;
if(y == y1) month_start = m1;
if(y == y2) month_end = m2;
for(m = month_start; m <= month_end; m++)
{
int day_start = 1;
int day_end = get_days_in_month(y, m);
if(y == y1 && m == m1) day_start = d1;
if(y == y2 && m == m2) day_end = d2;
for(d = day_start; d <= day_end; d++)
{
int test = 0;
if(is_holiday(m, d))
{
test = 1;
printf("holiday %d %d %d\n", y, m, d);
}
int weekday = get_weekday(y, m, d);
if(weekday == 0 || weekday == 6)
{
test = 1;
printf("weekend %d %d %d %s\n", y, m, d, (weekday == 0) ? "sunday" : "staurday");
}
if(!test)
{
count++;
}
}
}
}
*ptr = count;
//return success
return 1;
}
int main()
{
int count = 0;
CountWorkDays(2016, 1, 1, 2016, 12, 31, &count);
printf("count %d\n", count);
return 0;
}

Tic Tac Toe AI error

char checkwinner(char ttt[][3]) {
char winner = 0;
for (int p = 0; winner == 0 && p < 2; p++) {
char XO = p == 0 ? 'x' : 'o';
for (int i = 0; winner == 0 && i < 3; i++) {
if (ttt[i][0] == XO && ttt[i][1] == XO && ttt[i][2] == XO)
winner = XO;
else
if (ttt[0][i] == XO && ttt[1][i] == XO && ttt[2][i] == XO)
winner = XO;
}
if (winner == 0 && ttt[0][0] == XO && ttt[1][1] == XO && ttt[2][2] == XO)
winner = XO;
else
if (winner == 0 && ttt[0][2] == XO && ttt[1][1] == XO && ttt[2][0] == XO)
winner = XO;
}
return winner;
}
int main (void) {
char b[3][3] = {{'1', '2', '3'},
{'4', '5', '6'},
{'7', '8', '9'}};
int turn = 0, i, j, loc, type, counter = 0;
char XO, AL;
char theChar = 'A';
char junk ='A';
printf("Type in 1 to play with AL, or 2 to play with another human\n");
scanf("%d", &type);
while (turn <= 9) {
char winner = checkwinner(b);
if (winner == 'x' || winner == 'o') {
printf("%c has won! You get 100 million DOGECOINS! Just enter your debt card information to our website, as well as your checking account and social security number. Go to www.THIS_IS_NOT_A_SCAM.com to get your dogecoins today!\n", winner);
return (0);
} else
if (((b[0][0] == 'x') || (b[0][0] == 'o'))
&& ((b[0][1] == 'x') || (b[0][1] == 'o'))
&& ((b[0][2] == 'x') || (b[0][2] == 'o'))
&& ((b[1][0] == 'x') || (b[1][0] == 'o'))
&& ((b[1][1] == 'x') || (b[1][1] == 'o'))
&& ((b[1][2] == 'x') || (b[1][2] == 'o'))
&& ((b[2][0] == 'x') || (b[2][0] == 'o'))
&& ((b[2][1] == 'x') || (b[2][1] == 'o'))
&& ((b[2][2] == 'x') || (b[2][2] == 'o'))) {
printf("This is a tie.\n");
return (0);
} //<---- missing brace!
if (type == 1) {
counter = counter + 1;
if (counter == 1) { XO = 'x'; }
if (counter == 2) { XO = 'o'; }
if (counter == 3) { XO = 'x'; }
if (counter == 4) { XO = 'o'; }
if (counter == 5) { XO = 'x'; }
if (counter == 6) { XO = 'o'; }
if (counter == 7) { XO = 'x'; }
if (counter == 8) { XO = 'o'; }
if (counter == 9) { XO = 'x'; }
}
if (type == 2) {
XO = 'x';
AL = 'o';
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
b[i][j] = AL;
printArray(b);
}
}
}
theChar = getchar();
putchar(theChar);
printf("Enter number: ");
scanf("%d", &loc);
j = (loc - 1) % 3;
i = (loc - 1) / 3;
if ((b[i][j] == 'x') || (b[i][j] == 'o')) {
printf("That spot has been taken!\n");
return (0);
}
putchar('\n');
junk = getchar();
b[i][j] = XO;
printArray(b);
}
}
void printArray(char thearray[3][3]) {
int i, j;
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
printf("%c ", thearray[i][j]);
}
printf("\n");
}
}
Right now I'm trying to finish the AI mode. Rather than just going and finding the first empty space and printing a single 'o' my game prints 9 boards like this:
o 2 3
4 5 6
7 8 9
o o 3
4 5 6
7 8 9
o o o
4 5 6
7 8 9
o o o
o 5 6
7 8 9
o o o
o o 6
7 8 9
o o o
o o o
7 8 9
o o o
o o o
o 8 9
o o o
o o o
o o 9
o o o
o o o
o o o
How do I get the game to stop after printing one 'o', and then letting 'x' pick a move? All help is appreciated.
Your code to find the place for AL to play is incorrect:
if (type == 2) {
XO = 'x';
AL = 'o';
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
b[i][j] = AL;
printArray(b);
}
}
}
You just play every spot on the grid and print it!
Try this instead:
if (type == 2) {
XO = 'x';
AL = 'o';
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
if (b[i][j] != 'x' && b[i][j] != 'o') {
b[i][j] = AL;
i = j = 2; /* ugly way to exit the nested loops */
}
}
}
printArray(b);
}
But this gaming strategy will be easy to beat!
Also you forget to increment turn, but if you did, you could replace the tedious test for a tie with a simple if (turn == 9).
EDIT: exiting from this nested loop requires more logic... it is better to move the AL game play to a separate function. Furthermore, your logic is flawed: you let AL play if type is 2 instead of 1...
Here is a simplified and corrected version that can play both sides:
#include <stdio.h>
char checkwinner(char b[3][3]) {
for (int i = 0; i < 3; i++) {
if (b[i][0] == b[i][1] && b[i][1] == b[i][2])
return b[i][0];
if (b[0][i] == b[1][i] && b[1][i] == b[2][i])
return b[0][i];
}
if ((b[0][0] == b[1][1] && b[1][1] == b[2][2])
|| (b[0][2] == b[1][1] && b[1][1] == b[2][0])) {
return b[1][1];
}
return 0;
}
void printArray(char b[3][3]) {
for (int i = 0; i < 3; i++) {
printf("%c %c %c\n", b[i][0], b[i][1], b[i][2]);
}
printf("\n");
}
void playAl(char b[3][3], char AL) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (b[i][j] != 'x' && b[i][j] != 'o') {
b[i][j] = AL;
return;
}
}
}
}
int main (void) {
char board[3][3] = {{'1', '2', '3'},
{'4', '5', '6'},
{'7', '8', '9'}};
int turn, i, j, loc, type;
printf("What does AL play? (0:none, 1:x, 2:o, 3:both) ");
scanf("%d", &type);
for (turn = 0;; turn++) {
printArray(board);
char winner = checkwinner(board);
if (winner == 'x' || winner == 'o') {
printf("%c has won! Game over\n", winner);
return 0;
}
if (turn == 9) {
printf("This is a tie.\n");
return 0;
}
char XO = "xo"[turn % 2];
if (type & (1 << (turn % 2))) {
/* AL's turn to play */
playAl(board, XO);
continue;
}
for (;;) {
printf("Enter number: ");
if (scanf("%d", &loc) != 1)
return 1;
j = (loc - 1) % 3;
i = (loc - 1) / 3 % 3;
if (board[i][j] != 'x' && board[i][j] != 'o')
break;
printf("This spot is already taken!, try again\n");
}
board[i][j] = XO;
}
}

Struggling programming TicTacToe in C

I'm new to C and programming and I tried to code a simple TicTacToe game. I new that I defintaly did many dumb things.
So I have a main .c file and two header files, which I will post here:
main.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "game.h"
#include "random.h"
#define NAMELENGTH 20
int main(void) {
char names[2][NAMELENGTH];
// field positions
char field[9];
int winner = -2;
getnames(names);
printf("\n\n");
initField(field);
// set field positions to 'empty'
char actualPlayer = (char)(get_random_number()*10.0) % 2;
while (1) {
drawField(field);
turn(actualPlayer, names, field);
winner = isWinner(actualPlayer, field);
drawField(field);
if (winner >= 0) {
printwinner(winner, names);
return 0;
}
else if (winner == -1) {
printDrawGame(names);
return 0;
}
actualPlayer = (actualPlayer + 1) % 2;
system("cls");
}
return 0;
}
game.h:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NAMELENGTH 20
#pragma warning(disable:4996)
void drawField(char *field) {
printf("________________________\n");
printf("| | | |\n");
printf("| %c | %c | %c |\n", field[1], field[2], field[3]);
printf("|_______|_______|______|\n");
printf("| | | |\n");
printf("| %c | %c | %c |\n", field[4], field[5], field[6]);
printf("|_______|_______|______|\n");
printf("| | | |\n");
printf("| %c | %c | %c |\n", field[7], field[8], field[9]);
printf("|_______|_______|______|\n");
}
void getnames(char nameField[][NAMELENGTH]) {
printf("Name of the first player: ");
scanf("%s", &nameField[0]);
printf("Name of the second player: ");
scanf("%s", &nameField[1]);
}
void initField(char *field) {
for (int i = 1; i < 10; i++)
{
field[i] = i+48;
}
}
void turn(char actualPlayer, char names[][NAMELENGTH], char *field) {
char symbol = ' ';
int k;
int m;
if (actualPlayer == 1)
{
do {
printf("\nIts Player %s's turn.", names[0]);
char symbol = 'X';
printf("\nNumber of the field which you want to put your symbol in: ");
scanf("%i", &k);
if (field[k] == 'X' || field[k] == 'O')
{
printf("\nField is already occupied!");
k = 10;
}
} while (k < 1 || k > 9);
field[k] = 'X';
}
else {
do {
printf("\nIts Player %s's turn.", names[1]);
char symbol = 'O';
printf("\nNumber of the field which you want to put your symbol in: ");
scanf("%i", &m);
if (field[m] == 'X' || field[m] == 'O')
{
printf("\nField is already occupied!");
m = 10;
}
} while (m < 1 || m > 9);
field[m] = 'X';
}
}
int isWinner(char actualPlayer, char *field) {
int w = 2;
if (((field[1] = 'O') && (field[2] = '0') && (field[3] = '0')) || (field[4] = '0') && (field[5] = '0') && (field[6] = '0') || (field[7] = '0') && (field[8] = '0') && (field[9] = '0') || (field[1] = '0') && (field[5] = '0') && (field[9] = '0') || (field[3] = '0') && (field[5] = '0') && (field[7] = '0') || (field[1] = '0') && (field[4] = '0') && (field[7] = '0') || (field[2] = '0') && (field[5] = '0') && (field[8] = '0') || (field[3] = '0') && (field[6] = '0') && (field[9] = '0'))
{
int w = 1;
}
if (((field[1] = 'X') && (field[2] = 'X') && (field[3] = 'X')) || (field[4] = 'X') && (field[5] = 'X') && (field[6] = 'X') || (field[7] = 'X') && (field[8] = 'X') && (field[9] = 'X') || (field[1] = 'X') && (field[5] = 'X') && (field[9] = 'X') || (field[3] = 'X') && (field[5] = 'X') && (field[7] = 'X') || (field[1] = 'X') && (field[4] = 'X') && (field[7] = 'X') || (field[2] = 'X') && (field[5] = 'X') && (field[8] = 'X') || (field[3] = 'X') && (field[6] = 'X') && (field[9] = 'X'))
{
int w = 0;
}
else
{
int w = -1;
}
return w;
}
void printwinner(char winnerNumber, char names[][NAMELENGTH]) {
if (winnerNumber == 0)
{
printf("Player %s won!", names[0]);
system("exit");
}
else if (winnerNumber == 1)
{
printf("Player %s won!", names[1]);
system("exit");
}
}
void printDrawGame(char names[][NAMELENGTH]) {
printf("Draw!");
system("exit");
}
and random.h:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
static int _initialized;
void init() {
srand(time(NULL));
_initialized = 1;
}
double get_random_number() {
init();
if (!_initialized)
printf("Warning: init() should be called first!\n");
double random;
random = (double)rand() / ((double)(RAND_MAX)+1);
return random;
}
So the Program itself runs till I type in which field I want to put in the symbol. I get a weird error ("Stack around the variable 'field' was corrupted.") and also the random function doesnt work like I want. Would be happy and thankful for you help guys :)
You declared field to be an array of 9 elements. The indices will be 0 to 8. In game.h you have a function initField in which you do:
for (int i = 1; i < 10; i++)
{
field[i] = i+48;
}
This will produce indices 1 to 9, which steps out of bounds for the array.
You reinitialize the random number generator each time it is called. You pseudo random values will not be very random I'm afraid.
Fix it this way:
static int _initialized;
double get_random_number() {
if (!_initialized) {
srand(time(NULL));
_initialized = 1;
}
return = (double)rand() / ((double)(RAND_MAX)+1);
}
You should not write code in header files. Declarations belong in header files, code belongs in source files with the extension .c.

Occupied Position in Tic-Tac-Toe Game [C]

One question about this code: if the choice the player picks is already taken, how do I make him/her choose again?
If I compile the code now, it will change the the position for the one the user chose, and this can't happen.
Obs: the "drawing" of the tic-tac-toe game should appear before this ("\nInform your choice (1-9): ")
This is the code:
char mat[9];
int main(void)
{
int i,jogada,casa,jogo=0;
for(i=0; i<= 9; i++)
mat[i] = ' ';
do{
printf("\n");
printf("\t|\t|\n");
printf("\t|\t|\n");
printf("%c\t|%c\t|%c\n",mat[1],mat[2],mat[3]);
printf("--------|-------|-------\n");
printf("\t|\t|\n");
printf("%c\t|%c\t|%c\n",mat[4],mat[5],mat[6]);
printf("--------|-------|-------\n");
printf("\t|\t|\n");
printf("\t|\t|\n");
printf("%c\t|%c\t|%c\n\n",mat[7],mat[8],mat[9]);
printf("\nJOGADOR X ");
printf("\nInforme uma posicao livre (1-9): ");
scanf("%d",&casa);
}while((casa>=1)&&(casa<=9));
if((casa>=1)&&(casa<=9))
{
if(mat[casa] == 'X' || mat[casa] == 'O')
printf(" ");
else
mat[casa] = 'X';
}
printf("\n");
printf("\t|\t|\n");
printf("\t|\t|\n");
printf("%c\t|%c\t|%c\n",mat[1],mat[2],mat[3]);
printf("--------|-------|-------\n");
printf("\t|\t|\n");
printf("%c\t|%c\t|%c\n",mat[4],mat[5],mat[6]);
printf("--------|-------|-------\n");
printf("\t|\t|\n");
printf("\t|\t|\n");
printf("%c\t|%c\t|%c\n\n",mat[7],mat[8],mat[9]);
if(mat[1] != ' ' && mat[1] == mat[2] && mat[2] == mat[3]) {
jogo++;
printf("X Ganhou!\n");
break; }
else if(mat[4] != ' ' && mat[4] == mat[5] && mat[5] == mat[6]) {
printf("X Ganhou!\n");
jogo++;
break; }
else if(mat[7] != ' ' && mat[7] == mat[8] && mat[8] == mat[9]) {
printf("X Ganhou!\n");
jogo++;
break; }
else if(mat[1] != ' ' && mat[1] == mat[4] && mat[4] == mat[7]) {
printf("X Ganhou!\n");
jogo++;
break;}
else if(mat[2] != ' ' && mat[2] == mat[5] && mat[5] == mat[8]) {
printf("X Ganhou!\n");
jogo++;
break; }
else if(mat[3] != ' ' && mat[3] == mat[6] && mat[6] == mat[9]) {
printf("X Ganhou!\n");
jogo++;
break; }
else if(mat[1] != ' ' && mat[1] == mat[5] && mat[5] == mat[9]){
printf("X Ganhou!\n");
jogo++;
break;}
else if(mat[7] != ' ' && mat[7] == mat[5] && mat[5] == mat[3]) {
printf("X Ganhou!\n");
jogo++;
break; }
else if((mat[1] != ' ') && (mat[2] != ' ') && (mat[3] != ' ') && (mat[4] != ' ') && (mat[5] != ' ') && (mat[6] != ' ') && (mat[7] != ' ') && (mat[8] != ' ') && (mat[9] = ' ')){
printf("Velha!\n");
jogo++;
break;
}
printf("\nJOGADOR O ");
printf("\nInforme uma posicao livre (1-9): ");
scanf("%d",&casa);
if((casa>=1)&&(casa<=9))
{
if(mat[casa] == 'X' || mat[casa] == 'O')
;
else
mat[casa] = 'O';
}
printf("\n");
printf("\t|\t|\n");
printf("\t|\t|\n");
printf("%c\t|%c\t|%c\n",mat[1],mat[2],mat[3]);
printf("--------|-------|-------\n");
printf("\t|\t|\n");
printf("%c\t|%c\t|%c\n",mat[4],mat[5],mat[6]);
printf("--------|-------|-------\n");
printf("\t|\t|\n");
printf("\t|\t|\n");
printf("%c\t|%c\t|%c\n\n",mat[7],mat[8],mat[9]);
if(mat[1] != ' ' && mat[1] == mat[2] && mat[2] == mat[3]) {
printf("O Ganhou!\n");
jogo++;
break; }
else if(mat[4] != ' ' && mat[4] == mat[5] && mat[5] == mat[6]) {
printf("O Ganhou!\n");
jogo++;
break; }
else if(mat[7] != ' ' && mat[7] == mat[8] && mat[8] == mat[9]) {
printf("O Ganhou!\n");
jogo++;
break; }
else if(mat[1] != ' ' && mat[1] == mat[4] && mat[4] == mat[7]) {
printf("O Ganhou!\n");
jogo++;
break; }
else if(mat[2] != ' ' && mat[2] == mat[5] && mat[5] == mat[8]) {
printf("O Ganhou!\n");
jogo++;
break;}
else if(mat[3] != ' ' && mat[3] == mat[6] && mat[6] == mat[9]) {
printf("O Ganhou!\n");
jogo++;
break; }
else if(mat[1] != ' ' && mat[1] == mat[5] && mat[5] == mat[9]){
printf("O Ganhou!\n");
jogo++;
break;}
else if(mat[7] != ' ' && mat[7] == mat[5] && mat[5] == mat[3]) {
printf("O Ganhou!\n");
jogo++;
break; }
else if((mat[1] != ' ') && (mat[2] != ' ') && (mat[3] != ' ') && (mat[4] != ' ') && (mat[5] != ' ') && (mat[6] != ' ') && (mat[7] != ' ') && (mat[8] != ' ') && (mat[9] = ' ')){
printf("Velha!\n");
jogo++;
break;
}
}
system("PAUSE");
return 0;
}
If the choice the player picks is already taken, how do I make him/her choose again?
Change your scanf() in 2 locations (X and O)
do {
printf("\nInforme uma posicao livre (1-9): ");
scanf("%d",&casa);
} while( (casa<1) || (casa>9) || (mat[casa] != ' ') );
You do have a bigger problem.
Change char mat[9] to char mat[10]. You are indexing your mat[] from 1 to 9 throughout your code. But char mat[9] only allows mat[0] to mat[8]. The quick fix is to make mat[] 1 char longer and not use mat[0]. Leave for(i=0; i<= 9; i++) as is.
OR -
A proper fix would be to keep char mat[9] and change all the many mat[i] references to mat[i-1]. e.g. mat[5] becomes mat[4]. Change to for(i=0; i < 9; i++).

Resources