# Thread: Help to improve a simple Lotto game code

1. ## Help to improve a simple Lotto game code

Hello,
Here are the steps I followed:
1. Generate Lotto numbers 1 - 20.
2. User makes a bet.
3. Swap Lotto numbers (swap left-right).
4. Computer picks (3) random numbers from Lotto and stores them in a separate array.
5. Bubble sort function sorts both user's winning numbers.
6. Compare if Lotto numbers and user's numbers coincide. If yes, show a number of iteration it took to get it done. If not, loop again.
Used the MS Visual Studio Community 2015.

Code:
```# include <stdio.h>
# include <stdlib.h>
# include <time.h>
# include <windows.h>
#pragma warning(disable:4996)

# define NUMS 20
# define BET 3

int main()
{
srand(unsigned(time(NULL)));
int iLotto[NUMS] = { 0, };
int iBet[BET] = { 0, };
int win_nums[BET] = { 0, };

/* 1. Generate Lotto numbers (1 - 20) */
for (int i = 0; i < NUMS; i++)
{
iLotto[i] = i + 1;
printf("%d  ", iLotto[i]);
}

/* 2. User makes a bet*/
printf("\nEnter (%d) numbers:\n", BET);
for (int i = 0; i < BET; i++)
{
scanf("%d", &iBet[i]);
}

int temp = 0;
int counter = 0;
while(true) // while loop begins
{

/* 3. Swap Lotto numbers (swap left-right) */
for (int i = 0; i < NUMS; i++)
{
int left = rand() % NUMS;
int right = rand() % NUMS;
temp = iLotto[left];
iLotto[left] = iLotto[right];
iLotto[right] = temp;
}

/* show swapped lotto numbers */
for (int i = 0; i < NUMS; i++)
{
printf("%d  ", iLotto[i]);
}

/* 4. Computer picks (3) random numbers from Lotto and stores them in a separate array */
for (int i = 0; i < BET; i++)
{
win_nums[i] = iLotto[i];
}
putchar('\n');

/* 5. Bubble sort function sorts both user's winning numbers */
int swapped1;
int temp1 = 0;
while (1)
{
swapped1 = 0;
for (int i = 0; i < BET - 1; i++)
{
if (iBet[i] > iBet[i + 1])
{
temp1 = iBet[i];
iBet[i] = iBet[i + 1];
iBet[i + 1] = temp1;
swapped1 = 1;
}
}
if (swapped1 == 0)
{
break;
}
} /* end of bubble sort for a user */

int swapped2;
int temp2;
while (1)
{
swapped2 = 0;
for (int i = 0; i < BET - 1; i++)
{
if (win_nums[i] > win_nums[i + 1])
{
temp2 = win_nums[i];
win_nums[i] = win_nums[i + 1];
win_nums[i + 1] = temp2;
swapped2 = 1;
}
}
if (swapped2 == 0)
{
break;
}
} /*end of bubble sort for winning numbers*/

/* 6. Compare if winning numbers and user's numbers coincide. */
for (int i = 0; i < BET; i++)
{
for (int k = 0; k < BET; k++)
{
if (win_nums[i] == iBet[k])
{
counter++;
break;
}
else
continue;
}
}

/* If yes => show a number of iteration it took to get it done. If not => loop again.*/
if ((win_nums[0] == iBet[0]) && (win_nums[1] == iBet[1]) && (win_nums[2] == iBet[2]))
{
printf("Winning numbers: ");
for (int i = 0; i < BET; i++)
{
printf("%d ", win_nums[i]);
}
for (int i = 0; i < BET; i++)
{
printf("%d ", iBet[i]);
}
printf("\ncounter: %d\n", counter);
break;
}
}

system("pause");
return 0;
}```
When increased a total number from 20 to 40 and winning numbers up to 6, I had to add more to this line:
Code:
`if ((win_nums[0] == iBet[0]) && (win_nums[1] == iBet[1]) && (win_nums[2] == iBet[2]))`
So it became:
Code:
`if ((win_nums[0] == iBet[0]) && (win_nums[1] == iBet[1]) && (win_nums[2] == iBet[2]) && (win_nums[3] == iBet[3]) && (win_nums[4] == iBet[4]) && (win_nums[5] == iBet[5]))`
As a result it keeps on looping non stop. While it takes only 300--700 iterations with 20 numbers and 3 winning numbers to find a winner. Any idea on what's wrong?

