I am trying to make a mini game where you input a command about what to do, and you need to input your since most of my inputs will look like this:atk 1 or:health 1
The input must in one line, but there are commands that don't have a number after them.
I need to input them in one line, so I use scanf("%s %d") to do this, but I also have some commands that don't have a number after the string, but if I don't use scanf I don't have ways to input them in a same line.
Is there solutions for situation like this? Sometimes the input is a string with a number, and sometimes a string only.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXSIZE 100
struct status
{
int hp;
char name[MAXSIZE];
};
int main()
{
struct status you;
struct status enemy;
//your name and hp
scanf("%s %d", you.name, &you.hp);
//enemy's name and hp
scanf("%s %d", enemy.name, &enemy.hp);
char move[MAXSIZE];
int damage = 0;
int poison = 0;
int round = 0;
//game start
//you start first, than you input what enemy do in next round
//atk means attack, poison means you got poison by enemy on every end of rounds, health means you heal yourself, none means you skip this round
//show means to show your and enemy's curreny status
//end means end the game the process stop, it also stops when someone's hp is zero
while((you.hp > 0)&&(enemy.hp > 0) )
{
scanf("%s %d", move, &damage);
if( strcmp(move,"atk") == 0 )
{
if((round%2) == 0)
enemy.hp = enemy.hp - damage;
else
you.hp = you.hp = damage;
round++;
}
else if( strcmp(move,"health") == 0 )
{
you.hp = you.hp + damage;
round++;
}
else if( strcmp(move,"poison") == 0 )
{
poison = poison + damage;
round++;
}
else if( strcmp(move,"none") == 0 )
{
round++;
}
else if( strcmp(move,"show") == 0)
{
printf("%s %d %s %d\n", you.name, you.hp, enemy.name, enemy.hp);
continue;
}
else
break;
}
if( strcmp(move, "atk") == 0)
{
if((round%2) == 0)
printf("%s were defeated by attack", you.name);
else
printf("%s were defeated by your attack", enemy.name);
}
else if( strcmp(move, "end") == 0)
{
return 0;
}
else
printf("%s were defeated by poison", you.name);
return 0;
}
The general advice is to avoid
scanf.Instead,
fgetscan be used to read an entire line of input from a stream into a buffer. Then the buffer can be freely manipulated, or parsed multiple times, without having to worry about the state of the stream.The program below has examples of using both
strtok(+strtol) andsscanfto extract data from a string. Each of these tools has advantages and disadvantages; reading their documentation is recommended.Some additional suggestions:
The use of an
enumreduces the need to repeatedly compare strings, and its integral nature allows the use of aswitch. An array kept in parallel (actions) to the enumeration type acts as a lookup table for string<->enumconversions. At the same time, this array can be used to indicate if a command requires an argument.Placing your players in an array allows the use of modular arithmetic to determine the current player and next player without repeatedly checking the turn count. Alternatively, having a pointer to each player and swapping the values of the pointers each turn might prove easier to read.
poisonshould probably be an attribute of a player (struct status).Here is an example program with a few of these concepts to play around with:
Example usage: