Specific dice to reroll in C - c

I am working on a game of Yahtzee and one part of the game is the user can choose which dice out of 5 they wish to re-roll. I don't really know how to approach this besides writing a ton of if if-else statements, but there has to be a more efficient way to re-roll the specific die/ dice. I wrote out a snippet of what I am trying to accomplish, its not exactly like this in my actual code, but hopefully it is enough to answer the question :)
#include<stdio.h>
int main(void)
{
int die1 = 0, die2 = 0, die3 = 0, die4 = 0, die5 = 0;
int *ptr_die1 = &die1, *ptr_die2 = &die2, *ptr_die3 = &die3, *ptr_die4 = &die4, *ptr_die5 = &die5;
int choice = 0;
int die[5] = { 0 };
for (int i = 0; i < 5; i++)
{
die[i] = rand() % 6 + 1;
}
printf("Die[1] = %d\n", die[0]);
printf("Die[2] = %d\n", die[1]);
printf("Die[3] = %d\n", die[2]);
printf("Die[4] = %d\n", die[3]);
printf("Die[5] = %d\n", die[4]);
choice = printf("Please select which die to reroll\n");
scanf("%d", &choice);
printf("%d\n", choice);
for (int i = 0; i < 5; i++)
{
die[choice-1] = rand() % 6 + 1;
}
printf("Die[1] = %d\n", die[0]);
printf("Die[2] = %d\n", die[1]);
printf("Die[3] = %d\n", die[2]);
printf("Die[4] = %d\n", die[3]);
printf("Die[5] = %d\n", die[4]);
return 0;
}
after this I am really lost on how to change the die because the user could want to change just 1, or all 5 or any combination in between...

You have way too many variables that are not really needed.
int main(int argc, char **argv)
{
int i;
int choice;
int dices[5];
srand(time(NULL));
while(1){
for (i = 0; i < 5; i++)
dices[i] = rand() % 6 + 1;
choice = printf("Please select which die to reroll (or enter 0 to quit)");
scanf("%d", &choice);
if (choice == 0) // end the game
break;
if (choice < 1 || choice > 5 ){ // make sure that input is valid
fprintf(stderr, "error, input should be between 1 to 5 (inclusive)\n");
return -1;
}
printf("dice shows: %d", dices[choice-1]);
}
return 0;
}
You need to ask the user for the ending it, e.g. "Enter 0 to end the game". Otherwise it would be an infinite loop.

You could have the user input a comma-separatd list of die, instead of a single integer, which it looks like you're doing now. Then just parse the input, check that you have between 1 and 5 valid integers less than 6, and index into each die.
Or you could do like kaylum suggested and loop until the user inputs a special string indicating they're done, or prompt for 1, 2, ... 5 and ask for a yes or no answer to each.

Just use an array of int values to represent the set of dice:
#define DICE_COUNT 6
void rollDice(int* diceArray, size_t diceIndex) {
assert( 0 <= diceIndex && diceIndex < DICE_COUNT );
diceArray[ diceIndex ] = rand() % 6 + 1;
}
int main(int argc, char* argv[]) {
// Seed the RNG:
srand( (unsigned)time(&t) );
int dice[DICE_COUNT];
for(size_t i = 0; i < DICE_COUNT; i++) {
rollDice( dice, i );
}
while( true ) {
printf("Please select which die to reroll. Enter -2 to quit. (%d to %d inclusive)", 1, DICE_COUNT);
int selection = -1;
scanf("%d", &selection);
if( selection == -2 ) break;
if( 1 <= selection && selection <= DICE_COUNT ) {
selection--; // convert from 1-6 to 0-5.
rollDice( dice, selection );
}
}
return EXIT_SUCCESS;
}

I don't see any if..else statements in your code above. I will say, in this chunk of code:
for (int i = 0; i < 5; i++)
{
die[choice-1] = rand() % 6 + 1;
}
You don't need the for loop. You are not using the index, and rand() should work the first time through. I know rand() isn't the best written function, but if you seed it first, it should give you a pseudo-random number.
#include <time.h>
...
/* initialize random seed: */
srand ( time(NULL) );
...
die[choice-1] = rand() % 6 + 1;
Hope this was helpful, if you are still even working on that project!

Related

How do I generate 4 random variables and only printing if it doesn't contain the int 0

this is my code, I want to make a function that when it is called will generate a number between 1111 to 9999, I don't know how to continue or if I've written this right. Could someone please help me figure this function out. It suppose to be simple.
I had to edit the question in order to clarify some things. This function is needed to get 4 random digits that is understandable from the code. And the other part is that i have to make another function which is a bool. The bool needs to first of get the numbers from the function get_random_4digits and check if there contains a 0 in the number. If that is the case then the other function, lets call it unique_4digit, should disregard of that number that contained a 0 in it and check for a new one to use. I need not help with the function get_random_4digitsbecause it is correct. I need helt constructing a bool that takes get_random_4digits as an argument to check if it contains a 0. My brain can't comprehend how I first do the get_random_4digit then pass the answer to unique_4digits in order to check if the random 4 digits contains a 0 and only make it print the results that doesn't contain a 0.
So I need help with understanding how to check the random 4 digits for the integer 0 and not let it print if it has a 0, and only let the 4 random numbers print when it does not contain a 0.
the code is not suppose to get more complicated than this.
int get_random_4digit(){
int lower = 1000, upper = 9999,answer;
answer = (rand()%(upper-lower)1)+lower;
return answer;
}
bool unique_4digits(answer){
if(answer == 0)
return true;
if(answer < 0)
answer = -answer;
while(answer > 0) {
if(answer % 10 == 0)
return true;
answer /= 10;
}
return false;
}
printf("Random answer %d\n", get_random_4digit());
printf("Random answer %d\n", get_random_4digit());
printf("Random answer %d\n", get_random_4digit());
Instead of testing each generated code for a disqualifying zero just generate a code without zero in it:
int generate_zero_free_code()
{
int n;
int result = 0;
for (n = 0; n < 4; n ++)
result = 10 * result + rand() % 9; // add a digit 0..8
result += 1111; // shift each digit from range 0..8 to 1..9
return result;
}
You can run the number, dividing it by 10 and checking the rest of it by 10:
int a = n // save the original value
while(a%10 != 0){
a = a / 10;
}
And then check the result:
if (a%10 != 0) printf("%d\n", n);
Edit: making it a stand alone function:
bool unique_4digits(int n)
{
while(n%10 != 0){
n = n / 10;
}
return n != 0;
}
Usage: if (unique_4digits(n)) printf("%d\n", n);
To test if the number doesn't contain any zero you can use a function that returns zero if it fails and the number if it passes the test :
bool FourDigitsWithoutZero() {
int n = get_random_4digit();
if (n % 1000 < 100 || n % 100 < 10 || n % 10 == 0) return 0;
else return n;
}
"I need not help with the function get_random_4digits because it is correct."
Actually the following does not compile,
int get_random_4digit(){
int lower = 1000, upper = 9999,answer;
answer = (rand()%(upper-lower)1)+lower;
return answer;
}
The following includes modifications that do compile, but still does not match your stated objectives::
int get_random_4digit(){
srand(clock());
int lower = 1000, upper = 9999,answer;
int range = upper-lower;
answer = lower + rand()%range;
return answer;
}
" I want to make a function that when it is called will generate a number between 1111 to 9999,"
This will do it using a helper function to test for zero:
int main(void)
{
printf( "Random answer %d\n", random_range(1111, 9999));
printf( "Random answer %d\n", random_range(1111, 9999));
printf( "Random answer %d\n", random_range(1111, 9999));
printf( "Random answer %d\n", random_range(1111, 9999));
return 0;
}
Function that does work follows:
int random_range(int min, int max)
{
bool zero = true;
char buf[10] = {0};
int res = 0;
srand(clock());
while(zero)
{
res = min + rand() % (max+1 - min);
sprintf(buf, "%d", res);
zero = if_zero(buf);
}
return res;
}
bool if_zero(const char *num)
{
while(*num)
{
if(*num == '0') return true;
num++;
}
return false;
}

User defined values aren't honored in program at later points

In the code below, the user is supposed to be able to define what nurses won't be available for work that week. The user has a list of the names, and they are supposed to type a number that corresponds to the name. Once that value is stored into the slackers[4] array, it should be using those user supplied values to remove those nurses from being selected come making selections. It doesn't seem to be honoring those selected values, despite avail_nurses[9] having the correct values at any point in time (I tested using printf statements).
Everything seems to be in good shape except that essential piece of the puzzle. I would appreciate some constructive critique and useful suggestions. If you can avoid it, don't write the code for me--I gotta learn somehow. Thanks in advance!
#include "stdafx.h"
#include <stdlib.h>
#include <time.h>
char *names[] = { "Denise", "Inja", "Jane", "Karen", "Maggie", "Margaret", "MJ", "Queen", "Sherri", NULL }; //ptr for names, 9 nurses
/*0 = Denise, 1 = Inja, 2 = Jane, 3 = Karen, 4 = Maggie, 5 = Margaret, 6 = MJ, 7 = Queen, 8 = Sherri*/
const char days[5][10] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" };
int randomNurse();
#define total_nurses 9 //number of nurses on staff
#define days_in_week 5 //number of work days in a week
int main() {
srand(time(NULL));
int day, pos, rand_num, i, j;
int slackers[4] = { 0, 0, 0, 0 }; //array that holds the selections for who isn't working
int avail_nurses[total_nurses] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 }; //holds the status of each nurse, 0 = unavailable, 1 = available
/*this allows the user to repeat the program easily! flag determines if we run the program multiple times*/
while (char flag = 'y') {
/*prints names */
int temp_counter = 1; //counter
char **name_ptr = names;
while (*name_ptr) {
printf("%i) %s\n", temp_counter, *name_ptr);
name_ptr++;
temp_counter++;
}
/*this assumes that no more than FOUR nurses will be away on any given week*/
printf("\nEnter numbers that correspond to the nurses who won't be available for the week.\nType up to four numbers, each separated by a space.\n");
printf("When you are done, press \"Enter\".\n");
printf("If less than four nurses will be on leave, type a \"0\" in place of a selection.\n");
printf("Example: 1 2 5 0\n\n\n");
/*week selection of unavailable nurses*/
do {
printf("Who won't be here? ");
} while (scanf("%i %i %i %i", &slackers[0], &slackers[1], &slackers[2], &slackers[3]) != 4);
/*checks the selections made, and sets the available nurses to the correct value, zero if they are slacking||vacationing*/
for (int n = 0; n < 4; n++) {
int slacker = slackers[n];
if (slacker >= 1 && slacker <= 9)
avail_nurses[slacker - 1] = -1;
}
/*-----WEEKLY_ASSIGNMENT-----*/
int pos_per_day[days_in_week] = { 5, 9, 9, 8, 5 }; //number of nurses needed each day
int selection[days_in_week][total_nurses]; //the selected nurses per day
for (i = 0; i < days_in_week; i++) {
for (j = 0; j < total_nurses; j++) {
selection[i][j] = -1; //initialize to -1 which means no nurse is selected
}
}
//fill all the days of week
for (day = 0; day < days_in_week; day++) {
for (pos = 0; pos < pos_per_day[day]; pos++) { //for every position needed that day
do {
rand_num = randomNurse();
} while (!avail_nurses[rand_num]); //looks for available nurses (phrasing)
avail_nurses[rand_num] = 0; //change nurses status to not available
selection[day][pos] = rand_num; //fill the output array with appropriate nurse
}
for (i = 0; i < total_nurses; i++) {
avail_nurses[i] = 1; //initialize the nurses status for next day use
}
for (int n = 0; n < 4; n++) { //make sure we shame the slackers...
int slacker = slackers[n];
if (slacker >= 1 && slacker <= 9)
avail_nurses[slacker - 1] = -1;
}
/*DEBUGGING PRINTFs
printf("\n\nSELECTION:\n");
for (int x = 0; x < days_in_week; x++) {
for (int y = 0; y < total_nurses; y++) {
printf("%i\t", selection[x][y]);
}
printf("\n");
}*/
}
printf("\n");
/*-----PRINTS SCHEDULE FOR WEEK-----*/
for (i = 0; i < days_in_week; i++) {
printf("%-10s: ", days[i]);
for (j = 0; j < total_nurses; j++) {
if (selection[i][j] != -1)
printf("%-10s ", names[selection[i][j]]);
}
printf("\n");
}
fflush(stdin);
/*asks user if they want the program to run again*/
printf("\n\nDo you want to run the program again? (y/n) ");
scanf("%c", &flag);
if (flag == 'n' || flag == 'N') {
printf("\n");
break;
}
else {
printf("\n\n\n");
continue;
}
}
return 0;
}
/*function to generate random nurse*/
int randomNurse() {
return rand() % 9; //random number 0-8, to pick nurse
}
Your avail_nurses array uses the value 1 to indicate a nurse that's available, the value 0 to indicate a nurse that's not available as that nurse has already been assigned, and -1 to indicate a nurse that's not available because that nurse is a slacker. You then test whether or not a nurse is available with !avail_nurses[rand_num]. This statement is true if avail_nurses[rand_num] is 0 and is false if it's any other value. The means when avail_nurses[rand_num] is -1 it will exit the loop just like it does when it's 1.
To fix this bug either change the test to avail_nurses[rand_num] <= 0 or use only 0 to indicate unavailable nurses regardless of the reason why.

