I am trying to implement the Lee algorithm on a 2D grid. The flood loop is however stopping too early, claiming to have not found any more "empty" cells. I am completely stumped as to why.
#define WIDTH 6
#define HEIGHT 6
int gridArray[WIDTH][HEIGHT];
void InitialiseGrid() {
srand(time(NULL)); // initialise the randomiser
for (int y = 0; y < HEIGHT; y++) {
for (int x = 0; x < WIDTH; x++) {
if (rand() % 4 == 0)
gridArray[x][y] = -2;
else
gridArray[x][y] = -1;
}
}
}
bool foundEmpty = true;
bool foundEnd = false;
int it = 0;
while (foundEmpty && !foundEnd) {
DrawGrid();
cout << endl << endl;
for (int y = 0; y < HEIGHT; y++) {
for (int x = 0; x < WIDTH; x++) {
if (gridArray[x][y] == it) {
// initially assume neighbouring cells are not empty
foundEmpty = false;
// check east cell
if (x < WIDTH) {
int *e = &gridArray[x + 1][y];
if (*e == -1) {
*e = it + 1;
foundEmpty = true;
}
else if (*e == -3) {
foundEnd = true;
}
}
// check west cell
if (x > 0) {
int *w = &gridArray[x - 1][y];
if (*w == -1) {
*w = it + 1;
foundEmpty = true;
}
else if (*w == -3) {
foundEnd = true;
}
}
// check south cell
if (y < HEIGHT) {
int *s = &gridArray[x][y + 1];
if (*s == -1) {
*s = it + 1;
foundEmpty = true;
}
else if (*s == -3) {
foundEnd = true;
}
}
// check north cell
if (y > 0) {
int *n = &gridArray[x][y - 1];
if (*n == -1) {
*n = it + 1;
foundEmpty = true;
}
else if (*n == -3) {
foundEnd = true;
}
}
}
}
}
it++;
}
void DrawGrid() {
std::string message = "";
for (int y = 0; y < HEIGHT; y++) {
cout << endl;
for (int x = 0; x < WIDTH; x++) {
if (gridArray[x][y] == 0)
message = "start";
else if (gridArray[x][y] == -3)
message = "end";
else if (gridArray[x][y] == -2)
message = "X";
else
message = std::to_string(gridArray[x][y]);
cout << "|" << "\t" << message << "\t" << "|";
}
cout << endl;
}
}
The end on the path is specified by assigning a cell to -3. Cells that are blocked are -2. Cells that are empty are -1. The starting cell is 0.
Not sure what your problem is, but your algorithm seems to be solid. I have cleaned it a little and it seems to be working fine:
#include <iostream>
#include <string>
#include <iomanip>
#define WIDTH 7
#define HEIGHT 7
int gridArray[WIDTH][HEIGHT] =
{
{ -1,-1,-1,0,-2,-1,-2 },
{ -2,-1,-1,-1,-1,-2,-2 },
{ -2,-1,-1,-1,-1,-2,-2 },
{ -2,-2,-1,-1,-1,-2,-1 },
{ -1,-2,-2,-2,-1,-1,-2 },
{ -1,-2,-1,-1,-1,-2,-2 },
{ -2,-2,-3,-1,-1,-2,-2 }
};
void DrawGrid()
{
for (int x = 0; x < WIDTH; x++)
{
for (int y = 0; y < HEIGHT; y++)
{
std::string message;
if (gridArray[x][y] == 0)
message = "S";
else if (gridArray[x][y] == -3)
message = "E";
else if (gridArray[x][y] == -2)
message = "#";
else if (gridArray[x][y] == -1)
message = ".";
else
message = std::to_string(gridArray[x][y]);
std::cout << std::setw(3) << message << " ";
}
std::cout << std::endl << std::endl;
}
std::cout << std::endl << std::endl;
}
void SolveMaze()
{
bool foundEnd = false;
int it = 0;
while (!foundEnd)
{
bool foundEmpty = false;
for (int x = 0; x < WIDTH && !foundEnd; ++x)
{
for (int y = 0; y < HEIGHT; ++y)
{
if (gridArray[x][y] == it)
{
// check east cell
if (x < WIDTH - 1)
{
int &east = gridArray[x + 1][y];
if (east == -3)
{
foundEnd = true;
break;
}
else if (east == -1)
{
east = it + 1;
foundEmpty = true;
}
}
// check west cell
if (x > 0)
{
int &west = gridArray[x - 1][y];
if (west == -3)
{
foundEnd = true;
break;
}
else if (west == -1)
{
west = it + 1;
foundEmpty = true;
}
}
// check south cell
if (y < HEIGHT - 1)
{
int &south = gridArray[x][y + 1];
if (south == -3)
{
foundEnd = true;
break;
}
else if (south == -1)
{
south = it + 1;
foundEmpty = true;
}
}
// check north cell
if (y > 0)
{
int &north = gridArray[x][y - 1];
if (north == -3)
{
foundEnd = true;
break;
}
else if (north == -1)
{
north = it + 1;
foundEmpty = true;
}
}
}
}
}
if (!foundEnd && !foundEmpty)
{
std::cout << "This maze has no solution!" << std::endl << std::endl;
break;
}
it++;
}
}
int main()
{
DrawGrid();
SolveMaze();
DrawGrid();
system("pause");
return 0;
}
Related
Me and my group is making a game for our project and I keep running into this error, after some testing, it looks like it happens at the end of the main function. I have no idea how this happen as most of the code is from our teacher, we need to fix the intentional bugs placed by him and add additional functionalities.
This is the code:
#include <winuser.h>
#include <iostream>
#include <time.h>
#include <conio.h>
#include <thread>
using namespace std;
#define MAX_CAR 5
#define MAX_CAR_LENGTH 40
#define MAX_SPEED 3
POINT** X;
POINT Y;
int cnt = 0;
int MOVING;
int SPEED;
int HEIGHT_CONSOLE = 29, WIDTH_CONSOLE = 119;
bool STATE;
void FixConsoleWindow() {
HWND consoleWindow = GetConsoleWindow();
LONG_PTR style = GetWindowLongPtr(consoleWindow, GWL_STYLE);
style = style & ~(WS_MAXIMIZEBOX) & ~(WS_THICKFRAME);
SetWindowLongPtr(consoleWindow, GWL_STYLE, style);
}
void GotoXY(int x, int y) {
COORD coord;
coord.X = x;
coord.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
void ResetData() {
MOVING = 'D';
SPEED = 1;
Y = { 18, 19 };
if (X == NULL) {
X = new POINT * [MAX_CAR];
for (int i = 0; i < MAX_CAR; i++) {
X[i] = new POINT[MAX_CAR_LENGTH];
}
for (int i = 0; i < MAX_CAR; i++) {
int temp = rand() % (WIDTH_CONSOLE - MAX_CAR_LENGTH) + 1;
for (int j = 0; j < MAX_CAR_LENGTH; j++) {
X[i][j].x = temp + j;
X[i][j].y = 2 + 5 * i;
}
}
}
}
void DrawBoard(int x, int y, int width, int height, int curPosX = 0, int curPosY = 0) {
GotoXY(x, y);
for (int i = 1; i < width; i++) {
cout << 'X';
}
cout << 'X';
GotoXY(x, height + y);
for (int i = 1; i < width; i++) {
cout << 'X';
}
cout << 'X';
for (int i = y + 1; i < height + y; i++) {
GotoXY(x, i);
cout << 'X';
GotoXY(x + width, i);
cout << 'X';
}
GotoXY(curPosX, curPosY);
}
void StartGame() {
system("cls");
ResetData();
DrawBoard(0, 0, WIDTH_CONSOLE, HEIGHT_CONSOLE);
STATE = true;
}
void GabageCollect() {
for (int i = 0; i < MAX_CAR; i++) {
delete[] X[i];
}
delete[] X;
}
void ExitGame(HANDLE t) {
GabageCollect();
system("cls");
TerminateThread(t, 0);
}
void PauseGame(HANDLE t) {
SuspendThread(t);
}
void ProcessDeath() {
STATE = false;
GotoXY(0, HEIGHT_CONSOLE + 2);
cout << "Dead, type y to continue or any key to exit";
}
void ProcessFinish(POINT& p) {
SPEED == MAX_SPEED ? SPEED = 1 : SPEED++;
p = { 18,19 };
MOVING = 'D';
}
void DrawCars() {
for (int i = 0; i < MAX_CAR; i++) {
for (int j = 0; j < MAX_CAR_LENGTH; j++) {
GotoXY(X[i][j].x, X[i][j].y);
std::cout << '.';
}
}
}
void DrawPlayer(const POINT& p, char s) {
GotoXY(p.x, p.y);
cout << s;
}
bool IsImpact(const POINT& p) //d=Y.y p = Y
{
if (p.y == 1 || p.y == 19) return false;
for (int i = 0; i < MAX_CAR; i++)
{
for (int j = 0; j < MAX_CAR_LENGTH; j++)
{
if (p.x == X[i][j].x && p.y == X[i][j].y) return true;
}
}
return false;
}
void MoveCars(int x1, int y1)
{
for (int i = 1; i < MAX_CAR; i += 2)
{
cnt = 0;
do
{
cnt++;
for (int j = 0; j < MAX_CAR_LENGTH - 1; j++)
{
X[i][j] = X[i][j + 1];
}
X[i][MAX_CAR_LENGTH - 1].x + 1 == WIDTH_CONSOLE + x1 ? X[i][MAX_CAR_LENGTH - 1].x = 1 : X[i][MAX_CAR_LENGTH - 1].x++;
} while (cnt < SPEED);
}
for (int i = 0; i < MAX_CAR; i += 2)
{
cnt = 0;
do
{
cnt++;
for (int j = MAX_CAR_LENGTH - 1; j > 0; j--)
{
X[i][j] = X[i][j - 1];
}
X[i][0].x - 1 == 0 + x1 ? X[i][0].x = WIDTH_CONSOLE + x1 - 1 : X[i][0].x--;
} while (cnt < SPEED);
}
}
void EraseCars()
{
for (int i = 0; i < MAX_CAR; i += 2)
{
cnt = 0;
do
{
GotoXY(X[i][MAX_CAR_LENGTH - 1 - cnt].x, X[i][MAX_CAR_LENGTH - 1 - cnt].y);
cout << " ";
cnt++;
} while (cnt < SPEED);
}
for (int i = 1; i < MAX_CAR; i += 2)
{
cnt = 0;
do
{
GotoXY(X[i][0 + cnt].x, X[i][0 + cnt].y);
cout << " ";
cnt++;
} while (cnt < SPEED);
}
}
void MoveRight()
{
if (Y.x < WIDTH_CONSOLE - 1)
{
DrawPlayer(Y, ' ');
Y.x++;
DrawPlayer(Y, 'Y');
}
}
void MoveLeft()
{
if (Y.x > 1)
{
DrawPlayer(Y, ' ');
Y.x--;
DrawPlayer(Y, 'Y');
}
}
void MoveDown()
{
if (Y.y < HEIGHT_CONSOLE - 1)
{
DrawPlayer(Y, ' ');
Y.y++;
DrawPlayer(Y, 'Y');
}
}
void MoveUp()
{
if (Y.y > 1)
{
DrawPlayer(Y, ' ');
Y.y--;
DrawPlayer(Y, 'Y');
}
}
void SubThread()
{
while (1)
{
if (STATE)
{
switch (MOVING)
{
case 'A':
MoveLeft();
break;
case 'D':
MoveRight();
break;
case'W':
MoveUp();
break;
case'S':
MoveDown();
break;
}
MOVING = ' ';
EraseCars();
MoveCars(0, 0);
DrawCars();
if (IsImpact(Y))
{
ProcessDeath();
}
if (Y.y == 1)
{
ProcessFinish(Y);
Sleep(50);
}
}
}
}
void main()
{
int temp;
FixConsoleWindow();
srand(time(NULL));
StartGame();
thread t1(SubThread);
while (1)
{
temp = toupper(_getch());
if (STATE == 1)
{
EraseCars();
if (temp == 27)
{
ExitGame(t1.native_handle());
break;
}
else if (temp == 'P')
{
PauseGame(t1.native_handle());
temp = toupper(_getch());
if (temp == 'B')
ResumeThread((HANDLE)t1.native_handle());
}
else
{
if (temp == 'D' || temp == 'A' || temp == 'W' || temp == 'S')
{
MOVING = temp;
}
}
}
else
{
if (temp == 'Y') StartGame();
else
{
ExitGame(t1.native_handle());
break;
}
}
}
}
And this is the image of the error: https://imgur.com/PGJJX2w
Basically, this is a crossing road game, every time you go to the top, it saves the location and you cannot go that location again (still working on this), game finish when you run into the cars (lines of dots as of the moment). Thanks in advance
You created a std::thread object here:
thread t1(SubThread);
but you didn't call join() nor detach() for that.
This causes that std::terminate() is called (the program aborts) when the object is destructed.
Call t1.join() if you want to wait until the thread ends or t1.detach() if you want to let the thread run freely before returning from the main() function.
Another option is using CreateThread() directly instead of std::thread to create threads. This may be better because you are using t1.native_handle() for operations on the thread.
I am trying to create a c++ unbeatable tic tac toe AI. after watching several videos on the topic i thought I had it all figured out. An error pops up on the screen saying "Expression: vector subscript out of range". I believe the error is coming from the availableMoves() function. however I do not know why.
The game itself works fine. any help would be appreciated.
#include <iostream>
#include <vector>
#include <ctime>
bool in(std::vector<int> v, int element)
{
for (int i = 0; i < v.size(); i++)
{
if (element == v[i])
{
return true;
}
}
return false;
}
class Board
{
private:
char board[3][3] = { {'1', '2', '3'}, {'4', '5', '6'}, {'7', '8', '9'} };
public:
void displayBoard()
{
std::cout << "___________________" << std::endl;
for (int i = 0; i < 3; i++)
{
std::cout << "| ";
for (int j = 0; j < 3; j++)
{
std::cout << board[i][j] << " | ";
}
std::cout << std::endl;
}
std::cout << "___________________" << std::endl;
}
std::vector<int> availableMoves()
{
std::vector<int> moves;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (board[i][j] != 'X' && board[i][j] != 'O')
{
moves.push_back(i * 3 + j);
}
}
}
return moves;
}
void move(int choice, char mark)
{
int y = choice / 3;
int x = choice - y * 3;
board[y][x] = mark;
}
void revert(int choice)
{
int y = choice / 3;
int x = choice - y * 3;
board[y][x] = (char)choice + 48;
}
int checkWin()
{
for (int i = 0; i < 3; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2])
{
if (board[i][0] == 'X')
{
return 1;
}
else if (board[i][0] == 'O')
{
return -1;
}
}
}
for (int i = 0; i < 3; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i])
{
if (board[0][i] == 'X')
{
return 1;
}
else if (board[0][i] == 'O')
{
return -1;
}
}
}
if (board[0][0] == board[1][1] && board[1][1] == board[2][2])
{
if (board[0][0] == 'X')
{
return 1;
}
else if (board[0][0] == 'O')
{
return -1;
}
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0])
{
if (board[0][2] == 'X')
{
return 1;
}
else if (board[0][2] == 'O')
{
return -1;
}
}
return 0;
}
int evaluate()
{
return (checkWin() * -1) * (availableMoves().size() + 1);
}
Board& operator=(Board& b)
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
board[i][j] = b.board[i][j];
}
}
return (*this);
}
};
class TicTacToe
{
private:
Board board;
int turn;
int searches = 0;
public:
TicTacToe()
{
std::srand(time(0));
turn = std::rand() % 2;
}
int minimax(int depth, Board curBoard, bool is_max)
{
searches++;
if (depth == 0 || curBoard.checkWin() != 0)
{
return board.evaluate();
}
if (is_max)
{
int max_eval = -2147483647;
for (int i = 0; i < curBoard.availableMoves().size(); i++)
{
curBoard.move(curBoard.availableMoves()[i], 'O');
depth -= 1;
int eval = minimax(depth, curBoard, false);
curBoard.revert(curBoard.availableMoves()[i]);
if (eval > max_eval)
{
max_eval = eval;
}
}
return max_eval;
}
if (!is_max)
{
int min_eval = 2147483647;
for (int i = 0; i < curBoard.availableMoves().size(); i++)
{
curBoard.move(curBoard.availableMoves()[i], 'X');
depth -= 1;
int eval = minimax(depth, curBoard, true);
curBoard.revert(curBoard.availableMoves()[i]);
if (eval < min_eval)
{
min_eval = eval;
}
}
return min_eval;
}
}
void game()
{
while (board.checkWin() == 0 && board.availableMoves().size() != 0)
{
board.displayBoard();
if (turn % 2 == 0)
{
std::cout << std::endl;
int choice;
std::cout << "Enter Your Move: ";
std::cin >> choice;
choice -= 1;
while (!in(board.availableMoves(), choice))
{
std::cout << "Enter A Valid Move: ";
std::cin >> choice;
}
board.move(choice, 'X');
std::cout << std::endl;
turn++;
}
board.displayBoard();
if (board.checkWin() != 0)
{
break;
}
if (turn % 2 == 1)
{
int ai = minimax(9 - (turn % 2), board, true);
std::cout << searches;
std::cin.get();
turn++;
}
}
if (board.checkWin() == 1)
{
std::cout << "You Won" << std::endl;
}
else if (board.checkWin() == -1)
{
std::cout << "You Lost" << std::endl;
}
else
{
std::cout << "Tie" << std::endl;
}
std::cout << "Would You Like To Play Again Y/N: ";
char playAgain;
std::cin >> playAgain;
if (playAgain == 'Y')
{
Board newBoard;
board = newBoard;
game();
}
}
};
int main()
{
TicTacToe ticTacToe;
ticTacToe.game();
}
Do you know how to debug? If not, you should definitely learn this, it's pretty helpful. But here's some things I found out.
The problem is not in availableMoves(), but in minimax(), more precisely in line 215, where the program calls curBoard. revert(curBoard. availableMoves()[i]).
void revert(int choice)
{
int y = choice / 3;
int x = choice - y * 3;
board[y][x] = (char)choice + 48;
}
for (int i = 0; i < curBoard.availableMoves().size(); i++)
{
curBoard.move(curBoard.availableMoves()[i], 'X');
depth -= 1;
int eval = minimax(depth, curBoard, true);
curBoard.revert(curBoard.availableMoves()[i]);
if (eval < min_eval)
{
min_eval = eval;
}
}
The error happens in the function revert, but I am not sure why. Maybe availableMoves also returns something wrong. Variable i is permanently 0 in the for-loop. So it is possible that there is something wrong at position 0 of the vector moves, which revert cannot handle. Try debugging yourself, maybe you'll find the problem.
I have a major problem in my minimax algorithm. I have to implement a game, where is a player and an AI player. Both of them can step up,down,right,left diagonal and after that they have to block a cell, where the other player can't step (ofc, where the other player stays is a blocked cell and can't block that one, and you can't block an already blocked cell too). I wrote a little minimax algorithm for that, but for a strange thing the AI can't decide the best root.
struct Position
{
int x, y;
} MaxP, MinP;
int k = 2;
char board[10][10];
int currentPlayer = 2;
//Here are my global variables, MaxP is the AI, and MinP is the player.
I set the cells B (as blocked) around my table.
The minimax calculation algorithm:
int nyertesErtek(int result) //return a winning value, if result=1 Ai Wins, if result=2 Player Wins, if result=0, then the game it's still going
{
if (result == 1) return 10;
if (result == 2) return -10;
}
int minimax(char pBoard[10][10], int depth, bool isMaximizing)
{
int result = 0;
if (isMaximizing==true)
{
int checkX[8] = { -1,-1,0,1,1,1,0,-1 };
int checkY[8] = { 0,1,1,1,0,-1,-1,-1 };
bool lephetMax = false;
bool lephetMin = false;
for (int i = 0; i < 8; i++)
{
if (pBoard[MaxP.x + checkX[i]][MaxP.y + checkY[i]] != 'B')
{
lephetMax = true;
break;
}
}
if (lephetMax == false)
{
result = 2;
}
}
if (isMaximizing == false)
{
int checkX[8] = { -1,-1,0,1,1,1,0,-1 };
int checkY[8] = { 0,1,1,1,0,-1,-1,-1 };
bool lephetMin = false;
for (int i = 0; i < 8; i++)
{
if (pBoard[MinP.x + checkX[i]][MinP.y + checkY[i]] != 'B')
{
lephetMin = true;
break;
}
}
if (lephetMin == false)
{
result = 1;
}
}
if (result != 0) //ha nem terminal state
{
//cout << "Resultra jutott"<<endl;
//cout << "---------------->Kovetkezne a: " << isMaximizing << " Result=" << result << " NyeresErtek=" << nyertesErtek(result) <<" depth="<<depth<< "<---------------"<<endl;
//printBoard();
return nyertesErtek(result);
}
int checkX[8] = { -1,-1,0,1,1,1,0,-1 };
int checkY[8] = { 0,1,1,1,0,-1,-1,-1 };
if (isMaximizing)
{
int bestScore = -INT_MAX;
int szabadX;
int szabadY;
for (int l = 0; l < 8; l++)
{
if (pBoard[MaxP.x + checkX[l]][MaxP.y + checkY[l]] != 'B')
{
int oldMaxPX = MaxP.x;
int oldMaxPY = MaxP.y;
MaxP.x = MaxP.x + checkX[l];
MaxP.y= MaxP.y + checkY[l];
pBoard[MaxP.x][MaxP.y] = 'B';
pBoard[oldMaxPX][oldMaxPY] = 'o';
for (int i = 1; i <= k; i++)
{
for (int j = 1; j <= k; j++)
{
if (pBoard[i][j] != 'B')
{
szabadX = i;
szabadY = j;
pBoard[szabadX][szabadY] = 'B';
//cout << "Maximizing, depth=" << depth << endl;
//printBoard();
int score = minimax(pBoard, depth + 1, false);
pBoard[szabadX][szabadY] = 'o';
if (score > bestScore)
{
bestScore = score;
}
}
}
}
pBoard[MaxP.x][MaxP.y] = 'o';
pBoard[oldMaxPX][oldMaxPY] = 'B';
MaxP.x = oldMaxPX;
MaxP.y = oldMaxPY;
}
}
return bestScore;
}
else
{
int bestScore = INT_MAX;
int szabadX;
int szabadY;
for (int l = 0; l < 8; l++)
{
if (pBoard[MinP.x + checkX[l]][MinP.y + checkY[l]] != 'B')
{
int oldMinPX = MinP.x;
int oldMinPY = MinP.y;
MinP.x = MinP.x + checkX[l];
MinP.y = MinP.y + checkY[l];
//pBoard[MinP.x + checkX[l]][MinP.y + checkY[l]] = 'B';
pBoard[MinP.x][MinP.y] = 'B';
pBoard[oldMinPX][oldMinPY] = 'o';
//cout << "Minimizing depth= " << depth << endl;
//printBoard();
for (int i = 1; i <= k; i++)
{
for (int j = 1; j <= k; j++)
{
if (pBoard[i][j] != 'B')
{
szabadX = i;
szabadY = j;
pBoard[szabadX][szabadY] = 'B';
int score = minimax(pBoard, depth + 1, true);
//pBoard[MinP.x + checkX[l]][MinP.y + checkY[l]] = 'o';
pBoard[szabadX][szabadY] = 'o';
if (score < bestScore)
{
bestScore = score;
}
}
}
}
pBoard[MinP.x][MinP.y] = 'o';
pBoard[oldMinPX][oldMinPY] = 'B';
MinP.x = oldMinPX;
MinP.y = oldMinPY;
}
}
return bestScore;
}
}
And moving the AI is in this function:
void bestMove() {
int checkX[8] = { -1,-1,0,1,1,1,0,-1 };
int checkY[8] = { 0,1,1,1,0,-1,-1,-1 };
int bestScore = -INT_MAX;
Position move;
int AIBlockX, AIBlockY;
int szabadX;
int szabadY;
for (int l = 0; l < 8; l++)
{
if (board[MaxP.x + checkX[l]][MaxP.y + checkY[l]] != 'B')
{
int oldMaxPX = MaxP.x;
int oldMaxPY = MaxP.y;
MaxP.x = MaxP.x + checkX[l];
MaxP.y = MaxP.y + checkY[l];
board[MaxP.x][MaxP.y] = 'B';
board[oldMaxPX][oldMaxPY] = 'o';
for (int i = 1; i <= k; i++)
{
for (int j = 1; j <= k; j++)
{
if (board[i][j] != 'B')
{
szabadX = i;
szabadY = j;
board[szabadX][szabadY] = 'B';
int score = minimax(board, 0, false);
cout << endl << "Ennyi a score amit kaptam pech=" << score << endl;
board[szabadX][szabadY] = 'o';
if (score > bestScore)
{
bestScore = score;
move.x = MaxP.x;
move.y = MaxP.y;
AIBlockX = szabadX;
AIBlockY = szabadY;
cout << "BESTMOVE: " << move.x << " " << move.y << " bestscore= " << bestScore << endl;
}
}
}
}
board[MaxP.x][MaxP.y] = 'o';
board[oldMaxPX][oldMaxPY] = 'B';
MaxP.x = oldMaxPX;
MaxP.y = oldMaxPY;
}
}
board[move.x][move.y] = 'B';
board[MaxP.x][MaxP.y] = 'o';
MaxP.x = move.x;
MaxP.y = move.y;
board[AIBlockX][AIBlockY] = 'B';
currentPlayer = 2;
}
I think my main problem is something in the minimax function: when I check where the player can go -> and after that all the possible blocking moves. And in that triple for when I rewrite the best score with the current score I can't return the value directly because I have to check other possible moves in the firs for iteration.
So after all (:D) my question is that how can I save the best move after the cell blocking was done and return that to my AI to step there? Thank you for you answer. :)
ps:I'm sorry if this post is too long, but I thought to fully understand my problem, you also have to see the algorithm part.
I want the program to print "You win" when any of the instances in the champion() function are given. It only shows a winner when "123" is inputted. Whenever three X's are displayed anywhere else the program continues. For instance if three X's are given diagonally the program will still continue. Novice programmer so any criticism is greatly appreciated.
class TicTacToe {
private:
char map[GRID_SIZE][GRID_SIZE];
public:
void computers_turn() {
while (true) {
int choice = (rand() % 9) + 1;
int row = choice / 3;
int col = choice % 3;
char grid_position = map[row][col];
if (grid_position == 'X' || grid_position == 'O') {
std::cout << "Space taken. Try again" << std::endl;
} else {
map[row][col] = (char)'O';
break;
}
}
}
void champion() {
const char* possiblities[8] = {"123", "456", "789", "147",
"258", "369", "159", "753"};
for (int i = 0; i < 8; i++) {
char previous_pos = '0';
bool winner = true;
const char* possible_moves = possiblities[i];
for (int index = 0; index < GRID_SIZE; index++) {
char character = possible_moves[i];
int entered_num = character - '0';
int grid_space = entered_num - '1';
int row = index / GRID_SIZE;
int col = index % GRID_SIZE;
char grid_coordinate = map[row][col];
if (previous_pos == '0') {
previous_pos = grid_coordinate;
} else if (previous_pos == grid_coordinate) {
continue;
} else {
winner = false;
break;
}
}
if (winner) {
puts("You win");
exit(0);
break;
}
}
}
void playgame() {
std::string input;
while (true) {
std::cout << "Go player one" << std::endl;
getline(std::cin, input);
if (input != " ") {
char entered = input.c_str()[0];
if (entered >= '1' && entered <= '9') {
int entered_num = entered - '0';
int index = entered_num - 1;
int row = index / 3;
int col = index % 3;
char grid_position = map[row][col];
if (grid_position == 'X' || grid_position == 'O') {
std::cout << "Space taken. Try again" << std::endl;
} else {
map[row][col] = (char)'X';
break;
}
} else {
std::cout << "Only numbers 1 - 9" << std::endl;
}
} else {
std::cout << "Have to enter something, try again" << std::endl;
}
}
}
void generateGrid() {
int number = 1;
for (int x = 0; x < GRID_SIZE; x++) {
for (int y = 0; y < GRID_SIZE; y++) {
map[x][y] = std::to_string(number).c_str()[0];
number += 1;
}
}
}
void tictacToeMap() {
std::cout << std::endl;
for (int x = 0; x < GRID_SIZE; x++) {
for (int y = 0; y < GRID_SIZE; y++) {
std::printf(" %c ", map[x][y]);
}
std::cout << std::endl;
}
}
TicTacToe() {
generateGrid();
while (true) {
champion();
tictacToeMap();
playgame();
computers_turn();
}
}
};
int main() {
TicTacToe ticTacToe;
return 0;
}
How to use local variable treasureX in another function win? In the win function, the program works using board[6][t] but not treasureX. The treasureX variable is global but code is not working as intended.
#include <iostream>
#include <random>
#include <ctime>
char board[8][8];
char treasureX;
int t;
void Board() {
for (int x = 1; x < 7; x++) {
for (int y = 1; y < 7; y++) {
board[x][y] = '.';
}
}
}
void treasureSpawn() {
t = rand() % 6 + 1;
board[6][t] = 'X';
treasureX = board[6][t];
}
int displayBoard() {
for (int x = 0; x<8; x++) {
for (int y = 0; y<8; y++) {
std::cout << board[x][y];
if (y == 7) {
std::cout << std::endl;
}
}
}
return 0;
}
char playerPosition;
char playerSpawn() {
int randomY;
randomY = rand() % 6 + 1;
board[1][randomY] = 'G';
playerPosition = board[1][randomY];
return playerPosition;
}
int movement() {
char move;
std::cout << "Use WASD keys to move." << std::endl;
std::cin >> move;
for (int x = 1; x<7; x++) {
for (int y = 0; y<8; y++) {
if (board[x][y] == 'G') {
board[x][y] = '.';
if (move == 'W' || move == 'w') {
return board[x - 1][y] = 'G';
}
else if (move == 'A' || move == 'a') {
return board[x][y - 1] = 'G';
}
else if (move == 'D' || move == 'd') {
return board[x][y + 1] = 'G';
}
else if (move == 'S' || move == 's') {
return board[x + 1][y] = 'G';
}
else {
std::cout << "Wrong key!" << std::endl;
movement();
}
}
}
}
return 0;
}
int win() {
if (treasureX == 'G') { // when player arrives at 'X' this function does not execute. Works if I put 'board[6][t]' instead of 'treasureX'.
std::cout << "You win" << std::endl;
return 0;
}
}
int main() {
srand(time(0));
Board();
playerSpawn();
outOfBounds();
treasureSpawn();
displayBoard();
do {
movement();
checkIf();
displayBoard();
} while (win() != 0);
}
Change the definition of treasureX to be const char & treasureX = treasureSpawn(); and treasureSpawn to be
const char & treasureSpawn() {
t = rand() % 6 + 1;
board[6][t] = 'X';
return board[6][t];
}
then the value of treasureX will change when the player moves over it
Here, TreasureX is a variable inintialized in function void treasureSpawn(), and its value is not changed throughout the program (And always be 'X').
However, board[6][t] is changed while the program is executing, more precisely in the int movement() function, hence their values are different when the program executed the function win()