It's a simple game,just aim to input a character,move the snake and print the table everytime.
The switch statement in the main function settle 4 cases'a' 's' 'd' 'w' without default,However,when the program is running,if a character out of the cases is input,the program still reacts and output the table(besides,the talbe is output twice).Why?
Besides,it also confused me that the snake don't move correctly if the input is in the cases.
Forgot to add 'break'after cases before:)but the problem still confuse me.Now if I use'break'under default,the program still print the table twice,if I use 'continue'under default,the program won't react to the incorrect input.
But the snake still don't move correctly.:(
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define SNAKE_MAX_LENGTH 20
void snakeMove(int, int);
void put_money(void);
void output(void);
void gameover(void);
char map[12][12] =
{"************",
"*XXXXH *",
"* *",
"* *",
"* *",
"* *",
"* *",
"* *",
"* *",
"* *",
"* *",
"************"};
int snakeX[SNAKE_MAX_LENGTH] = {1, 2, 3, 4, 5};
int snakeY[SNAKE_MAX_LENGTH] = {1, 1, 1, 1, 1};
int snakeLength = 5;
int game=1,origin=1,eaten=0;
int main() {
char ch;
srand(time(NULL));
put_money();
output();
origin=0;
while(game) {
scanf("%c",&ch);
switch(ch) {
case 'w':
snakeMove(1,1);
break;
case 's':
snakeMove(2,1);
break;
case 'a':
snakeMove(3,1);
break;
case 'd':
snakeMove(4,1);
break;
default:
continue;
}
if(eaten==1) {
put_money();
eaten=0;
}
output();
}
gameover();
return 0;
}
void snakeMove(int direction, int distance) {
int i,move=1;
switch(direction) {
case 1:
if(snakeY[3]==snakeY[4]+distance)
move=0;
else
snakeY[4]=snakeY[4]+distance;
break;
case 2:
if(snakeY[3]==snakeY[4]-distance)
move=0;
else
snakeY[4]=snakeY[4]-distance;
break;
case 3:
if(snakeX[3]==snakeX[4]-distance)
move=0;
else
snakeX[4]=snakeX[4]-distance;
break;
case 4:
if(snakeX[3]==snakeX[4]+distance)
move=0;
else
snakeX[4]=snakeX[4]+distance;
}
if (move==1) {
for(i=3;i>=0;i--){
snakeX[i]=snakeX[i+1];
snakeY[i]=snakeY[i+1];
}
}
}
void output(void) {
int x, y,i;
if(origin==0) {
for(x=1;x<11;x++) {
for(y=1;y<11;y++) {
if(map[x][y]!='$')
map[x][y]=' ';
}
}
if(map[snakeX[4]][snakeY[4]]=='$')
eaten=1;
for(i=0;i<4;i++)
map[snakeX[i]][snakeY[i]]='X';
map[snakeX[4]][snakeY[4]]='H';
if(snakeX[4]==0||snakeX[4]==11||snakeY[4]==0||snakeY[4]==11)
game=0;
for(i=0;i<4;i++) {
if(snakeX[4]==snakeX[i]&&snakeY[4]==snakeY[i])
game=0;
}
}
for(x=0;x<12;x++) {
for(y=0;y<12;y++)
printf("%c",map[x][y]);
printf("\n");
}
}
void gameover(void) {
printf("Game Over!!!\n");
exit(0);
}
void put_money(void) {
int foodx,foody,done=0;
while(done==0) {
foodx=rand()%12;
foody=rand()%12;
if(map[foodx][foody]==' ') {
map[foodx][foody]='$';
done=1;
}
}
}
Interesting. Your switch statement was fine. Here is a working code with changes commented, followed by a whole code:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define SNAKE_MAX_LENGTH 20
void snakeMove(int, int);
void put_money(void);
void update_snake(void);
void output(void);
void gameover(void);
char map[12][12] =
{"************",
"*XXXXH *",
"* *",
"* *",
"* *",
"* *",
"* *",
"* *",
"* *",
"* *",
"* *",
"************"};
int snakeX[SNAKE_MAX_LENGTH] = {1, 2, 3, 4, 5};
int snakeY[SNAKE_MAX_LENGTH] = {1, 1, 1, 1, 1};
int snakeLength = 5;
int game=1,origin=1,eaten=0;
int main() {
char ch;
srand(time(NULL));
put_money();
output();
origin=0;
while(game) {
As said by Cool guy, a space in scanf works. This is because when you press enter, the newline is counted as a character.
scanf(" %c",&ch);
switch(ch) {
case 'w':
snakeMove(1,1);
break;
case 's':
snakeMove(2,1);
break;
case 'a':
snakeMove(3,1);
break;
case 'd':
snakeMove(4,1);
break;
default:
continue;
}
if(eaten==1) {
put_money();
eaten=0;
}
output();
}
gameover();
return 0;
}
This update function was added because you need to update the snake before you update the head. Otherwise, you'd lose the original head when you try to send it back.
void update_body()
{
int i;
for(i=0;i<4;i++){
snakeX[i]=snakeX[i+1];
snakeY[i]=snakeY[i+1];
}
}
void snakeMove(int direction, int distance) {
int move=1;
switch(direction) {
case 1:
The third issue is that in graphics, the origin, (0, 0) is in the top left corner instead of the bottom left. That means to go up, you have to subtract and to go down you have to add.
if(snakeY[3]==snakeY[4]-distance)
move=0;
else{
update_body();
snakeY[4]=snakeY[4]-distance;
}
break;
case 2:
if(snakeY[3]==snakeY[4]+distance)
move=0;
else{
update_body();
snakeY[4]=snakeY[4]+distance;
}
break;
case 3:
if(snakeX[3]==snakeX[4]-distance)
move=0;
else{
update_body();
snakeX[4]=snakeX[4]-distance;
}
break;
case 4:
if(snakeX[3]==snakeX[4]+distance)
move=0;
else{
update_body();
snakeX[4]=snakeX[4]+distance;
}
}
}
void output(void) {
int x, y,i;
if(origin==0) {
for(x=1;x<11;x++) {
for(y=1;y<11;y++) {
if(map[x][y]!='$')
map[x][y]=' ';
}
}
The last problem is that the map is upside down. This means that the X and Y coordinates were 1st and 2nd, when they should have been 2nd and 1st.
if(map[snakeY[4]][snakeX[4]]=='$')
eaten=1;
for(i=0;i<4;i++)
map[snakeY[i]][snakeX[i]]='X';
map[snakeY[4]][snakeX[4]]='H';
if(snakeX[4]==0||snakeX[4]==11||snakeY[4]==0||snakeY[4]==11)
game=0;
for(i=0;i<4;i++) {
if(snakeX[4]==snakeX[i]&&snakeY[4]==snakeY[i])
game=0;
}
}
for(x=0;x<12;x++) {
for(y=0;y<12;y++)
printf("%c",map[x][y]);
printf("\n");
}
}
void gameover(void) {
printf("Game Over!!!\n");
exit(0);
}
void put_money(void) {
int foodx,foody,done=0;
while(done==0) {
foodx=rand()%12;
foody=rand()%12;
if(map[foodx][foody]==' ') {
map[foodx][foody]='$';
done=1;
}
}
}
Here's the code whole
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define SNAKE_MAX_LENGTH 20
void snakeMove(int, int);
void put_money(void);
void update_body();
void output(void);
void gameover(void);
char map[12][12] =
{"************",
"*XXXXH *",
"* *",
"* *",
"* *",
"* *",
"* *",
"* *",
"* *",
"* *",
"* *",
"************"};
int snakeX[SNAKE_MAX_LENGTH] = {1, 2, 3, 4, 5};
int snakeY[SNAKE_MAX_LENGTH] = {1, 1, 1, 1, 1};
int snakeLength = 5;
int game=1,origin=1,eaten=0;
int main() {
char ch;
srand(time(NULL));
put_money();
output();
origin=0;
while(game) {
scanf(" %c",&ch);
switch(ch) {
case 'w':
snakeMove(1,1);
break;
case 's':
snakeMove(2,1);
break;
case 'a':
snakeMove(3,1);
break;
case 'd':
snakeMove(4,1);
break;
default:
continue;
}
if(eaten==1) {
put_money();
eaten=0;
}
output();
}
gameover();
return 0;
}
void update_body()
{
int i;
for(i=0;i<4;i++){
snakeX[i]=snakeX[i+1];
snakeY[i]=snakeY[i+1];
}
}
void snakeMove(int direction, int distance) {
int move=1;
switch(direction) {
case 1:
if(snakeY[3]==snakeY[4]-distance)
move=0;
else{
update_body();
snakeY[4]=snakeY[4]-distance;
}
break;
case 2:
if(snakeY[3]==snakeY[4]+distance)
move=0;
else{
update_body();
snakeY[4]=snakeY[4]+distance;
}
break;
case 3:
if(snakeX[3]==snakeX[4]-distance)
move=0;
else{
update_body();
snakeX[4]=snakeX[4]-distance;
}
break;
case 4:
if(snakeX[3]==snakeX[4]+distance)
move=0;
else{
update_body();
snakeX[4]=snakeX[4]+distance;
}
}
}
void output(void) {
int x, y,i;
if(origin==0) {
for(x=1;x<11;x++) {
for(y=1;y<11;y++) {
if(map[x][y]!='$')
map[x][y]=' ';
}
}
if(map[snakeY[4]][snakeX[4]]=='$')
eaten=1;
for(i=0;i<4;i++)
map[snakeY[i]][snakeX[i]]='X';
map[snakeY[4]][snakeX[4]]='H';
if(snakeX[4]==0||snakeX[4]==11||snakeY[4]==0||snakeY[4]==11)
game=0;
for(i=0;i<4;i++) {
if(snakeX[4]==snakeX[i]&&snakeY[4]==snakeY[i])
game=0;
}
}
for(x=0;x<12;x++) {
for(y=0;y<12;y++)
printf("%c",map[x][y]);
printf("\n");
}
}
void gameover(void) {
printf("Game Over!!!\n");
exit(0);
}
void put_money(void) {
int foodx,foody,done=0;
while(done==0) {
foodx=rand()%12;
foody=rand()%12;
if(map[foodx][foody]==' ') {
map[foodx][foody]='$';
done=1;
}
}
}
Related
I am writing code for snake game using C programming language. In my code, when I am trying to take bigger length and height value for game border then output is somehow got distorted. Please let me know how can I make border which could cover whole console window and what is the issue with existing code.
My code:-
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#define MAXTL 100
int len=20,wid=20;
int headX,headY,fruitX,fruitY,gameOver,level,flag=0,score=0;
int tailX[MAXTL];int tailY[MAXTL];
int countTail=0;
void draw();
void defaultsetting();
void userinput();
void my_sleep(int level);
//void delay();
void draw(){
system("cls");
for(int i=0;i<len;i++)
{
for(int j=0;j<wid;j++){
if(i==0 || i==len-1){
printf("=");
}
else if(j==0 || j==wid-1){
printf("#");
}
else{
if(i==headX && j==headY){
printf("O");
}
else if(i==fruitX && j==fruitY){
printf("*");
}
else{
int tail=0;
for(int k=0;k<countTail;k++){
if(i==tailX[k]&& j==tailY[k]){
printf("-");
tail=1;
}
}
if(tail==0){
printf(" ");
}
}
}
}
printf("\n");
}
}
void defaultsetting(){
gameOver=0;
srand(time(0));
headX=len/2;
headY=wid/2;
do{
fruitX=rand()%20;
fruitY=rand()%20;
}while(fruitX==0||fruitY==0);
}
void userinput(){
if(kbhit()){
switch(getch()){
case 72://up
flag=1;
break;
case 75://left
flag=2;
break;
case 77://right
flag=3;
break;
case 80://down
flag=4;
break;
case 'q':
gameOver=1;
break;
}
}
}
void logic(){
srand(time(0));
int i,prev2X,prev2Y;
int prevX=tailX[0];
int prevY=tailY[0];
tailX[0]=headX;
tailY[0]=headY;
for(i=1;i<countTail;i++){
prev2X=tailX[i];
prev2Y=tailY[i];
tailX[i]=prevX;
tailY[i]=prevY;
prevX=prev2X;
prevY=prev2Y;
}
switch(flag){
case 1:
headX--;
break;
case 2:
headY--;
break;
case 3:
headY++;
break;
case 4:
headX++;
break;
default:
//printf("Inside default");
break;
}
if(headX <0|| headX>len||headY<0||headY>wid){
gameOver=1;
}
for(i=0;i<countTail;i++){
if(i==tailX[i]&& i==tailY[i]){
gameOver=1;
}
}
if(headX==fruitX&& headY==fruitY)
{
do{
fruitX=rand()%20;
fruitY=rand()%20;
}while(fruitX==0 ||fruitY==0);
score+=10;
countTail++;
}
}
int main(){
int m,n;
char c;
defaultsetting();
printf("Enter level of game\n");
scanf("%d",&level);
while(!gameOver)
{
draw();
userinput();
logic();
my_sleep(level);
}
printf("Your Score =%d",score);
return 0;
}
void my_sleep(int level){
if(level==1){
sleep(1);
}
else if(level==2){
sleep(0.4);
}
else if(level==3){
sleep(0.02);
}
}
More precisely.. How do I add a "go back to main menu" function as all other softwares and games have?
void showMenu()
{
puts( "1. Create school\n"
"2. Add room\n"
"3.Add student to room\n"
"4.Find student\n"
"5. Show students in room\n"
"\n" "6. Exit");
}
int main()
{
clrscr();
studentList *foundStudent;
int input;
showMenu();
while( scanf("%d", &input) )
{
if(input == 6)
{
periods("Exiting");
break;
}
if(input == 1)
{
school *school;
school = createSchool();
}
if(input == 2)
{
int room, roomNr;
printf("Enter room Nr. and Class:");
scanf("%d %d", &room, &roomNr);
}
}
return 0;
}
Anything I attempted didn't work and just created more redundancy, never expected how goto can be so confusing.
Although switch makes more sense, I don't believe it fixes my problem.
Here is a working example.
The solution for this problem was simply making a "menu within a menu" kind of, I did use some gotos but as far as commandline menu goes, this may be all.
#define clrscr() printf("\e[1;1H\e[2J")
void periods(char* message)
{
const int trigger = 500; // ms
const int numDots = 3;
while (1)
{
// Return and clear with spaces, then return and print prompt.
printf("\r%*s\r%s", sizeof(message) - 1 + numDots, "", message);
fflush(stdout);
// Print numDots number of dots, one every trigger milliseconds.
for (int i = 0; i < numDots; i++)
{
usleep(trigger * 1000);
fputc('.', stdout);
fflush(stdout);
}
break;
}
}
void showmenu()
{
clrscr();
puts("1. New Game\n"
"2. Load Game\n"
"3. Credits\n\n"
"4. Exit\n" );
}
int checkString(char *str)
{
int status = 0;
int ln = strlen(str);
for(int i = 0; i < ln; i++)
{
if(isdigit( str[i] ) )
status = 1;
break;
}
return status;
}
int main(){
char choice;
clrscr();
int status, isNum = -101;
char *name, *buffer, YN;
showmenu();
while(1)
{
scanf(" %c", &choice);
if( isdigit(choice) )
{
break;
}
else
{
fflush(stdin);
printf("Please only enter numbers!\n");
sleep(1);
showmenu();
}
}
do{
switch(choice)
{
case '1':
{
createG:;
clrscr();
printf("Enter name or press 0 to return\n");
scanf("%s", buffer);
status = checkString(buffer);
if(status == 1)
{
clrscr();
break;
}
clrscr();
name = (char*)malloc(strlen(buffer)+1);
strcpy(name, buffer);
printf("New game created, welocome %s!\n");
for(int i = 0; i < 5; i++)
{
sleep(1);
printf("%d\n", i);
}
break;
}
case '2':
{
int what;
caseL:;
clrscr();
printf("No saves!\n Create new game? [Y/N] \n to return press 0\n");
scanf(" %c", &YN);
if(YN == 'N') what = 0;
if(YN == '0') what = -1;
if(YN == 'Y') what = 1;
switch(YN)
{
case 'N':
{
goto caseL;
}
case '0':
{
break;
}
case 'Y':
{
choice = 1;
goto createG;
break;
}
}
break;
}
case '3':
{
periods("Hello World");
break;
}
case '4':
{
clrscr();
periods("Goodbye");
clrscr();
exit(1);
}
default:
{
printf("Wrong input\n Try again");
sleep(1);
break;
}
}
}while(choice != -2);
return 0;
}
This may still need a lot of error checking and handling for "unexpected" inputs but it answers the problem.
Does anyone know why when I run this code it goes for P2_TURN and how to make this enum active that when P2 move then P1 goes and whoever win the correct statement will be given from print_status()… also is there an easier/cleaner way to assign the winner. At the void process_move(struct game* p_game_info) is there a way to replace digits 0-8 with user input without switch case….Sorry for being a bit chaotic with this query but it’s almost 4 in the morning so hope you’ll forgive me….
game.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "game.h"
void play_game()
{
struct game *p_game_info = 0;
p_game_info = malloc(sizeof(struct game));
initialise_game (p_game_info, "John", "Annie");
draw_banner();
display_board(p_game_info->board);
system("cls");
display_board_positions ();
draw_banner();
process_move( p_game_info);
display_board(p_game_info->board);
print_status ( p_game_info );
}
void initialise_game(struct game* p_game_info, char* name1, char* name2)
{
for (int r=0; r<3; r++)
for(int c=0; c<3; c++)
p_game_info->board[r][c] = SPACE;
display_board_positions ();
p_game_info->status=P1_TURN;
// p_game_info->finished = False;
strncpy(p_game_info->playerNames[0], name1,MAX_NAME_LEN);
strncpy(p_game_info->playerNames[1], name2,MAX_NAME_LEN);
}
void draw_banner(){
printf("---------------\n");
printf(" GAME STATUS \n");
printf("---------------\n");
}
void display_board( char board[3][3]){
printf("---------------\n");
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
printf(" %c ", board[i][j]);
if (j != 2)
printf("|");
}
if (i != 2)
printf("\n-----------");
printf("\n");
}
printf("---------------\n");
}
void print_status (struct game*p_game_info ){
if ((p_game_info->finished=False)&&
(p_game_info->status=P1_TURN))
{
printf("John's Turn\n");
}
else if ((p_game_info->finished=False)&&
(p_game_info->status=P2_TURN))
{
printf("Annie's Turn\n");
}
else if
(p_game_info->status==P1_WON)
{
printf( "Well done John, you have won\n");
}
else if
(p_game_info->status==P2_WON)
{
printf("Well done Annie, you have won\n");
}
else if
(p_game_info->status==DRAW)
{
printf("Game Over It is a draw\n");
}
}
void display_board_positions (){
int count = 0;
printf("---------------\n");
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
printf(" %d ", count);
count++;
if (j != 2)
printf("|");
}
if (i != 2)
printf("\n-----------");
printf("\n");
}
printf("---------------\n");
}
void process_move(struct game* p_game_info){
if (p_game_info->status==P1_TURN){
printf("enter number for 'X' from 0-8\n");
char ckey = (char) getchar();
switch (ckey){
case '0':
if(p_game_info->board[0][0]==SPACE){
p_game_info->board[0][0]=X_SYMBOL;
}
break;
case '1':
if(p_game_info->board[0][1]==SPACE){
p_game_info->board[0][1]=X_SYMBOL;
}
break;
case '2':
if(p_game_info->board[0][2]==SPACE){
p_game_info->board[0][2]=X_SYMBOL;
}
break;
case '3':
if(p_game_info->board[1][0]==SPACE){
p_game_info->board[1][0]=X_SYMBOL;
}
break;
case '4':
if(p_game_info->board[1][1]==SPACE){
p_game_info->board[1][1]=X_SYMBOL;
}
break;
case '5':
if(p_game_info->board[1][2]==SPACE){
p_game_info->board[1][2]=X_SYMBOL;
}
break;
case '6':
if(p_game_info->board[2][0]==SPACE){
p_game_info->board[2][0]=X_SYMBOL;
}
break;
case '7':
if(p_game_info->board[2][1]==SPACE){
p_game_info->board[2][1]=X_SYMBOL;
}
break;
case '8':
if(p_game_info->board[2][1]==SPACE){
p_game_info->board[2][1]=X_SYMBOL;
}
break;
default:
;
}p_game_info->status=P2_TURN
}
else if (p_game_info->status=P2_TURN){
printf("enter number for 'O' from 0-8\n");
char ckey = (char) getchar();
switch (ckey){
case '0':
if(p_game_info->board[0][0]==SPACE){
p_game_info->board[0][0]=O_SYMBOL;
}
break;
case '1':
if(p_game_info->board[0][1]==SPACE){
p_game_info->board[0][1]=O_SYMBOL;
}
break;
case '2':
if(p_game_info->board[0][2]==SPACE){
p_game_info->board[0][2]=O_SYMBOL;
}
break;
case '3':
if(p_game_info->board[1][0]==SPACE){
p_game_info->board[1][0]=O_SYMBOL;
}
break;
case '4':
if(p_game_info->board[1][1]==SPACE){
p_game_info->board[1][1]=O_SYMBOL;
}
break;
case '5':
if(p_game_info->board[1][2]==SPACE){
p_game_info->board[1][2]=O_SYMBOL;
}
break;
case '6':
if(p_game_info->board[2][0]==SPACE){
p_game_info->board[2][0]=O_SYMBOL;
}
break;
case '7':
if(p_game_info->board[2][1]==SPACE){
p_game_info->board[2][1]=O_SYMBOL;
}
break;
case '8':
if(p_game_info->board[2][1]==SPACE){
p_game_info->board[2][1]=O_SYMBOL;
}
break;
default:
;
}}
}
void finished_game(struct game* p_game_info){
if((p_game_info->board[0][0]==O_SYMBOL)&&(p_game_info->board[0] [1]==O_SYMBOL)&&(p_game_info->board[0][2]==O_SYMBOL)||
(p_game_info->board[1][0]==O_SYMBOL)&&(p_game_info->board[1][1]==O_SYMBOL)&& (p_game_info->board[1][2]==O_SYMBOL)||
(p_game_info->board[2][0]==O_SYMBOL)&&(p_game_info->board[2][1]==O_SYMBOL)&&(p_game_info->board[2][2]==O_SYMBOL)||
(p_game_info->board[0][0]==O_SYMBOL)&&(p_game_info->board[1][0]==O_SYMBOL)&&(p_game_info->board[2][0]==O_SYMBOL)||
(p_game_info->board[0][1]==O_SYMBOL)&&(p_game_info->board[1][1]==O_SYMBOL)&&(p_game_info->board[2][1]==O_SYMBOL)||
(p_game_info->board[0][2]==O_SYMBOL)&&(p_game_info->board[1][2]==O_SYMBOL)&&(p_game_info->board[2][2]==O_SYMBOL)||
(p_game_info->board[0][0]==O_SYMBOL)&&(p_game_info->board[1][1]==O_SYMBOL)&&(p_game_info->board[2][2]==O_SYMBOL)||
(p_game_info->board[0][2]==O_SYMBOL)&&(p_game_info->board[1][1]==O_SYMBOL)&&(p_game_info->board[2][0]==O_SYMBOL))
{
p_game_info->status=P2_WON;
return;
}
else if((p_game_info->board[0][0]==X_SYMBOL)&&(p_game_info->board[0][1]==X_SYMBOL)&&(p_game_info->board[0][2]==X_SYMBOL)||
(p_game_info->board[1][0]==X_SYMBOL)&&(p_game_info->board[1][1]==X_SYMBOL)&&(p_game_info->board[1][2]==X_SYMBOL)||
(p_game_info->board[2][0]==X_SYMBOL)&&(p_game_info->board[2][1]==X_SYMBOL)&&(p_game_info->board[2][2]==X_SYMBOL)||
(p_game_info->board[0][0]==X_SYMBOL)&&(p_game_info->board[1][0]==X_SYMBOL)&&(p_game_info->board[2][0]==X_SYMBOL)||
(p_game_info->board[0][1]==X_SYMBOL)&&(p_game_info->board[1][1]==X_SYMBOL)&&(p_game_info->board[2][1]==X_SYMBOL)||
(p_game_info->board[0][2]==X_SYMBOL)&&(p_game_info->board[1][2]==X_SYMBOL)&&(p_game_info->board[2][2]==X_SYMBOL)||
(p_game_info->board[0][0]==X_SYMBOL)&&(p_game_info->board[1][1]==X_SYMBOL)&&(p_game_info->board[2][2]==X_SYMBOL)||
(p_game_info->board[0][2]==X_SYMBOL)&&(p_game_info->board[1][1]==X_SYMBOL)&&(p_game_info->board[2][0]==X_SYMBOL))
{
p_game_info->status=P1_WON;
return;
}
else
{
p_game_info->status=DRAW;
return;
}
}
game.h
#ifndef GAME_H_INCLUDED
#define GAME_H_INCLUDED
#define MAX_NAME_LEN 50
enum Bool { False, True };
enum status { P1_TURN, P2_TURN, P1_WON, P2_WON, DRAW };
typedef enum Bool boolean;
static const char SPACE= '-';
static const char X_SYMBOL = 'X';
static const char O_SYMBOL = 'O';
struct game {
char board[3][3];
char playerNames[2][MAX_NAME_LEN];
int status;
boolean finished;
};
void play_game();
void initialise_game(struct game* p_game_info, char* name1, char* name2);
void draw_banner();
void display_board( char board[3][3]);
void print_status (struct game*p_game_info );
void display_board_positions ();
void process_move(struct game* p_game_info);
void finished_game(struct game* p_game_info);
#endif // game
Current output
---------------
0 | 1 | 2
3 | 4 | 5
6 | 7 | 8
GAME STATUS
enter number for 'O' from 0-8
2
- | - | O
- | - | -
- | - | -
Process returned 0 (0x0) execution time : 7.731 s
Press any key to continue.
Your question is indeed chaotic. I'm not sure what you really want to know, but notice that 'else if (p_game_info->status=P2_TURN){' is wrong. You need a double equal sign there.
I've been turning around and around trying to figure out how to give my players turns. The questions is for there to be two players playing tic tac toe but I can't figure how to do that. Here's my code:
#include <stdio.h>
#include <stdlib.h>
void displayBoard(char [3][3]);enter code here
int playerType (int player, char boardArray[3][3]);
int selectLocation(char [3][3], int , int );
char setTurn(char [3][3], int , int , char );
int main()
{
int player,location;
char position;
char boardArray[3][3]={{'1','2','3'},
{'4','5','6'},
{'7','8','9'}};
player= playerType (player, boardArray);
int i;
for(i=0;i<9;i++)
{
if (player==3)
break;
else{
location=selectLocation(boardArray, player, location);
position=setTurn(boardArray, location, player, position);
}
}
return 0;
}
void displayBoard(char boardArray [3][3]) //This displays the tic tac toe board
{
printf("\t%c|%c|%c\n", boardArray[0][0], boardArray[0][1], boardArray[0][2]);
printf("\t%c|%c|%c\n", boardArray[1][0], boardArray[1][1], boardArray[1][2]);
printf("\t%c|%c|%c\n", boardArray[2][0], boardArray[2][1], boardArray[2][2]);
}
int playerType (int player, char boardArray [3][3]) //This decides who plays first
{
player=0;
printf("Enter 1 for Player X.\n");
printf("Enter 2 for Player O.\n");
printf("Enter 3 to Quit. \n");
scanf("%d", &player);
if (player == 1)
{
printf("You're player X.\n");
displayBoard(boardArray);
}
else if (player == 2)
{
printf("You're player O.\n");
displayBoard(boardArray);
}
else if(player == 3)
printf("You Quit.\n");
else
printf("Invalid Entry.\n");
return player;
}
int selectLocation(char boardArray[3][3], int player, int location) //This takes in the location
{
printf("Pick a location from 1-9.\n");
scanf("%d", &location);
return location;
}
char setTurn(char boardArray[3][3], int location, int player, char position) //This outputs the location
{
if (player == 1)
{
switch(location)
{
case 1:
{
boardArray[0][0]='x';
break;
}
case 2:
{
boardArray[0][1]='x';
break;
}
case 3:
{
boardArray[0][2]='x';
break;
}
case 4:
{
boardArray[1][0]='x';
break;
}
case 5:
{
boardArray[1][1]='x';
break;
}
case 6:
{
boardArray[1][2]='x';
break;
}
case 7:
{
boardArray[2][0]='x';
break;
}
case 8:
{
boardArray[2][1]='x';
break;
}
case 9:
{
boardArray[2][2]='x';
break;
}
default:
printf("invalid");
}
}
else if (player == 2)
{
switch(location)
{
case 1:
{
boardArray[0][0]='O';
break;
}
case 2:
{
boardArray[0][1]='O';
break;
}
case 3:
{
boardArray[0][2]='O';
break;
}
case 4:
{
boardArray[1][0]='O';
break;
}
case 5:
{
boardArray[1][1]='O';
break;
}
case 6:
{
boardArray[1][2]='O';
break;
}
case 7:
{
boardArray[2][0]='O';
break;
}
case 8:
{
boardArray[2][1]='O';
break;
}
case 9:
{
boardArray[2][2]='O';
break;
}
default:
printf("Invalid");
}
}
printf("\t%c|%c|%c\n", boardArray[0][0], boardArray[0][1], boardArray[0][2]);
printf("\t%c|%c|%c\n", boardArray[1][0], boardArray[1][1], boardArray[1][2]);
printf("\t%c|%c|%c\n", boardArray[2][0], boardArray[2][1], boardArray[2][2]);
return position;
}
Change player selection part player= playerType (player, boardArray); inside for loop like this -
int player,location;
char position;
char boardArray[3][3]={{'1','2','3'},
{'4','5','6'},
{'7','8','9'}};
int i;
for(i=0;i<9;i++)
{
player= playerType (player, boardArray);
if (player==3)
break;
else
{
location=selectLocation(boardArray, player, location);
position=setTurn(boardArray, location, player, position);
}
}
I am trying the following program on TurboC. I am getting a linker error for one of the function prototypes.
The error is: undefined symbol checkbranch(char near*) in module student.cpp where student.cpp is the name of the file.
The code compiles with no errors and I am not able to detect the error here. Any help would be appreciated.
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<iomanip.h>
#include<fstream.h>
#include<string.h>
#include<ctype.h>
void checkbranch(char string[]);
void checkusn(char string[]);
void checksem(char string[]);
void checkname(char string[]);
fstream file;
class iobuffer
{
public: char maxbyte[120];
iobuffer();
};
iobuffer::iobuffer()
{
for(int i=0; i<120; i++)
maxbyte[i]='\0';
}
class student
{
public: char usn[20], name[25], sem[10], address[20], branch[10];
student()
{
strcpy(name,"");
strcpy(usn, "");
strcpy(sem, "");
strcpy(branch, "");
strcpy(address, "");
}
void read();
void display();
void rsem();
void rname();
void rusn();
void rbranch();
void raddress();
};
void student::rusn()
{
cout<<"\n\tEnter the new usn: ";
gets(usn);
checkusn(usn);
}
void student::rname()
{
cout<<"\n\tEnter the name: ";
gets(name);
checkname(name);
}
void student::rsem()
{
cout<<"\n\tEnter the sem: ";
gets(sem);
checksem(sem);
}
void checkbranch(char string[]);
void student::rbranch()
{
cout<<"\n\tEnter the branch: ";
gets(branch);
checkbranch(branch);
}
void student::raddress()
{
cout<<"\n\tEnter the address: ";
gets(address);
}
void checkname(char arr[])
{
for(int j=0; arr[j]!='\0'; j++)
if((!isalpha(arr[j]))&&(arr[j]!=' '))
{
cout<<"\n\tWrong input. Re-enter: ";
gets(arr);
j=-1;
}
}
void student::read()
{
cout<<"\n\tUSN: ";
gets(usn);
checkusn(usn);
cout<<"\n\tName: ";
gets(name);
checkname(name);
cout<<"\n\tSem: ";
gets(sem);
checksem(sem);
cout<<"\n\tBranch: ";
gets(branch);
checkbranch(branch);
cout<<"\n\tAddress: ";
gets(address);
}
void checksem(char arr[])
{
int x=0;
if((strcmp(arr,"1")==0)||(strcmp(arr,"2")==0)||(strcmp(arr,"3")==0)||(strcmp(arr,"4")==0)||(strcmp(arr,"5")==0)||(strcmp(arr,"6")==0)||(strcmp(arr,"7")==0)||(strcmp(arr,"8")==0))
x=1;
if(x==0)
{
cout<<"\n\tInvalid sem. Re-enter: ";
gets(arr);
checksem(arr);
}
}
void checkusn(char string[])
{
fstream ftemp;
char temp[20], tempusn[20], usn[20];
int i;
if((strlen(string)!=10)||(!isdigit(string[0]))||(!isdigit(string[3]))||(!isdigit(string[4]))||(!isdigit(string[7]))||(!isdigit(string[8]))||(!isdigit(string[9]))||(!isalpha(string[1]))||(!isalpha(string[2]))||(!isalpha(string[5]))||(!isalpha(string[6])))
{
cout<<"\n\tInvalid USN. Re-enter: ";
gets(string);
checkusn(string);
}
file.open("studentdb.txt",ios::in|ios::binary);
while(file.read(temp,120))
{
i=0;
while((tempusn[i]=temp[i])!='|')
i++;
tempusn[i]='\0';
if(strcmp(tempusn,string)==0)
{
cout<<"\n\tUSN already exists. Re-enter: ";
gets(string);
checkusn(string);
}
}
file.close();
}
void student::display()
{
cout<<setiosflags(ios::left);
cout<<setw(15)<<usn<<setw(20)<<name<<setw(10)<<sem<<setw(15)<<branch<<setw(25)<<address;
}
class fixedlength:public iobuffer
{
public: char buffer[120];
void pack(student s);
void unpack(student s);
};
void fixedlength::pack(student s)
{
strcpy(maxbyte, "");
strcpy(maxbyte, s.usn);
strcat(maxbyte,"|");
strcat(maxbyte, s.name);
strcat(maxbyte, "|");
strcat(maxbyte, s.sem);
strcat(maxbyte, "|");
strcat(maxbyte, s.branch);
strcat(maxbyte, "|");
strcat(maxbyte, s.address);
strcat(maxbyte, "#");
}
void fixedlength::unpack(student s)
{
strcpy(buffer, maxbyte);
for(int i=0, j=1, k=0; j<=5; i++, j++)
{
switch(j)
{
case 1: while(buffer[i]!='|')
s.usn[k++]=buffer[i++];
s.usn[k]='\0';
k=0;
break;
case 2: while(buffer[i]!='|')
s.name[k++]=buffer[i++];
s.name[k]='\0';
k=0;
break;
case 3: while(buffer[i]!='|')
s.sem[k++]=buffer[i++];
s.sem[k]='\0';
k=0;
break;
case 4: while(buffer[i]!='|')
s.branch[k++]=buffer[i++];
s.branch[k]='\0';
k=0;
break;
case 5: while(buffer[i]!='\0')
s.address[k++]=buffer[i++];
s.address[k]='\0';
k=0;
}
}
}
class delim:public fixedlength
{
public: void writerecord(student);
void readrecord(student);
void deleterecord(student, char*);
void searchrecord(student, char*);
void modifyrecord(student, char*);
};
void delim::writerecord(student s)
{
pack(s);
file.open("studentdb.txt", ios::app|ios::binary);
file.write((char*)&maxbyte, sizeof(maxbyte));
file.close();
}
void delim::readrecord(student s)
{
file.open("studentdb.txt", ios::in|ios::binary);
cout<<"\n\n File Contents\n\n";
while(file.read((char*)&maxbyte, sizeof(maxbyte)))
{
unpack(s);
cout<<endl;
s.display();
}
getch();
file.close();
}
void delim::searchrecord(student s, char *key)
{
int flag=0;
file.open("studentdb.txt",ios::in|ios::binary);
while((file.read((char*)&maxbyte,sizeof(maxbyte)))&&flag==0)
{
unpack(s);
if(!strcmp(s.usn,key))
{
flag=1;
s.display();
}
}
if(flag==0)
{
cout<<"\n\tSpecified record doesn't exist";
getch();
file.close();
}
}
void delim::deleterecord(student s, char *a)
{
int flag=0;
char x;
fstream ftemp;
file.open("studentdb.txt",ios::in|ios::binary);
ftemp.open("temp.txt", ios::out|ios::trunc|ios::binary);
cout<<"\n\tAre you sure you want to delete (y/n)?";
cin>>x;
if(x=='y'||x=='Y')
{
while(file.read((char*)&maxbyte, sizeof(maxbyte)))
{
unpack(s);
if(strcmp(s.usn,a)==0)
flag=1;
else
ftemp.write((char*)&maxbyte,sizeof(maxbyte));
}
}
if(flag==1)
{
file.close();
ftemp.close();
remove("studentdb.txt");
rename("temp.txt","studentdb.txt");
}
if(flag==0)
{
cout<<"\n\tThe specified record is not found\n";
file.close();
ftemp.close();
}
}
void delim::modifyrecord(student s, char *a)
{
int flag=0, choice;
file.open("studendb.txt",ios::in|ios::out|ios::binary);
while(file.read((char*)&maxbyte,sizeof(maxbyte)))
{
unpack(s);
if(strcmp(s.usn,a)==0)
{
char x;
flag=1;
cout<<"\n\t Current contents: \n\n\n";
s.display();
do
{
cout<<"What do you want to change: ";
cout<<"\n\t1.Name\n\t2. Sem\n\t3. Branch\n\t4. Address\n\t5. Confirm changes\n\t6. Return to main\n";
cout<<"Enter choic: ";
cin>>choice;
switch(choice)
{
case 1: s.rname(); break;
case 2: s.rsem(); break;
case 3: s.rbranch(); break;
case 4: s.raddress(); break;
case 5: break;
case 6: return;
default: cout<<"Invalid option\n";
}
}while(choice==1||choice==2||choice==3||choice==4);
cout<<"\n\tDo you want to modify (y\n)?";
cin>>x;
if(x=='y'||x=='Y')
{
pack(s);
file.seekg(-120,ios::cur);
file.write((char*)&maxbyte,sizeof(maxbyte));
}
else
break;
}
}
if(flag==0)
{
cout<<"\n\t Specified record doesn't exist\n";
file.close();
}
}
void main()
{
clrscr();
iobuffer i;
student s;
fixedlength f;
delim d;
int option;
char no[20], key[20];
for(;;)
{
cout<<"\n\nMenu:- ";
cout<<"\n\t1. Insert\n\t2. Display\n\t3. Delete\n\t4. Modify\n\t5. Search\n\t6. End\n\t";
cin>>option;
switch(option)
{
case 1: s.read();
d.writerecord(s);
break;
case 2: d.readrecord(s);
break;
case 3: cout<<"Enter the usn to delete\n";
gets(no);
d.deleterecord(s, no); break;
case 5: cout<<"\nEnter usn to be searched\n";
gets(key);
d.searchrecord(s,key);
break;
case 4: cout<<"\n\tEnter the usn to be modified\n";
gets(no);
d.modifyrecord(s,no);
break;
case 6: exit(0); break;
}
}
}
I wasn't sure what the error would be therefore I tried:
Reordering the function prototypes statements (even then error would
only be for checkbranch)
Writing the function prototype for checkbranch elsewhere (again error would occur)
Removing the prototype itself (and then get the compilation error for lack of
prototype)
You have to implement the checkbranch function, compiler can not do that for you.