NIM game against PC beginner - c++

My professor gave me a asignment to write a 16 matches Nim game.
One part of a task is to make PC to make moves as well. So, I tried to solve the problem by using SRAND but PC picked the same row and the same amount of sticks. What is more, PC also takes emty rows wich and hits the wall when he takes the zero massive.
So, thats is what I hve already done. Any thoughts?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define row 4
int main()
{
int theChecker = 1, sticks[row] = {1,3,5,7}, stickSum, i, choiceRow, choiceStick, pcRow, pcStick;
char answer;
do
{
printf("\n\n\t ************ \n");
printf("\t *THE NIM GAME* \n");
printf("\t ************ \n\n");
stickSum = sticks[0] + sticks[1] + sticks[2] + sticks[3];
while(stickSum > 0)
{
printf("\nStick log:\n");
for(i = 0; i < row; i++)
printf("Row %d: %d\n", i+1, sticks[i]);
printf("\n");
if(theChecker == 1)
{
printf("Choose a row: ");
scanf("%d", &choiceRow);
printf("Choose a sick: ");
scanf("%d", &choiceStick);
while((choiceRow <= 0) || (choiceRow > 4) || (sticks[choiceRow - 1] < choiceStick) || (choiceStick == 0))
{
printf("\n\t !!!ERROR!!!\n\tInvalid row or stick\n\nCheck stick log above\n\n");
printf("Choose a row: ");
scanf("%d", &choiceRow);
printf("Choose a sick: ");
scanf("%d", &choiceStick);
}
sticks[choiceRow-1] -= choiceStick;
stickSum -= choiceStick;
}
else //pc move starts-------------------------------------------
{
while(((pcRow <= 0) || (pcRow > 4)) && sticks[choiceRow - 1] == 0)
{
time_t seconds;
seconds = 0;
time(&seconds);
srand((unsigned int)seconds);
pcRow = rand() % 4;
}
printf("PC ROW: %d\n", pcRow);
while((sticks[pcRow - 1] < pcStick) || (pcStick == 0))
{
time_t seconds2;
seconds2 = 0;
time(&seconds2);
srand((unsigned int)seconds2);
pcStick = rand() % 16;
}
printf("PC STICK: %d\n\n", pcStick);
sticks[pcRow-1] -= pcStick;
stickSum -= pcStick;
}
if((theChecker == 1) && (stickSum == 0))
printf("\n\n!!!GAME OVER!!! You took the last stick!!!\n\n");
else if((theChecker == 2) && (stickSum == 0))
printf("\n\n!!!CONGRATS!!! You won!!!\n\n");
theChecker++;
if(theChecker == 3)
theChecker -= 2;
}
printf("\nPress r to restart the game or any key to end the game: ");
scanf("%c", &answer);
printf("\n");
}
while(answer == 'r');
return 0;`enter code here`
}

Don't call srand() more than once, it's used to initialize the random seed, which you are always initializing to the same value, the internal state gets reset over and over, always producing the same pseudo-random values.
I say that you always pass the same seed, because time() has seconds resolution, and in once second, the whole game was played and terminated.
You just need a call to srand() at the beginning of the program to prevent the program from choosing the same values across runs of the program, not in the same run.

Related

Logic error with array and for loop

If I enter an amount of 5 players (5 elements in the score[] array) in the scanf("%d", &numPlayers) the for loop cycles the players all the way up to player 5 (element 4 of score[]), and then jumps to the winMsg function. The score of that element is a large value, even though I set all the score[] element's to 0 in the first for loop. If I enter 6 or more elements, the second for loop never executes. Program runs no problem with 4 or less elements in score[]. I am using gedit and terminal in Ubuntu. Any ideas? Fairly new to programming. I appreciate any help.
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
int rollDie(){
return (rand()%6 + 1);
}
void winMsg(int winRoll, int player, int winScore){
printf("Congratulations Player %d! Your winning roll was a %d, putting your score at %d!\n\nGame Over\n\n", player + 1, winRoll, winScore);
return;
}
int main(){
srand(time(NULL));
int numPlayers = 0;
int roll = 0;
int i = 0;
int score[numPlayers];
char choice[2];
printf("Welcome to the \"Roll to Win\" game. Each roll adds to the current player's score, according to the die's number. A roll of 1 will cause the player to recieve no points that round, and then be skipped to the next player. First player to reach 100 or over wins! Please enter number of players: \n\n");
scanf("%d", &numPlayers);
printf("\n");
while (numPlayers >= 100 || numPlayers <= 0){
printf("Please enter a number of players less than 100, greater than 0.\n\n");
scanf("%d", &numPlayers);
printf("\n");
}
for (i = 0; i < numPlayers; ++i){
score[i] = 0;
printf("Set Player %d score to %d.\n", i + 1, score[i]);
}
printf("Starting with Player 1.\n\n");
for (i = 0; i < numPlayers; ++i){
roll = rollDie();
if (roll == 1){
printf("Player %d rolled a 1. Skipping turn. Current score: %d.\n\n", i + 1, score[i]);
}
else{
do{
score[i] += roll;
if (score[i] >= 100){
winMsg(roll, i, score[i]);
exit(0);
}
printf("Player %d rolled a %d, continue rolling (enter r to roll, or sr to stop rolling)? Current score: %d.\n\n", i + 1, roll, score[i]);
scanf("%s", choice);
printf("\n");
while ((strcmp ("r",choice) != 0) & (strcmp ("sr",choice) != 0)){
printf("Please enter a correct selection (enter r to roll, or sr to stop rolling).\n\n");
scanf("%s", choice);
printf("\n");
}
if (strcmp ("sr",choice) == 0){
printf("Player %d decided to stop rolling. Continuing to next player.\n\n", i + 1);
break;
}
roll = rollDie();
if (roll == 1){
printf("Player %d rolled a 1. Skipping turn. Current score: %d.\n\n", i + 1, score[i]);
break;
}
} while (strcmp (choice,"r") == 0);
}
if (i == numPlayers - 1){
i = -1;
}
}
}
Notice, that you set the size when initializing array before it is known, therefore you end up with garbage.
Doing int score[numPlayers]; and later scanf("%d", &numPlayers); will not do what you think it does.
it is not standard C++ to have a static array size which is not a constant,if you want that behavior you should use std::vector.
Even if this is working for you, then you should first ask for the number of players and then create the array. i.e
scanf("%d", &numPlayers);//first
....
int score[numPlayers];//then