2. First, I don't think your bubble sorts are working properly. Try making a new C file that simply generates an array of random numbers, then print them out, bubble sort them, and print them again to verify it's working.

Once you have bubble sort working, comparing the win_nums and iBet array is just a matter of looping over them BET (3) times and incrementing a counter if the numbers (at the current index) are the same. After the loop ends you have the number of matching array elements, and if it's equal to BETS (3), they all matched and the player wins. Something like...

Code:
```    int counter = 0;
for (int i = 0; i < BET; i++)
{
if (win_nums[i] == iBet[i])
{
counter++;
}
}

if (counter == BET)
{
printf("You win!\n");
}
else
{
printf("You lose!\n");
}```
BTW, I would suggest using something like srand(123) when you're debugging rather than having it based on the time. That way, the "random" numbers are the same each time you run your program. After you've fixed all the bugs, change it back.

3. Originally Posted by dOOk
First, I don't think your bubble sorts are working properly.
The bubble sort is just written a little strangely and less efficiently than usual, but it works.

OP:

Use qsort to sort the arrays. And even if you write your own sort, NOBODY uses bubble sort. Selection sort or insertion sort are the common inefficient sorts (actually they are efficient for small arrays).

A somewhat more normal bubble sort implementation.
Code:
```void bubble_sort(int *a, int size) {
int swapped;
do {
swapped = 0;
for (int i = 0; i < size - 1; i++)
if (a[i] > a[i + 1]) {
int t = a[i]; a[i] = a[i+1]; a[i+1] = t;
swapped = i + 1;
}
size = swapped; // array is in order from swapped upwards
} while (swapped != 0);
}```
Don't include windows.h if you're not using it.

You don't need to sort the user's numbers over and over again. Just sort them once before the main loop.

Use memcmp to compare arrays.

Your shuffle routine is extremely bad. A (not perfect but) better shuffle:
Code:
```void shuffle(int *a, int size) {
for (int i = size; i > 1; ) {
int r = rand() % i--;
int t = a[i]; a[i] = a[r]; a[r] = t;
}
}```
You don't need to transfer the first BET numbers to another array. Just compare the user's numbers against the first BET numbers (after sorting them).

And your variable and macro names leave something to be desired. If the "i" before lotto and bet is supposed to stand for "integer" then that's pointless. And BET and NUMS are pretty bad, too.
Code:
```#define LOTTO_SIZE  20
#define TICKET_SIZE  3
...
int lotto[LOTTO_SIZE];
int ticket[TICKET_SIZE];```
BTW, it looks like you're compiling your C program as C++ since you use "true" at one point without including stdbool.h.

4. Hello, it's been a long time. Taking into consideration your suggestions I came up with the following code:

