I am trying to make a Tic-Tac-Toe game. I have written the code which I believe should work fine, but instead it is throwing logical errors.
#include <stdio.h>
#define size 9
char game_logic();
int game_win();
char array[size] = { '1', '2', '3', '4', '5', '6', '7', '8', '9' };
int main()
{
printf("\n\t\t Welcome to Tic-Tac-Toe game\n\n");
printf(" In this game, there will be two players taking turns for their moves\n\n");
printf("\t\t Player 1 = 'X' and Player 2 = 'O'\n\n");
for (int i = 0; i < size; i++)
{
printf("\t%c", array[i]);
if (array[i] == '1' || array[i] == '2' || array[i] == '4' ||
array[i] == '5' || array[i] == '7' || array[i] == '8')
{
printf(" |");
}
if (array[i] == '3' || array[i] == '6')
{
printf("\n -----------------------\n");
}
}
printf("\n\n");
do
{
game_logic();
} while (game_win() != 1 || game_win() != 2 || game_win != 3);
if (game_win() == 1)
{
printf("\nThe Player 1 has won the game\n");
}
else if (game_win() == 2)
{
printf("\nThe Player 2 has won the game\n");
}
else if (game_win() == 3)
{
printf("\nThe game is draw\n");
}
return 0;
}
char game_logic()
{
int n, m;
for (int i = 0; i < size; i++)
{
if (i % 2 == 0)
{
printf("Player 1, Please select the number = ");
scanf("%d", &n);
if (n > 0 && n < 10)
{
array[n] = 'X';
return array[n];
break;
}
}
else if (i % 2 != 0)
{
printf("Player 2, Please select the number = ");
scanf("%d", &m);
if (n > 0 && n < 10)
{
array[n] = 'O';
return array[n];
break;
}
}
}
}
int game_win()
{
game_logic();
if (array[0] == array[1] == array[2] == 'X' ||
array[2] == array[5] == array[8] == 'X' ||
array[6] == array[7] == array[8] == 'X' ||
array[0] == array[3] == array[6] == 'X' ||
array[0] == array[4] == array[8] == 'X' ||
array[2] == array[4] == array[6] == 'X' ||
array[1] == array[4] == array[7] == 'X' ||
array[3] == array[4] == array[5] == 'X')
{
return 1;
}
else
if (array[0] == array[1] == array[2] == 'O' ||
array[2] == array[5] == array[8] == 'O' ||
array[6] == array[7] == array[8] == 'O' ||
array[0] == array[3] == array[6] == 'O' ||
array[0] == array[4] == array[8] == 'O' ||
array[2] == array[4] == array[6] == 'O' ||
array[1] == array[4] == array[7] == 'O' ||
array[3] == array[4] == array[5] == 'O')
{
return 2;
}
else
{
return 3;
}
}
The basic plan was to execute game_logic which will decide how the game will run, it will take input from the user in the form of integers between 1 and 9. The number selected by the user will be replaced by X in the global array if player 1 inputs it, and will be replaced by O if player 2 selects it.
The results of game_logic is to be sent to the game_win which will determine if the game has been won or not by returning the values to the main function.
But when I ran the code, a loop occurs which says "Player 1, Please select the number = ", and this keeps on going by taking infinite input.
I have tried debugging it, but it is unable to help me. So can please suggest solutions for the logic made, or if my logic is correct.
The output:
Welcome to Tic-Tac-Toe game
In this game, there will be two players taking turns for their moves
Player 1 = 'X' and Player 2 = 'O'
1 | 2 | 3
-----------------------
4 | 5 | 6
-----------------------
7 | 8 | 9
Player 1, Please select the number = 3
Player 1, Please select the number = 2
Player 1, Please select the number = 3
Player 1, Please select the number = 4
Player 1, Please select the number = 3
Player 1, Please select the number = 2
Player 1, Please select the number = 2
Player 1, Please select the number = 3
Player 1, Please select the number = 4
and this keeps on going.
There are at least these major problems:
the test in the do ... while loop is incorrect: the loop iterates while (game_win() != 1 || game_win() != 2 || game_win != 3)... the third test compare the function name with 3 not return value of the function call, and even if you fix this problem, the test is always true since game_win() cannot be both 1 and 2 and 3. You should instead write:
do {
game_logic();
} while (game_win() != 0);
the tests in game_win() are incorrect: array[0] == array[1] == array[2] == 'X' should be written:
(array[0] == 'X' && array[1] == 'X' && array[2] == 'X')
game_win() does not properly test for a draw and never returns 0 in other cases.
if you call game_logic() in the loop, game_win() should not also call game_logic(). It would make sense for game_logic() to return the game_win() result, which would simplify the loop as:
while (game_logic())
continue;
the slot modified in game_logic() is incorrect: the number n is between 1 and 9, but the array elements start at 0 so you should modify array[n - 1].
the slot for player 2 is read into m, whereas the code uses n afterwards.
it would be more user friendly to redisplay the board before each turn.
Here is a modified version:
#include <stdio.h>
#define SIZE 9
int game_win(void);
int game_logic(int i);
char array[SIZE] = { '1', '2', '3', '4', '5', '6', '7', '8', '9' };
void display_board(void) {
printf("\n ");
for (int i = 1; i <= SIZE; i++) {
printf(" %c", array[i - 1]);
if (i == 1 || i == 2 || i == 4 || i == 5 || i == 7 || i == 8) {
printf(" |");
}
if (i == 3 || i == 6) {
printf("\n -----------------------\n ");
}
}
printf("\n\n");
}
int game_win(void) {
if ((array[0] == 'X' && array[1] == 'X' && array[2] == 'X') ||
(array[3] == 'X' && array[4] == 'X' && array[5] == 'X') ||
(array[6] == 'X' && array[7] == 'X' && array[8] == 'X') ||
(array[0] == 'X' && array[3] == 'X' && array[6] == 'X') ||
(array[1] == 'X' && array[4] == 'X' && array[7] == 'X') ||
(array[2] == 'X' && array[5] == 'X' && array[8] == 'X') ||
(array[0] == 'X' && array[4] == 'X' && array[8] == 'X') ||
(array[2] == 'X' && array[4] == 'X' && array[6] == 'X')) {
return 1;
}
if ((array[0] == 'O' && array[1] == 'O' && array[2] == 'O') ||
(array[3] == 'O' && array[4] == 'O' && array[5] == 'O') ||
(array[6] == 'O' && array[7] == 'O' && array[8] == 'O') ||
(array[0] == 'O' && array[3] == 'O' && array[6] == 'O') ||
(array[1] == 'O' && array[4] == 'O' && array[7] == 'O') ||
(array[2] == 'O' && array[5] == 'O' && array[8] == 'O') ||
(array[0] == 'O' && array[4] == 'O' && array[8] == 'O') ||
(array[2] == 'O' && array[4] == 'O' && array[6] == 'O')) {
return 2;
}
for (int i = 1; i <= SIZE; i++) {
if (array[i - 1] == '0' + i)
return 0;
}
return 3;
}
int game_logic(int i) {
for (;;) {
char buf[32];
int player, n;
char mark;
if (i % 2 == 0) {
player = 1;
mark = 'X';
} else {
player = 2;
mark = 'O';
}
printf("Player %d, Please select the number = ", player);
if (!fgets(buf, sizeof buf, stdin)) {
/* end of file reached: abort */
return -1;
}
if (sscanf(buf, "%d", &n) != 1 || n < 1 || n > 9) {
printf("please enter a number between 1 and 9\n");
continue;
}
if (array[n - 1] != '0' + n) {
printf("slot %d is already played\n", n);
continue;
}
array[n - 1] = mark;
return game_win();
}
}
int main() {
printf("\n\t\t Welcome to Tic-Tac-Toe game\n\n");
printf(" In this game, there will be two players taking turns for their moves\n\n");
printf("\t\t Player 1 = 'X' and Player 2 = 'O'\n\n");
for (int i = 0; i < SIZE; i++) {
display_board();
if (game_logic(i) != 0)
break;
}
switch (game_win()) {
case 0:
printf("\nThe game was aborted\n");
break;
case 1:
display_board();
printf("\nThe Player 1 has won the game\n");
break;
case 2:
display_board();
printf("\nThe Player 2 has won the game\n");
break;
case 3:
display_board();
printf("\nThe game is draw\n");
break;
}
return 0;
}
In the loop inside the game_logic function, it returns after Player1 entered a valid number. And then game_logic is called in a loop, so i gets never increased and this causes the endless loop.
Related
i'm a beginner to programming and I'm running into a problem. I think that this is quite basic but I have looked around everywhere and can't find a solution (probably because of my own lack of understanding). This is my code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
char inputString[999];
char inputArray[99][99];
int a = 0;
int b = 0;
fgets(inputString, sizeof inputString, stdin);
for(int i = 0; i <= (strlen(inputString)); i++) {
if(inputString[i] == ' ' || inputString[i] == '\0') {
inputArray[a][b] = '\0';
a++;
b = 0;
}
else {
inputArray[a][b] = inputString[i];
b++;
}
}
for (int i = 0; i < 99; i++) {
if (inputArray[i][0] == '\0') {
break;
}
for (int j = 0; j < 99; j++) {
iif (inputArray[i][0] == 'a' || inputArray[i][0] == 'e' || inputArray[i][0] == 'i' || inputArray[i][0] == 'o' || inputArray[i][0] == 'u' ||
inputArray[i][0] == 'A' || inputArray[i][0] == 'E' || inputArray[i][0] == 'I' || inputArray[i][0] == 'O' || inputArray[i][0] == 'U') {
if (inputArray[i][j] == '.') {
inputArray[i][j] = '\0';
if (inputArray[i][j] == '\0') {
inputArray[i][j] = 'm';
inputArray[i][j + 1] = 'o';
inputArray[i][j + 2] = 'o';
inputArray[i][j + 3] = '.';
inputArray[i][j + 4] = '\0';
i++;
j = 0;
}
}
else if (inputArray[i][j] == ',') {
inputArray[i][j] = '\0';
if (inputArray[i][j] == '\0') {
inputArray[i][j] = 'm';
inputArray[i][j + 1] = 'o';
inputArray[i][j + 2] = 'o';
inputArray[i][j + 3] = ',';
inputArray[i][j + 4] = '\0';
i++;
j = 0;
}
}
else {
if (inputArray[i][j] == '\0') {
inputArray[i][j] = 'm';
inputArray[i][j + 1] = 'o';
inputArray[i][j + 2] = 'o';
inputArray[i][j + 3] = '\0';
i++;
j = 0;
}
}
}
else if (inputArray[i][0] != 'a' || inputArray[i][0] != 'e' || inputArray[i][0] != 'i' || inputArray[i][0] != 'o' || inputArray[i][0] != 'u' ||
inputArray[i][0] != 'A' || inputArray[i][0] != 'E' || inputArray[i][0] != 'I' || inputArray[i][0] != 'O' || inputArray[i][0] != 'U' || inputArray[i][0] != '\0') {
printf("a");
i++;
j = 0;
}
}
}
for (int i = 0; i < 99; i++) {
printf("%s ", inputArray[i]);
if (inputArray[i][0] == '\0') {
break;
}
}
return 0;
}
Essentially I'm trying to input a string, separate them into words using a 2-D array, and then check if the first letters of each string in that array is a consonant or a vowel.
I'm using printf("a"); to test if my code works, but when i run the program and input something like "yo", this is the output:
yo
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaayo
The letter "a" is printed 99 times, which is as many times as the inner for loop is ran, so i'm guessing it has something to do with the fact that the first element of every string in the array is also not a vowel and maybe it's a null character, so I tried adding if (inputArray[i][0] == '\0') { (like in the code), but it still doesn't work.
I'd really appreciate if you guys can help me out
EDIT: I changed the code a bit to make it more readable (thanks Benjamin Maurer!), but essentially what I'm trying to do in the first if statement is add "moo" to the end of a word if it starts with a vowel.
Your code starts normal, but why did you then switch from array notation to this absolute madness in the second loop with pointer dereferences? I'm not even going to try to understand that code, bc. it's unreadable.
According to your description, each of inputArray[i] is a string. So checking if inputArray[i][0] is a consontant/vowel should suffice, no?
#include <ctype.h>
#include <stdio.h>
// ...Read input...
for (int i = 0; i < 99; ++i) {
if (isalpha(inputArray[i][0])) {
char c = toupper(inputArray[i][0]);
switch (c) {
// Intentional fallthroughs
case 'A':
case 'E':
case 'I':
case 'O':
case 'U':
puts("is vowel!");
break;
default:
puts("is consonant");
}
}
}
Both isalpha and toupper are from ctype.h.
islapha checks whether the argument is an alphabetic latin character (a letter).
Hello I'm trying to code a pattern game, but the problem is I don't know how to keep track of the previous input of the user, so whenever a new game starts, you cannot input the previous letter. Is there a way to code this?
Example would be like :
Round 1 :
User: inputs -> A
(New Game)
User : inputs -> A // again
Invalid.
Round 2 :
User : inputs -> A
(New Game)
User : inputs -> B
Valid
Round 3 :
User : inputs -> A
(New Game)
User : inputs -> A
Invalid
The code is here :
#include <stdio.h>
#include <string.h>
int main ()
{
int i=0;
int roundCount = 1;
int pos = 0;
int over = 0;
int f = 1;
char G[2];
printf("Game Start!\n");
do
{
printf("Round %d!\n", roundCount++);
printf("Input selection upon prompt.\n");
printf("Player 1: ");
scanf(" %c", &G[0] );
printf("Player 2: ");
scanf(" %c", &G[1]);
if((G[0] == 'L' && G[1] == 'V') || (G[0] == 'V' && G[1] == 'S') || (G[0] == 'S' && G[1] == 'P') || (G[0] == 'P' && G[1] == 'R') || (G[0] == 'R' && G[1] == 'L') || (G[0] == 'R' && G[1] == 'S') || (G[0] == 'P' && G[1] == 'V') || (G[0] == 'S' && G[1] == 'L') || (G[0] == 'V' && G[1] == 'R') || (G[0] == 'L' && G[1] == 'P') )
{
f++;
pos--;
printf("Uno Wins! Pos[%d]\n\n", pos);
}
else if ((G[0] == 'R' && G[1] == 'P' ) || (G[0] == 'L' && G[1] == 'R') || (G[0] == 'R'&& G[1] == 'V') || (G[0] == 'P'&& G[1] =='S')|| (G[0] == 'P'&& G[1] == 'L') || (G[0] == 'S' && G[1] == 'R') || (G[0] == 'S' && G[1] == 'V') || (G[0] == 'L' && G[1] == 'S' )|| (G[0] == 'V'&& G[1] == 'P') || (G[0] == 'V'&& G[1] == 'L'))
{
f++;
pos++;
printf("Dos Wins Pos[%d]!\n\n", pos);
}
else if ((G[0] == 'R' && G[1] == 'R' ) || (G[0] == 'P' && G[1] == 'P') || (G[0] == 'S' && G[1] == 'S') || (G[0] == 'L' && G[1] == 'L') || (G[0] == 'V' && G[1] == 'V'))
{
f++;
pos = pos;
}
if (pos == -3 || pos == 3){
printf("Game over\n");
break;
}
if(f == 5 && pos != -3 && pos != 3)
{
if((G[0] == 'L' && G[1] == 'V') || (G[0] == 'V' && G[1] == 'S') || (G[0] == 'S' && G[1] == 'P') || (G[0] == 'P' && G[1] == 'R') || (G[0] == 'R' && G[1] == 'L') || (G[0] == 'R' && G[1] == 'S') || (G[0] == 'P' && G[1] == 'V') || (G[0] == 'S' && G[1] == 'L') || (G[0] == 'V' && G[1] == 'R') || (G[0] == 'L' && G[1] == 'P') )
{
printf("Uno Wins!\n");
break;
}
else if((G[0] == 'R' && G[1] == 'P' ) || (G[0] == 'L' && G[1] == 'R') || (G[0] == 'R'&& G[1] == 'V') || (G[0] == 'P'&& G[1] =='S')|| (G[0] == 'P'&& G[1] == 'L') || (G[0] == 'S' && G[1] == 'R') || (G[0] == 'S' && G[1] == 'V') || (G[0] == 'L' && G[1] == 'S' )|| (G[0] == 'V'&& G[1] == 'P') || (G[0] == 'V'&& G[1] == 'L'))
{
printf("Dos Win!\n");
break;
}
}
} while (f < 5);
return 0;
}
See code above,
It resets at G[0] and G[1] again, i cannot keep track of the previous input because it resets. Is there a way to improve this code? I would gladly appreciate the help.
Caveat: This isn't a full solution, but a bug fix and some cleanup:
Your scanf sequence produces a bad value for G[1]. Better to use fgets to get a full line cleanly.
Your if statements are unwieldy. They can be greatly simplified with a switch/case and some macro trickery.
Here's some cleaned up code:
#include <stdio.h>
#include <string.h>
#define SWITCH(_g0,_g1) \
(_g0 << 8) | (_g1 << 0)
#define CASE(_g0,_g1) \
case SWITCH(_g0,_g1)
int
getval(const char *prompt)
{
char *cp;
char buf[100];
int val;
while (1) {
printf("%s: ",prompt);
fflush(stdout);
cp = fgets(buf,sizeof(buf),stdin);
// handle end of file
if (cp == NULL) {
val = -1;
break;
}
// get the first char on the line
val = buf[0];
if (val != '\n')
break;
}
return val;
}
int
main()
{
int i = 0;
int roundCount = 1;
int pos = 0;
int over = 0;
int f = 1;
int G[2];
printf("Game Start!\n");
do {
printf("Round %d!\n", roundCount++);
printf("Input selection upon prompt.\n");
G[0] = getval("Player 1");
if (G[0] < 0)
break;
G[1] = getval("Player 2");
if (G[1] < 0)
break;
printf("DEBUG: %2.2X %2.2X\n",G[0],G[1]);
switch (SWITCH(G[0],G[1])) {
CASE('L','V'):
CASE('V','S'):
CASE('S','P'):
CASE('P','R'):
CASE('R','L'):
CASE('R','S'):
CASE('P','V'):
CASE('S','L'):
CASE('V','R'):
CASE('L','P'):
f++;
pos--;
printf("Uno Wins! Pos[%d]\n\n", pos);
break;
CASE('R','P'):
CASE('L','R'):
CASE('R','V'):
CASE('P','S'):
CASE('P','L'):
CASE('S','R'):
CASE('S','V'):
CASE('L','S'):
CASE('V','P'):
CASE('V','L'):
f++;
pos++;
printf("Dos Wins Pos[%d]!\n\n", pos);
break;
CASE('R','R'):
CASE('P','P'):
CASE('S','S'):
CASE('L','L'):
CASE('V','V'):
f++;
pos = pos;
break;
}
if (pos == -3 || pos == 3) {
printf("Game over\n");
break;
}
if (f == 5 && pos != -3 && pos != 3) {
switch (SWITCH(G[0],G[1])) {
CASE('L','V'):
CASE('V','S'):
CASE('S','P'):
CASE('P','R'):
CASE('R','L'):
CASE('R','S'):
CASE('P','V'):
CASE('S','L'):
CASE('V','R'):
CASE('L','P'):
printf("Uno:Wins!\n");
break;
CASE('R','P'):
CASE('L','R'):
CASE('R','V'):
CASE('P','S'):
CASE('P','L'):
CASE('S','R'):
CASE('S','V'):
CASE('L','S'):
CASE('V','P'):
CASE('V','L'):
printf("Dos Win!\n");
break;
}
}
} while (f < 5);
return 0;
}
Looking at your code, it looks like you have a persistence problem!
You can solve this a couple ways, but it looks like you only want the data to be around for each 'set' of games. In this case, you need to define the array that holds the user input outside of the loop that the games take place in, otherwise you reinitialize the array each gameplay. That would need to be another array, separate from G[2] that is the maximum size you expect the data to be. From your code it looks like you play 5 games, so 5x2=10, maybe a buffer called Q[10]?
When you finish a loop, set the next 2 members of Q to the user input, and that should work.
Another way to keep the data between runs would be to use a file to maintain the data. That's a little more complicated, but is laid out pretty well in this question:
Write to .txt file?
I hope that helps! Let me know if anything is unclear :)
I'm beginner learner in C and one of the assignments I got was to write a Tic Tac Toe game. I have the game running but every time you place X on O position or vice versa it overwrites it. I would also appreciate comments on optimizing the code, because I'm a beginner and don't know a lot of concepts. Thank you! this is what I've got so far
#include<stdio.h>
void redrawBoard(char array[]);
void markBoard (int x, int o, char array[]);
int checkForWin(char array[]);
int checkForWin(char array[])
{
int a;
char x = 'X';
char o = 'O';
if (array[0] == x && array[4] == x && array[8] == x) // winning cases for x
return 1;
if (array[2] == x && array[4] == x && array[6] == x)
return 1;
if (array[0] == x && array[1] == x && array[2] == x)
return 1;
if (array[3] == x && array[4] == x && array[5] == x)
return 1;
if (array[6] == x && array[7] == x && array[8] == x)
return 1;
if (array[0] == x && array[3] == x && array[6] == x)
return 1;
if (array[1] == x && array[4] == x && array[7] == x)
return 1;
if (array[2] == x && array[5] == x && array[8] == x)
return 1;
if (array[1] == x && array[4] == x && array[6] == x && array[8] ==x) //checking for draw with x combinations 1st pattern
return 3;
if (array[0] == x && array[2] == x && array[4] == x && array[7] ==x)
return 3;
if (array[0] == x && array[4] == x && array[5] == x && array[6] ==x)
return 3;
if (array[2] == x && array[3] == x && array[4] == x && array[8] ==x)
return 3;
if (array[1] == x && array[4] == x && array[5] == x && array[6] ==x) //checking for draw with x combinations 2nd pattern
return 3;
if (array[0] == x && array[4] == x && array[5] == x && array[7] ==x)
return 3;
if (array[2] == x && array[3] == x && array[4] == x && array[7] ==x)
return 3;
if (array[1] == x && array[3] == x && array[4] == x && array[8] ==x)
return 3;
if (array[0] == o && array[4] == o && array[8] == o) //// winning cases for o
return 2;
if (array[2] == o && array[4] == o && array[6] == o)
return 2;
if (array[0] == o && array[1] == o && array[2] == o)
return 2;
if (array[3] == o && array[4] == o && array[5] == o)
return 2;
if (array[6] == o && array[7] == o && array[8] == o)
return 2;
if (array[0] == o && array[3] == o && array[6] == o)
return 2;
if (array[1] == o && array[4] == o && array[7] == o)
return 2;
if (array[2] == o && array[5] == o && array[8] == o)
return 2;
if (array[1] == o && array[4] == o && array[6] == o && array[8] == o) //checking for draw with o combinations 1st pattern
return 3;
if (array[0] == o && array[2] == o && array[4] == o && array[7] == o)
return 3;
if (array[0] == o && array[4] == o && array[5] == o && array[6] == o)
return 3;
if (array[2] == o && array[3] == o && array[4] == o && array[8] == o)
return 3;
if (array[1] == o && array[4] == o && array[5] == o && array[6] == o) //checking for draw with o combinations 2nd pattern
return 3;
if (array[0] == o && array[4] == o && array[5] == o && array[7] == o)
return 3;
if (array[2] == o && array[3] == o && array[4] == o && array[7] == o)
return 3;
if (array[1] == o && array[3] == o && array[4] == o && array[8] == o)
return 3;
else
return 0;
return(a);
}
void markBoard (int x, int o, char array[])
{
int i = 0;
char j = 'X';
char k = 'O';
while( x >= 1 && x <= 9)
{
array[x - 1] = j;
redrawBoard(array);
break;
}
while (o >= 1 && o <= 9)
{
array[o - 1] = k;
redrawBoard(array);
break;
}
}
void redrawBoard(char array[])
{
printf(" Player 1 is X; Player 2 is O;\n\n");
printf(" | | \n");
printf(" %c | %c | %c \n",array[0],array[1],array[2]);
printf(" ______|______|______ \n");
printf(" | | \n");
printf(" %c | %c | %c \n",array[3],array[4],array[5]);
printf(" ______|______|______ \n");
printf(" | | \n");
printf(" %c | %c | %c \n",array[6],array[7],array[8]);
printf(" | | \n");
}
int main()
{
int x;
int o;
char array[9] = {'1', '2','3','4','5','6','7','8','9'};
printf("tic tac toe game\n");
redrawBoard(array);
while (checkForWin(array) == 0)
{
printf("P1 start \n");
scanf("%d",&x);
markBoard(x,o,array);
printf("P2 go on\n");
scanf("%d", &o);
markBoard(x,o,array);
}
if (checkForWin(array) == 1)
printf("P1 won\n");
if (checkForWin(array) == 2)
printf("P2 won\n");
if (checkForWin(array) == 3)
printf("draw \n");
return 0;
}
The problem you mentioned is that you do not have a test when you already have a value in this cell.
About optimization:
Avoid a lot of if cases! Think about better check for checking who is winner.
For example, look at this check:
char winnerIs(char** Board, int i, int j) {
if (Board[i][j] == Board[i][(j+1)%3]
&& Board[i][j] == Board[i][(j+2)%3])
{
// got a column
return Board[i][j];
}
else if (Board[i][j] == Board[(i+1)%3][j] && Board[i][j] == Board[(i+2)%3][j])
{
// got a row
return Board[i][j];
}
else if (i == j && Board[i][j] == Board[(i+1)%3][(j+1)%3]
&& Board[i][j] == Board[(i+2)%3][(j+2)%3])
{
// got the forward diagonal
return Board[i][j];
}
else if (i+j == 2 && Board[i][j] == Board[(i+2)%3][(j+1)%3]
&& Board[i][j] == Board[(i+1)%3][(j+2)%3])
{
// got the reverse diagonal
return Board[i][j];
}
else {
// got nothing
return 0;
}
Avoid a lot of printing! Better use one structure for the game, for example a board - which is char board[][] or better char** Board if you want a dynamic game. And print the whole board once.
Instead of next code:
printf("P1 start \n");
scanf("%d",&x);
markBoard(x,o,array);
printf("P2 go on\n");
scanf("%d", &o);
markBoard(x,o,array);
Make something like this:
int player = 1;
char row, col;
player = (player % 2) ? 1 : 2;
scanf("%c %c", &row, &col);
markBoard(row, col, board);
Like that you don't need to duplicate a same code and it is automatic knows each turn, who's turn now.
Instead of next code:
if (checkForWin(array) == 1)
printf("P1 won\n");
if (checkForWin(array) == 2)
printf("P2 won\n");
if (checkForWin(array) == 3)
printf("draw \n");
Connect some conditions, like that:
if (checkForWin(array) == 1 || checkForWin(array) == 2) {
printf("Congratulations %c!\n", winner);
} else {
printf("Game ends in a draw.\n");
}
To make more "beauty" code, you can added a structs which will manage the whole game, for example:
typedef struct {
int size;
int **board; // the board
/* scores of all options */
int *rowScores;
int *colScores;
int topLeftBottomRightDiagonalScores;
int topRightBottomLeftDiagonalScores;
} Game;
typedef struct { // position on the board
int x;
int y;
} Position;
Your void markBoard (int x, int o, char array[]) function makes to much iterations to print the whole board. Better create the whole board once and after that run on the whole board.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I have an array formed from a text file imported by stdin.
The text file looks like this:
"Name"
"Number"
"Name"
"Number"
...
The entire code:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(int argc, char** argv)
{
//number of arguments
if (argc > 2)
{
fprintf(stderr, "Too many arguments\n");
return 1;
}
//check argument 1
{
if (argc == 2)
{
unsigned i = 0;
while (i < strlen(argv[1]))
{
if ((isdigit(argv[1][i])) == 0)
{
fprintf(stderr, "Enter a number\n");
return 1;
}
i++;
}
}
else
{
fprintf(stderr, "argument\n");
return -1;
}
}
//find \n and separate
int g = 0;
int c = 0;
char buffer[102];
char people[42][102];
char numbers[42][102];
while (fgets(buffer, sizeof buffer, stdin) != NULL)
{
if (g % 2 == 0)
{
strcpy(people[c], buffer);
//printf("%s", people[c]);
}
if (g % 2 == 1)
{
strcpy(numbers[c], buffer);
c++;
}
g++;
}
//convert and remove \n
char conv_people[42][102];
for (int i = 0; i < c; i++)
{
for (unsigned j = 0; j < strlen(people[i]); j++)
{
if (islower(people[i][j]) == 0 && people[i][j] != ' ' && people[i][j] != '.')
{
if (people[i][j] == '\n')
{
conv_people[i][j] = '\0';
}
people[i][j] = conv_people[i][j] + 32;
}
}
}
//covert to numbers
char conv[42][102];
for (int i = 0; i < c; i++)
{
for (unsigned j = 0; j < strlen(people[i]); j++)
{
if (conv_people[i][j] == ' ' || conv_people[i][i] == '.' || conv_people[i][i] == '\n' || conv_people[i][i] == '\0')
{
conv[i][j] = '0';
}
if (conv_people[i][j] == 'a' || conv_people[i][j] == 'b' || conv_people[i][j] == 'c')
{
conv[i][j] = '2';
}
if (conv_people[i][j] == 'd' || conv_people[i][j] == 'e' || conv_people[i][j] == 'f')
{
conv[i][j] = '3';
}
if (conv_people[i][j] == 'g' || conv_people[i][j] == 'h' || conv_people[i][j] == 'i')
{
conv[i][j] = '4';
}
if (conv_people[i][j] == 'j' || conv_people[i][j] == 'k' || conv_people[i][j] == 'l')
{
conv[i][j] = '5';
}
if (conv_people[i][j] == 'm' || conv_people[i][j] == 'n' || conv_people[i][j] == 'o')
{
conv[i][j] = '6';
}
if (conv_people[i][j] == 'p' || conv_people[i][j] == 'q' || conv_people[i][j] == 'r' || conv_people[i][j] == 's')
{
conv[i][j] = '7';
}
if (conv_people[i][j] == 't' || conv_people[i][j] == 'u' || conv_people[i][j] == 'v')
{
conv[i][j] = '8';
}
if (conv_people[i][j] == 'w' || conv_people[i][j] == 'x' || conv_people[i][j] == 'y' || conv_people[i][j] == 'z')
{
conv[i][j] = '9';
}
}
}
//compare
int i = 0;
while (i < c)
{
if (strstr(conv[i], argv[1]) != NULL)
printf("%s, %s", people[i], numbers[i]);
if (strstr(numbers[i], argv[1]) != NULL)
printf("%s, %s", people[i], numbers[i]);
i++;
}
return 0;
}
The program takes a list of people and their phone numbers and searches it using argv[1]
The output always omits the first capital letter in each word
So if the file contains a name like: Barrack Obama
the program returns arrack bama
The numbers and converted names are working fine
I didn't want to post the whole thing because it's extremely ugly.
I've run the code and John is output as Éohn. It likely comes from
people[i][j] = conv_people[i][j] + 32;
because you never set any values in conv_people[i] except a terminator.
If I add this first line in the loop
strcpy(conv_people[i], people[i]);
then is outputs
john
with a lower case initial letter.
Aside: it is safer and convenient to use
people[i][j] = tolower(conv_people[i][j]);
which doesn't even need to be tested to see if an uppercase letter was passed.
My question is for the if statement under the "checks for duplicate move" section of the code. Sometimes the if statement works, but sometimes it just doesn't do it. The if statement is supposed to check the input from the user and compare it to the character currently in the coordinate. If the character is a 'X' or 'O' then it should not overwrite the character currently in that part of the array, tells the user it was an invalid move, and subtracts 1 from counter so it is still either X's or O's turn.
#include <stdio.h>
struct coordinate{
int i;
int j;
};
//function that prints the tic-tac-toe board
int printTable( char array[3][3]){
printf(" X's first O's second\n");
printf("\n 0 1 2\n");
printf("\n | | \n");
printf(" 0 %c | %c | %c \n", array[0][0], array[0][1], array[0][2]);
printf(" ___|___|___\n");
printf(" | | \n");
printf(" 1 %c | %c | %c \n", array[1][0], array[1][1], array[1][2]);
printf(" ___|___|___\n");
printf(" | | \n");
printf(" 2 %c | %c | %c \n", array[2][0], array[2][1], array[2][2]);
printf(" | | \n\n");
return 0;
}
int main (void){
struct coordinate move;
char game;
int counter;
char ttt[3][3] = {
{'-', '-', '-'},
{'-', '-', '-'},
{'-', '-', '-'}
};
printf("\nWelcome to tic tac toe!\n");
//Checks if you want to play
printf("Would you like to play? y/n\n");
scanf("%c", &game);
//stops game by returning zero
if(game == 'n'){
printf("Have a pleasant day");
return 0;
}
//starts game! =)
if(game == 'y'){
for(counter = 1; counter <= 9; counter++){
printTable(ttt);
//asks player where they want to move
printf("Where would you like to move?");
scanf("%i %i", &move.i, &move.j);
//Checks for duplicate move
if( ttt[move.i][move.j] == 'O' || ttt[move.i][move.j] == 'X' ){
ttt[move.i][move.j] = ttt[move.i][move.j];
printf("\n\n\nInvalid move. Try again\n\n\n");
counter = counter - 1;
}
//O wins
if( ttt[0][0] == 'O' && ttt[0][1] == 'O' && ttt[0][2] == 'O' || ttt[1][0] == 'O' && ttt[1][1] == 'O' && ttt[1][2] == 'O' || ttt[2][0] == 'O' && ttt[2][1] == 'O' && ttt[2][2] == 'O' || ttt[0][0] == 'O' && ttt[1][0] == 'O' && ttt[2][0] == 'O' || ttt[0][1] == 'O' && ttt[1][1] == 'O' && ttt[2][1] == 'O' || ttt[0][2] == 'O' && ttt[1][2] == 'O' && ttt[2][2] == 'O' || ttt[0][0] == 'O' && ttt[1][1] == 'O' && ttt[2][2] == 'O' || ttt[2][0] == 'O' && ttt[1][1] == 'O' && ttt[0][2] == 'O'){
printf("O WINS!!!!!");
return 0;
}
//X wins
if( ttt[0][0] == 'X' && ttt[0][1] == 'X' && ttt[0][2] == 'X' || ttt[1][0] == 'X' && ttt[1][1] == 'X' && ttt[1][2] == 'X' || ttt[2][0] == 'X' && ttt[2][1] == 'X' && ttt[2][2] == 'X' || ttt[0][0] == 'X' && ttt[1][0] == 'X' && ttt[2][0] == 'X' || ttt[0][1] == 'X' && ttt[1][1] == 'X' && ttt[2][1] == 'X' || ttt[0][2] == 'X' && ttt[1][2] == 'X' && ttt[2][2] == 'X' || ttt[0][0] == 'X' && ttt[1][1] == 'X' && ttt[2][2] == 'X' || ttt[2][0] == 'X' && ttt[1][1] == 'X' && ttt[0][2] == 'X'){
printf("X WINS!!!!!");
return 0;
}
//X's turns
if( counter == 0 || counter == 2 ||counter == 4 ||counter == 6 ||counter == 8){
ttt[move.i][move.j] = 'X';
}
//Y's turns
if( counter == 1 || counter == 3 ||counter == 5 ||counter == 7 ){
ttt[move.i][move.j] = 'O';
}
//CATS GAME
if( counter == 9){
printf("Cat's Game =(");
return 0;
}
}
}
return 0;
}
First of all, you could just write that if it is Y's turn, the if statement could look like
if(counter%2 == 1)
and respectively for X's turn:
if(counter%2 == 0)
What's more, this part of the code
//O wins
if( ttt[0][0] == 'O' && ttt[0][1] == 'O' && ttt[0][2] == 'O' || ttt[1][0] == 'O' && ttt[1][1] == 'O' && ttt[1][2] == 'O' || ttt[2][0] == 'O' && ttt[2][1] == 'O' && ttt[2][2] == 'O' || ttt[0][0] == 'O' && ttt[1][0] == 'O' && ttt[2][0] == 'O' || ttt[0][1] == 'O' && ttt[1][1] == 'O' && ttt[2][1] == 'O' || ttt[0][2] == 'O' && ttt[1][2] == 'O' && ttt[2][2] == 'O' || ttt[0][0] == 'O' && ttt[1][1] == 'O' && ttt[2][2] == 'O' || ttt[2][0] == 'O' && ttt[1][1] == 'O' && ttt[0][2] == 'O'){
printf("O WINS!!!!!");
return 0;
}
//X wins
if( ttt[0][0] == 'X' && ttt[0][1] == 'X' && ttt[0][2] == 'X' || ttt[1][0] == 'X' && ttt[1][1] == 'X' && ttt[1][2] == 'X' || ttt[2][0] == 'X' && ttt[2][1] == 'X' && ttt[2][2] == 'X' || ttt[0][0] == 'X' && ttt[1][0] == 'X' && ttt[2][0] == 'X' || ttt[0][1] == 'X' && ttt[1][1] == 'X' && ttt[2][1] == 'X' || ttt[0][2] == 'X' && ttt[1][2] == 'X' && ttt[2][2] == 'X' || ttt[0][0] == 'X' && ttt[1][1] == 'X' && ttt[2][2] == 'X' || ttt[2][0] == 'X' && ttt[1][1] == 'X' && ttt[0][2] == 'X'){
printf("X WINS!!!!!");
return 0;
}
could be arranged to be a function checkWin(char c)
by the way:
ttt[move.i][move.j] = ttt[move.i][move.j];
this line does nothing useful (it writes the value of an element to the same element so nothing changes) - you can simply delete this line
You should add a 'continue' after the duplicate check (see below) so that your code doesnot do all the checking of who wins after a duplicate move. I believe this is the main source of your issue. However it could be more useful if you could elaborate little more what you meant by 'sometimes it works and sometimes it dont'
if( ttt[move.i][move.j] == 'O' || ttt[move.i][move.j] == 'X' ){
printf("\n\n\nInvalid move. Try again\n\n\n");
counter = counter - 1;
continue;
}
There are some issues in your code - I will explain the one, that are not already pointed out by the other comments.
Your 'if' conditionals are very Long and confusing - you don't have to check against 'X' and 'O' respectively - you can just compare them and whatever result is hold there, it wins. However a Special check for '-' is needed, but it's easier maintainable in my opinion. However that's not the main Point here.
Your mistake was, that you checked if theres a winner BEFORE you actually set the current cell. so the winner would only appear one round to late. Consider the improved code (i also applied some of the improvements from the other comments):
#include <stdio.h>
struct coordinate{
int i;
int j;
};
//function that prints the tic-tac-toe board
int printTable( char array[3][3]){
printf(" X's first O's second\n");
printf("\n 0 1 2\n");
printf("\n | | \n");
printf(" 0 %c | %c | %c \n", array[0][0], array[0][1], array[0][2]);
printf(" ___|___|___\n");
printf(" | | \n");
printf(" 1 %c | %c | %c \n", array[1][0], array[1][1], array[1][2]);
printf(" ___|___|___\n");
printf(" | | \n");
printf(" 2 %c | %c | %c \n", array[2][0], array[2][1], array[2][2]);
printf(" | | \n\n");
return 0;
}
int main (void){
struct coordinate move;
char game;
int counter, x, y;
char ttt[3][3] = {
{'-', '-', '-'},
{'-', '-', '-'},
{'-', '-', '-'}
};
printf("\nWelcome to tic tac toe!\n");
//Checks if you want to play
printf("Would you like to play? y/n\n");
scanf("%c", &game);
//stops game by returning zero
if(game == 'n'){
printf("Have a pleasant day");
}else /*if(game == 'y')*/{ //starts game! =)
for(counter = 1; counter <= 9; counter++){
printTable(ttt);
//asks player where they want to move
printf("Where would you like to move?");
scanf("%i %i", &move.i, &move.j);
//Checks for duplicate move
if( ttt[move.i][move.j] == 'O' || ttt[move.i][move.j] == 'X' ){
printf("\n\n\nInvalid move. Try again\n\n\n");
counter = counter - 1;
continue;
}
//X's turns
if( counter % 2 == 0){
ttt[move.i][move.j] = 'X';
}else if( counter % 2 == 1 ){
ttt[move.i][move.j] = 'O';
}
/* horizontal checks */
for(x = 0; x < 3; x++){
if(ttt[x][0] != '-' && ttt[x][0] == ttt[x][1] && ttt[x][1] == ttt[x][2]){
printf("%c WINS!!!!!", ttt[x][0]);
return 0;
}
}
/* vertical checks */
for(y = 0; y < 3; y++){
if(ttt[0][y] != '-' && ttt[0][y] == ttt[1][y] && ttt[1][y] == ttt[2][y]){
printf("%c WINS!!!!!", ttt[0][y]);
return 0;
}
}
/* diagonal checks */
if(ttt[0][0] != '-' && ttt[0][0] == ttt[1][1] && ttt[1][1] == ttt[2][2]){
printf("%c WINS!!!!!", ttt[0][0]);
return 0;
}else if(ttt[0][2] != '-' && ttt[0][2] == ttt[1][1] && ttt[1][1] == ttt[2][0]){
printf("%c WINS!!!!!", ttt[0][2]);
return 0;
}
if( counter >= 9){
printf("Cat's Game =(");
return 0;
}
}
}
return 0;
}