MiniMax TicTacToe doesn't work (c) - c

I have implemented a TicTacToe algorythm with MiniMax, but the problem is that the computer always just places an 'x' on the next possible spot instead of evaluating the game. Does anybody know why ? (The problem can only be in the MiniMax function, or the nextMove function.)
Thanks a lot in advance !!
Here's the code :
int MiniMax(struct Game g, enum Symbol pl){
int score;
if (pl==CROSS)
{
score = -98765;
}
else score = 98765;
int temp_cross =0;
int temp_circle =0;
//base case
if (game_over(g) == CROSS)
return 10;
else if (game_over(g) == CIRCLE)
return -10;
else if (game_over(g) == FULL)
return 0;
int x,y;
for (y=0; y<SIZE_Y_AXIS; y++)
{
for (x=0; x<SIZE_X_AXIS; x++)
{
if (g.board.fields[x][y] == NONE)
{
if (pl == CROSS)
g.board.fields[x][y] = CROSS;
else g.board.fields[x][y] = CIRCLE;
if (pl == CROSS)
temp_cross= MiniMax(g, CIRCLE);
else temp_circle = MiniMax(g, CROSS);
g.board.fields[x][y] = NONE;
if ((pl == CROSS) && (temp_cross > score))
score = temp_cross;
else if ((pl == CIRCLE) && (temp_circle < score))
score = temp_circle;
}
}
}
return score;
};
int nextMove(struct Game g, enum Symbol player){
int score_cross = -865435;
int score_cross_temp = 0;
int cross_position = 1;
int score_circle = 876545;
int score_circle_temp = 0;
int circle_position = 1;
int x,y;
for (y=0; y<SIZE_Y_AXIS; y++)
{
for (x=0; x<SIZE_X_AXIS; x++)
{
if (g.board.fields[x][y] == NONE)
{
if (player == CROSS)
{
score_cross_temp = MiniMax(g, CROSS);
printf("%d ",MiniMax(g, CROSS));
if (score_cross_temp > score_cross)
{
score_cross = score_cross_temp;
cross_position = (y)*3 + x+1;
}
}
else if (player == CIRCLE)
{
score_circle_temp = MiniMax(g, CIRCLE);
if (score_cross_temp < score_circle)
{
score_circle = score_circle_temp;
circle_position = (y)*3 + x+1;
}
}
}
}
}
if (player == CROSS)
{
//printf("%d",cross_position);
return cross_position;
}
else
{
//printf("%d",circle_position);
return circle_position;
}
};