Switch-Case statement seems to freeze my loops

Here are a few loops from my program I'm working on. The program seems to stop advancing after printf("TEST2");. Everything checks out at a glance. Is there something I'm missing?
I'm expecting the loop to repeat after setting the values in the switch-statement. I know it's getting through it at least once.
#include "stdafx.h"
#include <stdlib.h>
#include <time.h>
char *names[] = { "Denise", "Inja", "Jane", "Karen", "Maggie", "Margaret", "MJ", "Queen", "Sherri", NULL }; //ptr for names, 9 nurses
const char days[5][10] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" };
int randomNurse();
#define total_nurses 9 //number of nurses on staff
#define days_in_week 5 //number of work days in a week
int main() {
srand(time(NULL));
int day, pos, candidate, i, j;
int slackers[4] = { 1, 1, 1, 1 }; //array that holds the selections for who isn't working
char **name_ptr = names;
/*0 = Denise, 1 = Inja, 2 = Jane, 3 = Karen, 4 = Maggie, 5 = Margaret, 6 = MJ, 7 = Queen, 8 = Sherri*/
int avail_nurses[total_nurses] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 }; //holds the status of each nurse, 0 = unavailable, 1 = available
/*prints names */
int temp_counter = 1; //counter
while (*name_ptr) {
printf("%i) %s\n", temp_counter, *name_ptr);
name_ptr++;
temp_counter++;
}
/*this assumes that no more than FOUR nurses will be away on any given week*/
printf("\nEnter numbers that correspond to the nurses who won't be available for the week.\nType up to four numbers, each separated by a space.\n");
printf("When you are done, press \"Enter\".\n");
printf("If less than four nurses will be on leave, type a \"0\" in place of a selection.\n");
printf("Example: 1 2 5 0\n\n\n");
/*week selection of unavailable nurses*/
do {
printf("Who won't be here? ");
} while (scanf("%i %i %i %i", &slackers[0], &slackers[1], &slackers[2], &slackers[3]) != 4);
/*checks the selections made, and sets the available nurses to the correct value, zero if they are slacking||vacationing*/
for (int n = 0; n < 4; n++) {
int slacker = slackers[n];
if (slacker >= 1 && slacker <= 9)
avail_nurses[slacker] = -1;
}
/*-----WEEKLY_ASSIGNMENT-----*/
int pos_per_day[days_in_week] = { 5, 9, 9, 8, 5 }; //number of nurses needed each day
int selection[days_in_week][total_nurses]; //the selected nurses per day
for (i = 0; i < days_in_week; i++) {
for (j = 0; j < total_nurses; j++) {
selection[i][j] = -1; //initialize to -1 which means no nurse is selected
}
}
//fill all the days of week
for (day = 0; day < days_in_week; day++) {
for (pos = 0; pos < pos_per_day[day]; pos++) { //for every position needed that day
do {
candidate = randomNurse();
} while (!avail_nurses[candidate]); //looks for available nurses (phrasing)
avail_nurses[candidate] = 0; //change nurses status to not available
selection[day][pos] = candidate; //fill the output array with appropriate nurse
}
for (i = 0; i < total_nurses; i++) {
avail_nurses[i] = 1; //initialize the nurses status for next day use
}
for (int n = 0; n < 4; n++) { //make sure we shame the slackers...
int slacker = slackers[n];
if (slacker >= 1 && slacker <= 9)
avail_nurses[slacker] = -1;
}
}
/*-----PRINTS SCHEDULE FOR WEEK-----*/
for (i = 0; i < days_in_week; i++) {
printf("%-10s: ", days[i]);
for (j = 0; j < total_nurses; j++) {
if (selection[i][j] != -1)
printf("%-10s ", names[selection[i][j]]);
}
printf("\n");
}
return 0;
}
/*function to generate random nurse*/
int randomNurse() {
return rand() % 9; //random number 0-8, to pick nurse
}
You have Undefined Behaviour. The second value in pos_per_day is 9, which is outside the bounds of the select array. Subtracting one from each value in that array may be enough to fix it.
Other bad problems:
you need to validate the input data after scanf.
the switch statement is completely unnecessary. Replace it by a calculation.
don't use UPPER CASE for variables. By convention, that's only for defined constants.
don't hard code numbers like 5 and 9. Replace them by DEFINED CONSTANTS.
You must learn how to debug simple programs like this, using the debugger available to you.

