when i get user input cin >> x; and cin >> y;
I want to then compare this to an array "Location cord" L1[i][j], but when i use an if statement
- if (x && y == L1[i][j])
- if (x == L1[i] && y == L1[j])
Im not getting the result of "HIT" which is what i need.
This is a sort of minesweeper project. Any help, or pointers would be much appreciated!
#include "stdafx.h"
#include <iostream>
#include <cstdlib>
#include <iomanip>
#include <string>
char L1[8][8], L2[16][16], L3[24][24]; // grid location of cords
char B1[8][8], B2[16][16], B3[24][24]; // grid location of bombs
int i, j;
using namespace std;
// load and print grids L1 L2 L3
void loadgrid_L1()
{
for ( i = 0; i < 8; i++)
{
for ( j = 0; j < 8; j++)
{
L1[i][j] = 'X';
}
}
}
void printgrid_L1()
{
for ( i = 0; i < 8; i++)
{
for ( j = 0; j < 8; j++)
{
cout << L1[i][j];
}
cout << ("\n");
}
}
void loadgrid_L2()
{
for (i = 0; i < 16; i++)
{
for (j = 0; j < 16; j++)
{
L2[i][j] = 'X';
}
}
}
void printgrid_L2()
{
for (i = 0; i < 16; i++)
{
for (j = 0; j < 16; j++)
{
cout << L2[i][j];
}
cout << ("\n");
}
}
void loadgrid_L3()
{
for (i = 0; i < 24; i++)
{
for (j = 0; j < 24; j++)
{
L3[i][j] = 'X';
}
}
}
void printgrid_L3()
{
for (i = 0; i < 24; i++)
{
for (j = 0; j < 24; j++)
{
cout << L3[i][j];
}
cout << ("\n");
}
}
void bomb1()
{
L1[1][5] = 'O';
}
void bomb2()
{
L2[3][4] = 'O';
}
void bomb3()
{
L3[6][6] = 'O';
}
void menu() //need to work on this section
{
string lvl, x, y;
cout << "Please select a lvl to play L1, L2, L3 " << endl;
getline(cin, lvl);
if (lvl == "L1")
{
loadgrid_L1();
//moved bomb() from here
cout << "Please enter your co-ordinates for your move" << endl;
cout << "Cord 1: ";
getline(cin, x);
cout << "Cord 2: ";
getline(cin, y);
if (x == L1[i])
{
cout << "HIT!" << endl;
}
else if (x != L1[i])
{
cout << "SUCCESS!" << endl;
}
bomb1();
printgrid_L1();
}
else if (lvl == "L2")
{
loadgrid_L2();
bomb2();
printgrid_L2();
}
else if (lvl == "L3")
{
loadgrid_L3();
bomb3();
printgrid_L3();
}
else if ((lvl != "L1") && (lvl != "L2") && (lvl != "L3"))
{
cout << "You must pick a lvl" << endl;
while ((lvl != "L1") && (lvl != "L2") && (lvl != "L3"))
{
getline(cin, lvl);
if (lvl == "L1")
{
loadgrid_L1();
bomb1();
printgrid_L1();
}
else if (lvl == "L2")
{
loadgrid_L2();
bomb2();
printgrid_L2();
}
else if (lvl == "L3")
{
loadgrid_L3();
bomb3();
printgrid_L3(); // needs to stop
}
}
}
}
int main()
{
menu();
return 0;
}
You can easily change each of your loadgrid & printgrid functions to be 2 single functions as such:
void loadgrid( unsigned int lvl ) {
if ( lvl < 0 || lvl > 3 ) {
std::cout << "Error: invalid level entered: " << lvl << std::endl;
return;
}
int size = 0;
if ( lvl == 1 )
size = 8;
else if ( lvl == 2 )
size = 16;
else if ( lvl == 3 )
size = 24;
for ( int i = 0; i < size; i++ ) {
for ( int j = 0; j < size; j++ ) {
if ( lvl == 1 )
L1[i][j] = 'X';
else if ( lvl == 2 )
L2[i][j] = 'X';
else if ( lvl == 3 )
L3[i][j] = 'X';
}
}
}
And you can follow the same pattern above for print grid.
Then when you call the function you just pass what lvl you want to load and or print.
Related
so I am a relatively new to coding. So I have to make a Gomoku game for a project. Gomoku is like tic-tac-toe, but have to get five in a row. Have been given certain restrictions such as a board size of 6x6 to 15x15. The use of at least one class. I have chosen to use arrays. I have created PlayerOne as an algorithm which bases its moves on PlayerOne's last move, and moves one random block away from it in next move. The second algorithm is random. For when checking for a win, my horizontal and vertical checkers seem to work but both my diagonal checkers are giving problems, with them saying that 3 consecutive blocks in a row diagonally is 5 in a row. I created my checkers separately, filling in each row manually to test, and the diagonal checkers were fine there, but they're not fine in the whole code.
I'll share both the diagonal checkers up here, and then the whole code a little below so hopefully easier to read. Also quite a bit of it has cout statements as was trying to see where problems where earlier in the process. If anyone can see where the issue is occurring if could point out where, would be so appreciative.
int game::diagonalCheckerNegSlope(int arr[15][15], int size) {
int count1;
int count2;
int whoWon = 0;
for (int i = 0; i < size; i++) {
count1 = 0;
count2 = 0;
for (int j = 0; j < size; j++) {
if (arr[j][i] == 1) {
for (int d = 0; (i + d < size) && (j + d < size); d++)
if (arr[i + d][j + d] == 1) {
count1++;
if (count1 == 5) {
whoWon = 1;
}
} else {
count1 = 0;
}
}
if (arr[j][i] == 2) {
for (int d = 0; (i + d < size) && (j + d < size); d++)
if (arr[i + d][j + d] == 2) {
count2++;
if (count2 == 5) {
whoWon = 2;
}
} else {
count2 = 0;
}
}
}
}
if (whoWon != 1 && whoWon != 2) {
whoWon = 3;
}
return whoWon;
}
int game::diagonalCheckerPosSlope(int arr[15][15], int size) {
int count1;
int count2;
int whoWon = 0;
for (int i = 0; i < size; i++) {
count1 = 0;
count2 = 0;
for (int j = 0; j < size; j++) {
if (arr[i][j] == 1) {
for (int d = 0; (i + d < size) && (j - d < size); d++)
if (arr[i + d][j - d] == 1) {
count1++;
if (count1 == 5) {
whoWon = 1;
}
} else {
count1 = 0;
}
}
if (arr[i][j] == 2) {
for (int d = 0; (i + d < size) && (j - d < size); d++)
if (arr[i + d][j - d] == 2) {
count2++;
if (count2 == 5) {
whoWon = 2;
}
} else {
count2 = 0;
}
}
}
}
if (whoWon != 1 && whoWon != 2) {
whoWon = 3;
}
return whoWon;
}
int main code
#include <iostream>
#include <fstream>
#include "game.h"
#include <iomanip>
#include <ctime>
using namespace std;
int main() {
string inputSize = "input.txt";
int size =0;
srand(time(0));
int arr[15][15];
game Gomuko;
size = Gomuko.getSize(inputSize, arr);
if(size >=6 && size <=15){
Gomuko.initZero(arr, size);
// Gomuko.printArr(arr,size);
Gomuko.Play(arr, size);
Gomuko.printArr(arr,size);
}else{
cout << "Invalid input" << endl;
}
return 0;
}
The .h file of the class
#ifndef GAME_H_
#define GAME_H_
#include <string>
#include <ctime>
using namespace std;
class game {
public:
game();
int getSize(string inputFileName, int dataArray[15][15]);
void initZero(int arr[15][15], int size);
void printArr(int arr[15][15], int size);
void movePlayerOne(int arr[15][15], int size, int counter2);
void movePlayerTwo(int arr[15][15], int size);
void Play(int arr[15][15], int size);
int PlayerOneSurroundRow(int arr[15][15],int size);
int PlayerOneSurroundCol(int arr[15][15],int size);
int findFirstMoveRow(int arr[15][15], int size);
int findFirstMoveCol(int arr[15][15], int size);
bool isValid(int newRow, int newCol, int size);
int horizontalChecker(int arr[15][15], int size);
int verticalChecker(int arr[15][15], int size);
int diagonalCheckerNegSlope(int arr[15][15], int size);
int diagonalCheckerPosSlope(int arr[15][15], int size);
int WholeWinnerChecker(int arr[15][15], int size);
private:
int randRow(int size);
int randCol(int size);
};
#endif /* GAME_H_ */
And finally the .cpp file of the class
#include "game.h"
#include <iostream>
#include <fstream>
#include <iomanip>
#include <ctime>
using namespace std;
game::game() {
// TODO Auto-generated constructor stub
}
int game::getSize(string inputFileName, int dataArray[15][15]) {//make between 6 and 15.
ifstream inputData;
int size = 0;
int counter = 0;
inputData.open(inputFileName);
if (!inputData) {
cout << "Cannot open the file \"" << inputFileName << "\"" << endl;
}
else {
while (inputData >> size) {
counter++;
}
cout << "There are " << counter << " board sizes in the inputFile"
<< endl;
cout << "The size of the board is " << size << "x" << size << endl
<< endl;
}
return size;
}
void game::initZero(int arr[15][15], int size) {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
arr[i][j] = 0;
}
}
}
void game::printArr(int arr[15][15], int size) {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
cout << arr[i][j] << " ";
}
cout << endl;
}
cout << endl << endl;
}
int game::randRow(int size) {
int randNoRow = 0;
randNoRow = rand() % size;
return randNoRow;
}
int game::randCol(int size) {
int randNoCol = 0;
randNoCol = rand() % size;
return randNoCol;
}
int game::findFirstMoveRow(int arr[15][15], int size) {
int positionRow;
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
if (arr[i][j] == 1) {
positionRow = i;
}
}
}
return positionRow;
}
int game::findFirstMoveCol(int arr[15][15], int size) {
int positionCol;
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
if (arr[i][j] == 1) {
positionCol = j;
}
}
}
return positionCol;
}
int game::PlayerOneSurroundRow(int arr[15][15], int size) {
int positionRow = game::findFirstMoveRow(arr, size);
// cout << "The old row is " << positionRow << endl;
int oldRow = positionRow;
int randChoice = 0;
int newRow = 0;
randChoice = (rand() % 3);
// cout << "randChoice Row case: " << randChoice << endl;
switch (randChoice) {
case 0:
newRow = oldRow - 1;
break;
case 1:
newRow = oldRow;
break;
case 2:
newRow = oldRow + 1;
break;
}
// cout << "Test2" << endl << endl;
if (newRow > size - 1) {
// cout << "Row too big as Row is " << newRow << endl;
newRow = newRow - 1;
// cout << "Row is now " << newRow << endl;
}
if (newRow < 0) {
// cout << "Row too small as row is " << newRow << endl;
newRow = newRow + 1;
// cout << "Row is now " << newRow << endl;
}
// cout << "The new row is: " << newRow << endl;
return newRow;
}
int game::PlayerOneSurroundCol(int arr[15][15], int size) {
int positionCol = findFirstMoveCol(arr, size);
// cout << "The old col is " << positionCol << endl;
int oldCol = positionCol;
int randChoice = 0;
int newCol = 0;
randChoice = (rand() % 3);
cout << "randChoice Col case: " << randChoice << endl;
switch (randChoice) {
case 0:
newCol = oldCol - 1;
break;
case 1:
newCol = oldCol;
break;
case 2:
newCol = oldCol + 1;
break;
}
// cout << "Test2" << endl << endl;
if (newCol > size - 1) {
// cout << "Col too big as is " << newCol << endl;
newCol = newCol - 1;
// cout << "Col is now " << newCol << endl;
}
if (newCol < 0) {
// cout << "Col too small as is " << newCol << endl;
newCol = newCol + 1;
// cout << "Col is now " << newCol << endl;
}
// cout << "The new col is: " << newCol << endl;
return newCol;
}
bool game::isValid(int newRow, int newCol, int size) {
bool valid = false;
if (((newRow < size) && (newCol < size))
&& ((newRow >= 0) && (newCol >= 0))) {
valid = true;
}
return valid;
}
void game::movePlayerOne(int arr[15][15], int size, int counter2) {
int newRow = 0;
int newCol = 0;
int oldRow = 0;
int oldCol = 0;
int count3 = 0;
if (counter2 == 0) {
oldRow = randRow(size);
oldCol = randCol(size);
arr[oldRow][oldCol] = 1;
// cout << "Test1" << endl << endl << endl;
counter2++;
}
else {
// cout << "Test 3" << endl;
newRow = game::PlayerOneSurroundRow(arr, size);
newCol = game::PlayerOneSurroundCol(arr, size);
if (arr[newRow][newCol] == 0 && isValid(newRow, newCol, size)) {
arr[newRow][newCol] = 1;
// cout << "Test4" << endl;
// cout << "randNoRow = " << newRow << endl;
// cout << "randNoCol = " << newCol << endl;
oldRow = newRow;
oldCol = newCol;
}
else if ((arr[newRow][newCol] == 1) || (arr[newRow][newCol] == 2)
|| (newRow > size) || (newCol > size) || (newRow < 0)
|| (newCol < 0)) {
cout
<< "There has been a match, or even out of bounds, going again. "
<< endl << endl;
while ((arr[newRow][newCol] == 1) || (arr[newRow][newCol] == 2)) {
// cout << "Test5" << endl;
newRow = game::PlayerOneSurroundRow(arr, size);
newCol = game::PlayerOneSurroundCol(arr, size);
// cout << "randNoRow = " << newRow << endl;
// cout << "randNoCol = " << newCol << endl;
count3++;
if ((arr[newRow][newCol] != 1 && arr[newRow][newCol] != 2)
&& isValid(newRow, newCol, size)) {
arr[newRow][newCol] = 1;
// cout << "Test6" << endl;
//
// cout << "randNoRow = " << newRow << endl;
// cout << "randNoCol = " << newCol << endl;
oldRow = newRow;
oldCol = newCol;
break;
}
if (count3++ > 3) {
// cout << "Test 7" << endl;
// newRow = randRow(size);
// newCol = randCol(size);
while (arr[newRow][newCol] == 1 || arr[newRow][newCol] == 2) {
newRow = randRow(size);
newCol = randCol(size);
// cout << "Test 8" << endl;
// cout << "randNoRow = " << newRow << endl;
// cout << "randNoCol = " << newCol << endl;
if (arr[newRow][newCol] == 0) {
arr[newRow][newCol] = 1;
// cout << "Test 9" << endl;
// cout << "randNoRow = " << newRow << endl;
// cout << "randNoCol = " << newCol << endl;
oldRow = newRow;
oldCol = newCol;
break;
}
}
break;
}
}
}
}
}
void game::movePlayerTwo(int arr[15][15], int size) {
// cout << "Test" << endl;
int randNoRow = 0;
int randNoCol = 0;
randNoRow = randRow(size);
cout << "randNoRow = " << randNoRow << endl;
randNoCol = randCol(size);
cout << "randNoCol = " << randNoCol << endl;
cout << endl;
if ((arr[randNoRow][randNoCol] == 1) || (arr[randNoRow][randNoCol] == 2)) {
//cout << "There has been a match, going again. " << endl << endl;
while ((arr[randNoRow][randNoCol] == 1)
|| (arr[randNoRow][randNoCol] == 2)) {
int randNoRow = 0;
int randNoCol = 0;
randNoRow = randRow(size);
//cout << "randNoRow = " << randNoRow << endl;
randNoCol = randCol(size);
//cout << "randNoCol = " << randNoCol << endl;
//cout << endl;
if (arr[randNoRow][randNoCol] == 0) {
arr[randNoRow][randNoCol] = 2;
break;
}
}
} else {
arr[randNoRow][randNoCol] = 2;
}
}
int game::horizontalChecker(int arr[15][15], int size) {
int count1;
int count2;
int whoWon = 0;
for (int i = 0; i < size; i++) {
count1 = 0;
count2 = 0;
for (int j = 0; j < size; j++) {
if (arr[i][j] == 1) {
count1++;
if (count1 == 5) {
whoWon = 1;
}
} else {
count1 = 0;
}
if (arr[j][i] == 2) {
count2++;
if (count2 == 5) {
whoWon = 2;
}
} else {
count2 = 0;
}
}
if (whoWon != 1 && whoWon != 2) {
whoWon = 3;
}
}
return whoWon;
}
int game::verticalChecker(int arr[15][15], int size) {
int count1;
int count2;
int whoWon = 0;
for (int i = 0; i < size; i++) {
count1 = 0;
count2 = 0;
for (int j = 0; j < size; j++) {
if (arr[j][i] == 1) {
count1++;
if (count1 == 5) {
whoWon = 1;
}
} else {
count1 = 0;
}
if (arr[j][i] == 2) {
count2++;
if (count2 == 5) {
whoWon = 2;
}
} else {
count2 = 0;
}
}
if (whoWon != 1 && whoWon != 2) {
whoWon = 3;
}
}
return whoWon;
}
int game::diagonalCheckerNegSlope(int arr[15][15], int size) {
int count1;
int count2;
int whoWon = 0;
for (int i = 0; i < size; i++) {
count1 = 0;
count2 = 0;
for (int j = 0; j < size; j++) {
if (arr[j][i] == 1) {
for (int d = 0; (i + d < size) && (j + d < size); d++)
if (arr[i + d][j + d] == 1) {
count1++;
if (count1 == 5) {
whoWon = 1;
}
} else {
count1 = 0;
}
}
if (arr[j][i] == 2) {
for (int d = 0; (i + d < size) && (j + d < size); d++)
if (arr[i + d][j + d] == 2) {
count2++;
if (count2 == 5) {
whoWon = 2;
}
} else {
count2 = 0;
}
}
}
}
if (whoWon != 1 && whoWon != 2) {
whoWon = 3;
}
return whoWon;
}
int game::diagonalCheckerPosSlope(int arr[15][15], int size) {
int count1;
int count2;
int whoWon = 0;
for (int i = 0; i < size; i++) {
count1 = 0;
count2 = 0;
for (int j = 0; j < size; j++) {
if (arr[i][j] == 1) {
for (int d = 0; (i + d < size) && (j - d < size); d++)
if (arr[i + d][j - d] == 1) {
count1++;
if (count1 == 5) {
whoWon = 1;
}
} else {
count1 = 0;
}
}
if (arr[i][j] == 2) {
for (int d = 0; (i + d < size) && (j - d < size); d++)
if (arr[i + d][j - d] == 2) {
count2++;
if (count2 == 5) {
whoWon = 2;
}
} else {
count2 = 0;
}
}
}
}
if (whoWon != 1 && whoWon != 2) {
whoWon = 3;
}
return whoWon;
}
int game::WholeWinnerChecker(int arr[15][15], int size) {
int finalWinner = 0;
int outcome1 = horizontalChecker(arr, size);
if ((outcome1 == 1) || (outcome1 == 2)) {
finalWinner = outcome1;
cout << "Horizontal Win" << endl;
}
int outcome2 = verticalChecker(arr, size);
if ((outcome2 == 1) || (outcome2 == 2)) {
finalWinner = outcome2;
cout << "Vertical Win" << endl;
}
int outcome3 = diagonalCheckerPosSlope(arr, size);
if ((outcome3 == 1) || (outcome3 == 2)) {
finalWinner = outcome3;
cout << "Diag Pos Win" << endl;
}
int outcome4 = diagonalCheckerNegSlope(arr, size);
if ((outcome4 == 1) || (outcome4 == 2)) {
finalWinner = outcome4;
cout << "Diag Neg Win" << endl;
}
else if ((finalWinner != 1) && (finalWinner != 2)) {
finalWinner = 3;
}
return finalWinner;
}
void game::Play(int arr[15][15], int size) {
int counter = 0;
int Winner=0;
int boardFull= size*size;
while(((Winner != 1)&&(Winner != 2))&& (counter < boardFull)){
cout << "This is turn " << counter + 1 << endl;
if (counter % 2 == 0) {
cout << "PlayerOne: " << endl;
game::movePlayerOne(arr, size, counter);
if (counter >= 4) {
Winner = game::WholeWinnerChecker(arr, size);
if(Winner ==1){
cout << endl <<"======================" << endl;
cout << "Winner = " << Winner << endl;
cout <<"======================" << endl;
}
}
}
if (counter % 2 == 1) {
cout << "PlayerTwo:" << endl;
game::movePlayerTwo(arr, size);
if (counter >= 5) {
Winner = game::WholeWinnerChecker(arr, size);
if (Winner == 2) {
cout << endl << "======================" << endl;
cout << "Winner = " << Winner << endl;
cout << "======================" << endl;
}
}
}
if(counter == boardFull){
cout << "Draw" << endl;
}
counter++;
}
}
I have also been using an input of
6
The problem could be that you don't set count1 and count2 inside the j-loop, but rather count on the variable being reset in the else statement. But if your d-loop ends before the else statement is executed ((i + d < size) && (j - d < size) becomes false "prematurely") then the counter is not reset. Solution: move the zero-initialization to inside the j-loop.
Some improvements:
If lots of methods have the same parameter (such as int arr[15][15] and int size) then this could be the sign that these parameters should become members of the class.
It is possible to have only one checker function. Parameters of this function would be the direction of the search (int deltaX, int deltaY), and also the value that is being checked (1 or 2). Delta-values for all 8 directions are these:
(1, 0), (1, 1), (0, 1), (-1, 1), (-1, 0), (-1, 1), (0, 1), (1, 1)
So, in your d-loop you would not add or subtract d to and from i and j, but you would always add deltaX to i, and deltaY to j.
Also, a bit advanced, but also fun. It is possible to arrange the code in such a way that you can have three types of games: human vs human, human vs computer, computer vs computer. You just for instance assign object of a class HumanPlayer to player 1 and object of a class ComputerPlayer to player 2. This would enable you to pick who plays first, and also have several algorithms battling it out. Both classes would have to be derived from the base class Player with some known methods (like 'move'), and some GameCoordinator would in a loop call this method 'move' on both objects, update the game state, and check if game has ended.
I have changed a Tic-Tac-Toe program from using a normal 3x3 grid to a grid-size chosen by the user (between 3 and 9). I am using a global constant 'SIZE' to hold the value the user chooses. My issue is adapting my winMove(); function so that it adjusts to check for the winning move based on the current board size chosen by the user(SIZE). I have tried different loops but can't get it to work. Right now it will only work with a 3x3 board.
I am still learning c++ and I have been stuck on this for a few days so I'm hoping a friendly person can help. This is my full program so far, hope it's not too much of a mess!
#include <iostream>
using namespace std;
struct TicTacToe
{
char **board;
};
void makeBoard(TicTacToe&);
void deallocBoard(TicTacToe&);
void printBoard(TicTacToe);
bool isDraw(TicTacToe);
void convertInput(char, char, int&, int&);
char winMove(TicTacToe, int, int);
bool validateSIZE(int);
int SIZE = 1;
int main(){
while(SIZE < 3 || SIZE > 9)
{
cout << "Enter number between 3 and 9 for the length of board.\n";
cout << "Example: 4 will make a board with 4 rows and 4 columns: ";
cin >> SIZE;
validateSIZE(SIZE);
}
TicTacToe game;
makeBoard(game);
char winner = 0;
char turn = 'X';
char rowIn, colIn;
int row, column;
while(!winner && !isDraw(game))
{
printBoard(game);
cout << "\nPlayer " << turn << "'s move (input format: a1): ";
cin >> rowIn >> colIn;
convertInput(rowIn, colIn, row, column);
if (game.board[row][column]==' ')
{
game.board[row][column] = turn;
if (turn == 'X')
{turn = 'O';}
else
{turn = 'X';}
winner = winMove(game, row, column);
}
else
cout << "Taken, try again!\n";
}
printBoard(game);
if (winner == 'X' || winner == 'O')
{cout << " Congrats, the winner is " << winner << '.' << endl;}
else
{cout << " Game ends in a draw." << endl;}
cout << endl << "Game Over!" << endl << endl;
deallocBoard(game);
return 0;
}
// Need help with this function.
char winMove(TicTacToe gameIn, int i, int j)
{
//row win
if (gameIn.board[i][0]==gameIn.board[i][1] &&
gameIn.board[i][0]==gameIn.board[i][2])
{
return gameIn.board[i][j];
}
//column win
if (gameIn.board[0][j]==gameIn.board[1][j] &&
gameIn.board[0][j]==gameIn.board[2][j])
{
return gameIn.board[i][j];
}
//left diagonal win
if (gameIn.board[0][0] != ' ' &&
gameIn.board[0][0] == gameIn.board[1][1] &&
gameIn.board[0][0] == gameIn.board[2][2])
{
return gameIn.board[i][j];
}
//right diagonal win
if (gameIn.board[0][2] != ' ' &&
gameIn.board[0][2] == gameIn.board[1][1] &&
gameIn.board[0][2] == gameIn.board[2][0])
{
return gameIn.board[i][j];
}
return 0;
}
bool validateSIZE(int SIZE)
{
if(SIZE < 3 || SIZE > 9)
{
cout << "\n\nNumber must be between 3 and 9!\nTry again!\nPlease ";
return false;
}
return true;
};
void makeBoard(TicTacToe& gameIn)
{
gameIn.board = new char*[SIZE];
for(int i = 0; i < SIZE; i++)
{gameIn.board[i] = new char[SIZE];}
for(int j =0; j < SIZE; j++)
for(int k = 0; k < SIZE; k++)
{gameIn.board[j][k] = ' ';}
}
void deallocBoard(TicTacToe& gameIn)
{
for(int i = 0; i < SIZE; i++)
delete [] gameIn.board[i];
delete [] gameIn.board;
gameIn.board = NULL;
}
void printBoard(TicTacToe gameIn)
{
int temp = 1;
cout << " ";
while(temp < SIZE + 1)
{
cout << temp << " ";
temp++;
}
temp = 1;
cout << endl;
for(int i = 0; i < SIZE; i++)
{
cout << char(i + 'a') << '|';
for(int j = 0; j < SIZE; j++)
{
cout << gameIn.board[i][j] << '|';
}
cout << endl;
}
}
bool isDraw(TicTacToe gameIn)
{
bool full = true;
for(int i = 0; full && i < SIZE; i++)
for(int j = 0; full && j < SIZE; j++)
full = gameIn.board[i][j] != ' ';
return full;
}
void convertInput(char rowIn, char colIn, int& row, int& column)
{
row = toupper(rowIn) - 'A';
column = colIn - '1';
}
You can easily use 2 for loops to iterate every starting point and its direction to preform victory checking. Something that would look like this:
// hor ver diagonals
// dx[4] = {1, 0, 1, 1};
// dy[4] = {0, 1, 1, -1};
// check horizontal win
for(int i = 0; i < SIZE; ++i)
{
bool win = true;
for(int j = 1; j < SIZE; ++j)
{
if(gameIn.board[j][i] != gameIn.board[j - 1][i])
{
win = false;
break;
}
}
if(win == true){return ;}
}
// check vertical win
.
.
.
// check diagonal 1 win
for(int i = 1; i < SIZE; ++i)
{
if(gameIn.board[i][i] != gameIn.board[i - 1][i - 1])
break;
if(i == SIZE - 1)return ;
}
// check diagonal 2 win
for(int i = 1; i < SIZE; ++i)
{
if(gameIn.board[i][SIZE - i - 1] != gameIn.board[i - 1][SIZE - i])
break;
if(i == SIZE - 1)return ;
}
I'll leave the vertical win for you.
i'm trying to make a unbeatable tic tac toe for a side project and i can't make it right (i can actually beat it ironically).
It's actually a implementation of the MiniMax algorithm; i came with this code
#include <iostream>
#include <string>
using namespace std;
struct Move
{
int line, columns;
};
//Return the number of remainings turn based on the number of lest boxes
int remainingsTurns(char grid[3][3])
{
int remainingTurn = 0;
for (int k = 0; k < 3; k++)
{
for (int i = 0; i < 3; i++)
{
if (grid[k][i] == ' ')
{
remainingTurn++;
}
}
}
return remainingTurn;
}
//Print the grid on screen
void printGrid(char grid[3][3])
{
for (int k = 0; k < 3; k++)
{
for (int i = 0; i < 3; i++)
{
cout << "| " << grid[k][i] << " ";
}
cout << "|" << endl;
}
}
//Give a value to the board
int evaluateBoard(char grid[3][3])
{
//Check the board for lines
for (int k = 0; k < 3; k++)
{
if (grid[k][0] == grid[k][1] && grid[k][1] == grid[k][2])
{
if (grid[k][0] == 'x')
{
return +10;
}
else if (grid[k][0] == 'o')
{
return -10;
}
}
}
//Check the board for columns
for (int k = 0; k < 3; k++)
{
if (grid[0][k] == grid[1][k] && grid[1][k] == grid[2][k])
{
if (grid[0][k] == 'x')
{
return +10;
}
else if (grid[0][k] == 'o')
{
return -10;
}
}
}
//Check the board for diagonals
if (grid[0][0] == grid[1][1] && grid[0][0] == grid[2][2])
{
if (grid[0][0] == 'x')
{
return +10;
}
else if (grid[0][0] == 'o')
{
return -10;
}
}
if (grid[0][2] == grid[1][1] && grid[0][2] == grid[2][0])
{
if (grid[0][0] == 'x')
{
return +10;
}
else if (grid[0][0] == 'o')
{
return -10;
}
}
//if no ictory return 0
return 0;
}
// MiniMax algorithm
int miniMax(char grid[3][3], int turn, bool maxMove)
{
int score = evaluateBoard(grid);
if (score == 10)
{
return score;
}
if (score == -10)
{
return score;
}
//Check if the game is a tie
if (remainingsTurns(grid) == 0)
{
return 0;
}
if (maxMove)
{
int best = -1000;
for (int k = 0; k < 3; k++)
{
for (int i = 0; i < 3; i++)
{
if (grid[k][i] == ' ')
{
grid[k][i] = 'x';
best = max(best, miniMax(grid, turn + 1, !maxMove));
grid[k][i] = ' ';
}
}
}
return best;
}
else
{
int best = 1000;
for (int k = 0; k < 3; k++)
{
for (int i = 0; i < 3; i++)
{
if (grid[k][i] == ' ')
{
grid[k][i] = 'o';
best = min(best, miniMax(grid, turn + 1, !maxMove));
grid[k][i] = ' ';
}
}
}
return best;
}
}
Move playerMov(char grid[3][3])
{
Move playerMove;
int input = -1;
cout << "Enter the column you want to play (1, 2 or 3)" << endl;
cin >> input;
if (input == 1 || input == 2 || input == 3)
{
playerMove.columns = input-1;
input = -1;
}
else
{
cout << "Error, enter a valid number!" << endl;
playerMov(grid);
}
cout << "Enter the line you want to play (1, 2 or 3)" << endl;
cin >> input;
if (input == 1 || input == 2 || input == 3)
{
playerMove.line = input-1;
input = -1;
}
else
{
cout << "Error, enter a valid number!" << endl;
playerMov(grid);
}
return playerMove;
}
//return the best move using the MiniMax
Move findMove(char grid[3][3])
{
int best = -1000;
Move move;
move.line = -1;
move.columns = -1;
//Check all move to find if this move is the best possible move
for (int k = 0; k < 3; k++)
{
for (int i = 0; i < 3; i++)
{
if (grid[k][i] == ' ')
{
grid[k][i] = 'x';
int moveValue = miniMax(grid, 0, false);
grid[k][i] = ' ';
if (moveValue > best)
{
move.line = k;
move.columns = i;
}
}
}
}
return move;
}
int main()
{
char grid[3][3];
int turn = 0;
Move playerMove, algoMove;
for (int k = 0; k < 3; k++)
{
for (int i = 0; i < 3; i++)
{
grid[k][i] = ' ';
}
}
cout << "Welcome to the unbeatable Tic Tac Toe !" << endl;
do
{
printGrid(grid);
playerMove = playerMov(grid);
grid[playerMove.line][playerMove.columns] = 'o';
Move computerMove = findMove(grid);
grid[computerMove.line][computerMove.columns] = 'x';
} while (remainingsTurns(grid) > 0);
cout << endl;
}
but the movements of the algorithm doesn't seems right, it always choose the bottom right corner and i don't understand why...
This implementation is largely inspired by this article from Geek for Geek where i tried to steal the algorithm but i can't get it right to make it fit for single player.
What do i miss?
There are multiple bugs in your code:
You are checking the value of grid[0][0] in grid[0][2] == grid[1][1] && grid[0][2] == grid[2][0] case of the function evaluateBoard. It should be grid[0][2].
playerMov(grid); in the function playerMov should be return playerMov(grid);. Otherwise, the re-entered "correct" values will be dropped and (partly) uninitalized playerMov will be returned.
You should update best to moveValue when moveValue > best in the function findMove. (this should be the cause of the issue on your question)
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I decided to make the 2048 game. It is a very popular game for beginners.
The game is almost complete now but there's this error because of which my game keeps getting closed again and again as soon as I make my first move. I have tested a lot thoroughly and couldn't trace the error(s). I am new to programming.
#include<iostream>
#include<conio.h>
#include<ctime>
#include<string>
#include<cstdlib>
#include<fstream>
#include<Windows.h>
using namespace std;
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
const int limit = 4;
int board[limit][limit] = {};
int score = 0;
string name;
int highestScore;
void newGame();
void displayBoard();
bool gameOver();
int generateNum(); //generate random 2 or 4
void moveInDirection(int);
void generateNumInBoard();
int main()
{
int currentDirection;
char command, choice;
char direction[128];
string currentName;
direction['s'] = 0;
direction['w'] = 1;
direction['a'] = 3;
direction['d'] = 2;
ifstream inFile;
inFile.open("Score.txt");
inFile >> name >> highestScore;
inFile.close();
ofstream outFile;
outFile.open("Score.txt");
cout << "Please enter your name = ";
getline(cin, currentName);
newGame();
while (true)
{
system("CLS");
displayBoard();
cout << "\nEnter what you want to do = ";
command = _getche();
if (command == 'n')
{
newGame();
}
else if (command == 'e')
{
break;
}
else
{
currentDirection = direction[command];
moveInDirection(currentDirection);
}
if (gameOver())
{
if (score > highestScore)
{
outFile << currentName << " " << score;
}
do {
system("CLS");
cout << "YOU HAVE LOST :("
<< "Your score was " << score << endl
<< "Do you want to play again ( New game (n) / Exit (e) ) = ";
command = _getche();
} while (command != 'n' && command != 'e');
if (command == 'e')
{
exit(1);
}
}
}
return 0;
}
void newGame()
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
board[i][j] = 0;
}
}
board[0][0] = 2;
}
void displayBoard()
{
SetConsoleTextAttribute(hConsole, 9);
cout << "\n2048 THE GAME\n\n a = left , s = down , w = up , d = right , n = newgame , e = exit\n\n If all boxes get filled you lose\n\nBest player = " << name << " Best score = " << highestScore << "\n\n Your Score = " << score << "\n\n" << endl;
for (int i = 0; i < limit; i++)
{
cout << "\t\t|";
for (int j = 0; j < limit; j++)
{
if (board[i][j] == 0)
{
cout << " - |";
}
else
{
cout << " " << board[i][j] << " |";
}
}
cout << endl;
}
}
void moveInDirection(int currentDirection)
{
int count = 0;
bool flag = false;
if (currentDirection == 2)
{
while (count != 4)
{
for (int i = 0; i < limit; i++)
{
for (int j = limit - 1; j > 0; j--)
{
if ((board[i][j] == board[i][j - 1]) && board[i][j] != 0 && board[i][j - 1] != 0)
{
board[i][j] += board[i][j - 1];
board[i][j - 1] = 0;
score += board[i][j];
}
else if ((board[i][j] == 0) && (board[i][j - 1] != 0))
{
flag = true;
swap(board[i][j], board[i][j - 1]);
}
}
}
count++;
}
if (flag)
{
generateNumInBoard();
}
}
else if (currentDirection == 3)
{
while (count != 4)
{
for (int i = 0; i < limit; i++)
{
for (int j = 0; j < limit - 1; j++)
{
if ((board[i][j] == board[i][j + 1]) && board[i][j] != 0 && board[i][j + 1] != 0)
{
board[i][j] += board[i][j + 1];
board[i][j + 1] = 0;
score += board[i][j];
}
else if ((board[i][j] == 0) && (board[i][j + 1] != 0))
{
flag = true;
swap(board[i][j], board[i][j + 1]);
}
}
}
count++;
}
if (flag)
{
generateNumInBoard();
}
}
else if (currentDirection == 1)
{
while (count != 4)
{
for (int i = 0; i < limit - 1; i++)
{
for (int j = 0; j < limit; j++)
{
if ((board[i][j] == board[i + 1][j]) && board[i][j] != 0 && board[i + 1][j] != 0)
{
board[i][j] += board[i + 1][j];
board[i + 1][j] = 0;
score += board[i][j];
}
else if ((board[i][j] == 0) && (board[i + 1][j] != 0))
{
flag = true;
swap(board[i][j], board[i + 1][j]);
}
}
}
count++;
}
if (flag)
{
generateNumInBoard();
}
}
else if (currentDirection == 0)
{
while (count != 4)
{
for (int i = limit - 1; i >= 0; i--)
{
for (int j = 0; j < limit; j++)
{
if ((board[i][j] == board[i - 1][j]) && board[i][j] != 0 && board[i - 1][j] != 0)
{
board[i][j] += board[i - 1][j];
board[i - 1][j] = 0;
score += board[i][j];
}
else if ((board[i][j] == 0) && (board[i - 1][j] != 0))
{
flag = true;
swap(board[i][j], board[i - 1][j]);
}
}
}
count++;
}
if (flag)
{
generateNumInBoard();
}
}
}
int generateNum()
{
srand(time(NULL));
int randomNum = rand() % 4;
if (randomNum <= 2)
{
return 2;
}
else
{
return 4;
}
}
void generateNumInBoard()
{
bool flag = true;
for (int i = 0; i < limit; i++)
{
for (int j = 0; j < limit; j++)
{
if (board[i][j] == 0)
{
board[i][j] = generateNum();
flag = false;
break;
}
}
if (flag == false)
{
break;
}
}
}
bool gameOver()
{
for (int i = 0; i < limit; i++)
{
for (int j = 0; j < limit; j++)
{
if (board[i][j] == 0)
{
return true;
}
}
}
return false;
}
You made a small blunder at the fucntion gameOver() as you are making the game end if the compiler finds any 0 in the 2D array and you are display the zero as - in front end , You just need to make he false part true and viceversa.The game will work AOK :-)
bool gameOver()
{
for (int i = 0; i < limit; i++)
{
for (int j = 0; j < limit; j++)
{
if (board[i][j] == 0)
{
return false; //You need to make this false to not end game as soon as it starts
}
}
}
return true; //You need to make this true as the end condition
}
Recently, I created a text-based RPG in C++ and am now trying to incorporate a simple pathfinding algorithm. I have tested the algorithm itself and found that it works, however the while loop condition in the function started being ignored when I tried to incorporate it into the RPG. Here's my code:
int Strategy::path(char (&map)[25][100], int current_y, int current_x, int Target_x, int Target_y)
{
int i;
int n;
bool up=false;
bool down=false;
bool left=false;
bool right=false;
while (map[Target_y-1][Target_x]!='_'&&map[Target_y-1][Target_x]!='-'&&map[Target_y-1][Target_x]!='='&&map[Target_y+1][Target_x]!='_'&&map[Target_y+1][Target_x]!='-'&&map[Target_y+1][Target_x]!='='&&map[Target_y][Target_x-1]!='_'&&map[Target_y][Target_x-1]!='-'&&map[Target_y][Target_x-1]!='='&&map[Target_y][Target_x+1]!='_'&&map[Target_y][Target_x+1]!='-'&&map[Target_y][Target_x+1]!='=')
{
bool f=false;
int m=0;
system("cls");
printf("Time left: %i\n", time);
int x;
int y;
using namespace std;
for (y = 0; y<25; y++)
{
for (x = 0; x<100; x++)
{
cout << map[y][x];
}
printf("\n");
}
if (current_y > 0 && map[current_y - 1][current_x] ==' ')
{
map[current_y - 1][current_x] = '-';
}
if (current_y < 25 && map[current_y + 1][current_x] ==' ')
{
map[current_y + 1][current_x] = '-';
}
if (current_x > 0 && map[current_y][current_x - 1] ==' ')
{
map[current_y][current_x - 1] = '-';
}
if (current_x<100 && map[current_y][current_x + 1] ==' ')
{
map[current_y][current_x + 1] = '-';
}
map[current_y][current_x] = '=';
for (i = 0; i < 25; i++)
{
for (n = 0; n < 100; n++)
{
if (map[i][n] == '_')
{
current_y = i;
current_x = n;
f=true;
break;
}
}
if (f==true)
{
break;
}
}
for (i = 0; i < 25; i++)
{
for (n = 0; n < 100; n++)
{
if (map[i][n] == '-')
{
map[i][n] = '_';
m++;
}
}
}
if (m==0)
{
return 4;
}
}
bool r=false;
while (true)
{
int d=rand()%4;
if (map[Target_y + 1][Target_x] == '_' && d==0)
{
for (i = 0; i < 25; i++)
{
for (n = 0; n < 100; n++)
{
if (map[i][n] == '-'||map[i][n]=='_'||map[i][n]=='=')
{
map[i][n] = ' ';
}
}
}
return 0;
}
else if (map[Target_y - 1][Target_x] == '_' && d==1)
{
for (i = 0; i < 25; i++)
{
for (n = 0; n < 100; n++)
{
if (map[i][n] == '-'||map[i][n]=='_'||map[i][n]=='=')
{
map[i][n] = ' ';
}
}
}
return 1;
}
else if (map[Target_y][Target_x+1] == '_' && d==2)
{
for (i = 0; i < 25; i++)
{
for (n = 0; n < 100; n++)
{
if (map[i][n] == '-'||map[i][n]=='_'||map[i][n]=='=')
{
map[i][n] = ' ';
}
}
}
return 2;
}
else if (map[Target_y][Target_x-1] == '_' && d==3)
{
for (i = 0; i < 25; i++)
{
for (n = 0; n < 100; n++)
{
if (map[i][n] == '-'||map[i][n]=='_'||map[i][n]=='=')
{
map[i][n] = ' ';
}
}
}
return 3;
}
}
}
As all the other comments pointed out, you definitely should use a function in your while-condition. This really is an unreadable expression.
Maybe this will help you:
bool conditionValid(char (&map)[25][100], int target_x, int target_y)
{
char c='0';
for(int i = 0; i<4; ++i)
{
switch(i)
{
case 0: c = map[target_y-1][target_x]; break; //check the first character
case 1: c = map[target_y+1][target_x]; break; //check the second character
case 2: c = map[target_y][target_x-1]; break; //check the third character
case 3: c = map[target_y][target_x+1]; break; //check the forth character
}
switch(c)
{
case '_': std::cout << "aborting ... c" << i << "= " << c << std::endl; return false;
case '-': std::cout << "aborting ... c" << i << "= " << c << std::endl; return false;
case '=': std::cout << "aborting ... c" << i << "= " << c << std::endl; return false;
}
}
return true;
}
int Strategy::path(char (&map)[25][100], int current_y, int current_x, int Target_x, int Target_y)
{
int i;
int n;
bool up=false;
bool down=false;
bool left=false;
bool right=false;
while (conditionValid(map, Target_x, Target_y))
{
...
}
}
As soon as you understand, why your loop aborted, you can remove the std::cout's