Saving Data in a Basic Tic-Tac-Toe Game - c

I'm relatively new to C. In Kochan's "Programming in C" I'm currently on if-else statements. I'm trying to program a basic tic-tac-toe game but I've run into some difficulty. I'm not sure how to save the board once a player has placed an x or an o. Here's the code I have so far:
#include <stdio.h>
int main (void)
{
int board = "_|_|_\n
_|_|_\n
| | \n";
int player1, player2;
printf ("Print %i", board)
printf("Player 1, it's your move:")
scanf("%i", player1)
if(player1 == "upLeft")
printf("x|_|_\n
_|_|_\n
_|_|_\n
etc.
Am I still too much of a beginner to implement this feature?

First of all, this doesn't make sense:
int board = "_|_|_\n
_|_|_\n
| | \n";
An int is not a string, and you can't assign a string to an int. In C, strings are arrays of characters:
char board[] = "_|_|_\n_|_|_\n | | \n";
That makes more sense. But it's really not a good way to store the state of a tic tac toe board. What you should do instead is store some value for each position on the board. Don't worry about the actual format of the board, you can format it as you like when you display it. So store your board this way:
char board[9] = "---------";
where a "-" means the space is empty. When the player moves, you replace the character at the appropriate position in the array with an "X" or an "O" (or 1 and 2, or any other values that work for you). When you get some input from the user, you'll change just the corresponding value in the board array. If you number the positions 0-8 starting from the top left corner, the rightmost position in the middle row would be position 5, for example. (Remember, C arrays are zero-based, so the first index is 0.) So if the user wants to put an X at that spot, you'd say:
board[5] = 'X';
Next, you might want to write a function that prints the board. That is where you'll insert whatever characters you like to draw the board.
Finally, you're going to want to use some sort of loop to repeatedly read the user's input, modify the state of the board, print the board, and maybe display a prompt.

First-things-first, you cannot store
"_|_|_\n
_|_|_\n
| | \n";
in an integer variable. You need variables of other types (like char *, char a[][], etc).
OTOH, the pseudocode is as follows. Please try and follow this to write a C program on your own.
Let row = 3 and column = 3
Declare an array[row][column] and fill it all with 0
Let 1 represent the input of user-1 and 2 represent the input of user-2 (in the array)
i.e. if a[2][2] = 1 means, user-1 marked that location.
while ( ! all_locations_filled() ) {
take input from user-1
if user-1 chooses a valid_location(location) to mark, then mark_location(user-1, location)
check if user-1 won_the_game(user-1), if so break and congratulate user-1!
take input from user-2
if user-2 chooses a valid_location(location) to mark, then mark_location(user-2, location)
check if user-2 won_the_game(user-2), if so break and congratulate user-2!
}
valid_location(location l)
{
return array[l.row][l.column] == 0;
}
mark_location(user u, location l)
{
array[l.row][l.column] = (u==user-1) ? 1 : 2;
}
display_board()
{
for i=0 to row
for j=0 to col
if array[i][j] == 0 print ""
else print array[i][j]
/* print blank when that location is not yet marked */
}
all_locations_filled()
{
for i=0 to row
for j=0 to col
if array[i][j] == 0
return false
return true
}
won_the_game(user u)
{
/* You need to write the logic here */
:P
}

You can use a 2d array to represent the board, and maybe some small int, with 0 as nothing there, 1 as X and 2 as 0.
You cant save the like that
int board = "X|_|_\n
_|_|_\n
| | \n";
you can have something like board[0][0]=1;
then you can iterate that array and if its 1 print the X.

It's a bit of a beginner question, but you're a beginner, so that's okay! Let's go with some leading questions:
So, you're saying you want to save the board state. What do you want to save? At any point in the program, what do you want to be able to look up? The history of the moves? What the board looks like? What each corner contains? Each of these suggests a different way to change a variable when you get some input from the user.
As other people have said, you can't do all those things with int type, and even if you could, this program is still way too hard and frustrating until you have a few more tools in your toolbox. Chapter 7 is Arrays, which will be very useful, and Chapter 10 is Character Strings, which will show you how to deal with all these strings the right way in C. So my suggestion to you is go through a few more chapters of the book and the big picture will start to make a bit more sense. Happy hacking!

Here is a small template like thing I have given write your own logic inside the GetBestMove() function for the computers move (if you are building AI) else replace the call for the GetBestMove by GetMove function in the StartGame function
#include<stdio.h>
#define HUMAN_WIN 1
#define DRAW 0
#define HUMAN_LOSE -1
#define HUMAN_COIN 'X'
#define COMP_COIN 'O'
#define DEFAULT 0xFFF
int main(void)
{
StartGame();
}
enum turnOf{ Human = 0, Computer};
enum gameEndState{Lose = -1, Draw, Win};
int humanMove = 1;
int computerMove = 1;
char _board[3][3] = {'-', '-', '-', '-', '-', '-', '-', '-', '-'};
void StartGame()
{
enum turnOf turn = 0;
enum gameEndState state = -2;
while(1)
{
turn = 1 - turn;
if(turn == Human)
{
GetMove();
UpdateBoard(humanMove, turn);
}
else if(turn == Computer)
{
GetBestMove(turn);
UpdateBoard(computerMove, turn, _board);
}
state = win(_board);
switch(state)
{
case Win:
NotifyUser("You win.");exit(0);
case Draw:
NotifyUser("Match draw.");exit(0);
case Lose:
NotifyUser("You Lose.");exit(0);
}
}
}
int depth = 0;
int GetBestMove(enum turnOf turn, int *x, int *y)
{
depth++;
int i, j, MOV = -10, BESTMOVx, BESTMOVy;
enum turnOf now = turn;
char pebble = (now == Human) ? HUMAN_COIN : COMP_COIN;
for(i=0; i<3; i++)
{
for(j=0; j<3; j++)
{
if(_board[i][j] == '-')
{
_board[i][j] = pebble;
now = 1 - now;
int condition = win(_board);
if(condition != DRAW || condition != DEFAULT)
{
return (condition == HUMAN_LOSE) ? (depth - 10) : (10 - depth);
}
else
{
int state = GetBestMove(now, BESTMOVx, BESTMOVy);
if(state > MOV)
{
MOV = state;
}
}
}
}
}
}
int win(char a[3][3])
{
char pebble = HUMAN_COIN;
int i, j, p = 0;
i=0;
for(j = 0; j < 3; j++)
if(a[i][j] == pebble && a[i+1][j] == pebble && a[i+2][j] == pebble) return HUMAN_WIN;
j=0;
for(i = 0; i < 3; i++)
if(a[i][j] == pebble && a[i][j+1] == pebble && a[i][j+2] == pebble) return HUMAN_WIN;
if(a[0][0] == pebble && a[1][1] == pebble && a[2][2] == pebble) return HUMAN_WIN;
else if(a[0][2] == pebble && a[1][1] == pebble && a[2][0] == pebble) return HUMAN_WIN;
/// Recheck for lose
pebble = COMP_COIN;
i=0;
for(j = 0; j < 3; j++)
if(a[i][j] == pebble && a[i+1][j] == pebble && a[i+2][j] == pebble) return HUMAN_LOSE;
j=0;
for(i = 0; i < 3; i++)
if(a[i][j] == pebble && a[i][j+1] == pebble && a[i][j+2] == pebble) return HUMAN_LOSE;
if(a[0][0] == pebble && a[1][1] == pebble && a[2][2] == pebble) return HUMAN_LOSE;
else if(a[0][2] == pebble && a[1][1] == pebble && a[2][0] == pebble) return HUMAN_LOSE;
for(i = 0; i < 3; i++)
for(j = 0; j < 3; j++)
if(a[i][j] == '-') p++;
if(p == 0) return DRAW;
return DEFAULT;
}
void GetMove()
{
int x, y;
LoadFrame(_board);
printf("\nEnter your move : ");
humanMove = getche() - 48;
if(!(humanMove > 0 && humanMove < 10))
{
NotifyUser("Enter a valid location.");
GetMove();
}
GetCordinates(&x, &y, humanMove);
if(_board[x][y] != '-')
{
NotifyUser("The place is nonEmpty.");
GetMove();
}
}
void UpdateBoard(int move, enum turnOf player, char board[3][3])
{
int x, y;
char pebble = (player == Human) ? HUMAN_COIN : COMP_COIN;
GetCordinates(&x, &y, move);
board[x][y] = pebble;
LoadFrame(board);
}
void LoadFrame(char board[3][3])
{
int x, y;
system("cls");
for(x = 0; x < 3; x++)
{
printf("\n\t ");
for(y = 0; y < 3; y++)
{
printf(" %c ", board[x][y]);
}
}
}
void GetCordinates(int *x, int *y, int move)
{
switch(move)
{
case 1: *x = 0; *y = 0; break;
case 2: *x = 0; *y = 1; break;
case 3: *x = 0; *y = 2; break;
case 4: *x = 1; *y = 0; break;
case 5: *x = 1; *y = 1; break;
case 6: *x = 1; *y = 2; break;
case 7: *x = 2; *y = 0; break;
case 8: *x = 2; *y = 1; break;
case 9: *x = 2; *y = 2; break;
}
}
void NotifyUser(const char* message)
{
printf("\n\n%s\a", message);
getch();
system("cls");
LoadFrame(_board);
}

Related

how to see if there are 1 or 2 poker pairs in a hand in C

I am trying to develop a C program that checks if there are 1 or 2 pairs in a 5 card poker hand.
I am using a 5x3 array where every line is a card (the 3rd column being for the \0 character). Every time I execute the code it always shows the "two pairs" print.
I want to make sure that each letter (i, j, a, b) representing each line is different. Any help?
P.S.: This is for a university/college project, I have only started programming a few months ago from absolute scratch, so any detailed explanations on my mistakes would be very much appreciated :)
#include <stdio.h>
#include <stdlib.h>
char (cards[5][3])=
{
"5S", "6D", "4H", "KD", "5C"
};
int main ()
{
pair (cards[5][3]);
return 0;
}
void pair (char (arg[n][0]))
{
int i,j,a,b;
if (i!=j!=a!=b)
{
if ((arg[i][0]==arg[a][0])&&(arg[b][0]!=arg[j][0]))
{
printf("2 -> pair");
}
if ((arg[i][0]==arg[a][0])&&(arg[b][0]==arg[j][0]));
{
printf("3 -> two pairs");
}
if ((arg[i][0]!=arg[a][0])&&(arg[b][0]!=arg[j][0]))
{
printf("there is no pair");
}
}
else
{
printf("there is no pair");
}
}
The posted code has several issues, both logical and syntactical, some have been pointed out in the comments.
Just to pick one, consider this line
if ((arg[i][0]==arg[a][0])&&(arg[b][0]==arg[j][0]));
{
// This body will never be executed ^
}
I'd suggest to restart from scratch and to proceed in small steps. See, for instance, the following minimal implementation
// Include all the needed header files, not the unneeded ones.
#include <stdio.h>
// Declare the functions prototype before their use, they will be defined after.
int count_pairs(int n, char const cards[][3]);
// Always specify the inner size, ^ when passing a multidimensional array
void show_score(int n_pairs);
int have_the_same_value(char const *a, char const *b);
int main (void)
{
char hand[5][3] = {
// ^^^^^^ You could omit the 5, here
"5S", "6D", "4H", "KD", "5C"
};
int n_pairs = count_pairs(5, hand);
// Always pass the size ^ if there isn't a sentinel value in the array
show_score(n_pairs);
return 0;
}
// This is a simple O(n^2) algorithm. Surely not the best, but it's
// a testable starting point.
int count_pairs(int n, char const cards[][3])
{
// Always initialize the variables.
int count = 0;
// Pick every card...
for (int i = 0; i < n; ++i)
{
// Compare (only once) with all the remaining others.
for (int j = i + 1; j < n; ++j)
{ // ^^^^^
if ( have_the_same_value(cards[i], cards[j]) ) {
++count;
}
}
}
return count;
}
int have_the_same_value(char const *a, char const *b)
{
return a[0] == b[0];
}
// Interpret the result of count_pairs outputting the score
void show_score(int n_pairs)
{
switch (n_pairs)
{
case 1:
printf("one pair.\n");
break;
case 2:
printf("two pairs.\n");
break;
case 3:
printf("three of a kind.\n");
break;
case 4:
printf("full house.\n");
break;
case 6:
printf("four of a kind.\n");
break;
default:
printf("no pairs.\n");
}
}
Note that my count_pairs function counts every possible pair, so if you pass three cards of the same kind, it will return 3 (given AC, AS, AD, all the possible pairs are AC AS, AC AD, AS AD).
How to correctly calculate all the poker ranks is left to the reader.
Major improvements can be made to the pair function to make it slimmer. However, this answers your questions and solves several corner cases:
#include <stdio.h>
#include <stdlib.h>
void pairCheck(char hand[][2])
{
int pairCount = 0;
int tmpCount = 0;
char tmpCard = '0';
char foundPairs[2] = {0};
// Check Hand One
for(int i =0; i < 5; i++)
{
tmpCard = hand[i][0];
for(int j = 0; j < 5; j++)
{
if(tmpCard == hand[j][0] && i != j)
{
tmpCount++;
}
if(tmpCount == 1 && (tmpCard != foundPairs[0] && tmpCard != foundPairs[1]))
{
foundPairs[pairCount] = tmpCard;
pairCount++;
}
tmpCount = 0;
}
}
printf("Pair Count Hand One: %i\r\n",pairCount);
//Reset Variables
foundPairs[0] = 0;
foundPairs[1] = 0;
tmpCard = '0';
pairCount = 0;
// Check Hand One
for(int i =0; i < 5; i++)
{
tmpCard = hand[i][1];
for(int j = 0; j < 5; j++)
{
if(tmpCard == hand[j][1] && i != j)
{
tmpCount++;
}
if(tmpCount == 1 && (tmpCard != foundPairs[0] && tmpCard != foundPairs[1]))
{
foundPairs[pairCount] = tmpCard;
pairCount++;
}
tmpCount = 0;
}
}
printf("Pair Count Hand Two: %i",pairCount);
}
int main ()
{
char cards[5][2] = { {'5','H'},{'6','D'},{'4','H'},{'K','D'},{'5','C'}};
pairCheck(cards);
return 0;
}
This function will treat three, four, or five of a kind as a single pair. If you want a different behavior the change should be easy.

Snake Game implementation in C

I need some help with some homework. I am supposed to make a Snake Game by using mostly "basic" c, only simple concepts.
To explain my thought process: Controls are the usual WASD. The grid we re playing in is an array. Head is represented by '#' and the tail by "*". What I am trying to do is implement this thinking:
Get input from user, move the head. Check in 4 possible directions of head's initial position, find the " * ", move it to the initial position of the head. Repeat till all '*' have been moved.
Obviously, I am doing something wrong while checking and/or moving, but I cannot quite figure out what parts I am treating wrong and after 2 days I am stuck with this as my closest to working version. I know I have been looking at it for too long, but I cant afford to take more time with it as it needs to be turned in.
Here is my code. I hope my error is very obvious to "fresh eyes".
main:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char *argv[]){
//get size of grid from args
int size;
size = atoi(argv[1]);
while(size < 6){
printf("Please insert a number greater than 6 so the game is
playable\n");
scanf("%d\n", &size);
}
char grid[size][size];
int sx,sy; //coordinates of snake head
int length = 2; //length of tail (without head)
int score = 0;
sx = 1;
sy = size/2;
//generate empty grid
int x, y;
for (y = 0; y < size; ++y) {
for (x = 0; x < size; ++x) {
if (y == 0 || y == size - 1) {
grid[y][x] = '-';
} else if (x == 0 || x == size - 1) {
grid[y][x] = '|';
} else {
grid[y][x] = ' ';
}
}
}
//initialize snake position
grid[sx][sy] = '#';
grid[sx+1][sy] = '*';
grid[sx+2][sy] = '*';
grid[sx+3][sy-6] = 'X';//just to test if it works, will be generated
randomly
//print grid
printGrid(size, grid);
play(sx,sy,size,grid,&length);
printf("*********GAME OVER********** \n final score: %d\n", score);
}
play() function. Practically all of the game.
int play(int x, int y, int size, char grid[size][size], int length){
int x0,y0,x1,y1,x2,y2,valid;//x0,y0 = current, x1,y1 next to check,
//x2,y2 = move there x0,y0
char end,dir; //what did the head land on
int score = 0;
int checkl = 0;
while(1){
scanf("%c", &dir);
switch(dir){
//move head, change head coordinates
case 'w': end = grid[x-1][y];
grid[x-1][y] = grid[x][y];
grid[x][y] = ' ';
x0 = x;
y0 = y;
x--;
break;
case 's': end = grid[x+1][y];
grid[x+1][y] = grid[x][y];
grid[x][y] = ' ';
x0 = x;
y0 = y;
x++;
break;
case 'a': end = grid[x][y-1];
grid[x][y-1] = grid[x][y];
grid[x][y] = ' ';
x0 = x;
y0 = y;
y--;
break;
case 'd': end = grid[x][y+1];
grid[x][y+1] = grid[x][y];
grid[x][y] = ' ';
x0 = x;
y0 = y;
y++;
break;
}
if ((end == '-') | (end =='|') | (end == '*')){
break;
}
printf("POINT 1\n");
do{
check(x0,y0,&x1,&y1, size, grid);
move(x0,y0, x2,y2, size, grid);
//if(valid == 1){
x2 = x0;
y2 = y0;
x0 = x1;
y0 = y1;
//}
checkl++;
printf("POINT 2\n");
}while(checkl <= length);
printf("POINT 3\n");
if (end == 'X'){
grid[x1][y1] = '*';
length++;
score += 10;
}
clearScreen();
printGrid(size, grid);
}
return score;
}
check() function. Implements the "look for the next '*'" process
int check(int x0, int y0, int *x1, int *y1, int size, char grid[size]
[size]){
if (grid[x0][y0-1] == '*'){
*x1 = x0;
*y1 = y0-1;
return 1;
}
else if (grid[x0][y0+1] == '*'){
*x1 = x0;
*y1 = y0+1;
return 1;
}
else if (grid[x0-1][y0] == '*'){
*x1 = x0-1;
*y1 = y0;
return 1;
}
else if (grid[x0+1][y0] == '*'){
*x1 = x0+1;
*y1 = y0;
return 1;
}
else
return 0;
}
move(). Self-explanatory
void move(int x0, int y0, int x2, int y2, int size, char grid[size]
[size]){
grid[x2][y2] = grid[x0][y0];
grid[x0][y0] = ' ';
}
A function to clear the window
void clearScreen()
{
const char *CLEAR_SCREEN_ANSI = "\e[1;1H\e[2J";
write(STDOUT_FILENO, CLEAR_SCREEN_ANSI, 12);
}
PrintGrid. Also self explanatory, have it as a function for convenience
void printGrid(int size, char grid[size][size]){
int y,x;
for (y = 0; y < size; ++y) {
for (x = 0; x < size; ++x) {
printf("%c", grid[y][x]);
}
printf("\n");
}
}
I believe the error is either in check, move, and in the do-while condition with the length in play. However, as I said, with a lot of trial and error, I am still here.
All of this should be in one file, but i could not align it properly all together. Thanks for any help, very appreciated.
Edit: Edited part of the code out. Now what happens after running the code is: I get the grid and the snake. The head moves just fine, along with the first '" of the tail but the rest does not follow. When it "eats" an 'X', it grows the tail where it should, but the '' added disappears in the next move. Also, the score goes up 20 instead of 10 so for some reason it enters the if twice for one move. The movement of the head + the first '*' as well as the "game over" scenarios work as they should.
Tidbit: This is only 10 actual characters, not 12 because the \ characters don't count:
const char *CLEAR_SCREEN_ANSI = "\e[1;1H\e[2J";
Better is to let the compiler count for you:
void clearScreen()
{
static const char CLEAR_SCREEN_ANSI[] = "\e[1;1H\e[2J";
write(STDOUT_FILENO, CLEAR_SCREEN_ANSI, sizeof(CLEAR_SCREEN_ANSI)-1);
}
Note that CLEAR_SCREEN_ANSI is now an array, not a pointer, and the -1 is for the trailing NUL byte.
Aha:
if ((end == '-') | (end =='|') | (end == '*')){
The | are bitwise OR and you almost certainly mean logical OR ||:
if ((end == '-') || (end =='|') || (end == '*')){
Edit: They actually do the same thing in this case, but it's a common-enough error that it's worth fixing.
Hat tip to #Sami Kuhmonen
I've spent some time looking at this, and it's clear this is entirely about program logic and less about C, so that makes it a lot more difficult to dive into something unfamiliar (and without a real spec).
The general idea is that the program draws a square playing field with a three-part snake: an # for a head and two * for the body, and the keyboard lets you move the snake around on the field with awds keys. You can't move on top of yourself, you can't go past the walls, and you want to find the food at location marked with X.
I believe your approach was to look for * characters, but I am not sure how it could tell a * from the middle of the snake from one at the end, so my approach is to maintain an array of all the positions of the snake, and in the main function it's initialized:
int ysnake[4] = { 1, 2, 3, 4 };
int xsnake[4] = { 15, 15, 15, 16 };
plus an obvious function to draw the snake given the position array:
static void drawsnake(
int snakelen, int xsnake[snakelen], int ysnake[snakelen],
int size, char grid[size][size])
{
char snakechar = '#'; // start with snake head
for (int i = 0; i < snakelen; i++)
{
grid[ ysnake[i] ]
[ xsnake[i] ] = snakechar;
snakechar = '*'; // all the rest are tails
}
}
So now we have the play() function, and this required quite a bit of refactoring, but it works for me.
int play(
int snakelen, int xsnake[snakelen], int ysnake[snakelen],
int size, char grid[size][size])
{
int score = 0;
while (1)
{
char dir;
scanf ("%c", &dir);
int proposed_xhead = xsnake[0];
int proposed_yhead = ysnake[0];
switch (dir)
{
case 'w': // up
proposed_yhead--;
break;
case 's': // down
proposed_yhead++;
break;
case 'a': // left
proposed_xhead--;
break;
case 'd': // right
proposed_xhead++;
break;
default: // ignore this invalid char
continue;
}
// first make sure we didn't go off the edge of the field
if (proposed_yhead <= 0 || proposed_yhead >= (size-1)
|| proposed_xhead <= 0 || proposed_xhead >= (size-1))
{
// would head off the maze, LOSE
break;
}
const char char_at_proposed_head = grid[proposed_yhead][proposed_xhead];
// now make sure we're not bumping into ourself
if (char_at_proposed_head == '#' // we shouldn't ever be able to bump into our head
|| char_at_proposed_head == '*') // we bumped into our tail
{
break; // would run into ourself: LOSE
}
// NOW we know it's a legal move. Did we find the food?
if (char_at_proposed_head == 'X')
{
// found the food!
// update score, set new food, etc.
score += 10;
}
// blank out the former tail; we're about to lose that position
grid[ ysnake[ snakelen-1 ] ]
[ xsnake[ snakelen-1 ] ] = ' ';
// shift all items down in the array, dropping the last one
for (int i = snakelen-1; i > 0; i--)
{
xsnake[i] = xsnake[i-1];
ysnake[i] = ysnake[i-1];
}
xsnake[0] = proposed_xhead;
ysnake[0] = proposed_yhead;
drawsnake(snakelen, xsnake, ysnake, size, grid);
clearScreen ();
printGrid (size, grid);
}
return score;
}
There's a clear separation of duties, where the decoding of the direction key translates to a change in the snake's head position, then checking for out-of-bounds or running into yourself, and finding if you found the food.
Then we move the snake by shifting the entire array of positions: the tail element drops off and the new one shifts onto the front. Then we re-draw the snake with new positions.
The main function is the same as yours at the top to set up the grid, but the snake configuration and play looks like:
int main(int argc, argv)
{
...
int length = 4;
int ysnake[4] = { 1, 2, 3, 4 };
int xsnake[4] = { 15, 15, 15, 16 };
drawsnake(length, xsnake, ysnake, size, grid);
// Put the food somewhere
grid[sx + 3][sy - 6] = 'X'; //just to test if it works, will be generated randomly
printGrid (size, grid);
score = play(length, xsnake, ysnake, size, grid);
printf ("*********GAME OVER********** \n final score: %d\n", score);
}
I didn't really do anything meaningful with the score and have only barely tested it, but it does let the little guy slither around the screen, and it might be a bit easier to follow.
Good luck.

Replace a character with another character + Setting a tie game

This is for Homework
I have to create a game of TicTacToe for a project and I have two issues. Also I apologize if I'm violating a rule by having two questions within one post, If it's not allowed then I'd appreciate someone notifying me in the comments and I'll go ahead and break this into two separate posts. I'll post my code then ask my questions following the code.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
char table[3][3];
void clear_table();
void player1_move();
void player2_move();
void the_matrix(); // Like the movie
char check_three();
int main() {
srand(time(NULL));
char win;
printf("This program plays the game of Tic Tac Toe.\n");
win = ' ';
clear_table();
do {
the_matrix(); // Like the movie
player1_move();
win = check_three(); // Check win for player 1
if (win != ' ')
break;
player2_move();
win = check_three(); // Check win for player 2
}
while (win == ' ');
the_matrix(); // Shows the final move+Like the movie
if (win == 'O')
printf("Congratulations, Player 1 wins!\n");
else
printf("Congratulations, Player 1 lost!\n");
// the_matrix (); //Shows the final move+Like the movie
return 0;
}
void clear_table() {
// Creates empty spaces for the user and computer to enter stuff in
int i, j, k;
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++)
// for(l = 0; k < 3; j++)
table[i][j] = ' ';
}
}
void player1_move() {
// Moves that player 1 can and can't make
int x, y, z;
printf("Player 1 enter your selection[row, col]: ");
scanf("%d, %d", &x, &y);
x--;
y--;
// z--;
if (table[x][y] != ' ') {
printf("Space already taken, please try again.\n");
player1_move();
}
else
table[x][y] = 'O'; // O goes first for some reason
}
void player2_move() {
// Needs work!!
// Call srand in the main
int a = rand() % 3;
int b = rand() % 3;
// Make it so the game would end in a tie when possible
for (a = rand() % 3; a < 3; a++) {
for (b = rand() % 3; b < 3;
b++) // For loops causing issues in randomization?
// for(c = 0; c < 3; c++)
if (table[a][b] == ' ')
break;
if (table[a][b] == ' ') // Checks the rows and columns
break;
}
if (a * b == 9)
**Kinda works ? ** {
printf("Game Over, No Player Wins\n");
exit(0);
}
else
table[a][b] = 'X';
}
void the_matrix() { // Like the movie
**Get rid of the underscores **
int m;
printf("The current state of the board:\n");
for (m = 0; m < 3; m++) {
printf("%c_ %c_ %c_\n", table[m][0], table[m][1], table[m][2]);
}
printf("\n");
}
char check_three() {
int w;
// char table[3][3];
for (w = 0; w < 3; w++) {
if (table[w][0] == table[w][2] && table[w][0] == table[w][1])
return table[w][0]; // Row Check
}
for (w = 0; w < 3; w++) {
if (table[0][w] == table[2][w] && table[0][w] == table[1][w])
return table[0][w]; // Col Check
}
if (table[0][0] == table[1][1] && table[1][1] == table[2][2])
return table[0][0];
if (table[0][2] == table[1][1] && table[1][1] == table[2][0])
return table[0][2]; // Diag Check
return ' ';
}
First Question
So my first question is with a draw game. On the player two function I have a snip of code set to determine a draw game. Initially I assumed that if the X's and O's were to multiply to 9 then that would mean that the board would be filled up then that would result in a draw game. [This is within my third function - player2_move near the end of the function] It kind of works, but sometimes the program just preemptively ends the game. It's a bit hard to test it because the computers moves are randomized and most of the times I've tried, I ended up winning accidentally. My question is what would I need to do to set up my program to essentially have a better way of determining a draw game.
Second Question
On my 4th function called the_matrix I need help with formatting. The assignment requires the format to be a little like this where if I were to enter in the coordinates 1,1 then the board would look like this:
O _ _ with the proceeding lines near the bottom to be blank. However as my program is right now, it looks like this:
O_ _ _
What I want to do is swap or replace the underscore with the user's input. Not entirely sure how to do that and any help would be appreciated.
I apologize if I violated any rules for stackoverflow by having two questions in one and I'm also sorry for this huge post.

C: Comparing two elements not producing correct results?

My code is below, most of which may not be helpful, but maybe the problem lies outside of where I think it is. That being said, please read the following first because it gives the rundown of my code and states where I think the problem lies.
I'm trying to create a Battleship game in C. I first create two two-dimensional arrays, one representing the player's board and one representing the enemy's board. I fill both of them with periods. I print them out with numbers along the sides to make things look nice (using my initialPrintBoards function). I then set the locations of the enemy's ships by replacing some of the periods in the enemy's array with 's' and print it out to make sure they are where I want them to be. They are, which is great. I then have the player "fire" at the enemy's ship. This is done by replacing 's' in the enemy's array with 'x' (which represents a hit) or replacing '.' with 'o' (which represents a miss). I print this out, and everything works well.
Now, here's where I hit a problem. Up to this point, for the sake of testing, the enemy's ships have been completely visible to the player via my print method. I don't want that. So, what I figured I'd do is create a new print function (called printBoards) that does exactly what my previous print function does except it prints '.' on the board when it encounters 's' as an element in the enemy's array. My initial thought in accomplishing this was to use comparisons. Basically, if the element stored in the enemy's array at location whatever is 's', print '.', otherwise print out what's stored at that location in the array (which would be '.', 'x', or 'o'). Unfortunately, all it does is print all periods, even if there's an 'x' or 'o' stored at that location in the array. I'm at a loss as to why this is. I'm quite new to C (I've studied Java in the past), so maybe there's something about comparisons in C that I don't know about. But that's assuming the problem is with the comparisons, which it might not be.
Any help or hints would be greatly appreciated.
#include <stdio.h>
char playerBoard[8][8];
char enemyBoard[8][8];
void fillBoards()
{
int a;
for (a = 0; a < 8; a++)
{
int b;
for (b = 0; b < 8; b++)
{
enemyBoard[a][b] = '.';
}
}
int x;
for (x = 0; x < 8; x++)
{
int y;
for (y = 0; y < 8; y++)
{
playerBoard[x][y] = '.';
}
}
}
void initialPrintBoards()//This is used before the enemy's ships are set.
{
printf("Enemy Board\n*12345678\n");
int a;
for (a = 0; a < 8; a++)
{
printf("%d", a + 1);
int b;
for (b = 0; b < 8; b++)
{
printf("%c", enemyBoard[a][b]);
}
printf("\n");
}
printf("\n");
printf("Player Board\n*12345678\n");
int x;
for (x = 0; x < 8; x++)
{
printf("%d", x + 1);
int y;
for (y = 0; y < 8; y++)
{
printf("%c", playerBoard[x][y]);
}
printf("\n");
}
printf("\n");
}
void printGreeting()
{
printf("\nWelcome to Battleship!\n\n");
}
void setEnemyShips()
{
// Ship 1.
enemyBoard[3][2] = 's';
enemyBoard[4][2] = 's';
enemyBoard[5][2] = 's';
// Ship 2.
enemyBoard[1][1] = 's';
enemyBoard[1][2] = 's';
enemyBoard[1][3] = 's';
// Ship 3.
enemyBoard[6][5] = 's';
enemyBoard[6][6] = 's';
enemyBoard[6][7] = 's';
}
void playerFire()
{
if (enemyBoard[2][2] == 's')
{
enemyBoard[2][2] = 'x';
}
else
{
enemyBoard[2][2] = 'o';
}
}
void printBoards()//This is used after the enemy's ships are set.
{
printf("Enemy Board\n*12345678\n");
int a;
for (a = 0; a < 8; a++)
{
printf("%d", a + 1);
int b;
for (b = 0; b < 8; b++)
{
if (enemyBoard[1][0] == 's')
{
printf("%c", '.');
}
else
{
printf("%c", enemyBoard[1][0]);
}
}
printf("\n");
}
printf("\n");
printf("Player Board\n*12345678\n");
int x;
for (x = 0; x < 8; x++)
{
printf("%d", x + 1);
int y;
for (y = 0; y < 8; y++)
{
printf("%c", playerBoard[x][y]);
}
printf("\n");
}
printf("\n");
}
int main()
{
fillBoards();
printGreeting();
initialPrintBoards(); //This will print the boards before the enemy's ships are set.
setEnemyShips();
initialPrintBoards(); //This will end up printing the enemy ships' locations. Need a different print method.
playerFire();
initialPrintBoards(); //This prints to see if a hit or miss is properly printed.
printBoards(); //This prints to see if the ships are hidden and a hit or miss is properly printed.
return 0;
}
regarding this code, found in the printBoards() function:
if (enemyBoard[1][0] == 's')
{
printf("%c", '.');
}
else
{
printf("%c", enemyBoard[1][0]);
}
This always looks at the second row, first column to determine what is printed. As you saw, that is an error.
Suggest:
if (enemyBoard[a][b] == 's')
{
printf("%c", '.');
}
else
{
printf("%c", enemyBoard[a][b]);
}
Let the Board[][] variables contain the state '.' (water) or 'A', 'B' ... 'E' for the 5 ships.
When a ship is hit, change 'A' to 'a', etc.
When printing, pass in a control variable to control how the view is rendered: Enemy View, Player View, Programmer View.

Calculator in C using stack

I'm trying to create a calculator in c, which can calculate with priority and get right results for examples like these:
((5+5)/3)*3) -- > 9
((1+2) * 3) -- > 9
These examples my code below can calculate. But for something like this
(2+5) * (2+5), my program gives wrong answer.
I'm using 2 stacks. One for operators and one for numbers. It works on this principle:
follows:
((4 - 2) * 5) + 3 --> normal infix expression:
+ * - 4 2 5 3
Pseudo code:
Read + (an operation), push it onto the stack,
Read * (an operation), push it onto the stack,
Read - (an operation), push it onto the stack,
Read 4 (a number), the top of the stack is not a number, so push it onto the stack.
Read 2 (a number), the top of the stack is a number, so pop from the stack twice, you get 4 - 2, calculate it (2), and push the result (2) onto the stack.
Read 5 (a number), the top of the stack is a number, so pop from the stack twice, you get 2 * 5, push the result (10) onto the stack.
Read 3 (a number), the top of the stack is a number, so pop from the stack twice, you get 3 + 10, push the result (13) onto the stack.
Nothing left to read, pop from the stack and return the result (13).
Actual code:
#include <stdio.h>
#include<ctype.h>
#include<stdlib.h>
#include<string.h>
#define MAXSIZE 102
typedef struct
{
char stk[MAXSIZE];
int top;
}STACK;
typedef struct stack
{
int stk[MAXSIZE];
int itop;
}INT_STACK;
STACK s;
INT_STACK a;
void push(char);
char pop(void);
void display(void);
int main()
{
a.itop = 0;
char string[MAXSIZE],vyb,vyb2;
int cislo1,cislo2,vysledok;
while (gets(string) != NULL){
for(int j = strlen(string); j > 0; j--){
if(string[j] == '*' || string[j] == '/' || string[j] == '+' || string[j] == '-')
push(string[j]);
}
//display();
for(int j = 0; j < strlen(string); j++){
if(isdigit(string[j])&&!(a.itop)){
//display();
char pomoc[2];
pomoc[0] = string[j];
pomoc[1] = '\0';
int_push(atoi(pomoc));
}
else if(isdigit(string[j])&&(a.itop)){
cislo1 = int_pop();
vyb2 = pop();
char pomoc[2];
pomoc[0] = string[j];
pomoc[1] = '\0';
cislo2 = atoi(pomoc);
if(vyb2 == '+')
vysledok = cislo1+cislo2;
else if(vyb2 == '-')
vysledok = cislo1-cislo2;
else if(vyb2 == '*')
vysledok = cislo1*cislo2;
else if(vyb2 == '/')
vysledok = cislo1 / cislo2;
//printf(" v %d",vysledok);
int_push(vysledok);
}
}
printf("%d\n",int_pop());
}
}
/* Function to add an element to the stack */
void push (char c)
{
s.top++;
s.stk[s.top] = c;
//printf ("pushed element is = %c \n", s.stk[s.top]);
}
/* Function to delete an element from the stack */
char pop ()
{
char num = s.stk[s.top];
// printf ("poped element is = %c\n", s.stk[s.top]);
s.top--;
return(num);
}
int empty()
{
if (s.top == - 1)
{
printf ("Stack is Empty\n");
return (s.top);
}
return 1;
}
void display ()
{
int i;
if (!empty)
{
printf ("Stack is empty\n");
return;
}
else
{
printf ("\n The status of the stack is \n");
for (i = s.top; i >= 0; i--)
{
printf ("%c\n", s.stk[i]);
}
}
printf ("\n");
}
void int_push (int c)
{
a.itop++;
a.stk[a.itop] = c;
//printf ("pushed element is = %d \n", a.stk[a.itop]);
}
/* Function to delete an element from the stack */
int int_pop ()
{
int num = a.stk[a.itop];
// printf ("poped element is = %d\n", a.stk[a.itop]);
a.itop--;
return(num);
}
Is there any other way to create a calculator with priority, which can give good answers?
Thanks for your respond
Put breakpoints - you'll get the following expression:
+ + * 2 5 2 5. The problem with that, is your interpreter is interpeting this as (2+5+2)*5 instead of (2+5) * (2+5).
Well then, you might be wondering how to solve this. There's no simple single solution - you could either fix your own interpreter or build a whole new mechanic, because the way you build expressions just can't handle more then one pair of parthesises.
For example, you may want to calculate all the values in parnthesises before even building the expression seperatley, possibly using recursion in the case of parenthesiseception - however if you actually choose to use that method, you might want to change the way you work with the expressions entirely, because that's a different approach.
If you need me to show actual code examples to explain this further using parts of the code you made, just ask for it and i'll edit and provide what you need.
Either way, I really advise you to look up working with interpreters in general - you could really learn a lot about analysing strings and working with different inputs, and people even did similar stuff to yours with calculators before
EDIT: you asked for examples, so here you go - this is an example of a completely different method using recursion. This way, you handle a single pair of parenthesises at a time, and thus you won't have the problem you currently do. Note - the source i'm basing this on ( pretty much copy-pasted with edits from the thread and some personal comments ) is from codereview on stack exchange, you can see it here
if you're intrested.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void getInput(char * in) {
printf("> ");
fgets(in, 256, stdin);
}
int isLeftParantheses(char p) {
if (p == '(') return 1;
else return 0;
}
int isRightParantheses(char p) {
if (p == ')') return 1;
else return 0;
}
int isOperator(char p) {
if (p == '+' || p == '-' || p == '*' || p == '/') return p;
else return 0;
}
int performOperator(int a, int b, char p) {
switch(p) {
case '+': return a+b;
case '-': return a-b;
case '*': return a*b;
case '/':
if (b == 0) { printf("Can't divide by 0, aborting...\n"); exit(1); } // now we dont want the world to expload here do we.
return a/b;
default:
puts("Bad value in switch.\n"); // A replacement which was mentioned in the thread- better have a default response just in case something goes wrong.
break;
}
return 0;
}
char isDigit(char p) {
if (p >= '0' && p <= '9') return 1;
else return 0;
}
int charToDigit(char p) {
if (p >= '0' && p <= '9') return p - '0';
else return 0;
}
int isNumber(char * p) {
while(*p) {
if (!isDigit(*p)) return 0;
p++;
}
return 1;
}
int len(char * p)
{
return (int) strlen(p); // This was bugged in the source, so I fixed it like the thread advised.
}
int numOfOperands(char * p) {
int total = 0;
while(*p) {
if (isOperator(*p)) total++;
p++;
}
return total+1;
}
int isMDGRoup(char *p)
{
for(; *p; p++) // used to be a while loop in the source, but this is better imho. more readable, also mentioned on the thread itself.
{
if (!isDigit(*p) && *p != '/' && *p != '*') return 0;
}
return 1;
}
int getLeftOperand(char * p, char * l) {
// Grab the left operand in p, put it in l,
//and return the index where it ends.
int i = 0;
// Operand is part of multi-*/ group
if (isMDGRoup(p)) {
while(1) {
if (*p == '*' || *p == '/') break;
l[i++] = *p++;
}
return i;
}
// Operand is in parantheses (so that's how you write it! sorry for my bad english :)
if(isLeftParantheses(*p)) {
int LeftParantheses = 1;
int RightParantheses= 0;
p++;
while(1) {
if (isLeftParantheses(*p)) LeftParantheses++;
if (isRightParantheses(*p)) RightParantheses++;
if (isRightParantheses(*p) && LeftParantheses == RightParantheses)
break;
l[i++] = *p++;
}
// while (!isRightParantheses(*p)) {
// l[i++] = *p++;
// }
l[i] = '\0';
return i+2;
}
// Operand is a number
while (1) {
if (!isDigit(*p)) break;
l[i++] = *p++;
}
l[i] = '\0';
return i;
}
int getOperator(char * p, int index, char * op) {
*op = p[index];
return index + 1;
}
int getRightOperand(char * p, char * l) {
// Grab the left operand in p, put it in l,
//and return the index where it ends.
while(*p && (isDigit(*p) || isOperator(*p) ||
isLeftParantheses(*p) || isRightParantheses(*p))) {
*l++ = *p++;
}
*l = '\0';
return 0;
}
int isEmpty(char * p) {
// Check if string/char is empty
if (len(p) == 0) return 1;
else return 0;
}
int calcExpression(char * p) {
// if p = #: return atoi(p)
//
// else:
// L = P.LeftSide
// O = P.Op
// R = P.RightSide
// return PerformOp(calcExpression(L), calcExpression(R), O)
// ACTUAL FUNCTION
// if p is a number, return it
if (isNumber(p)) return atoi(p);
// Get Left, Right and Op from p.
char leftOperand[256] = ""; char rightOperand[256]= "";
char op;
int leftOpIndex = getLeftOperand(p, leftOperand);
int operatorIndex = getOperator(p, leftOpIndex, &op);
int rightOpIndex = getRightOperand(p+operatorIndex, rightOperand);
printf("%s, %c, %s", leftOperand, op, rightOperand);
getchar();
if (isEmpty(rightOperand)) return calcExpression(leftOperand);
return performOperator(
calcExpression(leftOperand),
calcExpression(rightOperand),
op
);
}
int main()
{
char in[256];
while(1) {
// Read input from user
getInput(in);
if (strncmp(in, "quit", 4) == 0) break;
// Perform calculations
int result = calcExpression(in);
printf("%d\n", result);
}
}

Resources