C programming. The FizzBuzz program [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 5 years ago.
Improve this question
I had a quiz and I wrote this code:
Print Fizz if it is divisible by 3 and it prints Buzz if it is
divisible by 5. It prints FizzBuss if it is
divisible by both. Otherwise, it will print the numbers between 1 and 100.
But after I arrived home, I wondered if could have
writen it with less code. However, I could not come out
with a shorter code.
Can I do it with a shorter code? Thanks.
This is what I wrote and I think it works well. But can I have done it
with less code.
#include <stdio.h>
int main(void)
{
int i;
for(i=1; i<=100; i++)
{
if(((i%3)||(i%5))== 0)
printf("number= %d FizzBuzz\n", i);
else if((i%3)==0)
printf("number= %d Fizz\n", i);
else if((i%5)==0)
printf("number= %d Buzz\n", i);
else
printf("number= %d\n",i);
}
return 0;
}
You could also do:
#include <stdio.h>
int main(void)
{
int i;
for(i=1; i<=100; ++i)
{
if (i % 3 == 0)
printf("Fizz");
if (i % 5 == 0)
printf("Buzz");
if ((i % 3 != 0) && (i % 5 != 0))
printf("number=%d", i);
printf("\n");
}
return 0;
}
A few lines shorter, and a lot easier to read.
I'm not sure when you'd start calling it unreadable, but there's this.
#include <stdio.h>
int main(void)
{
int i = 1;
for (; i<=100; ++i) {
printf("number= %d %s%s\n", i, i%3?"":"Fizz", i%5?"":"Buzz");
}
return 0;
}
If a number is divisible by both 3 and 5, then it's divisible by 15, so:
for each number 1 to 100:
if number % 15 == 0:
print number, "fizzbuzz"
else if number % 5 == 0:
print number, "buzz"
else if number % 3 == 0:
print number, "fizz"
else:
print number
Other than that, you probably won't get it much shorter, at least in a conventional language like C (and I'm assuming you don't want the normal code-golf style modifications that make your code unreadable).
You could also get the whole thing into two lines if you packed the entire main function onto a single large line, but I would hope you wouldn't be after that sort of trickery either.
You can possibly get it faster (though you should check all performance claims for yourself) with something like:
static const char *xyzzy[] = {
"", "", "fizz", "", "buzz",
"fizz", "", "", "fizz", "buzz",
"", "fizz", "", "buzz", "fizzbuzz",
// Duplicate those last three lines to have seven copies (7x15=105).
};
for (int i = 1; i <= 100; i++)
printf ("%d %s\n", i, xyzzy[i-1]);
As an aside, that array of char pointers is likely to be less space-expensive than you think, thanks to constant amalgamation - in other words, it will be likely that there will only be one of each C string.
As I say, whether it's faster should be tested. In addition, your original specs only called for the shortest code so it may be irrelevant.
#include <stdio.h>
char const * template[] = {
"%i",
"Buzz",
"Fizz",
"FizzBuzz"
};
const int __donotuseme3[] = { 2, 0, 0 };
const int __donotuseme5[] = { 1, 0, 0, 0, 0 };
#define TEMPLATE(x) (template[__donotuseme3[(x) % 3] | __donotuseme5[(x) % 5]])
int
main(void) {
int i;
for (i = 1; i <= 100; i++) {
printf(TEMPLATE(i), i);
putchar('\n');
}
return 0;
}
I would say that modulo is expensive while comparisons are cheap so only perform the modulo once. That would yield something like this.
int i;
for( i = 0; i!=100; ++i ) {
bool bModThree = !(i % 3);
bool bModFive = !(i % 5);
if( bModThree || bModFive ) {
if( bModThree ) {
printf( "Fizz" );
}
if( bModFive ) {
printf( "Buzz" );
}
} else {
printf( "%d", i );
}
printf( "\n" );
}
This one avoids some code repetition but requires a temporary variable char t
void FizzBuzz( ) {
char t = 0;
for (unsigned char i = 1; i <= 100; ++i, t = 2) {
(i % 3) ? --t : printf("Fizz");
(i % 5) ? --t : printf("Buzz");
if (!t) printf("%d", i);
printf("\n");
}
}
i would write something like that
main(){
if (i % 3 == 0){
cout<<"Fizz";
}
if (i % 5 == 0){
cout<<"Buzz";
}
// So if both are true, it will print “FizzBuzz” and augment the two strings
}
I'd go with a helper function :-)
#include <stdio.h>
int fbindex(int n) {
int i = 0;
if (n % 3 == 0) i += 1;
if (n % 5 == 0) i += 2;
return i;
}
int main(void) {
const char *fb[] = {"%d\n", "Fizz\n", "Buzz\n", "FizzBuzz\n"};
for (int i = 1; i <= 100; i++) printf(fb[fbindex(i)], i);
}
void main()
{
int i = 0;
char h[4];
while (++i <= 100)
{
sprintf(h, "%d", i);
printf("%s%s%s\n", i%3 ? "" : "fizz", i%5 ? "" : "buzz", (i%3 && i%5) ? h: "");
}
}
You can do it using a String:
String s="";
if(num%3==0)
s+="fizz";
if(num%5==0)
s+="buzz";
if(s.length()==0)
s+=num+"";
Obfuscated form of Mr Lister's answer
main(int i){while(i++<100){printf("number= %d %s%s",i,i%3?"":"Fizz",i%5?"":"Buzz");}}

Problems with Palindromes in C

I've written some code in C to try adn find whether or not a number is a Palindrome. The rule is that two 3 digit numbers have to be multiplied together and you have to find the highest palindrome. the answer should be 906609 but my code only gets to 580085.
the code:
#include <stdio.h>
#include <stdlib.h>
/* Intialise */
void CalcPalin();
int CheckPalin(int number);
/* Functions */
void CalcPalin()
{
int result = 0;
int palin = 0;
int FNumber = 0;
int FNumber2 = 0;
int number = 99;
int number2 = 100;
while(number2 < 1000)
{
number += 1;
/*times together - calc result*/
result = number * number2;
if(CheckPalin(result) == 1)
{
palin = result;
FNumber = number;
FNumber2 = number2;
}
if(number == 999)
{
number = 99;
number2 += 1;
}
}
printf(" Result = %d, by Multiplying [%d] and [%d]", palin, FNumber, FNumber2 );
}
int CheckPalin(int number)
{
int checknum, checknum2 = 0;
checknum = number;
while(checknum)
{
checknum2 = checknum2 * 10 + checknum % 10;
checknum /= 10;
}
if( number == checknum2)
return 1;
else
return 0;
}
int main( void)
{
CalcPalin();
return EXIT_SUCCESS;
}
Im pretty sure its a stupid answer and im over looking something simple but i cant seem to find it. Any help would be great
You have not tested whether the current result is higher than one old result. Add this check.
// test new result is higher than old palin before setting this as palin
if(CheckPalin(result) == 1 && palin < result)
Your algorithm print :
Result = 580085, by Multiplying [583] and [995]
It seems that you should find a way to increment more the 1st number. There is many possibility between 583 and 999 in order to get to 906609.
EDIT : In fact, you are looking for 993 * 913 = 906609.

Resources