I tried to program a simple TicTacToe in C. The program itselfs compiles and show no errors.
So the program draws the field, reads the names and let a player put his symbol in a specific field. All this happens in a while loop, the should be run until its a draw or someone wins.
But the program just run the loop one time so there is only one turn then the program stops.
So here is my code:
main.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "game.h"
#define NAMELENGTH 20
int main(void) {
char names[2][NAMELENGTH];
// field positions
char field[9];
int winner = -1;
getnames(names);
printf("\n\n");
initField(field);
// set field positions to 'empty'
char actualPlayer = (char)(get_random_number()*10.0) % 2;
while (1) {
drawField(field);
turn(actualPlayer, names, field);
winner = isWinner(actualPlayer, field);
drawField(field);
if (winner >= 1) {
printwinner(winner, names);
return 0;
}
else if (winner == 0) {
printDrawGame(names);
return 0;
}
actualPlayer = (actualPlayer + 1) % 2;
}
return 0;
}
game.h Headerfile:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define NAMELENGTH 20
#pragma warning(disable:4996)
extern void drawField(char *field);
extern void getnames(char nameField[][NAMELENGTH]);
extern void initField(char *field);
extern void turn(char actualPlayer, char names[][NAMELENGTH], char *field);
extern char isWinner(char actualPlayer, char *field);
extern void printwinner(char winnerNumber, char names[][NAMELENGTH]);
extern void printDrawGame(char names[][NAMELENGTH]);
extern double get_random_number();
and then my game.c where I defined my functions:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "game.h"
#define NAMELENGTH 20
#pragma warning(disable:4996)
void drawField(char *field) {
printf("________________________\n");
printf("| | | |\n");
printf("| %c | %c | %c |\n", field[0], field[1], field[2]);
printf("|_______|_______|______|\n");
printf("| | | |\n");
printf("| %c | %c | %c |\n", field[3], field[4], field[5]);
printf("|_______|_______|______|\n");
printf("| | | |\n");
printf("| %c | %c | %c |\n", field[6], field[7], field[8]);
printf("|_______|_______|______|\n");
}
void getnames(char nameField[][NAMELENGTH]) {
printf("Name of the first player: ");
scanf("%s", nameField[0]);
printf("Name of the second player: ");
scanf("%s", nameField[1]);
}
void initField(char *field) {
for (int i = 0; i <= 8; i++)
{
field[i] = i + '1';
}
}
void turn(char actualPlayer, char names[][NAMELENGTH], char *field) {
char symbol = ' ';
int p1fieldnumber;
int p2fieldnumber;
if (actualPlayer == 0)
{
do {
printf("\nIts Player %s's turn.", names[0]);
char symbol = 'X';
printf("\nNumber of the field which you want to put your symbol in: ");
scanf("%d", &p1fieldnumber);
if (field[p1fieldnumber] == 'X' || field[p1fieldnumber] == 'O')
{
printf("\nField is already occupied!");
p1fieldnumber = 10;
}
} while (p1fieldnumber < 1 || p1fieldnumber > 9);
field[p1fieldnumber-1] = 'X';
}
else {
do {
printf("\nIts Player %s's turn.", names[1]);
char symbol = 'O';
printf("\nNumber of the field which you want to put your symbol in: ");
scanf("%d", &p2fieldnumber);
if (field[p2fieldnumber] == 'X' || field[p2fieldnumber] == 'O')
{
printf("\nField is already occupied!");
p2fieldnumber = 10;
}
} while (p2fieldnumber < 1 || p2fieldnumber > 9);
field[p2fieldnumber-1] = 'O';
}
}
char isWinner(char actualPlayer, char *field) {
char pwinner = '3';
if (((field[0] == 'O') && (field[1] == 'O') && (field[2] == 'O')) ||
(field[3] == 'O') && (field[4] == 'O') && (field[5] == 'O') ||
(field[6] == 'O') && (field[7] == 'O') && (field[8] == 'O') ||
(field[0] == 'O') && (field[4] == 'O') && (field[8] == 'O') ||
(field[2] == 'O') && (field[4] == 'O') && (field[6] == 'O') ||
(field[0] == 'O') && (field[3] == 'O') && (field[6] == 'O') ||
(field[1] == 'O') && (field[4] == 'O') && (field[7] == 'O') ||
(field[2] == 'O') && (field[5] == 'O') && (field[8] == 'O'))
{
pwinner = '2';
}
else if (((field[0] == 'X') && (field[1] == 'X') && (field[2] == 'X')) ||
(field[3] == 'X') && (field[4] == 'X') && (field[5] == 'X') ||
(field[6] == 'X') && (field[7] == 'X') && (field[8] == 'X') ||
(field[0] == 'X') && (field[4] == 'X') && (field[8] == 'X') ||
(field[2] == 'X') && (field[4] == 'X') && (field[6] == 'X') ||
(field[0] == 'X') && (field[3] == 'X') && (field[6] == 'X') ||
(field[1] == 'X') && (field[4] == 'X') && (field[7] == 'X') ||
(field[2] == 'X') && (field[5] == 'X') && (field[8] == 'X'))
{
pwinner = '1';
}
else if (((field[0] == 'X') || (field[0] == 'O')) && ((field[1] == 'X') || (field[1] == 'O')) && ((field[2] == 'X') || (field[2] == 'O')) ||
((field[3] == 'X') || (field[3] == 'O')) && ((field[4] == 'X') || (field[4] == 'O')) && ((field[5] == 'X') || (field[5] == 'O')) ||
((field[6] == 'X') || (field[6] == 'O')) && ((field[7] == 'X') || (field[7] == 'O')) && ((field[8] == 'X') || (field[8] == 'O')) ||
((field[0] == 'X') || (field[0] == 'O')) && ((field[4] == 'X') || (field[4] == 'O')) && ((field[8] == 'X') || (field[8] == 'O')) ||
((field[2] == 'X') || (field[2] == 'O')) && ((field[4] == 'X') || (field[4] == 'O')) && ((field[6] == 'X') || (field[6] == 'O')) ||
((field[0] == 'X') || (field[0] == 'O')) && ((field[3] == 'X') || (field[3] == 'O')) && ((field[6] == 'X') || (field[6] == 'O')) ||
((field[1] == 'X') || (field[1] == 'O')) && ((field[4] == 'X') || (field[4] == 'O')) && ((field[7] == 'X') || (field[7] == 'O')) ||
((field[2] == 'X') || (field[2] == 'O')) && ((field[5] == 'X') || (field[5] == 'O')) && ((field[8] == 'X') || (field[8] == 'O')))
{
pwinner = '0';
}
return pwinner;
}
void printwinner(char winnerNumber, char names[][NAMELENGTH]) {
if (winnerNumber == '1') {
printf("Player %s won!", names[0]);
}
else if (winnerNumber == '2') {
printf("Player %s won!", names[1]);
}
}
void printDrawGame(char names[][NAMELENGTH]) {
printf("Draw!");
}
static int _initialized;
double get_random_number() {
if (!_initialized) {
srand(time(NULL));
_initialized = 1;
}
return (double)rand() / ((double)(RAND_MAX)+1);
}
There are multiple issues
isWinner returns characters '0', '1', '2' and '3'. Replace them with numbers 0, 1, 2, 3, because your are comparing with numbers in main.
In main instead of checking if (winner >= 1) {, which is true even if 3 is returned by isWinner, check for if (winner == 1 || winner == 2) {.
Suggest to use parentheses in isWinner around each condition separated by ||.
Parentheses as shown below for the first condition
if (((field[0] == 'O') && (field[1] == 'O') && (field[2] == 'O')) ||
((field[3] == 'O') && (field[4] == 'O') && (field[5] == 'O')) ||
((field[6] == 'O') && (field[7] == 'O') && (field[8] == 'O')) ||
((field[0] == 'O') && (field[4] == 'O') && (field[8] == 'O')) ||
((field[2] == 'O') && (field[4] == 'O') && (field[6] == 'O')) ||
((field[0] == 'O') && (field[3] == 'O') && (field[6] == 'O')) ||
((field[1] == 'O') && (field[4] == 'O') && (field[7] == 'O')) ||
((field[2] == 'O') && (field[5] == 'O') && (field[8] == 'O')))
Related
What I'm trying to do here is a tie toe game, but when my code enters the do - while part, it ends the process by itself. Since I could not solve this part, I did not have a chance to try whether there are other problems with the code, unfortunately, I would be glad if you could help with this issue.
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
char box_area[] = { '0','1','2','3','4','5','6','7','8','9' };
struct Player {
bool turn;
char mark;
int ID;
};
int main()
{
int return_result;
int player_number;
struct Player player1;
struct Player player2;
struct Player users[2];
users[0] = player1;
users[1] = player2;
(player1.mark = 'X') && (player2.mark = 'O');
(player1.turn = true) && (player2.turn = false);
(player1.ID = 1) && (player2.ID = 2);
do
{
box_creat();
for (int i = 0; i < 2; i++) {
if (users[i].turn == true)
{
make_move(users[i].ID);
box_creat();
users[i].turn = false;
users[i + 1].turn = true; \\ I made the logic of this section wrong
\\I will try to fix it, I realized after I sent the question
}
}
return_result = check_the_winner();
} while (return_result == 1 || return_result == -1);
return 0;
}
void box_creat(void) {
printf("| %c | %c | %c |", box_area[0], box_area[1], box_area[2]);
printf("\n\n");
printf("| %c | %c | %c |", box_area[3], box_area[4], box_area[5]);
printf("\n\n");
printf("| %c | %c | %c |", box_area[6], box_area[7], box_area[8]);
}
void make_move(int Player_ID)
{
int choice;
printf("Please select a area between 0-9 ");
scanf("%d", choice);
if (choice == '0' && box_area[0] == '0')
{
if (Player_ID == 1) {
box_area[0] = 'X';
}
else {
box_area[0] = 'O';
}
}
else if (choice == '1' && box_area[1] == '1')
{
if (Player_ID == 1) {
box_area[1] = 'X';
}
else {
box_area[1] = 'O';
}
}
else if (choice == '2' && box_area[2] == '2')
{
if (Player_ID == 1) {
box_area[2] = 'X';
}
else {
box_area[2] = 'O';
}
}
else if (choice == '3' && box_area[3] == '0')
{
if (Player_ID == 1) {
box_area[3] = 'X';
}
else {
box_area[3] = 'O';
}
}
else if (choice == '4' && box_area[4] == '0')
{
if (Player_ID == 1) {
box_area[4] = 'X';
}
else {
box_area[4] = 'O';
}
}
else if (choice == '5' && box_area[5] == '0')
{
if (Player_ID == 1) {
box_area[5] = 'X';
}
else {
box_area[5] = 'O';
}
}
else if (choice == '6' && box_area[6] == '0')
{
if (Player_ID == 1) {
box_area[6] = 'X';
}
else {
box_area[6] = 'O';
}
}
else if (choice == '7' && box_area[7] == '0')
{
if (Player_ID == 1) {
box_area[7] = 'X';
}
else {
box_area[7] = 'O';
}
}
else if (choice == '8' && box_area[8] == '0')
{
if (Player_ID == 1) {
box_area[8] = 'X';
}
else {
box_area[8] = 'O';
}
}
}
int check_the_winner(void)
{
if (box_area[0] && box_area[1] && box_area[2] == 'X' || 'O') {
return 1;
}
else if(box_area[3] && box_area[4] && box_area[5] == 'X' || 'O') {
return 1;
}
else if (box_area[6] && box_area[7] && box_area[8] == 'X' || 'O') {
return 1;
}
else if (box_area[2] && box_area[4] && box_area[6] == 'X' || 'O') {
return 1;
}
else if (box_area[0] && box_area[3] && box_area[6] == 'X' || 'O') {
return 1;
}
else if (box_area[2] && box_area[8] && box_area[5] == 'X' || 'O') {
return 1;
}
else if (box_area[0] && box_area[4] && box_area[8] == 'X' || 'O') {
return 1;
}
else if (box_area[1] && box_area[4] && box_area[7] == 'X' || 'O') {
return 1;
}
else {
return -1;
}
}
I tried out your program and found a few glitches that needed revision as well as adding in some additional bits of code just to neaten things up a bit. Following is your code with those revisions.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
char box_area[] = { '0','1','2','3','4','5','6','7','8','9' };
struct Player
{
bool turn;
char mark;
int ID;
};
void box_creat(void)
{
printf("| %c | %c | %c |", box_area[0], box_area[1], box_area[2]);
printf("\n\n");
printf("| %c | %c | %c |", box_area[3], box_area[4], box_area[5]);
printf("\n\n");
printf("| %c | %c | %c |", box_area[6], box_area[7], box_area[8]);
printf("\n"); /* Added for aesthetics */
}
void make_move(int Player_ID)
{
int choice;
printf("Player %d - please select a area between 0-9 ", Player_ID);
scanf("%d", &choice); /* Corrected missing ampersand */
printf("Player: %d makes a move\n", Player_ID);
if (choice == 0 && box_area[0] == '0') /* FYI - '0' is equivalent to integer value 48 */
{
if (Player_ID == 1)
{
box_area[0] = 'X';
}
else
{
box_area[0] = 'O';
}
}
else if (choice == 1 && box_area[1] == '1')
{
if (Player_ID == 1)
{
box_area[1] = 'X';
}
else
{
box_area[1] = 'O';
}
}
else if (choice == 2 && box_area[2] == '2')
{
if (Player_ID == 1)
{
box_area[2] = 'X';
}
else
{
box_area[2] = 'O';
}
}
else if (choice == 3 && box_area[3] == '3')
{
if (Player_ID == 1)
{
box_area[3] = 'X';
}
else
{
box_area[3] = 'O';
}
}
else if (choice == 4 && box_area[4] == '4')
{
if (Player_ID == 1)
{
box_area[4] = 'X';
}
else
{
box_area[4] = 'O';
}
}
else if (choice == 5 && box_area[5] == '5')
{
if (Player_ID == 1)
{
box_area[5] = 'X';
}
else
{
box_area[5] = 'O';
}
}
else if (choice == 6 && box_area[6] == '6')
{
if (Player_ID == 1)
{
box_area[6] = 'X';
}
else
{
box_area[6] = 'O';
}
}
else if (choice == 7 && box_area[7] == '7')
{
if (Player_ID == 1)
{
box_area[7] = 'X';
}
else
{
box_area[7] = 'O';
}
}
else if (choice == 8 && box_area[8] == '8')
{
if (Player_ID == 1)
{
box_area[8] = 'X';
}
else
{
box_area[8] = 'O';
}
}
}
int check_the_winner(void)
{
if ((box_area[0] == box_area[1]) && (box_area[1] == box_area[2]) && (box_area[0] != '0')) /* Corrected the testing for proper "and" conditioning */
{
return 1;
}
else if ((box_area[3] == box_area[4]) && (box_area[4] == box_area[5]) && (box_area[3] != '3'))
{
return 1;
}
else if ((box_area[6] == box_area[7]) && (box_area[7] == box_area[8]) && (box_area[6] != '6'))
{
return 1;
}
else if ((box_area[2] == box_area[4]) && (box_area[4] == box_area[6]) && (box_area[2] != '2'))
{
return 1;
}
else if ((box_area[0] == box_area[3]) && (box_area[3] == box_area[6]) && (box_area[0] != '0'))
{
return 1;
}
else if ((box_area[2] == box_area[5]) && (box_area[5] == box_area[8]) && (box_area[2] != '2'))
{
return 1;
}
else if ((box_area[0] == box_area[4]) && (box_area[4] == box_area[8]) && (box_area[4] != '4'))
{
return 1;
}
else if ((box_area[1] == box_area[4]) && (box_area[4] == box_area[7]) && (box_area[1] != '1'))
{
return 1;
}
else
{
return -1;
}
}
int main()
{
int return_result;
//int player_number; /* Compiler said that this wasn't being used */
int swap = 1;
int i;
struct Player player1;
struct Player player2;
struct Player *users[2]; /* Used these as address pointers to player "1" and player "2" */
users[0] = &player1; /* Before making these pointers, the users array just contained copies of the player structures */
users[1] = &player2;
(player1.mark = 'X') && (player2.mark = 'O');
(player1.turn = true) && (player2.turn = false);
(player1.ID = 1) && (player2.ID = 2);
do
{
box_creat();
swap += 1;
i = swap % 2;
if (i == 1)
{
make_move(users[1]->ID);
//box_creat(); /* Being performed at the top of the loop */
users[0]->turn = false;
users[1]->turn = true;
}
else
{
make_move(users[0]->ID);
//box_creat();
users[1]->turn = false;
users[0]->turn = true;
}
return_result = check_the_winner();
if (check_the_winner() == 1) /* Added when a winner has been sensed */
{
box_creat();
if (i == 1)
{
printf("Player 2 won!\n");
}
else
{
printf("Player 1 won!\n");
}
}
}
while (return_result != 1);
return 0;
}
I added comments to most of the places I had tweaked, but here are the highlights:
I shuffled some of the functions around so that the "main" function followed all of the helper functions (the compiler was giving warnings about the original sequence of the function positions).
I corrected the "choice" tests as "choice" is an integer, so the test of "choice" needed to be compared to an integer value (e.g. zero) as opposed to character '0' (which actually has a value of 48).
The tests for three letters in a row for either player do not work in that manner. Either a test needed to be made for each box for a certain row needed to tested for an "X" or an "O", and then if that test was true the test needed to be continued for the next box in the row, and then again for the third box in the row. In lieu of that route, the test was revised to basically say "if the character in the first box in the row is the same as the character in the second box in the row, and the character in the second box in the row is the same as the character in the third box in the row, and the first box does not contain a digit character (which means is contains an "X" or an "O"), then there is a winner.
It appears that an attempt was made to mirror the contents of "Player1" and "Player2" into an array of player structures. Although initially, structure "users[0]" contained the same data as "Player1" and structure "users[1]" contained the same data as "Player2", once the data in "Player1" and "Player2" were updated, those changes did to propagate over to the "users" array. So to utilize "users" in the spirit of this program, they were defined as pointers to their respective player structures.
Those were the most significant bits. The other bits were added for a logical conclusion of the game. Note that no logic was added for a draw.
Give that a test and see if that clarifies things and follows the spirit of the project.
Brief Explanation of the Problem - The aim of the code is to make a basic tic tac toe game using C. There are two players X and O , both can enter various numbers as choice from 1-9 for each individual chance.
The game board is similar to a 3 x 3 matrix, where -
Row 1 is for 1 to 3.
Row 2 is for 4 to 6.
Row 3 is for 7 to 9.
Any number except 1-9 will throw an error and will prompt the user to re-enter the number. Unfortunately, I'm getting the same Invalid input error for a valid input. Everything else seems to work except my loop.
Here's the code for reference -
#include<stdio.h> //Tic Tac Toe
#include<stdlib.h>
#include<conio.h>
char square[10] = {'0','1','2','3','4','5','6','7','8','9'};
int choice, player;
int checkForWin();
void displayBoard();
void mrkBoard(char mark);
int main()
{
int i;
char mark;
player = 1;
do
{
displayBoard();
player = (player % 2) ? 1:2;
printf("Player %d, enter the number: ",player);
scanf("%d",&choice);
mark = (player == 1) ? 'X' : 'O';
mrkBoard(mark);
i = checkForWin();
player++;
}while(i == -1);
return 0;
}
int checkForWin()
{
int returnValue = 0;
if (square[1] == square[2] && square[2] == square[3])
{
returnValue = 1;
}
else if (square[4] == square[5] && square[5] == square[6])
returnValue = 1;
else if (square[7] == square[8] && square[8] == square[9])
returnValue = 1;
else if (square[1] == square[5] && square[5] == square[9])
returnValue = 1;
else if (square[3] == square[5] && square[5] == square[7])
returnValue = 1;
else if (square[1] == square[4] && square[4] == square[7])
returnValue = 1;
else if (square[2] == square[5] && square[5] == square[8])
returnValue = 1;
else if (square[3] == square[6] && square[6] == square[9])
returnValue = 1;
else if(square[1] != '1' && square[2] != '2' && square[3] != '3' && square[4] != '4' &&
square[5] != '5' && square[6] != '6' && square[7] != '7' &&
square[8] != '8' && square[9] != '9')
returnValue = 0;
else
returnValue = -1;
return returnValue;
}
void displayBoard()
{
system("cls");
printf("\n\nTic Tac Toe\n\n");
printf("Player 1 (X) - Player 2 (O)\n\n\n");
printf(" | | \n");
printf(" %c | %c | %c \n", square[1], square[2],square[3]);
printf("_____|_____|_____\n");
printf(" | | \n");
printf(" %c | %c | %c\n", square[4], square[5],square[6]);
printf("_____|_____|_____\n");
printf(" | | \n");
printf(" %c | %c | %c\n", square[7], square[8],square[9]);
printf(" | | \n\n");
}
void mrkBoard(char mark)
{
if (choice == 1 && square[1] == '1')
square[1] = mark;
else if (choice == 2 && square[1] == '2')
square[2] = mark;
else if (choice == 3 && square[1] == '3')
square[3] = mark;
else if (choice == 4 && square[1] == '4')
square[4] = mark;
else if (choice == 5 && square[1] == '5')
square[5] = mark;
else if (choice == 6 && square[1] == '6')
square[6] = mark;
else if (choice == 7 && square[1] == '7')
square[7] = mark;
else if (choice == 8 && square[1] == '8')
square[8] = mark;
else if (choice == 9 && square[1] == '9')
square[9] = mark;
else
{
printf("Invalid ");
player--;
getch();
}
}
#include<stdio.h> //Tic Tac Toe
#include<stdlib.h>
#include<conio.h>
char square[10] = {'0','1','2','3','4','5','6','7','8','9'};
int choice, player;
int checkForWin();
void displayBoard();
void mrkBoard(char mark);
int main()
{
int i;
char mark;
player = 1;
do
{
displayBoard();
player = (player % 2) ? 1:2;
printf("Player %d, enter the number: ",player);
scanf("%d",&choice);
mark = (player == 1) ? 'X' : 'O';
mrkBoard(mark);
i = checkForWin();
player++;
}while(i == -1);
return 0;
}
int checkForWin()
{
int returnValue = 0;
if (square[1] == square[2] && square[2] == square[3])
{
returnValue = 1;
}
else if (square[4] == square[5] && square[5] == square[6])
returnValue = 1;
else if (square[7] == square[8] && square[8] == square[9])
returnValue = 1;
else if (square[1] == square[5] && square[5] == square[9])
returnValue = 1;
else if (square[3] == square[5] && square[5] == square[7])
returnValue = 1;
else if (square[1] == square[4] && square[4] == square[7])
returnValue = 1;
else if (square[2] == square[5] && square[5] == square[8])
returnValue = 1;
else if (square[3] == square[6] && square[6] == square[9])
returnValue = 1;
else if(square[1] != '1' && square[2] != '2' && square[3] != '3' && square[4] != '4' &&
square[5] != '5' && square[6] != '6' && square[7] != '7' &&
square[8] != '8' && square[9] != '9')
returnValue = 0;
else
returnValue = -1;
return returnValue;
}
void displayBoard()
{
system("cls");
printf("\n\nTic Tac Toe\n\n");
printf("Player 1 (X) - Player 2 (O)\n\n\n");
printf(" | | \n");
printf(" %c | %c | %c \n", square[1], square[2],square[3]);
printf("_____|_____|_____\n");
printf(" | | \n");
printf(" %c | %c | %c\n", square[4], square[5],square[6]);
printf("_____|_____|_____\n");
printf(" | | \n");
printf(" %c | %c | %c\n", square[7], square[8],square[9]);
printf(" | | \n\n");
}
void mrkBoard(char mark)
{
if (choice == 1 && square[1] == '1')
square[1] = mark;
else if (choice == 2 && square[2] == '2')
square[2] = mark;
else if (choice == 3 && square[3] == '3')
square[3] = mark;
else if (choice == 4 && square[4] == '4')
square[4] = mark;
else if (choice == 5 && square[5] == '5')
square[5] = mark;
else if (choice == 6 && square[6] == '6')
square[6] = mark;
else if (choice == 7 && square[7] == '7')
square[7] = mark;
else if (choice == 8 && square[8] == '8')
square[8] = mark;
else if (choice == 9 && square[9] == '9')
square[9] = mark;
else
{
printf("Invalid ");
player--;
getch();
}
}
Issue: I'm trying to utilize recTest to check and return the winner of a simple Tic-Tac-Toe game.
I'm just unsure of what I need to pass in the call (line I've highlighted), and how to integrate my public square array.
I apologize if this is overly simple, I'm just having a rough time connecting the dots.
#include<stdio.h>
#include<conio.h>
char square[10] = {'o', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
// returns -1 if no v[i] satisfies p
// returns i if v[i] satisfies p (picks largest i)
// (i>=0) and (i<n)
const int numwinpos = 8;
const int winpos[8][3] = {{1,2,3},
{4,5,6},
{7,8,9},
{1,4,7},
{2,5,8},
{3,6,9},
{1,5,9},
{3,5,7}};
//Function below, and variables above<--------------------------------------
int recTest(const int v[], const int n){
if( (n>0) && (!p(v[n-1])) )
return recTest(v,n-1);
else
return n-1;
}
/*int winnerCheck() {
//not even hard-coded tho...
if (square[1] == square[2] && square[2] == square[3])
return 1;
else if (square[4] == square[5] && square[5] == square[6])
return 1;
else if (square[7] == square[8] && square[8] == square[9])
return 1; //above 3 check across
else if (square[1] == square[4] && square[4] == square[7])
return 1;
else if (square[2] == square[5] && square[5] == square[8])
return 1;
else if (square[3] == square[6] && square[6] == square[9])
return 1; //above 3 check down
else if (square[1] == square[5] && square[5] == square[9])
return 1;
else if (square[3] == square[5] && square[5] == square[7])
return 1; //above 2 check diagonal
else if (square[1] != '1' && square[2] != '2' && square[3] != '3' && square[4]
!= '4' && square[5] != '5' &&
square[6] != '6' && square[7] != '7' && square[8]
!= '8' && square[9] != '9')
return 0;
else
//exit
return -1;
}
*/
void board() {
printf("\n\n\tTic Tac Toe\n\n");
printf("Player 1 (X) - Player 2 (O)\n\n\n");
//prints the board after every input
printf(" | | \n");
printf(" %c | %c | %c \n", square[1], square[2],square[3]);
printf("____|_____|____\n");
printf(" | | \n");
printf(" %c | %c | %c \n", square[4], square[5],square[6]);
printf("____|_____|____\n");
printf(" | | \n");
printf(" %c | %c | %c \n", square[7], square[8],square[9]);
printf(" | | \n");
}
int main() {
/*
char board[3][3] = {
};
printf("\t|\t|\t\n");
printf("\t|\t|\t\n");
printf("________|_______|________\n");
printf("\t|\t|\t\n");
printf("\t|\t|\t\n");
printf("________|_______|________\n");
printf("\t|\t|\t\n");
printf("\t|\t|\t\n");
printf("\t|\t|\t\n");
*/
int player = 1, i, choice;
char mark;
do {
board();
player = player % 2 ? 1 : 2;
printf("Player %d, enter a number: ", player);
scanf("%d", &choice);
//mark = (player == 1) ? 'X' : 'O';
if (player == 1) {
mark = 'X';
} else {
mark = 'O';
}
if (choice == 1)
square[1] = mark;
else if (choice == 2)
square[2] = mark;
else if (choice == 3)
square[3] = mark;
else if (choice == 4)
square[4] = mark;
else if (choice == 5)
square[5] = mark;
else if (choice == 6)
square[6] = mark;
else if (choice == 7)
square[7] = mark;
else if (choice == 8)
square[8] = mark;
else if (choice == 9)
square[9] = mark;
i = recTest(square, numwinpos); //HERE <--------------------------------------
player++;
} while (i == -1);
board();//call board
if (i == 1)
printf("----->\aPlayer %d WINS!<-----", --player);//nice alert sound when printed
else
printf("----->\aC-could it be...? Game draw!<-----");//nice alert sound when printed
//getch();//waits for user input before ending
return 0;
}
A quick and dirty way to use recursion would be to do something like below... and yes this can be optimized..
int winnerCheck(int x)
{
if(x < numwinpos)
{
if((square[winpos[x][0]] == 'x') && (square[winpos[x][1]] == 'x') && (square[winpos[x][2]] == 'x') ||
(square[winpos[x][0]] == 'o') && (square[winpos[x][1]] == 'o') && (square[winpos[x][2]] == 'o'))
return 1;
else
{
return winnerCheck(++x);
}
}
return 0;
}
The actual text file is just random stuff to test the lex and parse. The pic above is the result, the console is giving me during runtime. In the green it is calling an Identifier when it should be a newline or delim, so nothing should be needed. In the red it is not recognizing the separator, and in the yellow its not reading the something.something at all. I'm assuming it has something to do with with the previous c; not being seperated right.
So my question is how do I properly separate the tokens, and recognize the newline, or what am I doing wrong. Below is the code that I am using to do the separating and tokenizing.
#define _CRT_SECURE_NO_WARNINGS
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define BUFFER_SIZE 1024
// Returns 'true' if the character is a DELIMITER.
bool isDelimiter(char ch)
{
if (isspace (ch))
return (true);
return (false);
}
// Returns 'true' if the character is a SEPERATOR.
bool isSeperator(char str)
{
if (str == ',' || str == ';' || str == '>' ||
str == '<' || str == '(' || str == ')' || str == '[' || str == ']' ||
str == '{' || str == '}' || str == '.' )
return (true);
return (false);
}
// Returns 'true' if the character is an OPERATOR.
bool isOperator(char ch)
{
if (ch == '+' || ch == '-' || ch == '*' ||
ch == '/' || ch == '>' || ch == '<' ||
ch == '=')
return (true);
return (false);
}
// Returns 'true' if the string is a VALID IDENTIFIER.
bool validIdentifier(char* str)
{
if (str[0] == '0' || str[0] == '1' || str[0] == '2' ||
str[0] == '3' || str[0] == '4' || str[0] == '5' ||
str[0] == '6' || str[0] == '7' || str[0] == '8' ||
str[0] == '9' )
return (false);
return (true);
}
// Returns 'true' if the string is a KEYWORD.
bool isKeyword(char* str)
{
if (!strcmp(str, "if") || !strcmp(str, "else") ||
!strcmp(str, "while") || !strcmp(str, "do") ||
!strcmp(str, "break") || !strcmp(str, "elem") ||
!strcmp(str, "lout") || !strcmp(str, "file") ||
!strcmp(str, "console") || !strcmp(str, "read") ||
!strcmp(str, "write") || !strcmp(str, "mark") ||
!strcmp(str, "emblemnize") || !strcmp(str, "lin") ||
!strcmp(str, "send") || !strcmp(str, "dint") ||
!strcmp(str, "continue") || !strcmp(str, "int")
|| !strcmp(str, "double") || !strcmp(str, "float")
|| !strcmp(str, "return") || !strcmp(str, "char")
|| !strcmp(str, "case") || !strcmp(str, "char")
|| !strcmp(str, "sizeof") || !strcmp(str, "long")
|| !strcmp(str, "short") || !strcmp(str, "typedef")
|| !strcmp(str, "switch") || !strcmp(str, "unsigned")
|| !strcmp(str, "void") || !strcmp(str, "static")
|| !strcmp(str, "struct") || !strcmp(str, "goto"))
return (true);
return (false);
}
// Returns 'true' if the string is an INTEGER.
bool isInteger(char* str)
{
int i, len = strlen(str);
if (len == 0)
return (false);
for (i = 0; i < len; i++) {
if (str[i] != '0' && str[i] != '1' && str[i] != '2'
&& str[i] != '3' && str[i] != '4' && str[i] != '5'
&& str[i] != '6' && str[i] != '7' && str[i] != '8'
&& str[i] != '9' || (str[i] == '-' && i > 0))
return (false);
}
return (true);
}
// Returns 'true' if the string is a REAL NUMBER.
bool isRealNumber(char* str)
{
int i, len = strlen(str);
bool hasDecimal = false;
if (len == 0)
return (false);
for (i = 0; i < len; i++) {
if (str[i] != '0' && str[i] != '1' && str[i] != '2'
&& str[i] != '3' && str[i] != '4' && str[i] != '5'
&& str[i] != '6' && str[i] != '7' && str[i] != '8'
&& str[i] != '9' && str[i] != '.' ||
(str[i] == '-' && i > 0))
return (false);
if (str[i] == '.')
hasDecimal = true;
}
return (hasDecimal);
}
// Extracts the SUBSTRING.
char* subString(char* str, int left, int right)
{
int i;
char* subStr = (char*)malloc(sizeof(char) * (right - left + 2));
for (i = left; i <= right; i++)
subStr[i - left] = str[i];
subStr[right - left + 1] = '\0';
return (subStr);
}
// Parsing the input STRING.
void parse(char* str)
{
int left = 0, right = 0;
int len = strlen(str);
while (right <= len && left <= right)
{
if (isDelimiter(str[right]) == false)
right++;
if (isDelimiter(str[right]) == true && left == right)
{
if (isOperator(str[right]) == true)
printf("'%c' IS A OPERATOR\n", str[right]);
right++;
left = right;
}
if (isDelimiter(str[right]) == true && left == right)
{
if (isDelimiter(str[right]) == true)
printf("'%c' IS A DELIMITER\n", str[right]);
right++;
left = right;
}
if (isSeperator(str[right]) == true && left == right)
{
//needed to recognize seperator to the right
if (isSeperator(str[right]) == true)
printf("'%c' IS A SEPERATOR\n", str[right]);
right++;
left = right;
//needed to recognize seperator to the left
if (isSeperator(str[right]) == true)
printf("'%c' IS A SEPERATOR\n", str[left]);
right++;
left = right;
}
else if (isDelimiter(str[right]) == true && left != right
|| (right == len && left != right)) {
char* subStr = subString(str, left, right - 1);
if (isKeyword(subStr) == true)
printf("'%s' IS A KEYWORD\n", subStr);
else if (isInteger(subStr) == true)
printf("'%s' IS AN INTEGER\n", subStr);
else if (isRealNumber(subStr) == true)
printf("'%s' IS A REAL NUMBER\n", subStr);
else if (validIdentifier(subStr) == true
&& isDelimiter(str[right - 1]) == false
&& isSeperator(str[right - 1]) == false)
printf("'%s' IS A VALID IDENTIFIER\n", subStr);
left = right;
}
}
return;
}
int main(int argc, char *argv)
{
/* declare a file pointer */
FILE *file;
char *buffer;
long numbytes;
/* open an existing file for reading */
file = fopen("Text.txt", "r");
/* quit if the file does not exist */
if (file == NULL)
return 1;
/* Get the number of bytes */
fseek(file, 0L, SEEK_END);
numbytes = ftell(file);
/* reset the file position indicator to
the beginning of the file */
fseek(file, 0L, SEEK_SET);
/* grab sufficient memory for the
buffer to hold the text */
buffer = (char*)calloc(numbytes, sizeof(char));
/* memory error */
if (buffer == NULL)
return 1;
/* copy all the text into the buffer */
fread(buffer, sizeof(char), numbytes, file);
/* confirm we have read the file by
outputing it to the console */
printf(" The file called Text.txt contains this text \n \n %s \n\n", buffer);
parse(buffer); // calling the parse function
fclose(file);
/* free the memory we used for the buffer */
free(buffer);
return 0;
}
Looks like the problem is your isDelimiter function isn't picking up all possible values. If you change it to use isspace() it will match on all forms of whitespace.
bool isDelimiter(char ch)
{
if (isspace(ch))
return (true);
return (false);
}
As an example, here is a very simple state machine to give you an idea of what sort of thing I meant. It can be in either of one of two states - INSIDE_IDENTIFIER or OUTSIDE_IDENTIFIER - and it switches between those two states depending on what kind of character it is looking at.
#define OUTSIDE_IDENTIFIER (0)
#define INSIDE_IDENTIFIER (1)
void parse(char *str)
{
char *ch;
int state=OUTSIDE_IDENTIFIER;
char buffer[1000];
char *pos=buffer;
for(ch=str;*ch!='\0';ch++)
{
switch(state)
{
case INSIDE_IDENTIFIER:
if(isOperator(*ch))
{
*pos='\0';
printf("Identifier[%s]\n",buffer);
printf("Operator[%c]\n",*ch);
state=OUTSIDE_IDENTIFIER;
}
else if(isDelimiter(*ch))
{
*pos='\0';
printf("Identifier[%s]\n",buffer);
printf("Delimiter[%c]\n",*ch);
state=OUTSIDE_IDENTIFIER;
}
else if(isspace(*ch))
{
*pos='\0';
printf("Identifier[%s]\n",buffer);
printf("Space[%d]\n",*ch);
state=OUTSIDE_IDENTIFIER;
}
else
{
*pos=*ch;
pos++;
}
break;
case OUTSIDE_IDENTIFIER:
default:
if(isOperator(*ch))
{
printf("Operator[%c]\n",*ch);
}
else if(isDelimiter(*ch))
{
printf("Delimiter[%c]\n",*ch);
}
else if(isSeperator(*ch))
{
printf("Seperator[%c]\n",*ch);
}
else
{
state = INSIDE_IDENTIFIER;
pos=buffer;
*pos=*ch;
pos++;
}
break;
}
}
}
I'm new to C and programming and I tried to code a simple TicTacToe game. I new that I defintaly did many dumb things.
So I have a main .c file and two header files, which I will post here:
main.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "game.h"
#include "random.h"
#define NAMELENGTH 20
int main(void) {
char names[2][NAMELENGTH];
// field positions
char field[9];
int winner = -2;
getnames(names);
printf("\n\n");
initField(field);
// set field positions to 'empty'
char actualPlayer = (char)(get_random_number()*10.0) % 2;
while (1) {
drawField(field);
turn(actualPlayer, names, field);
winner = isWinner(actualPlayer, field);
drawField(field);
if (winner >= 0) {
printwinner(winner, names);
return 0;
}
else if (winner == -1) {
printDrawGame(names);
return 0;
}
actualPlayer = (actualPlayer + 1) % 2;
system("cls");
}
return 0;
}
game.h:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NAMELENGTH 20
#pragma warning(disable:4996)
void drawField(char *field) {
printf("________________________\n");
printf("| | | |\n");
printf("| %c | %c | %c |\n", field[1], field[2], field[3]);
printf("|_______|_______|______|\n");
printf("| | | |\n");
printf("| %c | %c | %c |\n", field[4], field[5], field[6]);
printf("|_______|_______|______|\n");
printf("| | | |\n");
printf("| %c | %c | %c |\n", field[7], field[8], field[9]);
printf("|_______|_______|______|\n");
}
void getnames(char nameField[][NAMELENGTH]) {
printf("Name of the first player: ");
scanf("%s", &nameField[0]);
printf("Name of the second player: ");
scanf("%s", &nameField[1]);
}
void initField(char *field) {
for (int i = 1; i < 10; i++)
{
field[i] = i+48;
}
}
void turn(char actualPlayer, char names[][NAMELENGTH], char *field) {
char symbol = ' ';
int k;
int m;
if (actualPlayer == 1)
{
do {
printf("\nIts Player %s's turn.", names[0]);
char symbol = 'X';
printf("\nNumber of the field which you want to put your symbol in: ");
scanf("%i", &k);
if (field[k] == 'X' || field[k] == 'O')
{
printf("\nField is already occupied!");
k = 10;
}
} while (k < 1 || k > 9);
field[k] = 'X';
}
else {
do {
printf("\nIts Player %s's turn.", names[1]);
char symbol = 'O';
printf("\nNumber of the field which you want to put your symbol in: ");
scanf("%i", &m);
if (field[m] == 'X' || field[m] == 'O')
{
printf("\nField is already occupied!");
m = 10;
}
} while (m < 1 || m > 9);
field[m] = 'X';
}
}
int isWinner(char actualPlayer, char *field) {
int w = 2;
if (((field[1] = 'O') && (field[2] = '0') && (field[3] = '0')) || (field[4] = '0') && (field[5] = '0') && (field[6] = '0') || (field[7] = '0') && (field[8] = '0') && (field[9] = '0') || (field[1] = '0') && (field[5] = '0') && (field[9] = '0') || (field[3] = '0') && (field[5] = '0') && (field[7] = '0') || (field[1] = '0') && (field[4] = '0') && (field[7] = '0') || (field[2] = '0') && (field[5] = '0') && (field[8] = '0') || (field[3] = '0') && (field[6] = '0') && (field[9] = '0'))
{
int w = 1;
}
if (((field[1] = 'X') && (field[2] = 'X') && (field[3] = 'X')) || (field[4] = 'X') && (field[5] = 'X') && (field[6] = 'X') || (field[7] = 'X') && (field[8] = 'X') && (field[9] = 'X') || (field[1] = 'X') && (field[5] = 'X') && (field[9] = 'X') || (field[3] = 'X') && (field[5] = 'X') && (field[7] = 'X') || (field[1] = 'X') && (field[4] = 'X') && (field[7] = 'X') || (field[2] = 'X') && (field[5] = 'X') && (field[8] = 'X') || (field[3] = 'X') && (field[6] = 'X') && (field[9] = 'X'))
{
int w = 0;
}
else
{
int w = -1;
}
return w;
}
void printwinner(char winnerNumber, char names[][NAMELENGTH]) {
if (winnerNumber == 0)
{
printf("Player %s won!", names[0]);
system("exit");
}
else if (winnerNumber == 1)
{
printf("Player %s won!", names[1]);
system("exit");
}
}
void printDrawGame(char names[][NAMELENGTH]) {
printf("Draw!");
system("exit");
}
and random.h:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
static int _initialized;
void init() {
srand(time(NULL));
_initialized = 1;
}
double get_random_number() {
init();
if (!_initialized)
printf("Warning: init() should be called first!\n");
double random;
random = (double)rand() / ((double)(RAND_MAX)+1);
return random;
}
So the Program itself runs till I type in which field I want to put in the symbol. I get a weird error ("Stack around the variable 'field' was corrupted.") and also the random function doesnt work like I want. Would be happy and thankful for you help guys :)
You declared field to be an array of 9 elements. The indices will be 0 to 8. In game.h you have a function initField in which you do:
for (int i = 1; i < 10; i++)
{
field[i] = i+48;
}
This will produce indices 1 to 9, which steps out of bounds for the array.
You reinitialize the random number generator each time it is called. You pseudo random values will not be very random I'm afraid.
Fix it this way:
static int _initialized;
double get_random_number() {
if (!_initialized) {
srand(time(NULL));
_initialized = 1;
}
return = (double)rand() / ((double)(RAND_MAX)+1);
}
You should not write code in header files. Declarations belong in header files, code belongs in source files with the extension .c.