Declaring winner in tic tac toe board - c

I wrote a code for a tic tac toe problem where you input the numbers into the array and the board will be printed out. There is also a function that declares the winner, but doesn't seem to be working, the function is supposed to declares the winner for any size of a tic tac toe board (right now it is 5x5).
I did a double for loop with it checking if the character is the same in the array as next to it so it moves along the rows, there's another for columns, one diagonal and the other. For some reason it isn't showing any winners, no winners always comes up. Any help is appreciated.
#include <stdio.h>
#define TRUE 1
#define FALSE 0
#define SIZE 3
#define NONE -1
#define NOUGHTS 0
#define CROSSES 1
#define EMPTY 2
void scanBoard(int board[SIZE][SIZE]);
void printBoard(int board[SIZE][SIZE]);
int getWinner(int board[SIZE][SIZE]);
int main( void ){
int board[SIZE][SIZE];
int winner;
printf("Please enter the board:\n");
scanBoard( board );
printf("Here is the board:\n");
printBoard( board );
printf("The winner is: ");
winner = getWinner(board);
if(winner == CROSSES){
printf("Crosses");
}
else if(winner == NOUGHTS){
printf("Noughts");
}
else{
printf("No one");
}
return 0;
}
void scanBoard(int board[SIZE][SIZE]){
int i;
int j;
for(i=0; i<SIZE; i++){
for(j=0; j<SIZE; j++){
scanf("%d", &board[i][j]);
}
}
}
void printBoard(int board[SIZE][SIZE]){
int i;
int j;
for(i=0; i<SIZE; i++){
for(j=0; j<SIZE; j++){
if(board[i][j] == EMPTY){
printf(". ");
}
else if(board[i][j] == CROSSES){
printf("X ");
}
else if(board[i][j] == NOUGHTS){
printf("O ");
}
}
printf("\n");
}
}
int getWinner(int board[SIZE][SIZE]){
int i;
int j;
int check;
int winner;
for(i=0; i<SIZE; i++){
for(j=0; j<SIZE-1 && check == TRUE; j++){
if(board[i][j] != board[i][j+1]){
check = FALSE;
}
}
if(check == TRUE && j == SIZE-1){
winner=board[i][0];
}
}
for(j=0; j<SIZE; j++){
for(i=0; i<SIZE-1 && check == TRUE; i++){
if(board[i][j] != board[i+1][j]){
check = FALSE;
}
}
if(check == TRUE && i == SIZE-1){
winner=board[0][j];
}
}
for(i=0; i<SIZE-1 && check == TRUE; i++){
if(board[i][i] != board[i+1][i+1]){
check = FALSE;
}
if(check == TRUE && i == SIZE-1){
winner=(board[i][i]);
}
}
for(i=SIZE; i>0 && check == TRUE; i--){
if( board[i][i] != board[i-1][i-1])
check = FALSE;
}
if(check == TRUE && i == SIZE-1){
winner=(board[i][i]);
}
return winner;
}

I did not go completely through your checking logic but here directly in getWinner, you are trigerring undefined behaviour:
for(j=0; j<SIZE-1 && check == TRUE; j++){
by reading check variable which has not been initialized (result of this is that any kind of behaviour can happen). So you may want to initialize it to default value first.
There are some implementationos of that game around, I suggest you look at some similar implementation and compare against your winner checking logic for example.

As Giorgi pointed out, you have to initialize check before you start testing its value. You also need to initialize winner to EMPTY at the start of the getWinner() function, otherwise if there is no winner, your function will return some unpredictable junk value and your main() function will probably print out the wrong result.
int getWinner(int board[SIZE][SIZE]){
int i;
int j;
int check;
int winner=EMPTY /* <<< */;
for(i=0; i<SIZE; i++){
for(j=0, check=TRUE /* <<< */; j<SIZE-1 && check == TRUE; j++){
if(board[i][j] != board[i][j+1]){
check = FALSE;
}
}
if(check == TRUE && j == SIZE-1){
winner=board[i][0];
}
}
for(j=0; j<SIZE; j++){
for(i=0, check=TRUE /* <<< */; i<SIZE-1 && check == TRUE; i++){
if(board[i][j] != board[i+1][j]){
/** etc... **/
(Note: There's also no need to continue checking once you've found a winner, so perhaps instead of winner=board[i][j]; you could just return board[i][j];. Not a big deal, though.)
You are also checking one of the diagonals twice (in two different directions). The other diagonal isn't being checked at all.

Related

Dynamically Allocating Memory In

I created the four in a row game in c. Now I want to dynamically allocate the memory of the board. It is a two-dimensional array and I want it stored there for use. I declare it as a global double-pointer and declare it in my initialization method in the code below. I am new to c and I'm not entirely sure how to go about handling the segmentation fault(core dumped) error that I get.
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define MAX 50
//size of board
#define rows 6
#define column 7
//player's name
char player1[100];
char player2[100];
//pointer to keep track of playes turn
char *playersTurn;
//counter to keep track of where we are on each column
int a = rows - 1;
int b = rows - 1;
int c = rows - 1;
int d = rows - 1;
int e = rows - 1;
int f = rows - 1;
int g = rows - 1;
//array of the board
//int board[rows][column];
int **board;
//boardlaying array elements
void boardlayArray(){
printf("Two Dimensional array elements:\n");
for(int i=0; i<rows; i++) {
for(int j=0;j<column;j++) {
printf("%d ", board[i][j]);
if(j==6){
printf("\n");
}
}
}
}
//recostruct board to empty places
void teardown(){
/*Counter variables for the loop*/
int i, j;
for(int i=0; i<rows; i++) {
for(int j=0;j<column;j++) {
board[i][j]=0;
}
}
boardlayArray();
}
//checks if the four in a row are the same
int checkFour(int a, int b, int c, int d){
return a == b && b == c && c == d;
}
//check for the horizontal win
void checkHorizontal(int player){
for(int i=0; i < rows; i++){
for(int j=0; j < column - 3; j++){
if ((board[i][j] != 0) && (board[i][j+1] != 0) && (board[i][j+2]!= 0) && (board[i][j+3] != 0)){
if (checkFour(board[i][j],board[i][j+1],board[i][j+2],board[i][j+3]) == 1){
printf("Game Over\n");
exit(0);
}
}
}
}
}
//check for vertical win
void checkVertical(int player){
for(int j=0; j < column; j++){
for(int i=rows - 1; i > rows - 3; i--){
if ((board[i][j] != 0) && (board[i-1][j] != 0) && (board[i-2][j]!= 0) && (board[i-3][j] != 0)){
if (checkFour(board[i][j],board[i-1][j],board[i-2][j],board[i-3][j]) == 1){
printf("Game Over\n");
exit(0);
}
}
}
}
}
//check for diagonal win
void checkDiagonal (int player){
// ascendingDiagonalCheck
for (int i=3; i<column; i++){
for (int j=0; j<rows-3; j++){
if ((board[i][j] != 0) && (board[i-1][j+1] != 0) && (board[i-2][j+2]!= 0) && (board[i-3][j+3] != 0)){
if (checkFour(board[i][j],board[i-1][j+1],board[i-2][j+2],board[i-3][j+3]) == 1){
printf("Game Over\n");
exit(0);
}
}
}
}
// descendingDiagonalCheck
for (int i=3; i<column; i++){
for (int j=3; j<rows; j++){
if ((board[i][j] != 0) && (board[i-1][j-1] != 0) && (board[i-2][j-2]!= 0) && (board[i-3][j-3] != 0)){
if (checkFour(board[i][j],board[i-1][j-1],board[i-2][j-2],board[i-3][j-3]) == 1){
printf("Game Over\n");
exit(0);
}
}
}
}
}
//places the players puck into the correct place and gives it a corresponding value
//Also checks and correspondingly updtaes the turn to same player if row is full
int updateWorld(char w, int playerNumber){
switch(w)
{
case 'A':
if(a == -1){
printf("This row is full\n");
return 0;
}
board[a][0] = playerNumber;
a--;
break;
case 'B' :
if(b == -1){
printf("This row is full\n");
return 0;
}
board[b][1] = playerNumber;
b--;
break;
case 'C' :
if(c == -1){
printf("This row is full\n");
return 0;
}
board[c][2] = playerNumber;
c--;
break;
case 'D' :
if(d == -1){
printf("This row is full\n");
return 0;
}
board[d][3] = playerNumber;
d--;
break;
case 'E' :
if(e == -1){
printf("This row is full\n");
return 0;
}
board[e][4] = playerNumber;
e--;
break;
case 'F' :
if(a == -1){
printf("This row is full\n");
return 0;
}
board[f][5] = playerNumber;
f--;
break;
case 'G' :
if(g == -1){
printf("This row is full\n");
return 0;
}
board[g][6] = playerNumber;
g--;
break;
case ' ' : printf("Nothing was entered\n");
break;
case 'Q' : printf("%s has quit game\n", playersTurn);
teardown();
exit(0);
break;
default: printf("Enter a wrong option\n");
}
boardlayArray();
checkHorizontal(playerNumber);
checkVertical(playerNumber);
checkDiagonal(playerNumber);
return 1;
}
//get player's names and dynamicaaly allocate memory for board
void initialization(){
printf("Enter the name of player 1:\n");
fgets(player1,MAX, stdin);
printf("Enter the name of player 2:\n");
fgets(player2,MAX, stdin);
board = (int **)malloc(rows * sizeof(int *));
for (int i=0; i<rows; i++)
board[i] = (int *)malloc(column * sizeof(int));
}
//get where player wants to play
char acceptInput(){
printf("Enter where you want to put the disc A-G. Enter Q if you want to quit.\n");
char w;
scanf("%[^\n]",&w);
return w;
}
int main(){
initialization();
char w;
//runs for the size of the board
for(int i = 1; i <= (rows * column); i++){
w = acceptInput();
w = toupper(w);
if(i%2 == 0){
playersTurn = (char*) player2;
if(updateWorld(w,2) == 0){
playersTurn = (char*) player1;
printf("%s won the game",playersTurn);
exit(0);
}
}
else{
playersTurn = (char*) player1;
if(updateWorld(w,1) == 0){
playersTurn = (char*) player2;
printf("%s won the game",playersTurn);
exit(0);
}
}
while(getchar() != '\n');
}
return 0;
}
How About using the heap?? That's the goto of a programmer for dynamic memory allocation , here is a simple 2d array allocation code :
int main()
{
int r = 3, c = 4, i, j, count;
int *arr[r];
//allocating memory for an array
for (i=0; i<r; i++)
arr[i] = (int *)malloc(c * sizeof(int));
/*code to debug */
//free memory before allocating again
for(i=0; i<r; i++)
free(arr[i]);
//reallocating memory for an array
for(i=0; i<r+2; i++)
arr[i] = (int *)malloc(c * sizeof(int));
return 0;
/* code to work on reallocated array */
}

How to check whether any data is provided in array or not in C?

I am making a program that sorts integers in ascending and descending order through bubble sort algorithm in C. So, I am providing a random data of 20 integers(fixed)first and then deciding in which manner to sort it, which is basically done through simple menu system which is like:
A. provide random data
B. Sort high to low
C. Sort low to high
*I want to print a message "Data not provided" if the user tries to sort without getting the random data first.
Code below:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void random_number_list(int array[]);
void low_to_high(int array[]);
void high_to_low(int array[]);
void display(int array[]);
int main(void)
{
int original_array[21];
char selection;
do
{
puts("----> Please make your selection from the following:\n\n"
" A.Define Random Number List\n"
" B.Sort Number List(High to Low)\n"
" C.Sort Number List(Low to High)\n"
" D.Exit ");
printf_s(" \nYour selection: ");
scanf_s("\n%c", &selection);
if (selection == 'A' || selection == 'a')
{
random_number_list(original_array);
}
else if (selection == 'B' || selection == 'b')
{
high_to_low(original_array);
}
else if (selection == 'C' || selection == 'c')
{
low_to_high(original_array);
}
else if (selection == 'D' || selection == 'd')
{
puts("\nThank you for using the application.\n");
return 0;
}
else
{
puts("\nSorry, input not understood. Please try again.\n");
}
}
while (selection != 'D');
}
void random_number_list(int array[])
{
srand(time(NULL));
printf("\n\nThe Random Data: ");
for (size_t i = 0; i < 20; i++)
{
array[i] = 1 + rand() % 100;
printf_s("%d,", array[i]);
}
puts("\n\n");
}
void low_to_high(int array[])
{
int i, j, temp;
for (i = 0;i < 20 - 1;i++)
{
for (j = i + 1;j < 20;j++)
{
if (array[i] > array[j])
{
temp = array[i];
array[i] = array[j];
array[j] = temp;
display(array);
printf("\n");
}
}
}
printf_s("\nSorted Data : ");
display(array);
puts("\n");
}
void high_to_low(int array[])
{
int i, j, temp;
for (i = 0; i < 20 - 1; i++)
{
for (j = i + 1; j < 20; j++)
{
if (array[i] < array[j])
{
temp = array[i];
array[i] = array[j];
array[j] = temp;
display(array);
printf("\n");
}
}
}
printf_s("\nSorted Data : ");
display(array);
puts("\n");
}
void display(int array[])
{
for (size_t i = 0; i < 20; i++)
{
printf("%d,", array[i]);
}
}
What about using a boolean flag indicating whether option A was called? Initialize that flag with false and set it true in option A. Then in options B and C, test if the flag is true. If false, complain.
Showing us the code you have so far would be helpful.
I would include stdbool.h and create a boolean variable in the main function called something like is_generated set to false by default and set it to true when the option A is entered. Then you can check it instead of checking if original_array is equal to zero.
You can use the sizeof operator and divide the result by the size of an element.
size_t n = sizeof your_array

Final bits on my Game Of Life program. Seemingly random results

So I think I'm nearly done on my game of life program, yet each pass of a grid is not how it should be, even though I feel I've implemented the rules correctly (see golRules).
Since our assignment has to be submitted with a specific input, the input is as follows:
rows columns steps
[Starting grid]
So an example input would be:
6 6 20
.X...X
X.X.X.
X...X.
X..XX.
..XX.X
...X.X
Yet my the first step of this particular example returns
X..X.X
XX...X
XX....
X..X..
.....X
.....X
If you're familiar with the game of life you'll notice this is totally wrong. I have a feeling in the golRules function when generating the next grid, its updating a specific element one by one, instead of all at the end.
Anyone lend a guy a hand please?
#include <stdio.h>
int neighbourCount(int m, int n, char grid[m][n]){
int count = 0;
if(grid[m-1][n-1] == 'X') {
count++;
}
if(grid[m-1][n] == 'X') {
count++;
}
if(grid[m-1][n+1] == 'X') {
count++;
}
if(grid[m][n-1] == 'X') {
count++;
}
if(grid[m][n+1] == 'X') {
count++;
}
if(grid[m+1][n-1] == 'X') {
count++;
}
if(grid[m+1][n] == 'X') {
count++;
}
if(grid[m+1][n+1] == 'X') {
count++;
}
return count;
}
void printGrid(int m, int n, char grid[m][n]) {
int i, j;
for(i=0; i<m; i++) {
for(j=0;j<n;j++) {
printf("%c", grid[i][j]);
if(j==m - 1){
printf("\n");
}
}
}
printf("\n");
}
void golRules(int m, int n, char grid[m][n]) {
int i;
int j;
int neighbour;
for(i=0; i<m; i++) {
for(j=0;j<n;j++) {
neighbour = neighbourCount(i, j, grid);
if(neighbour == 3) {
grid[i][j] = 'X';
}else if(neighbour == 2 && grid[i][j] =='X') {
grid[i][j] = 'X';
}else {
grid[i][j] = '.';
}
}
}
}
int main(){
int row;
int column;
int steps;
scanf("%d %d %d", &row, &column, &steps);
char grid[row][column];
int i, j;
for(i=0; i<row; i++) {
for(j=0;j<column;j++) {
scanf(" %c", &grid[i][j]);
}
}
printGrid(row, column, grid);
for(i=0; i<steps; i++) {
golRules(row, column, grid);
printGrid(row, column, grid);
}
}
As one of the comments points out, you will have to calculate the new cell values from the original one for all cells. So you will have to implement some kind of "shadow-grid", which, when fully calculated, is copied over the original grid:
void golRules(int m, int n, char grid[m][n]) {
char shadowgrid[m][n]
int i;
int j;
int neighbour;
for(i=0; i<m; i++) {
for(j=0;j<n;j++) {
neighbour = neighbourCount(i, j, grid);
if(neighbour == 3) {
shadowgrid[i][j] = 'X';
} else if(neighbour == 2 && grid[i][j] =='X') {
shadowgrid[i][j] = 'X';
} else {
shadowgrid[i][j] = '.';
}
}
}
memcpy(grid, shadowgrid, sizeof(shadowgrid));
}
This should work as you expect.

NULL confusion in C

I am creating a simple "ascending" program. When I find smallest int in array of int I want to replace it with some other value so it won't come as smallest number again in the array. For that, I assigned that int NULL. But now the results are not as expected.
Please tell me if I am doing anything wrong. If so then what I should replace with the value of that int ?
#include<stdio.h>
#include<conio.h>
void main()
{
clrscr();
int a[10],b,c=0,d=0;
printf("Enter number of values you want to enter \n");
scanf("%d",&b);
printf("Enter values \n");
for(int i=0;i<b;i++)
scanf("%d",&a[i]);
while(c<b)
{
for(int k=0;k<b;k++)
{
for(int j=0;j<b;j++)
{
if(a[k] > a[j])
{
d=1;
}
}
if(d!=1 && a[k]!=NULL)
{
c++;
printf("%d ",a[k]);
a[k]='\0' ; //assigning it as NULL
}
if(c >= b)
break;
d=0;
}
}
getch();
}
In C and related languages ints are not "nullable" - you could use a special value instead, e.g. a value that is well outside the expected range of your input data, such as INT_MAX:
#include <limits.h> // required header for INT_MAX et al
...
if(d!=1 && a[k]!=INT_MAX)
{
c++;
printf("%d ",a[k]);
a[k]=INT_MAX
}
However it would probably be a good idea to go back to the drawing board and see if you can come up with a better algorithm that doesn't require special values.
Read the differences between NULL and 0 and '\0' here. There is a type mismatch when you're trying a[k]!=NULL.
#include<stdio.h>
#include<conio.h>
int main()
{
clrscr();
int a[10], b, c = 0, d = 0;
int k, j, i;
printf("Enter number of values you want to enter \n");
scanf("%d",&b);
printf("Enter values \n");
for(i = 0;i < b;i++)
scanf("%d",&a[i]);
while(c < b)
{
for(k = 0;k < b;k++)
{
for(j = 0;j < b;j++)
{
if((a[k] > a[j]) && a[j] != 0)
{
d=1;
}
}
if(d != 1 && a[k] != 0)
{
c++;
printf("%d ",a[k]);
a[k] = 0; //assigning it as NULL
}
if(c >= b)
break;
d=0;
}
}
return 0;
getch();
}
This code fixes the problem.
What you're missing is a[j] != 0 in if((a[k] > a[j]) && a[j] != 0). Also I don't suggest this, as it won't work if there are 0's in the array entered.

Program that finds the biggest space between two appears of the entered character

So I made a program and it doesn't work right, and I wanted to see if anyone can help me. Maybe even the idea is not right, I'm not sure.
It should find the biggest space between two appears of the provided character, and print it, or if that character doesn't appear at least 2 times, print 0.
#include <stdio.h>
main()
{
int i=0,k=0,max,a[50],j;
char n,c;
printf("Insert the character:\n");
scanf("%c",&n);
while ((c=getchar()) != EOF)
{
if (c==n)
{
c=getchar();
while (c != n)
{
k++;
c=getchar();
}
a[i]=k;
k=0;
i++;
}
}
max=a[0];
for (j=1; j<i; j++)
if (a[j]>max) max=a[j];
if (max>=2) printf("%d\n",max);
else printf("0\n");
}
Initialize max and a[0].
Check for EOF in inner while loop.
#include <stdio.h>
int main()
{
int i=0,k=0,max,a[50],j;
char n,c;
a[0] = 0; // Initialize a[0]
max = 0; // Initialize max
printf("Insert the character:\n");
scanf("%c",&n);
int end_reached = 0;
while ((c=getchar()) != EOF)
{
if (c==n)
{
c=getchar();
while (c != n)
{
if(c == EOF) { // Check for EOF
end_reached = 1;
break;
}
k++;
c=getchar();
}
if(!end_reached) { // Store k in a only if end was not reached.
a[i]=k;
k=0;
i++;
}
}
}
max=a[0];
for (j=1; j<i; j++)
if (a[j]>max)
max=a[j];
if (max>=2)
printf("%d\n",max);
else
printf("0\n");
}

Resources