Code:
```# include <stdio.h>
# include <stdlib.h>
# include <time.h>
# include <stdbool.h>
# pragma warning (disable:4996)

void ticket_init(int *ticket1);
void lotto_nums_gen(int *arr);
void shuffle(int *a);
void print_user(int *usr);
void game_main(int *usr, int *pc);
int no_null(int *arr);
void welcome_screen();

# define LOTTO_SIZE 40
# define TICKET_SIZE 6

int main()
{
srand(unsigned(time(NULL)));
int lotto[LOTTO_SIZE] = { 0, };
int *p_lotto = lotto;
int ticket[TICKET_SIZE] = { 0, };
int *p_ticket = ticket;

welcome_screen();
ticket_init(ticket);
lotto_nums_gen(p_lotto);
print_user(p_ticket);
game_main(p_ticket, p_lotto);

system("pause");
return 0;
}

void welcome_screen()
{
printf("========================================\n");
printf("=======  WELCOME TO LOTTO GAME  ========\n");
printf("========================================\n");
printf("=== Enter (%d) numbers to play(1-40)  ===\n", TICKET_SIZE);
printf("== Wait until your ticket is complete ==\n");
printf("========================================\n");
}

void ticket_init(int *ticket1)
{
printf("Input: ");
for (int i = 0; i < TICKET_SIZE; i++)
{
while (true)
{
scanf("%d", &ticket1[i]);
if (ticket1[i] <= 0 || ticket1[i] > 40)
{
printf("Input (%d) is not within the range(1-40)\nEnter (%d out of %d) again:\n", ticket1[i], i+1, TICKET_SIZE);
}
else
{
printf("Input (%d out of %d) is successful\n", i + 1, TICKET_SIZE);
break;
}
}
}
}

void game_main(int *usr, int *pc)
{
int dup_n[TICKET_SIZE] = { 0, };
int *p_dup_n = dup_n;
int counter = 0;
int non_zero_cnt = 0;
while (true)
{
++counter;
printf("counter:(%d)...\n", counter);
print_user(usr);
shuffle(pc);
for (int i = 0; i < TICKET_SIZE; i++)
{
for (int j = 0; j < TICKET_SIZE; j++)
{
if (usr[i] == pc[j])
{
p_dup_n[i] = usr[i];
printf("Storing numbers:");
for (int i = 0; i < TICKET_SIZE; i++)
printf("%d ", p_dup_n[i]);
putchar('\n');
}
}
}
non_zero_cnt = no_null(p_dup_n);
if (non_zero_cnt > 0)
{
printf("No zero values found...\nExited with counter(%d)\n", counter);
break;
}
else
{
printf("Zero values exist...\nlooping again...\n");
continue;
}
}
}

void print_user(int *usr)
{
printf("USER: ");
for (int i = 0; i < TICKET_SIZE; i++)
printf("%d ", usr[i]);
putchar('\n');
}

void lotto_nums_gen(int *a)
{
for (int i = 0; i < LOTTO_SIZE; i++)
{
a[i] = i + 1;
printf("%d ", a[i]);
}
}

void shuffle(int *a)
{
for (int i = LOTTO_SIZE; i > 1; )
{
int r = rand() % i--;
int t = a[i]; a[i] = a[r]; a[r] = t;
}
printf("\nSHUFFLE: ");
for (int i = 0; i < TICKET_SIZE; i++)
printf("%d ", a[i]);
putchar('\n');
}

int no_null(int *a)
{
int cnt = 0;
for (int i = 0; i < TICKET_SIZE && cnt < TICKET_SIZE; i++)
if (a[i] != 0)
cnt++;
return cnt == TICKET_SIZE ? 1 : 0;
}```

5. I hope you realize that your program doesn't work. Does the output look sane to you? Do you think you could win a 6/40 lottery in that many attempts? On average it would take millions of attempts. The odds of winning on a single attempt would be 1 over 6 choose 40, or 1 / 3,838,380.

The problem is that you're not zeroing your dup array every iteration. Although the dup array is overkill since you could simply count the number of matches.

Also note that this is not C code:
Code:
`    srand( unsigned(time(NULL)) );`
You are obviously compiling your "C" program as C++. In C it would be
Code:
`    srand( (unsigned) time(NULL) );`
p_lotto, p_ticket and p_dup_n are totally useless. Just use lotto, ticket and dup_n. I have no idea what you think you are doing with those pointers. They are all pointless.

Changing "ticket" and "lotto" to "usr" and "pc" in game_main is unhelpful. Why not keep the same names?

Again, "print_user" is a strange change in nomenclature. Why not just "print_ticket"?