I believe there is a bug in your code. You initialize score as 10, and the temp variables as arbitrarily high and low numbers. This is backwards. TempCircle and TempCross are being overwritten anyway my the calls to minimax. It is the score variable that must be set like that. replace
int score = 10;
int temp_cross = -9876543;
int temp_circle = 9876543;
with
int score;
if(pl==cross){
score = 9876543
}
else{
score = -9876543
}
int temp_cross;
int temp_circle;
There also seems to be another bug in your nextMove function. I assume that its purpose is to iterate over all possible moves, find the one with the highest minimax value, and return that move (correct me if I'm wrong). That is not what the function does. It iterates over all the moves, but does't make any of them. x and y are never even used, except to update the move. You are essentially calling the same minimax several times. Instead, I would either get rid of the function completely, as there is a way to do this inside the minimax function, or fix this function. To fix the function, I would change it to this:
int nextMove(struct Game g, enum Symbol player){
int score_cross = -865435;
int score_cross_temp = 0;
int cross_position = 1;
int score_circle = 876545;
int score_circle_temp = 0;
int circle_position = 1;
int x,y;
for (y=0; y<SIZE_Y_AXIS; y++)
{
for (x=0; x<SIZE_X_AXIS; x++)
{
if (g.board.fields[x][y] == NONE)
{
if (player == CROSS)
{
g.board.fields[x][y] = CROSS;
score_cross_temp = MiniMax(g, CIRCLE);
printf("%d ",MiniMax(g, CROSS));
g.board.fields[x][y] = NONE;
if (score_cross_temp > score_cross)
{
score_cross = score_cross_temp;
cross_position = (y)*3 + x+1;
}
}
else if (player == CIRCLE)
{
g.board.fields[x][y] = CIRCLE;
score_circle_temp = MiniMax(g, CROSS);
g.board.fields[x][y] = NONE;
if (score_cross_temp < score_circle)
{
score_circle = score_circle_temp;
circle_position = (y)*3 + x+1;
}
}
}
}
}
if (player == CROSS)
{
//printf("%d",cross_position);
return cross_position;
}
else
{
//printf("%d",circle_position);
return circle_position;
}
};
Or you can edit minimax to keep track of which call to the function it is. If it is the first recursive call (the root) , keep track of the move itself as well as its value. Then return the move.

Related

pass by value not supported XDP

I am creating a function to loop through some loops and try to match a set. It is supposed to work fine, but unfortunately, it is not. I get a "pass by value not supported" error. How can I fix this?
int matchSet(Program p, int match[], int action)
{
int matchState = 0;
int match[4] = {3,4,5,6}; //set as example
int p.set[10] = {2,1,3,4,5,6,9,10,11,12}; //set as example (normal p.set)
for (int i = 0; i < 10; i++)
{
if (matchState != 2)
{
if (p.set[i] == match[0] && p.set[i + 1] == match[1])
{
matchState = 0;
for (int j = 0; j <= 4; j++)
{
bpf_printk("test");
if (matchState == 0)
{
bpf_printk("test3");
if (p.set[i] != match[j])
{
bpf_printk("test4");
matchState = 1;
break;
}
}
}
if (matchState == 0)
{
bpf_printk("test6");
matchState = 2;
}
}
}
}
if(matchState == 2) {
return action;
}
}
I call the function by:
Program p;
.....
int set[10] = {2,1,3,4,5,6,9,10,11,12};
p.set = set;
int match[4] = {3,4,5,6};
matchSet(p, match, 1);
Error:
error: pass by value not supported 0x1aca7c8: i64 = GlobalAddress<i32 (%struct.Program*, i8*, i32)* #matchSet> 0
You need to change your function to take a pointer to a Program like so:
int matchSet(Program *p, int match[], int action){
...
And then also change your callsite:
Program p;
matchSet(&p, match, 1);

How do I make this code shorter and more efficient?

This is my solution for the Credit problem on CS50's Pset1. It involves using Luhn's Algorithm to test the validity of the Credit Card Number entered and based on a few conditions attempts to identify the Credit Card Company.
Check_Length attempts to find the length of the number entered.
Check_Company attempts to ID the company.
Check_Luhn validates the number based on Luhn's Algorithm.
I'd like to know if this could be done with fewer lines of code.
#include <stdio.h>
#include <cs50.h>
#include <stdbool.h>
int check_length(long);
void check_company(int,long);
bool check_luhn(long,int);
int length;
int main(void)
{
long c = get_long("Enter Credit Card Number: ");
check_length(c);
check_luhn(c,length);
if(check_luhn(c,length)==true)
{
check_company(length,c);
}
else printf("INVALID\n");
}
int check_length(long w)
{
for(int i=12;i<16;i++)
{
long power = 1;
for (int k=1;k<i+1;k++)
{
power = power * 10;
}
int scale = w/power;
if (scale<10 && scale>0)
{
length = i+1;
}
}
return length;
}
void check_company(int x,long z)
{
if(x == 15)
{
int y = z/10000000000000; //z/10^13
if(y==34||y==37)
{
printf("AMEX\n");
}
else
{
printf("INVALID\n");
}
}
else if(x==13)
{
int y = z/100000000000; //z/10^11
if(y==4)
{
printf("VISA\n");
}
}
else if(x==16)
{
int q = z/1000000000000000;
int y = z/100000000000000;
if(y==51||y==52||y==53||y==54||y==55)
{
printf("MASTERCARD\n");
}
else
if(q==4)
{
printf("VISA\n");
}
else printf("INVALID\n");
}
else printf("INVALID\n");
}
bool check_luhn(long a,int b)
{
int f = 0;
int j=0;
for(int d=1;d<b+1;d++)
{
int e = a%10;
a = a/10;
if(d%2==1)
{
f = f+e;
}
else
{
int m = 2*e;
int g = m%10;
int h = m/10;
j = j+g+h;
}
}
int l = j + f;
if(l%10==0)
{
return true;
}
else return false;
}

Why is the computer's input not being considered?

In the code below there is an error I can't locate causing the computer's selection to not be accounted for. The user's input is being considered in the Nim game yet the computer's pieces are not being subtracted.
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
void printInstructions();
int getUserInput(int);
int randomRange(int,int);
int PlayerTurn(int);
int smartCompMove(int);
int dumbCompMove(int);
int main()
{
srand(time(NULL));
int pieceAmount = randomRange(12,24);
char smartCompOrDumb;
printf("Do you want to play a smart computer or a dumb one? Select 'S' or 'D'.");
scanf("%c",&smartCompOrDumb);
bool gameOver = false;
bool playerTurn = true;
printInstructions();
while(pieceAmount > 0 && gameOver == false)
{
if (playerTurn == false)
{
if(pieceAmount <= 4)
{
printf("\nThe Computer has won :P ");
gameOver = true;
exit(0);
}
if (smartCompOrDumb == 's' || smartCompOrDumb == 'S')
{
playerTurn = true;
pieceAmount = smartCompMove(pieceAmount);
printf("%d",pieceAmount);
}
else if (smartCompOrDumb == 'd' || smartCompOrDumb == 'D')
{
playerTurn = true;
pieceAmount = dumbCompMove(pieceAmount);
printf("%d",pieceAmount);
}
}
else
{
if(pieceAmount <= 4)
{
printf("\nYou have won :) ");
gameOver = true;
exit(0);
}
playerTurn = false;
pieceAmount = PlayerTurn(pieceAmount);
printf("%d",pieceAmount);
}
}
return 0;
}
void printInstructions()
{
printf("\nThis game is called Nim and it is thousands of years old.");
printf("\nTake turns picking one to three pieces from a pile and whomever picks the last piece wins.");
printf("\n__________________________________________________________________________________________");
}
int randomRange(int low,int high)
{
return rand()% (high - low) + low;
}
int PlayerTurn(int pieceAmount)
{
pieceAmount = getUserInput(pieceAmount);
return pieceAmount;
}
int getUserInput(int pieceAmount)
{
int userInput = 0;
bool flag = true;
while (flag == true)
{
if (pieceAmount > 4)
{
printf("\nThere are %d pieces remaining.\n",pieceAmount);
printf("\nHow many pieces do you want to select? ");
scanf("%d", &userInput);
if (userInput >= 1 && userInput < 5)
{
pieceAmount = pieceAmount - userInput;
flag = false;
}
else
{
printf("This is not a valid move so try again.");
}
}
}
return pieceAmount;
}
int dumbCompMove(int pieceAmount)
{
int dumbPick = rand() % 3 + 1;
printf("\nComputer will pick from the stack. \n");
pieceAmount = pieceAmount - dumbPick;
printf("\nComputer picked %d pieces. \n", dumbPick );
return pieceAmount;
}
int smartCompMove(int pieceAmount)
{
int smartPick = 1;
printf("\nThe computer will select their pieces. \n");
if (pieceAmount >= 15 && pieceAmount < 24)
{
smartPick = 2;
pieceAmount = pieceAmount - smartPick;
}
else if (pieceAmount >= 10 && pieceAmount < 15)
{
smartPick = 4;
pieceAmount = pieceAmount - smartPick;
}
else if (pieceAmount >= 6 && pieceAmount < 10)
{
smartPick = 1;
pieceAmount = pieceAmount -smartPick;
}
else
pieceAmount = 3;
printf("\nThe computer selected %d pieces. \n",smartPick);
return pieceAmount;
}
I had this code working earlier yet somehow I must have altered something minor and now it will not function properly. I am using the Cloud9 program to run it.

Having trouble coming up with a 'display function' or added functionality - c

Finishing up a program and been told that I need to have the cards be displayed after the user quits.
Tried having draw return the hand variable and printing that, and storing each result of the draw(), which I had turned to int; although I am showing you the working function, which is void.
So far nothing works and I am lost.
void draw(int deck[SIZE], int a) {
int numCards = 10;
int i;
int hand[numCards];
int card;
for(i = 0; i < numCards && top > 0; i++) {
card = deck[top-1];
hand[i] = card;
top--;
}
if(a != 0) {
printcards(card);
} else {
for(i = 0; i < numCards && top > 0; i++)
printcards(card);
}
}
Program can print off cards as drawn and edited version looks like:
int draw(int deck[SIZE], int a) {
int numCards = 10;
int i;
int hand[numCards];
int card;
for(i = 0; i < numCards && top > 0; i++) {
card = deck[top-1];
hand[i] = card;
top--;
}
if(a != 0) {
printcards(card);
} else {
for(i = 0; i < numCards && top > 0; i++)
printcards(card);
}
return card; /* or return hand */
}
void printcards(int card) {
char suits[4][9] = {
"Hearts",
"Diamonds",
"Clubs",
"Spades"
};
if(card%13 == 0 || card%13 == 10 || card%13 == 11 || card%13 == 12) {
printf("%s ", facecheck(card%13) );
} else {
printf("%d ", card%13+1);
}
printf("of %s \n", suits[card/13]);
}
This function is the actual printing of cards:
void players(int deck[]) {
int x;
int a;
int yourhand[10];
a = 1;
printf("Player 1 \n");
printf("Your Hand is: \n");
draw(deck, a);
draw(deck, a);
while(a == 1) {
printf("What would you like to do: Press 1 to Draw. 2 to Stay. \n");
scanf("%d" , &x);
if(x == 1) {
draw(deck, a);
} else {
a--;
}
}
}
This function calls the draw() with user input, then need to add a display() after the else, before a-- or store result of draw into your hand and print result. So far nothing has worked.

Missing output from C Blackjack game's int array

So I am trying to write a Blackjack game in C just for the fun of it (something I have never tried before). I have gotten past the first few steps such as how to set up the deck and how to give the cards to the dealer and player. However, the displayed output is not showing what I want it too (showing the dealer only has 1 card when it should be showing 2). Here is a screenshot:
I did run this on my phone (easier to get a screenshot), but I am having the same results on my computer using Code::Blocks. Anyways, I have two functions to handle setting up the deck and to display the current cards. The dealing of the cards I am handling in the main() function using loops. I know that the makeDeck() function is working correctly, so I am assuming that my error is somewhere else. Have a look at my code and let me know what's going on (also, any suggestions for improvement would be appreciated):
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/*Function Prototypes*/
int* makeDeck();
/*Usage - returns an int* to be used for the deck */
void showHands(int[], int[]);
/*Usage - pass dealerHand[], then playerHand[] */
int main() {
srand(time(0)); //Make a new rand() seed value
int x, count = 0, choice = 1;
int* cards = makeDeck();
int dealerCards[12]; //cards in hand will never exceed 11
int playerCards[12]; //4 A's, 4 2's, 3 3's
/*Loop to run the game. One iteration per hand */
while(choice != 0) {
for(x = 0; x < 12; x++) {
dealerCards[x] = 0;
playerCards[x] = 0;
}
//Deal 2 cards to dealer and player
for(x = 0; x < 2; x++) {
dealerCards[x] = cards[count];
count++;
}
for(x = 0; x < 2; x++) {
playerCards[x] = cards[count];
count++;
}
showHands(dealerCards, playerCards);
/*DEBUGGING */
printf("\nEnter 0 to exit loop: ");
scanf("%i", &choice);
}
return 0;
}
//Declare placeholder variable "bunchOfCards" globally
int bunchOfCards[52];
int* makeDeck(){
int* deck = bunchOfCards;
int x = 0,
y = 0,
card = 0;
for(x = 0; x < 52; x++) { //set all cards to 0
deck[x] = 0;
}
for(x = 0; x < 4; x++) { //set up deck
for(y = 1; y < 14; y++) {
card = (rand() % 52);
//check if deck position is already used
while(deck[card] != 0) {
card = (rand() % 52);
}
deck[card] = y;
}
}
/* DEBUGGING
for(x = 0; x < 52; x++) {
printf("%i\t", deck[x]);
} */
return deck;
}
void showHands(int* dealer, int* player) {
int x; char card[3] = { '\0', '\0', '\0' };
puts("The hands are: \n\nDealer:");
//Display dealer cards
for(x = 0; x < 12; x++) {
if(dealer[x] != 0) {
if((dealer[x] < 10) && (dealer[x] != 1)) {
card[0] = (char)(((int)'0') + dealer[x]);
card[1] = '\0';
} else if(dealer[x] == 1) {
card[0] = 'A';
card[1] = '\0';
} else if(dealer[x] == 10) {
card[0] = '1';
card[1] = '0';
} else if(dealer[x] == 11) {
card[0] = 'J';
card[1] = '\0';
} else if(dealer[x] == 12) {
card[0] = 'Q';
card[1] = '\0';
} else if(dealer[x] == 13) {
card[0] = 'K';
card[1] = '\0';
}
printf("\t%s", card);
}
//Display player cards
puts("\nPlayer: ");
for(x = 0; x < 12; x++) {
if(player[x] != 0) {
if((player[x] < 10) && (player[x] != 1)) {
card[0] = (char)(((int)'0') + player[x]);
card[1] = '\0';
} else if(player[x] == 1) {
card[0] = 'A';
card[1] = '\0';
} else if(player[x] == 10) {
card[0] = '1';
card[1] = '0';
} else if(player[x] == 11) {
card[0] = 'J';
card[1] = '\0';
} else if(player[x] == 12) {
card[0] = 'Q';
card[1] = '\0';
} else if(player[x] == 13) {
card[0] = 'K';
card[1] = '\0';
}
printf("\t%s", card);
}
}
}
}
Your for-loops appear to include each other.
for(x = 0; x < 12; x++) {
if(dealer[x] != 0) {
...
}
puts("\nPlayer: ");
for(x = 0; x < 12; x++) {
...
}
}
The first for-loop starts with x = 0, the second for loop goes up to x = 12, then the first for-loop stops before executing a second time because it reached the terminating condition.

Resources