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 5 days ago.
Improve this question
I'm a rusty c programmer. I created a tictactoe program in python and wanted to do the same in c. Unfortunately, the compiler I installed is running my much older attempt at a tic tac toe game and the online compilers seem to be stuck on the while loops that are involved in decision-making. The while loops are marked out by comments in the code below
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int main(int argc, char *argv[]) {
int XO, E, turn = 1;
char A[9] = " ";
srand(time(0));
printf(" | | \n | | \n--------------\n | | \n | | \n--------------\n | | \n | | \n");
printf("Enter '1' for x and '-1' for o: ");
scanf("%d", &XO);
while(true)
{
if(turn == -XO)
{
do
{
E = rand() % 9;
}while(A[E] != " "); #Is stuck on this
if(-XO == -1)
{
A[E] = "o";
}
else
{
A[E] = "x";
}
turn *= -1;
}
else if(turn == XO)
{
do
{
printf("Enter the position you want to put yours in. 0 for top left. 1 for top middle. 3 for middle left. 4 for middle middle and so on...\n");
scanf("%d", &E);
}while(A[E] != " "); #Is stuck on this
if(XO == -1)
{
A[E] = "o";
}
else
{
A[E] = "x";
}
turn *= -1;
}
printf(" %c | %c | %c \n | | \n--------------\n %c | %c | %c \n | | \n--------------\n %c | %c | %c \n | | ", A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[8]);
if (((A[0] == "o" && A[1] == "o" && A[2] == "o") || (A[3] == "o" && A[4] == "o" && A[5] == "o") || (A[6] == "o" && A[7] == "o" && A[8] == "o") || (A[0] == "o" && A[4] == "o" && A[8] == "o") || (A[2] == "o" && A[4] == "o" && A[6] == "o") && XO == 1) || ((A[0] == "x" && A[1] == "x" && A[2] == "x") || (A[3] == "x" && A[4] == "x" && A[5] == "x") || (A[6] == "x" && A[7] == "x" && A[8] == "x") || (A[0] == "x" && A[4] == "x" && A[8] == "x") || (A[2] == "x" && A[4] == "x" && A[6] == "x") && XO == -1))
{
printf("You won!");
break;
}
else if (((A[0] == "o" && A[1] == "o" && A[2] == "o") || (A[3] == "o" && A[4] == "o" && A[5] == "o") || (A[6] == "o" && A[7] == "o" && A[8] == "o") || (A[0] == "o" && A[4] == "o" && A[8] == "o") || (A[2] == "o" && A[4] == "o" && A[6] == "o") && XO == -1) || ((A[0] == "x" && A[1] == "x" && A[2] == "x") || (A[3] == "x" && A[4] == "x" && A[5] == "x") || (A[6] == "x" && A[7] == "x" && A[8] == "x") || (A[0] == "x" && A[4] == "x" && A[8] == "x") || (A[2] == "x" && A[4] == "x" && A[6] == "x") && XO == 1))
{
printf("You lost!");
break;
}
}
return 0;
}
Here's the version that's on the compiler I installed:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
int XO, E, turn = 1;
char A[9] = " ";
srand(time(0));
printf(" | | \n | | \n--------------\n | | \n | | \n--------------\n | | \n | | ");
printf("Enter '1' for x and '-1' for o");
scanf("%d", &XO);
while(1)
{
if(turn == -XO)
{
do
{
E = rand() % 9;
}while(A[E] != " ");
if(-XO == -1)
{
A[E] = "o";
}
else
{
A[E] = "x";
}
turn *= -1;
}
else if(turn == XO)
{
do
{
printf("Enter the position you want to put yours in. 0 for top left. 1 for top middle. 3 for middle left. 4 for middle middle and so on...");
scanf("%d", &E);
}while(A[E] != " ");
if(XO == -1)
{
A[E] = "o";
}
else
{
A[E] = "x";
}
turn *= -1;
}
printf(" %c | %c | %c \n | | \n--------------\n %c | %c | %c \n | | \n--------------\n %c | %c | %c \n | | ", A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[8]);
if (((A[0] == "o" && A[1] == "o" && A[2] == "o") || (A[3] == "o" && A[4] == "o" && A[5] == "o") || (A[6] == "o" && A[7] == "o" && A[8] == "o") || (A[0] == "o" && A[4] == "o" && A[8] == "o") || (A[2] == "o" && A[4] == "o" && A[6] == "o") && XO == 1) || ((A[0] == "x" && A[1] == "x" && A[2] == "x") || (A[3] == "x" && A[4] == "x" && A[5] == "x") || (A[6] == "x" && A[7] == "x" && A[8] == "x") || (A[0] == "x" && A[4] == "x" && A[8] == "x") || (A[2] == "x" && A[4] == "x" && A[6] == "x") && XO == -1))
{
printf("You won!");
break;
}
else if (((A[0] == "o" && A[1] == "o" && A[2] == "o") || (A[3] == "o" && A[4] == "o" && A[5] == "o") || (A[6] == "o" && A[7] == "o" && A[8] == "o") || (A[0] == "o" && A[4] == "o" && A[8] == "o") || (A[2] == "o" && A[4] == "o" && A[6] == "o") && XO == -1) || ((A[0] == "x" && A[1] == "x" && A[2] == "x") || (A[3] == "x" && A[4] == "x" && A[5] == "x") || (A[6] == "x" && A[7] == "x" && A[8] == "x") || (A[0] == "x" && A[4] == "x" && A[8] == "x") || (A[2] == "x" && A[4] == "x" && A[6] == "x") && XO == 1))
{
printf("You lost!");
break;
}
}
return 0;
}
First of all, there are quite a lot of warnings and logic operations to fix. Some people already provided fixes in comments that you should apply.
Your program does not handle a fully filled array A. If A happens to become full without any win, you end up with infinite loops where you put comments. I think this is the source of the bug.
Also, at the end of your main loop, when you look for any win or defeat, you do not look for any "vertical win" by verifying (A[0] == 'x') && (A[3] == 'x') && (A[6] == 'x') for example.
Finally, adding #include <time.h> will fix the implicit declaration warning.
Related
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.
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.
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;
}
I am new to C. I am experienced in GWBASIC. In an effort to learn, I am attempting to write a program that will convert the individual chars in a string to a numerical value as so:
1 2 3 4 5 6 7 8 9
a b c d e f g h i
j k l m n o p q r
s t u v w x y z
For example, user input for string A could be 'dog',
said program would then store [d][o][g] as [4][6][7] in string B.
The below code works for a string w/up to four chars, but there must be a more efficient way of doing this.
int main()
{
char a[0];
char b[0];
scanf("%s",a);
if (a[0] == 'a' || a[0] == 'j' || a[0] == 's') b[0] = '1';
if (a[0] == 'b' || a[0] == 'k' || a[0] == 't') b[0] = '2';
if (a[0] == 'c' || a[0] == 'l' || a[0] == 'u') b[0] = '3';
if (a[0] == 'd' || a[0] == 'm' || a[0] == 'v') b[0] = '4';
if (a[0] == 'e' || a[0] == 'n' || a[0] == 'w') b[0] = '5';
if (a[0] == 'f' || a[0] == 'o' || a[0] == 'x') b[0] = '6';
if (a[0] == 'g' || a[0] == 'p' || a[0] == 'y') b[0] = '7';
if (a[0] == 'h' || a[0] == 'q' || a[0] == 'z') b[0] = '8';
if (a[0] == 'i' || a[0] == 'r') b[0] = '9';
if (a[1] == 'a' || a[1] == 'j' || a[1] == 's') b[1] = '1';
if (a[1] == 'b' || a[1] == 'k' || a[1] == 't') b[1] = '2';
if (a[1] == 'c' || a[1] == 'l' || a[1] == 'u') b[1] = '3';
if (a[1] == 'd' || a[1] == 'm' || a[1] == 'v') b[1] = '4';
if (a[1] == 'e' || a[1] == 'n' || a[1] == 'w') b[1] = '5';
if (a[1] == 'f' || a[1] == 'o' || a[1] == 'x') b[1] = '6';
if (a[1] == 'g' || a[1] == 'p' || a[1] == 'y') b[1] = '7';
if (a[1] == 'h' || a[1] == 'q' || a[1] == 'z') b[1] = '8';
if (a[1] == 'i' || a[1] == 'r') b[1] = '9';
if (a[2] == 'a' || a[2] == 'j' || a[2] == 's') b[2] = '1';
if (a[2] == 'b' || a[2] == 'k' || a[2] == 't') b[2] = '2';
if (a[2] == 'c' || a[2] == 'l' || a[2] == 'u') b[2] = '3';
if (a[2] == 'd' || a[2] == 'm' || a[2] == 'v') b[2] = '4';
if (a[2] == 'e' || a[2] == 'n' || a[2] == 'w') b[2] = '5';
if (a[2] == 'f' || a[2] == 'o' || a[2] == 'x') b[2] = '6';
if (a[2] == 'g' || a[2] == 'p' || a[2] == 'y') b[2] = '7';
if (a[2] == 'h' || a[2] == 'q' || a[2] == 'z') b[2] = '8';
if (a[2] == 'i' || a[2] == 'r') b[2] = '9';
if (a[3] == 'a' || a[3] == 'j' || a[3] == 's') b[3] = '1';
if (a[3] == 'b' || a[3] == 'k' || a[3] == 't') b[3] = '2';
if (a[3] == 'c' || a[3] == 'l' || a[3] == 'u') b[3] = '3';
if (a[3] == 'd' || a[3] == 'm' || a[3] == 'v') b[3] = '4';
if (a[3] == 'e' || a[3] == 'n' || a[3] == 'w') b[3] = '5';
if (a[3] == 'f' || a[3] == 'o' || a[3] == 'x') b[3] = '6';
if (a[3] == 'g' || a[3] == 'p' || a[3] == 'y') b[3] = '7';
if (a[3] == 'h' || a[3] == 'q' || a[3] == 'z') b[3] = '8';
if (a[3] == 'i' || a[3] == 'r') b[3] = '9';
printf("%s\n",b);
return 0;
}
Assuming that your compiler uses an ASCII encoding then you can use the following simple arithmetic to get your answer:
1 + (strA[i] - 'a') % 9
You really don't want to implement this with a long list of if statements or indeed a switch statement.
Naturally you will have input validation issues if you have non alphabetical characters, numeric characters, upper-case characters and so on. I presume you can simply ignore those for a learning exercise.
To correct your original approach, you need to do two things:
Use single quotes around character constants;
Use == to check for equality;
Terminate statements with ;.
... so your snippet becomes:
if (strA[0] == 'a')
strB[0] = '1';
if (strA[0] == 'b')
strB[0] = '2';
if (strA[0] == 'c')
strB[0] = '3';
You can type the following exactly into a gwbasic editor and it will solve your problem
10 INPUT A$
12 L = LEN(A$)
15 FOR T = 1 TO L
20 M$ = MID$(A$,T,1)
25 GOSUB 70
30 B$ = B$ + V$
35 NEXT T
40 PRINT B$
50 END
55 REM -----------------
70 REM - Subroutine to convert m$ into v$
72 X = ASC(M$) : REM this is the ascii value of m$ (eg. "a" = 97)
74 X = X - 96 : REM so that 97 becomes "1"
80 IF X > 9 THEN X = X - 9 : GOTO 80
90 V$ = STR$(X) : REM just converting to a string type variable
95 RETURN : REM takes you back to line 30 where this value is added to the
96 REM final resulting B$ - when I say added I mean a char added to a string
97 REM such that "APPL" + "E" = "APPLE"
98 REM ------------------------------------------ DONE
For ASCII, it would go somewhat like:
... make sure strB has enough space ...
for (i = 0; i < ... length of strA ... ; i++) {
/* you should always check your input is valid */
if (strA[i] >= 'a' && strB[i] <= 'z')
strB[i] = (strA[i] - 'a') % 9 + 1;
else
strB[i] = ... some default value ...
}
For EBCDIC:
for (i = 0; i < ... length of strA ... ; i++) {
/* you should always check your input is valid */
if (strA[i] >= 'a' && strB[i] <= 'r')
strB[i] = strA[i] & 0xF;
else if (strA[i] >= 's' && strB <= 'z')
strB[i] = (strA[i] & 0xF) - 1;
else
strB[i] = ... some default value ...
}
Have a closer look at an ASCII table. You'll see that all letters are encoded with some integer value. As a start, if you only have lower case letters, it's enough to substract the character code of 'a' from any letter to get what you want
int nr = strA[0] - 'a' + 1;
//now you'd need to convert back to a string; better: strB should be an array of integer
Also, = is the assignment operator; you need to use == to check for equality.
try this :)
int strB[MAX_LEN] = {0};
char *strA = malloc (MAX_LEN * sizeof(char));
int i,c = 0,x;
scanf("%s",strA);
for(i = 0 ; i<strlen(strA) ; i++){
x = strA[i] - 'a' + 1;
if(x >= 1 && x <= 9)
strB[c] = x;
else if(x <= 18){
strB[c] = x - 10;
else if(x <= 26){
strB[c] = x - 19;
if(x <= 26)
c++;
}
or you can use ninjalj approach in the for loop, if you aleady checked the input:
for(i=0 ; i<strlen(strA) ; i++){
strB[i] = (strA[i] - 'a') % 9 + 1;
}
or this :
for(i=0 ; i<strlen(strA) ; i++){
if(strA[i] >= 'a' && strA[i] <= 'z'){
strB[c] = (strA[i] - 'a') % 9 + 1;
c++;
}
}