C programming , array not printing properly

So for class we are doing some encryption/ decryption algorithms with prime numbers. I am in the first part of making the program. I am trying to get the program to check if a number is prime or not. After this, I want the program to store all prime numbers before that number in an array called prime_array. And I was trying to get those results to print out on the screen. It's not working the way I intended. I'm later going to use this in decryption of something a bit more complex. Just wandering if anyone could see what part of my code is causing the issues.
Code:
#include <stdio.h>
int main()
{
int n;
int prime;
int prime_array[1000];
int prime_answer;
int j=0;
printf("enter a number for n : ");
scanf_s("%d", &n);
if (n % 2 == 1)
{
printf("Number is prime.");
getchar();
getchar();
for (int i = 0; i <= n; i++)
{
if (n - 1 % 2 == 1)
{
n--;
prime_array[j] = n;
j++;
}
else
{
// do nothing
}
}
}
else if (n % 2 == 0)
{
printf("Number is not prime.");
getchar();
getchar();
}
for (int k = 0; k<= 10; k++)
{
printf("\n\n %d",prime_array[k]);
if (k == 10);
{
getchar();
getchar();
}
}
}
Problem is this condition-
if (n - 1 % 2 == 1)
This exression is treated as (n-(1 % 2))==1 , because % has higher precedence than - ,therefore , 1 % 2 is evaluated first .As 1 % 2 is 1 and expression become n-1 ,so condition will not be true until n is 2 (not as you would desire ) .
You need to write like this -
if ((n - 1) % 2 == 1)

Why can't I get the user input to output with the result

I am working on this currency project, it is supposed to output how many ways there is to makeup change,
For example when I input 2 dollars the program should output 293 ways.
I got the program to work but couldn't get the program to print the proper result
for example I want the program to print out
There are [the number of ways] ways to make up [user input]
but my program doesn't printout the last part [user input]
output of the code below is [when entered 2]
There are 293 ways to make up // The user input is missing
#include <iostream>
#include <cmath>
using namespace std;
int currency[11] = { 10000, 5000, 2000, 1000, 500, 200, 100, 50, 20, 10, 5 };
int f20(int n, int j)
{
int i = 0, t;
if (n == 0) return 1;
else
{
if (n<5) return 0;
}
for (t = 0; t<11; t++)
if (n >= currency[t] && j >= currency[t])
i += f20(n - currency[t], currency[t]);
return i;
}
int main(void){
int counter;
float usernum;
do{
cout << "Enter Total amount:";
cin >> usernum;
usernum = usernum * 100;
for (counter = 0; counter<11; counter++)
if (currency[counter] <= usernum)
{
printf("There are %d ways to make up \n\n", f20(usernum, currency[counter]), usernum); break;
}
} while (usernum != 0);
return 0;
}
The problem is in your if statement. currency[0] equals 10000. If usernum = 2 at first then usernum*100 = 200. Now, is 10000 < 200? No, so it evaluate to false, and you answer is not displayed. Rethink you condition.
Well don't you think it should be -
printf("There are %d ways to make up %d \n\n", f20(usernum, currency[counter]), usernum); break;
instead of -
printf("There are %d ways to make up \n\n", f20(usernum, currency[counter]), usernum); break;
You missed a %d
Thanks everyone for the help, i took ooga's advice and got rid of printf and inserted cout instead and fixed the problem.
cout << "There are " << f20(usernum, currency[counter]) << " ways to make up : " << usernum / 100 << "\n\n"; break;

