Im currently making a one-armed bandit game and this is what it's supposed to do:
The user should be able to put money into the machine, 50, 100 or 500
The user should be able to bet money for each game
After the user have betted money symbols should be randomized in a field like this:
[ o ] [ p ] [ x ]
[ x ] [ x ] [ x ]
[ x ] [ o ] [ x ]
(1 columns/ lines wins 2x money, 2 columns/ lines wins 4x money etc.)
This field should each time be randomized with letters , also a two-dimensional array should be used to represent the gamearea.
I've ran into some problems, basically after I bet some money the game closes and I cant see any errors etc, any help that clarifies this problem would be greatly appreciated, aswell as any improvements I could do to my code etc.
This is my code:
#include <iostream>
#include <ctime>
using namespace std;
int main(int args, const char* argv[])
{
int svar = 0;
int bokstav = 0;
int insert;
int build;
int bet;
int credit;
int array;
int jackpot;
int tal;
int spin_1x = 0;
int spin_1y = 0;
int spin_2x = 0;
int spin_2y = 0;
cout << "Welcome to the one-armed bandit!" << endl;
cout << endl;
cout << "To play start by betting some money!" << endl;
cout << endl;
cout << "Insert 50/ 100/ 500 kr to your account!" << endl;
cout << endl;
cin >> insert;
while (insert < 50 || insert > 500)
{
cout << "You either inserted to little or to much" << endl;
cin >> insert;
}
cout << "You inserted" << insert;
cout << endl;
while (insert > 50)
{
cout << "Bet some money to play!" << endl;
cout << endl;
cin >> bet;
cout << endl;
while (bet !=50 && bet !=100 && bet !=500)
{
if (bet == 50) return 1;
{
cout << "You have betted 50 kr!" << endl;
}
{
if (bet == 100) return 2;
{
cout << "You have betted 100 kr!" << endl;
}
{
if (bet == 500)
{
cout << "You have betted 500 kr!" << endl;
}
char a = '£';
char b = '$';
char c = '*';
char build [4][4] = {
{ ' ', 'A', 'B', 'C',},
{ '1', ' ', ' ', ' ',},
{ '2', ' ', ' ', ' ',},
{ '3', ' ', ' ', ' ',},
};
int array();
cout << build[0][1] << " " << build[0][2] <<" "<< build[0][3] <<" " << endl;
cout << build[1][0] <<"|_|" <<"|_|" << "|_|" << endl
<< build[2][0] <<"|_|" <<"|_|" << "|_|" << endl
<< build[3][0] <<"|_|" <<"|_|" << "|_|" << endl;
return 0;
srand(time(0));
spin_1x=rand() % 4 + 1;
spin_1y=rand() % 4 + 1;
spin_2x=rand() % 4 + 1;
spin_2y=rand() % 4 + 1;
int y = 0;
int x = 0;
if (x == spin_1x && y == spin_1y)
{
build[x][y]='0';
cout << "Congrats you won!" << endl;
}
else if (x == spin_2x && y == spin_2y)
cout << "Congrats you won!" << endl;
cout << endl;
cout << "JACKPOT!" << endl;
{
if (insert <= 0)
{
cout << "You dont have any money left! Game's over!" << endl;
}
int insert;
if ((a == 7 && b == 7 && c == 7))
{
cout << "You have won x2 your bet!($" << ( bet*2) << ")" << endl;
credit = credit + (bet*2);
}
else if ((a == b == c) && ! (a == 7 && b == 7 && c == 7))
{
cout << "You have won x4 your bet!($" << (bet*4) << ")" << endl;
credit = credit + (bet*4);
}
else if ((a == b || a == c || b == c) && !(a == b == c) && !(a == 7 && b == 7 && c == 7))
{
credit = credit + (bet*8);
cout << "You have won x8 your bet!($" << (bet*8) << ")" << endl;
}
else if ((a == b || a == c || b == c) && ! (a == b == c) && ! (a == 7 && b == 7 && c == 7))
{
credit = credit + (bet*16);
cout << "You have won x16 your bet!($" << (bet*16) << ")" << endl;
}
else if (( a == b || a == c || b == c) && ! (a == b == c) && ! (a == 7 && b == 7 && c == 7))
{
credit = credit + (bet*128);
cout << "You have won x128 your bet!($" << (bet*128) << ")" << endl;
}
else
{
cout << "You have lost your betting!($-" << bet << ")" << endl;
credit = credit - bet;
}
return credit;
}
}
return 0;
}
}
}
}
The issue, as others stated, is that you are returning from your main which terminates the program. My suggestion:
Move your game logic into a separate method(s)
Place the logic call inside a while loop in the main that checks if the player wants to play again
Only return from main when the player wants to stop
Example partial code (you should get the idea):
void printWelcome( )
{
std::cout << "Welcome to the One-Armed Bandit!" << std::endl;
// etc.
}
int getBet( )
{
int betAmount;
std::cout << "To play start by betting some money!\n"
<< "Insert 50/ 100/ 500 kr to your account!" << std::endl;
std::cin >> betAmount;
return betAmount;
}
void playGame( )
{
// All of your game logic in here
}
bool wantsToPlay( )
{
std::cout << "Do you want to play again? (y/n)" << std::endl;
char response;
std::cin >> response;
if( response == 'y' )
{
return true;
}
else
{
return false;
}
}
int main( int argc, char** argv )
{
int betAmount = 0;
printWelcome( );
do
{
betAmount = getBet( );
if( betAmount != 50 && betAmount != 100 && betAmount != 150 )
{
// Restart the game loop (ask for bet again)
continue;
}
playGame( );
} while( wantsToPlay( ) );
std::cout << "Thank you for playing!" << std::endl;
return 0;
}
Your console is closing because the program is terminated when the main function hits a return , put a cin before each return. That will "pause" the application just before it terminates letting you see your traces.
Run your program by yourself instead of computer and you will see why its closing so fast. Remember that return in main() means "close program now".
Related
I pressed 1 and entered information related to students. Then press 2 to get the calculations that fit the information I entered, but the trash values come out.
#include <iostream>
#include <cstring>
using namespace std;
struct Subject { //과목 정보
char Subname[30]; //과목이름
int Hakjum; //과목학점
char Grade[10]; //과목등급
float GPA; //과목평점
};
struct Student { //학생정보
char StdName[30]; //학생이름
int Hakbun; //학번
Subject Sub[3]; //과목
float AveGPA; //교과목 평균 평점
};
int main()
{
cout.precision(2);
cout << fixed;
int n = 0;
struct Student Stu[10]; //구조체변수 선언
while (n < 3) //반복문을 통해 1또는 2를 눌렀을 때 메뉴판으로 돌아오기
{
cout << "===== 메뉴 =====\n"; //메뉴판
cout << "1. 학생 성적 입력\n";
cout << "2. 전체 학생 성적 보기\n";
cout << "3. 프로그램 종료\n";
cout << "\n";
cout << "원하는 기능을 입력하세요 : ";
cin >> n;
if (n <= 1) { //1번 선택하였을 경우
for (int t = 0; t <= 1; t++)
{
cout << "*" << t + 1 << " 번째 학생 이름과 학번을 입력하세요.\n"; //이름과 학번을 입력 받음
cout << "이름 : ";
cin >> Stu[t].StdName;
cout << "학번 : ";
cin >> Stu[t].Hakbun;
cout << "\n";
cout << "\n";
cout << "* 수강한 과목3개와 각 교과목명, 과목학점, 과목등급을 입력하세요.\n"; //과목과, 학점, 등급을 입력받음
for (int a = 0; a < 3; a++)
{
cout << "교과목명 : ";
cin >> Stu[t].Sub[a].Subname;
cout << "과목학점수 : ";
cin >> Stu[t].Sub[a].Hakjum;
cout << "과목등급<A+ ~ F> : ";
cin >> Stu[t].Sub[a].Grade;
cout << "\n";
}
cout << "\n\n\n";
}
}
else if (n <= 2) { //2번 선택하였을 경우
cout << "\n\t\t전체 학생 성적 보기\n";
cout << "===================================================================\n";
for (int t = 0; t <= 1; t++) {
cout << "이름 : " << Stu[t].StdName << "\t학번 : " << Stu[t].Hakbun << "\n"; //학생의 개인정보 출력
cout << "===================================================================\n";
cout << "\t\t과목명 \t 과목학점 \t과목등급 \t과목평점\n";
cout << "===================================================================\n";
for (int a = 0; a < 3; a++) { //문자열 비교 연산자를 사용하여 등급을 평점으로 바꿈
if (Stu[t].Sub[a].Grade, "A+" == 0) {
Stu[t].Sub[a].GPA = 4.5 * Stu[t].Sub[a].Hakjum;
}
else if (Stu[t].Sub[a].Grade, "A0" == 0) {
Stu[t].Sub[a].GPA = 4.0 * Stu[t].Sub[a].Hakjum;
}
else if (Stu[t].Sub[a].Grade, "B+" == 0) {
Stu[t].Sub[a].GPA = 3.5 * Stu[t].Sub[a].Hakjum;
}
else if (Stu[t].Sub[a].Grade, "B0" == 0) {
Stu[t].Sub[a].GPA = 3.0 * Stu[t].Sub[a].Hakjum;
}
else if (Stu[t].Sub[a].Grade, "C+" == 0) {
Stu[t].Sub[a].GPA = 2.5 * Stu[t].Sub[a].Hakjum;
}
else if (Stu[t].Sub[a].Grade, "C0" == 0) {
Stu[t].Sub[a].GPA = 2.0 * Stu[t].Sub[a].Hakjum;
}
else if (Stu[t].Sub[a].Grade, "D+" == 0) {
Stu[t].Sub[a].GPA = 1.5 * Stu[t].Sub[a].Hakjum;
}
else if (Stu[t].Sub[a].Grade, "D0" == 0) {
Stu[t].Sub[a].GPA = 1.0 * Stu[t].Sub[a].Hakjum;
}
else if (Stu[t].Sub[a].Grade, "F" == 0) {
Stu[t].Sub[a].GPA = 0.0 * Stu[t].Sub[a].Hakjum;
}
Stu[t].AveGPA = (Stu[t].Sub[0].GPA + Stu[t].Sub[1].GPA + Stu[t].Sub[2].GPA) / (Stu[t].Sub[0].Hakjum + Stu[t].Sub[1].Hakjum + Stu[t].Sub[2].Hakjum); //평균 평점을 구함
cout << "\t\t" << Stu[t].Sub[a].Subname << "\t\t" << Stu[t].Sub[a].Hakjum << "\t " << Stu[t].Sub[a].Grade << "\t\t " << Stu[t].Sub[a].GPA << "\n"; //과목명, 과목학점, 과목등급, 과목평점 출력
}
cout << "===================================================================\n";
cout << "\t\t\t\t평균평점\t" << Stu[t].AveGPA << "\n\n";
}
}
}
return 0;
}
The output
enter image description here
I get a trash value in the "subject grade".
Expected
I want it to be calculated according to the number I enter.
I hope the "과목평점" is right.
This is garbage:
if (Stu[t].Sub[a].Grade, "A+" == 0) {
What it does is use comma operator. So first it will get Stu[t].Sub[a].Grade and... do nothing with it. Then it will get "A+" == 0, which is comparing string literal (const char* pointer) to 0, which is same as nullptr, which is false because string literal is not going to be nullptr. So this condition is always false. It's the last experssion with the comman operator, so this false result will be used for the if. Same for the rest of them.
It should be
if (std::strcmp(Stu[t].Sub[a].Grade, "A+") == 0) {
The function std::strcmp is declared in cstring header, which you already have included, and since you have using namespace std there, you can leave the std:: out if you feel confident you know std:: namespace functions well enough.
I'm working on a little poker application and i've run into the first problem I just can't seem to comprehend.
while (allplayersGood != 1) { //round table till all decided
cout << "TOP OF WHILE LOOP";
for (int i = 0; i < PLAYER_COUNT; i++) { //for loop for decisions from non button or blinds
int player_decision = 1;
char choice;
if ((players[i].playerhand.card1.value != 'F') && (players[i].playerhand.card1.value != 'C')) {
if ((players[i].blind != 1 && players[i].blind != 2) && players[i].button != true) {
cout << "\n\n";
cout << " POT: " << playerTable->currentPot;
cout << "\n";
for (int i = 0; i < PLAYER_COUNT; i++) {
cout << "Player " << players[i].playernumber;
cout << " (" << players[i].chip_amount << ") ";
}
while (player_decision == 1) {
if (playerTable->currentBet > players[i].currentBet) {
cout << "\n\nPlayer " << players[i].playernumber << " ("; players[i].playerhand.printhand(); cout << ") " << "Type F for Fold, B for Call, R for Raise: ";
cin >> choice;
players[i].choice = choice;
if (choice == 'F') {
player_decision = 0;
players[i].fold();
}
if (choice == 'R') {
player_decision = 0;
players[i].bet(playerTable);
}
if (choice == 'B') {
player_decision = 0;
players[i].call(playerTable);
}
}
if ((playerTable->currentBet == players[i].currentBet) && player_decision != 0) { //big blind after round table
cout << "\n\nPlayer " << players[i].playernumber << " ("; players[i].playerhand.printhand(); cout << ") " << "Type C for Check, R for Raise: ";
cin >> choice;
players[i].choice = choice;
if (choice == 'B') {
player_decision = 0;
players[i].bet(playerTable);
}
if (choice == 'C') {
if (players[i].check(playerTable) == true) {
player_decision = 0;
}
}
}
}
}
else if (players[i].blind == 1 || players[i].blind == 2) {
if (players[i].blind == 1) {
players[i].chip_amount -= sblind;
playerTable->currentPot += sblind;
players[i].blind = 0;
players[i].currentBet = sblind;
}
if (players[i].blind == 2) {
players[i].chip_amount -= bblind;
playerTable->currentPot += bblind;
players[i].blind = 0;
players[i].currentBet = bblind;
}
}
}
}
for (int i = 0; i < PLAYER_COUNT; i++) { //seperate loop for button and blinds that were ignored in loop above
int player_decision = 1;
char choice;
if (players[i].button == true || players[i].blind == 1) { //button and small blind
cout << "\n\n";
cout << " POT: " << playerTable->currentPot;
cout << "\n";
for (int i = 0; i < PLAYER_COUNT; i++) {
cout << "Player " << players[i].playernumber;
cout << " (" << players[i].chip_amount << ") ";
}
while (player_decision == 1) {
cout << "\n\nPlayer " << players[i].playernumber << " ("; players[i].playerhand.printhand(); cout << ") " << "Type F for Fold, B for Call, R for Raise: ";
cin >> choice;
players[i].choice = choice;
if (choice == 'F') {
player_decision = 0;
players[i].fold();
}
if (choice == 'R') {
player_decision = 0;
players[i].bet(playerTable);
}
if (choice == 'B') {
player_decision = 0;
players[i].call(playerTable);
}
}
}
cout << i;
if (players[i].blind == 2) { //big blind
cout << "\n\n";
cout << " POT: " << playerTable->currentPot;
cout << "\n";
for (int i = 0; i < PLAYER_COUNT; i++) {
cout << "Player " << players[i].playernumber;
cout << " (" << players[i].chip_amount << ") ";
}
while (player_decision == 1) {
cout << "\n\nPlayer " << players[i].playernumber << " ("; players[i].playerhand.printhand(); cout << ") " << "C for Check, R for Raise: ";
cin >> choice;
players[i].choice = choice;
if (choice == 'C') {
if (players[i].check(playerTable) == true) {
player_decision = 0;
}
}
if (choice == 'R') {
player_decision = 0;
players[i].bet(playerTable);
}
}
}
}
int playersBetting = 0;
int playersGood = 0;
int playersChecked = 0;
int playersNot = 0;
for (int i = 0; i < PLAYER_COUNT; i++) {
if (players[i].playerhand.card1.value != 'F') {
playersBetting++;
if (players[i].currentBet == playerTable->currentBet) {
playersGood++;
}
}
}
for (int i = 0; i < PLAYER_COUNT; i++) {
if (players[i].playerhand.card1.value != 'F') {
if (players[i].isChecked == true) {
playersChecked++;
}
else {
playersNot++;
}
}
}
cout << playersBetting << playersGood;
if ((playersBetting == playersGood) || (playersNot == 0)) {
cout << "NEXT ROUND STARTED";
}
}
The issue is, during the second for loop with comment "seperate loop for button and blinds that were ignored in loop above" after the first if statement succeeds because players[0] has button equal to true, the player will make the terminal input as a decision, and the program will exit the for loop and go down to the end with the playersBetting and playersGood loops, then return back to the for loop at index 1 correctly.
I'm sorry if this is a little complicated to understand there is a lot of code that I probably didn't put into context very well, if you need any extra information please let me know.
Thank you.
You seem to have different loops inside one another. This is possible, but in that case, you need to use another loop variable (j instead of i), let me show you what happens:
for i ...
for j ...
This causes the following values to be taken for i and j:
i j
1 1
1 2
1 ...
1 n
2 1
2 2
2 ...
2 n
...
n 1
n 2
...
n n
... and here it stops.
If you keep using i in the inner loop, this is what you get:
i (outside loop) i (inside loop)
1 1
2 2 // indeed: changing i inside also changes i outside
... ...
n n
So you jump out of the outside loop, even after just having looped the inside loop one time.
I figured it out, it was unrelated to the actual loop and actually had to do with a value I changed upstream. Thank you for the few who tried to help with such little context haha
Have a good one
I wanted to expand on an older Tic Tac Toe game I made where two players can play versus each other. I want to give the user the option of playing against a difficult AI. The issue is that the AI won't pick the best move all the time. For instance, it will always pick spot 1 if going first. If the user picks spot 2, it will pick spot 4. After this, no matter what the user picks (besides spot 7) the AI won't pick spot 7. Victory for the AI is far from inevitable (the user can still win the game at this point), so that's not the problem.
Any help is appreciated. Thanks!
I'm positive the problem is with my minimax or bestmove functions. It may just be that I haven't properly implemented by minimax function, but I can't spot the issue.
#include <iostream>
#include <iomanip>
#include <string>
#include <array>
// This is a program to play a single game of tic-tac-toe
// between either two human (non-AI) players or an AI.
using namespace std;
void PrintBoard(array <char, 9>);
int programprogress();
int checkwin(array <char, 9>);
int minimax(array <char, 9>, int, int, bool);
int bestMove(array <char, 9>, int);
int Opposite(int);
char PlayerSymbol(int);
const int SIZE = 9;
array <char, SIZE> Pos = { '1', '2', '3', '4', '5', '6', '7', '8', '9' };
int player_number = 1;
int k = -11, result;
bool AI = false, first;
// Global variables used by 2 or more functions.
// Array had to be initialized with numbers instead of blank spaces
// because the check win function wouldn't work properly.
int main()
{
string userinp;
cout << "This is tic tac toe! Here's your board!" << endl;
PrintBoard(Pos);
cout << "Would you like to play versus an AI? (Y/N)" << endl;
cin >> userinp;
if (userinp[0] == 'Y')
{
cout << "Excellent! Would you like to start first, or second? (F/S)" << endl;
cin >> userinp;
if (userinp[0] == 'F')
{
cout << "You will start first!" << endl;
first = false;
player_number = 2;
}
else
{
cout << "The AI will start first!" << endl;
first = true;
}
AI = true;
}
else
{
cout << "Excellent! Your game will start soon." << endl;
}
result = programprogress();
player_number--;
PrintBoard(Pos);
if (result == 1)
cout << endl << "Player " << player_number << " has won!!!\n";
else if (result == 10)
cout << endl << "The AI has won! Better luck next time!\n";
else if (result = -10)
cout << endl << "You beat the world's best AI! Congratulations!\n";
else
cout << endl << "The game has been drawn!" << endl;
return 0;
}
void PrintBoard(array <char, 9> Pos)
{
system("cls");
cout << setw(6) << "|" << setw(6) << "|" << endl << setw(3) << Pos[0] << setw(3) << "|" << setw(3) << Pos[1] << setw(3) << "|" << setw(3) << Pos[2] << " TIC TOE" << endl;
cout << "_____|_____|_____" << endl;
cout << setw(6) << "|" << setw(6) << "|" << endl << setw(3) << Pos[3] << setw(3) << "|" << setw(3) << Pos[4] << setw(3) << "|" << setw(3) << Pos[5] << " TAC " << endl;
cout << "_____|_____|_____" << endl;
cout << setw(6) << "|" << setw(6) << "|" << endl << setw(3) << Pos[6] << setw(3) << "|" << setw(3) << Pos[7] << setw(3) << "|" << setw(3) << Pos[8] << " TIC TOE " << endl;
cout << " | |" << endl;
}
int programprogress()
{
while (k == -11 && AI)
{
bool InvalidChoice = false;
char letter;
//player_number = (player_number % 2) ? 1 : 2;
int PlayerChoice;
if (player_number == 2)
{
cout << endl << "What is your move?" << endl;
cin >> PlayerChoice;
while ((PlayerChoice < 1) || (PlayerChoice > 9))
{
cout << "That's an invalid choice! Please choose a number that is 1-9!" << endl;
cin >> PlayerChoice;
}
PlayerChoice--;
letter = (!first) ? 'X' : 'O';
if (Pos[PlayerChoice] == '1' || Pos[PlayerChoice] == '2' || Pos[PlayerChoice] == '3' || Pos[PlayerChoice] == '4' || Pos[PlayerChoice] == '5' || Pos[PlayerChoice] == '6' || Pos[PlayerChoice] == '7' || Pos[PlayerChoice] == '8' || Pos[PlayerChoice] == '9')
{
Pos[PlayerChoice] = letter;
PrintBoard(Pos);
}
/*else
{
cout << "That space is already taken!" << endl;
player_number--;
}*/
k = checkwin(Pos);
if (k != -11)
k = k * -10;
player_number = 1;
}
else
{
cout << endl << "The computer has made its move!" << endl;
letter = (first) ? 'X' : 'O';
if (first)
PlayerChoice = bestMove(Pos, 1);
else
PlayerChoice = bestMove(Pos, 2);
Pos[PlayerChoice] = letter;
PrintBoard(Pos);
k = checkwin(Pos);
if (k != -11)
k = k * 10;
player_number = 2;
}
}
while (k == -11 && !AI)
{
bool InvalidChoice = false;
char letter;
player_number = (player_number % 2) ? 1 : 2;
int PlayerChoice;
cout << endl << "What's player " << player_number << "'s move?" << endl;
cin >> PlayerChoice;
while ((PlayerChoice < 1) || (PlayerChoice > 9))
{
cout << "That's an invalid choice! Please choose a number that is 1-9!" << endl;
cin >> PlayerChoice;
}
PlayerChoice--;
letter = (player_number == 1) ? 'X' : 'O';
if (Pos[PlayerChoice] == '1' || Pos[PlayerChoice] == '2' || Pos[PlayerChoice] == '3' || Pos[PlayerChoice] == '4' || Pos[PlayerChoice] == '5' || Pos[PlayerChoice] == '6' || Pos[PlayerChoice] == '7' || Pos[PlayerChoice] == '8' || Pos[PlayerChoice] == '9')
{
Pos[PlayerChoice] = letter;
PrintBoard(Pos);
}
else
{
cout << "That space is already taken!" << endl;
player_number--;
}
k = checkwin(Pos);
player_number++;
}
return k;
}
int checkwin(array <char, SIZE> Pos)
{
if (Pos[0] == Pos[1] && Pos[1] == Pos[2])
return 1;
else if (Pos[3] == Pos[4] && Pos[4] == Pos[5])
return 1;
else if (Pos[6] == Pos[7] && Pos[7] == Pos[8])
return 1;
else if (Pos[0] == Pos[3] && Pos[3] == Pos[6])
return 1;
else if (Pos[1] == Pos[4] && Pos[4] == Pos[7])
return 1;
else if (Pos[2] == Pos[5] && Pos[5] == Pos[8])
return 1;
else if (Pos[0] == Pos[4] && Pos[4] == Pos[8])
return 1;
else if (Pos[2] == Pos[4] && Pos[4] == Pos[6])
return 1;
else if (Pos[0] != '1' && Pos[1] != '2' && Pos[2] != '3'
&& Pos[3] != '4' && Pos[4] != '5' && Pos[5] != '6'
&& Pos[6] != '7' && Pos[7] != '8' && Pos[8] != '9')
return 0;
else
return -11;
}
int minimax(array <char, SIZE> newpos, int depth, int player, bool opp)
{
int scale = 0;
if ((player == 1 && first) || (player == 2 && !first))
scale = 10;
else
scale = -10;
//cout << scale;
int score = scale*checkwin(newpos);
if (score < 0)
score += depth;
else if (score > 0)
score -= depth;
if (score == -10 || score == 10 || score == 0)
return score;
if (opp)
{
int best = -1000;
for (int i = 0; i < SIZE; i++)
{
if (newpos[i] != 'X' && newpos[i] != 'O')
{
char temp = newpos[i];
newpos[i] = PlayerSymbol(player);
best = max(best, minimax(newpos, depth + 1, Opposite(player), !opp));
newpos[i] = temp;
}
}
return best;
}
else
{
int best = 1000;
for (int i = 0; i < SIZE; i++)
{
if (newpos[i] != 'X' && newpos[i] != 'O')
{
char temp = newpos[i];
newpos[i] = PlayerSymbol(player);
best = min(best, minimax(newpos, depth + 1, Opposite(player), !opp));
newpos[i] = temp;
}
}
return best;
}
}
int bestMove(array <char, SIZE> newpos, int player)
{
int best = -1000;
int bestpos = -1;
for (int i = 0; i < SIZE; i++)
{
if (newpos[i] != 'X' && newpos[i] != 'O')
{
char temp = newpos[i];
newpos[i] = PlayerSymbol(player);
int move = minimax(newpos, 0, player, !first);
newpos[i] = temp;
if (move > best)
{
//cout << "I like pineapple on pizza" << endl;
bestpos = i;
best = move;
}
/*if (move == best)
{
cout << "I like pineapple on pizza" << endl;
}*/
}
}
cout << bestpos;
return bestpos;
}
int Opposite(int x)
{
if (x == 1)
return 2;
else
return 1;
}
char PlayerSymbol(int x)
{
if (x == 1)
return 'X';
else
return 'O';
}
An out of bounds error due to the -1 value of bestpos. I'm not sure how to change this, though.
There are 4 issues that I could find. Solving them seems to lead to the intended behavior.
Firstly, when you call minimax(newpos, 0, player, !first); from inside the bestMove function, you pass player rather than Opposite(player), indicating that the first minimax step will be performed by the same player as the bestMove step. In other words: The AI makes two successive moves for itself. Therefore player needs to be changed to Opposite(player).
Secondly, minimax has a bool variable named opp that seems to indicate whether it is the AI or its opponent making the move. For the first minimax step, opp is set to !first, indicating that only if the AI goes first, the opponent will make a move after the AI. That is incorrect. It is always the opponent making a move after the AI. So bestMove should call minimax with true rather than !first. As an aside, opp is redundant, because you can use (player == 1 && first) || (player == 2 && !first) to check whether it's the AI or its opponent making the move.
Thirdly, the scale is set the wrong way around. With (player == 1 && first) || (player == 2 && !first) you check whether its the AI making a move. But you do that in the next minimax step, after the potentially winning move. So if the AI is making a move and the game is already won, then the opponent made the winning move, not the AI. Ergo, the scale should be
if ((player == 1 && first) || (player == 2 && !first))
scale = -10;
else
scale = 10;
instead.
Lastly, you check whether the score is 10 or -10 after adding the depth. If depth is not 0, then this check will always fail. So beyond depth 0, the AI can only see a draw, never a win. You could instead write
if (score == -10 || score == 10 || score == 0)
{
if (score < 0)
score += depth;
else if (score > 0)
score -= depth;
return score;
}
Hope this answers your question fully.
My GetMark() function, which is supposed to check for correct range and afterwards return the value, if correct to the given array gets stuck in a infinite loop when a parameter is given outside of the accepted range, before i added the SearchMark() function it worked correctly and looped only until the user finally entered a value in the given range (0 - 100) but now after the first out of range value is given it loops no matter what is entered, I will be thankful for any suggestions. full code:
int GetMark(int ModuleIndex) //user input function
{
bool help;
if (ModuleIndex < 0 || ModuleIndex >100)
{
help = false;
while (help != true)
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "hey, that's a invalid value, try again!" << endl;
GetMark(ModuleIndex);
if ((ModuleIndex > 0) &&( ModuleIndex < 101))
{
help = true;
}
}
}
return ModuleIndex;
}
int SearchMark(int A[], int a) //search grades array for numbers of specific grades
{
int i = 0;
int ii = 0;
while (i < 12)
{
if (A[i] == a)
ii++;
i++;
}
cout << "Mark " << a << " was found: " << ii << " times" << endl;
return 0;
}
int main()
{
int marks[12];
int i = 0;
int sum = 0;
int grades[12];
while (i < 12)
{
cout << "enter mark (0 - 100): " << endl;
cin >> marks[i];
GetMark(marks[i]);
sum = sum + marks[i];
if (marks[i] > 69)
{
grades[i] = 1;
}
else if (marks[i] > 59 && marks[i] < 70)
{
grades[i] = 2;
}
else if (marks[i] > 49 && marks[i] < 60)
{
grades[i] = 22;
}
else if (marks[i] > 39 && marks[i < 50])
{
grades[i] = 3;
}
else if (marks[i] < 35)
{
grades[i] = 4;
}
i++;
}
sum = sum / 12;
cout << "your average is: " << sum << endl;
if (sum > 69)
{
cout << "You passed with 1st!" << endl;
}
else if ((sum > 59) && (sum < 70))
{
cout << "You passed with 2i!" << endl;
}
else if ((sum > 49) && (sum < 60))
{
cout << "You passed with 2ii!" << endl;
}
else if ((sum > 39) && (sum < 50))
{
cout << "You passed with 3rd!" << endl;
}
else if (sum < 40)
{
cout << "Your average is too low! You failed." << endl;
}
i = 0;
while (i < 12)
{
if (marks[i] < 35)
{
cout << "Referred in module " << i + 1 << " mark too low." << endl;
}
i++;
}
SearchMark(grades, 1);
SearchMark(grades, 2);
SearchMark(grades, 22);
SearchMark(grades, 3);
SearchMark(grades, 4);
return 0;
}`
That function is overly complicated for what it does. Just loop while the value is bad, and prompt for a new value:
int GetMark(int ModuleIndex) {
while (ModuleIndex < 0 || ModuleIndex > 100) {
std::cout << "Invalid value.\n"
std::cin >> ModuleIndex;
}
return ModuleIndex;
}
Recursion is very handy in theoretical analysis, but in practice it's almost always a mistake.
You need to allow the user to specify a new value of marks[i] / ModuleIndex within GetMarks. After clearing cin, read a new value from cin. You also need to return that value so that main's marks[i] can be updated with that value instead of the original out-of-range value.
Basically what you need to do is remove the recursion from this method and just rely on the while loop. Instead of recalling the function you need to prompt for input again with the failed input and then test the value again to escape the loop.
int GetMark(int ModuleIndex) //user input function
{
bool help;
if (ModuleIndex < 0 || ModuleIndex >100)
{
help = false;
while (help != true)
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "hey, that's a invalid value, try again!" << endl;
cout << "enter mark (0 - 100): " << endl;
cin >> ModuleIndex;
if ((ModuleIndex > 0) &&( ModuleIndex < 101))
{
help = true;
}
}
}
return ModuleIndex;
}
It is apparently in you getMark, inside the while loop you are calling getMark recursively with the same invalid ModuleIndex value. So you need to get it from the standard input before recursion. e.g:
int GetMark(int ModuleIndex){
bool help;
if (ModuleIndex < 0 || ModuleIndex > 100){
help = false;
while (help != true){
cout << "enter new ModuleIndex: \n";
cin >> ModuleIndex;
GetMark(ModuleIndex);
// ...
}
return ModuleIndex;
}
Your code is unreadable, in addition you can use class std::vector.
I propose to test this code:
int GetMarkIndex(const std::vector<double>& vMarks, const double Search) {
auto beg{ vMarks.begin() }, end{ vMarks.end() };
while (beg != end && *beg != Search)
++beg;
return beg != end ? beg - vMarks.begin() : -1;
}
int main() {
std::vector<double> marks(5);
int value;
auto i{ 0U };
auto sz{ marks.size() };
while (i != sz) {
std::cout << "Enter marks 1-->100" << std::endl;
if (cin >> value && value > 0 && value < 101) {
marks[i] = value;
++i;
}
else
std::cout << "Invalid input!" << std::endl;
}
for (auto e : marks)
cout << e << ", ";
std::cout << std::endl;
double Search = 15;
auto index{GetMarkIndex(marks, Search)};
(index != -1) ? (std::cout << Search << " Found at index: " << index) : (std::cout << Search << " Not found!" << std::endl);
std::cout << std::endl;
}
The combination of the way you have defined GetMark and the way you use it is flawed.
No matter what you do in GetMark, the value entered in main does not change.
Change GetMark to:
int GetMark()
{
std::cout << "enter mark (0 - 100): " << std::endl;
int mark;
while ( std::cin >> mark )
{
if ( mark >= 0 && mark <= 100)
{
return mark;
}
std::cout << "Invalid value " << mark << std::endl;
std::cout << "enter mark (0 - 100): " << std::endl;
}
// Unable to read.
// Throw exception, or exit with an error message.
}
and change its usage. Instead of
cout << "enter mark (0 - 100): " << endl;
cin >> marks[i];
GetMark(marks[i]);
use
marks[i] = GetMark();
A working version of GetMark:
int GetMark()
{
std::cout << "enter mark (0 - 100): " << std::endl;
std::string line;
while ( getline(std::cin, line) )
{
std::istringstream str(line);
int mark;
if ( str >> mark )
{
if ( mark >= 0 && mark <= 100)
{
return mark;
}
}
std::cout << "Invalid input: " << line << std::endl;
std::cout << "enter mark (0 - 100): " << std::endl;
}
// Unable to read.
// Throw exception, or exit with an error message.
return 0;
}
Live Demo.
The title kind of says it all. I'm not sure exactly why the Tic Tac Toe program is not detecting a tie. I've attached the main function, additional functions, etc.. I'm not sure what im doing wrong. Any help is greatly appreciated.
#include <string>
#include <iostream>
#include <cstdlib>
using namespace std;
string displayBoard(string board[9]); // displays tic tac toe board
bool isGameOver(string board[9]); // checks if game is over
void displayGameWelcome(); // displays welcome message
int main()
{
string board[9]; // tic tac toe, top row 0 thru 2, middle row 3 thru 5, bottom row 6 thru 8
int position = 0; // player's position
bool gameOver = false; // flag variable to mark end of the game
bool validMove = false; // determines if move is valid or not
displayGameWelcome();
// initializing board with blank spaces
for (int i = 0; i < 9; i++)
{
board[i] = " ";
}
while (!gameOver)
{
// player #1's turn **************************
validMove = false;
while (!validMove)
{
cout << "Enter your position: ";
cin >> position;
if (position >= 0 && position <= 8 && board[position] == " ")
{
validMove = true;
board[position] = "x"; // placing x in desired board location
}
else
{
cout << "That position is already occupied." << endl;
cout << displayBoard(board) << endl;
}
}
cout << displayBoard(board) << endl;
if (isGameOver(board))
{
gameOver = true;
}
// player #2's turn **********************************
validMove = false;
while (!validMove)
{
cout << "Enter your position: ";
cin >> position;
if (position >= 0 && position <= 8 && board[position] == " ")
{
validMove = true;
board[position] = "o"; // placing o in desired board position
}
else
{
cout << "That position is already occupied." << endl;
cout << displayBoard(board) << endl;
}
}
cout << displayBoard(board) << endl;
if (isGameOver(board))
{
gameOver = true;
}
}// end of validMove while loop
system("pause");
return 0;
}// end of main
// ************************** functions *************************
void displayGameWelcome()
{
cout << "Welcome to Tic Tac Toe v3.2" << endl;\
cout << "by Brett Singley & Nick Canarelli" << endl;
cout << "****************************\n\n\n";
}// end of displayGameWelcome
// checks if game is over
bool isGameOver(string board[9])
{
if (board[0] == "x" && board[1] == "x" && board[2] == "x")
{
cout << endl << "The game is over - x wins" << endl;
return true;
}
else if (board[0] == "o" && board[1] == "o" && board[2] == "o")
{
cout << endl << "The game is over - o wins" << endl;
return true;
}
else if (board[3]=="x" && board[4]=="x" && board[5]=="x")
{
cout <<endl << "The game is over - X wins" <<endl;
}
else if (board[3]=="o" && board[4]=="o" && board[5]=="o")
{
cout <<endl << "The game is over - o wins" <<endl;
}
else if (board[0]=="x" && board[3]=="x" && board[6]=="x")
{
cout <<endl << "The game is over - X wins" <<endl;
}
else if (board[0]=="o" && board[3]=="o" && board[6]=="o")
{
cout <<endl << "The game is over - o wins" <<endl;
}
else if (board[6]=="x" && board[7]=="x" && board[8]=="x")
{
cout <<endl << "The game is over - X wins" <<endl;
}
else if (board[6]=="o" && board[7]=="o" && board[8]=="o")
{
cout <<endl << "The game is over - O wins" <<endl;
}
else if (board[1]=="x" && board[4]=="x" && board[7]=="x")
{
cout <<endl << "The game is over - X wins" <<endl;
}
else if (board[1]=="o" && board[4]=="o" && board[7]=="o")
{
cout <<endl << "The game is over - O wins" <<endl;
}
else if (board[2]=="x" && board[5]=="x" && board[8]=="x")
{
cout <<endl << "The game is over - X wins" <<endl;
}
else if (board[2]=="o" && board[5]=="o" && board[8]=="o")
{
cout <<endl << "The game is over - o wins" <<endl;
}
else if (board[0]=="x" && board[4]=="x" && board[8]=="x")
{
cout <<endl << "The game is over - X wins" << endl;
}
else if (board[0]=="o" && board[4]=="o" && board[8]=="o")
{
cout <<endl << "The game is over - o wins" <<endl;
}
else if (board[2]=="x" && board[4]=="x" && board[6]=="x")
{
cout <<endl << "The game is over - X wins" <<endl;
}
else if (board[2]=="o" && board[4]=="o" && board[6]=="o")
{
cout <<endl << "The game is over - o wins" <<endl;
}
else
{
cout << "WOAH!!!!! Tie Game" <<endl;
}
// more to do here (don't forget to check for draw)
return false;
}// end of isGameOver
// displays tic tac toe board in the format
// |0 1 2|
// |3 4 5|
// |6 7 8|
string displayBoard(string board[9])
{
string str = "";
for (int i = 0; i < 9; i++)
{
if (i == 0)
{
str = str + "|" + board[i];
}
else if (i == 2 || i == 5)
{
str = str + board[i] + "|\n|";
}
else if (i == 8)
{
str = str + board[i] + "|\n";
}
else
{
str = str + board[i];
}
}
return str;
}// end of displayBoard
You can simplify checking for a winner by using for loops and realizing that the value in the three spaces are equal (to something other than the initial value). Also, since there are 3 rows and 3 columns, the rows and columns can be checked inside the same for loop:
const char initial_value = ' ';
const unsigned int max_rows_or_columns = 3;
bool Is_Game_Over(int board[9], char& winner)
{
for (unsigned int i = 0; i < max_rows_or_columns; ++i)
{
// Check the row
if ( (board[(i * 3) + 0] == board[(i * 3) + 1])
&& (board[(i * 3) + 1) == board[(i * 3) + 2]))
{
// By transitive property, board[(i * 3) + 0] == board[(i * 3) + 2]
winner = board[(i * 3) + 0];
if (winner != initial_value)
{
break;
}
}
else // Check the columns
{
if ( (board[(0 * 3) + i] == board[(1 * 3) + i])
&& (board[(1 * 3) + i] == board[(2 * 3) + i]))
{
winner = board[(0 * 3) + i];
if (winner != initial_value)
{
break;
}
}
}
bool winner_found = true;
if (i >= max_rows_or_columns)
{
winner_found = false;
}
return winner_found;
}
The checking of the diagonals is left as an exercise for the reader.