homework: fast manipulations in a set of bits (represented as a character array)

there is certain practice question in a site interviewstreet that has kinda taken up lot of my time...
the following code crosses only 8/11 testcases. the rest it exceeds time limit. i would really appreciate if you could suggest some optimizations
the question is as follows.....
there are two binary numbers of length n
there are three kinds of operation
set_a idx x : it sets A[idx] = x
set_b idx x : sets B[idx] = x
get_c idx : Print C[idx], where C=A+B, and 0<=idx
Sample Input
5 5
00000
11111
set_a 0 1
get_c 5
get_c 1
set_b 2 0
get_c 5
Sample Output
100
so i need to optimize the get_c operation
void reverse(char*a, int len)
{
//this function reverses the string
}
void get_c(int i)
{
k = i-1;
f = 0;
while (k>=0)
{
if (a[k] == '1' && b[k] == '1')
{
f = 1;
break;
}
else if (a[k] == '0' && b[k] == '0')
break;
--k;
}
if (f==0)
cout<<(a[i] == b[i]?0:1);
else if (f==1)
cout<<(a[i] == b[i]?1:0);
}
int main()
{
scanf("%d %d", &n, &q); // n = number of bits in number, q = number of operations
// enter the strings a and b
reverse(a, n);
reverse(b, n);
while (q--)
{
scanf("%s", query);
scanf("%d", &idx);
if (query is get_c)
{
get_c(idx);
}
else if (query is set_a)
{
cin>>x;
a[idx] = x;
}
else if (query is set_b)
{
cin>>x;
b[idx] = x;
}
}
return 0;
}
It seems that you've implemented your binary numbers using arrays when it would be faster to implement them simply as numbers and query/modify them with bit masks and bit shifts. That would remove the need for you to use an iterative approach in get_c; your get_c function would be constant time instead of linear time.

If-construct advice needed

I have a for loop in which I placed several if statements. The objective of these conditionals is to check divisibility of a number and then output a string if the number is divisible by 3. If the number is divisible by 5, another string will be outputted. However, if the number is divisible by both 3 and 5, an entirely different string will be outputted in its place instead of the other strings.
Here is my code:
for (i = 1; i <= file_int; i++){
if (i % 3 == 0) {
printf("Hoppity \n");
}
if (i % 5 == 0) {
printf("Hophop \n");
}
if (i % 5 == 0 && i % 3 == 0) {
printf("Hop \n");
}
}
As you can see, the last conditional doesn't quite work. What type of control construct should I use? else?
Thanks alot.
for (i = 1; i <= file_int; i++){
if (i % 5 == 0 && i % 3 == 0) {
printf("Five and three\n");
} else if (i % 3 == 0) {
printf("Three\n");
} else if (i % 5 == 0) {
printf("Five\n");
} else {
printf("None of the conditions passed\n");
}
}
I would use else-ifs and make us of the fact that
(i % 5 == 0 && i % 3 == 0) <=> (i % 15 == 0):
for (i = 1; i <= file_int; i++){
if (i % 15 == 0)
printf("Hop \n");
else if (i % 3 == 0)
printf("Hoppity \n");
else if (i % 5 == 0)
printf("Hophop \n");
}
Of course you can also get away without using any control structures except the for-loop at all:
const char* values[15] = {"Hop \n", "", "", "Hoppity \n", "",
"Hophop \n", "Hoppity \n", "", "", "Hoppity \n",
"Hophop \n", "", "Hoppity \n", "", ""};
for (int i = 1; i <= 100; i++)
printf(values[i % 15]);
That solution is slightly insane for this example, but it shows how you can do things differently (and it's not so farfetched when writing code where you shall never ever have more then a certain number of branch paths in one function (overzealous coding conventions...)).
Just for the sake of it, and not recommending it, as it can be harder to read as it abuses conversions from bool to int:
int msg = (i % 3 == 0) + 2*(i % 5 == 0);
switch ( msg ) {
case 3:
cout << "Multiple of 3 and 5";
case 2:
cout << "Multiple of 5";
case 1:
cout << "Multiple of 3";
}
which can be further condensed into:
const char* msgs[] = { "", "Multiple 3", "Multiple 5", "Multiple 3 and 5" };
cout << msgs[ (i%3==0) + 2*(i%5==0) ];
Of course, both solutions are against the question itself, as they are not if constructs, but rather avoid the use of if in the first case, and branches in general in the second case.
An alternative solution, keeping closer to your original code. Although the else solution is indeed more efficient (and elegant).
for (i = 1; i <= file_int; i++){
if (i % 3 == 0 && i % 5 != 0) {
printf("Hoppity \n");
}
if (i % 5 == 0 && i % 3 != 0) {
printf("Hophop \n");
}
if (i % 5 == 0 && i % 3 == 0) {
printf("Hop \n");
}
}