We have to make Connect4 in C++ as our last assignment for one of my classes. As of right now I have a fairly functional version. I had a really promising idea for a recursive solution for checking if the game is over but the issue is it only checks starting from the token it is starting at. For example if the most recently placed token has 3 of the same kind in any direction that is valid it works, but if it has 2 in one direction and 1 the opposite way it doesn't work. Does anyone have any ideas for how I could edit my function to incorporate the 2nd situation or should I just scrap it and rewrite it differently. Here is my code.
//TODO implement checking spots other than start
#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
int runGame(int, int, int);
void promptUser(int**, int[], int, int, int);
void genRanMove(int**, int[], int, int);
bool checkGameOver(int**, int, int, int, int, int, int, int, int);
void showBoard(int**, int, int);
void playAgain();
using namespace std;
int main(int argc, char *argv[]) {
if (argc < 4) {
cerr << "Not enough input, syntax is 1/2 players, # columns, and # of rows" << endl;
exit(0);
}
if (argc == 4 && (argv[1][0] == '1' || argv[1][0] == '2') && (argv[2][0] >= '1' && argv[2][0] <= '9') && (argv[3][0] >= '1' && argv[3][0] <= '9')) {
cout << "\n\nYou have chosen to play Connect 4 in " << argv[1][0] << " player mode and with " << argv[2][0] << " columns and with " << argv[3][0] << " rows.\n" << endl;
}
else {
cerr << "Improper syntax, syntax is 1/2 players, # columns, and # of rows" << endl;
exit(0);
}
cout << "Welcome to Connect 4, each player will take a turn choosing a column to select, a metaphorical coin will fall down to the highest availible row.\nThe game ends when a player has gotten 4 of their coins in a row horizontally, vertically, or diagonally.\nPlayer 1 will always use 1's and Player 2 will always be 2's.\nThe AI will always be 3's.\nEmpty slots will be shown as 0's.\n\n" << endl;
srand(time(NULL));
int winner = runGame(argv[1][0] - '0', argv[2][0] - '0', argv[3][0] - '0');
if (winner == 1 || winner == 2) {
cout << "Winner was player # " << winner << endl;
}
else if (winner == 3)
cout << "You let the AI win :(" << endl;
else if (winner == -1)
cout << "The game ended in a tie" << endl;
playAgain();
}
/******************************************************
** Function: runGame
** Description: runsGame
** Parameters: gameMode columns rows
** Pre-Conditions:
** Post-Conditions: returns winning player, 1 or 2 for player # and 3 for ai
******************************************************/
int runGame(int gameMode, int columns, int rows) { //returns which player won
int holdPoints[2] = { 0, 0 };
switch (gameMode) {
case 1:
cout << "You have chosen to play against an AI" << endl;
break;
case 2:
cout << "You have chosen to play with another human player" << endl;
break;
}
int** board = new int*[columns];
for (int i = 0; i< columns; i++) {
board[i] = new int[rows];
}
for (int i = 0; i< columns; i++) {
for (int j = 0; j< rows; j++) {
board[i][j] = 0;
}
}
for (int i = 0; i< rows*columns/2; i++) { //check for number of possible moves in order to have a tie
showBoard(board, rows, columns);
promptUser(board, holdPoints, rows, columns, 1);
if (checkGameOver(board, holdPoints[0], holdPoints[1], 0, 1, 0, 1, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], 1, 1, 0, 1, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], 1, 0, 0, 1, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], 0, -1, 0, 1, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], -1, -1, 0, 1, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], -1, 0, 0, 1, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], 1, -1, 0, 1, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], -1, 1, 0, 1, rows, columns)) {
return 1;
}
cout << "\n\n";
showBoard(board, rows, columns);
if (gameMode == 2) {
promptUser(board, holdPoints, rows, columns, 2);
if (checkGameOver(board, holdPoints[0], holdPoints[1], 0, 1, 0, 2, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], 1, 1, 0, 2, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], 1, 0, 0, 2, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], 0, -1, 0, 2, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], -1, -1, 0, 2, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], -1, 0, 0, 2, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], 1, -1, 0, 2, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], -1, 1, 0, 2, rows, columns)) {
return 2;
}
}
else if (gameMode == 1) {
genRanMove(board, holdPoints, rows, columns);
if (checkGameOver(board, holdPoints[0], holdPoints[1], 0, 1, 0, 3, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], 1, 1, 0, 3, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], 1, 0, 0, 3, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], 0, -1, 0, 3, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], -1, -1, 0, 3, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], -1, 0, 0, 3, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], 1, -1, 0, 3, rows, columns) || checkGameOver(board, holdPoints[0], holdPoints[1], -1, 1, 0, 3, rows, columns)) {
return 3;
}
}
//showBoard(board, rows, columns);
cout << "\n\n";
}
for (int i = 0; i < columns; i++) {
delete[] board[i];
}
delete[] board;
return -1; //signifies a tie
}
/******************************************************
** Function: promptUser
** Description: gets input from user for their turn, stores the resting place of their token in points
** Parameters: board and array to hold point,num columns
** Pre-Conditions:
** Post-Conditions:
******************************************************/
void promptUser(int** board, int point[], int numRows, int numColumns, int playerNum) {
int col, lowZero;
lowZero = -1;
cout << "What column would you like to choose" << endl;
cin >> col;
if (col<0 || col > numColumns -1) {
cout << "The # you chose must be >=0 and <= " << numColumns-1 << endl;
promptUser(board, point, numRows, numColumns, playerNum);
}
//now need to find the lowest possible row in the given column that has a 0
for (int i = 0; i < numRows; i++) {
if (board[col][i] == 0)
lowZero = i;
}
if (lowZero != -1) {
board[col][lowZero] = playerNum;
cout << "Player " << playerNum << " dropped a token in column " << col << " that rested at row " << lowZero << endl;
point[0] = col;
point[1] = lowZero;
return;
}
else {
cout << "Column " << col << " was full, please pick a new one" << endl;
promptUser(board, point, numRows, numColumns, playerNum);
}
}
/******************************************************
** Function: genRanMove
** Description: gets random column from "ai", stores the resting place of their token in points
** Parameters: board and array to hold point
** Pre-Conditions:
** Post-Conditions:
******************************************************/
void genRanMove(int** board, int point[], int numRows, int numColumns) {
cout << "AI is finding a column" << endl;
int col = rand() % numColumns;
int lowZero = -1;
for (int i = 0; i < numRows; i++) {
if (board[col][i] == 0)
lowZero = i;
}
if (lowZero != -1) {
board[col][lowZero] = 3;
cout << "AI dropped a token in column " << col << " that rested at row " << lowZero << endl;
point[0] = col;
point[1] = lowZero;
return;
}
//didnt find a row that works
genRanMove(board, point, numRows, numColumns);
}
/******************************************************
** Function: showBoard
** Description: prints he current gameboard
** Parameters: the board, numrows and numcolumns
** Pre-Conditions:
** Post-Conditions:
******************************************************/
void showBoard(int** board, int numRows, int numColumns) {
for (int i = 0; i < numColumns; i++) {
for (int j = 0; j < numRows; j++) {
cout << board[j][i] << " ";
}
cout << endl;
}
}
/******************************************************
** Function: playAgain
** Description: gets info to play again
** Parameters: n/a
** Pre-Conditions:
** Post-Conditions:
******************************************************/
void playAgain() {
int again;
int mode, rows, columns;
cout << "Would you like to play again? Type 1 if so." << endl;
cin >> again;
if (again) {
cout << "What mode? 1 for 1 player and 2 for 2 player" << endl;
cin >> mode;
cout << "How many rows?" << endl;
cin >> rows;
cout << "How many columns?" << endl;
cin >> columns;
if ((mode<=0 || mode >2) || rows<= 0 || columns<= 0) {
cout << "Improper inputs. Mode must be 1/2 and rows and columns must both be >0" << endl;
playAgain();
}
else {
runGame(mode, columns, rows);
}
}
}
/******************************************************
** Function: checkGameOver
** Description: checks if game is over by recursively checking spots around original
** Parameters: board, curr col, curr row, change col, change row, total found, and what number it is looking for in the board
** Pre-Conditions:
** Post-Conditions:
******************************************************/
bool checkGameOver(int** board, int currCol, int currRow, int changeCol, int changeRow, int totalFound, int numSearch, int numRows, int numColumns) {
if (totalFound == 4) //base case
return true;
if (currRow <0 || currRow >numRows - 1 || currCol<0 || currCol> numColumns - 1)
return false;
if (board[currCol][currRow] == numSearch)
totalFound++;
else
return false; // the checked index didnt contain the same # we wanted
return checkGameOver(board, currCol + changeCol, currRow + changeRow, changeCol, changeRow, totalFound, numSearch, numRows, numColumns);
}
... or should I just scrap it and rewrite it differently?
That's the option I'd be going for :-)
While a recursive solution may be clever, you're probably better off, for a game-space of this size, keeping the code simple and just checking every single possibility rather than trying to recurse out from the newly-populated cell(a).
You can do this in "specialist" chunks so you don't have to worry about going off the edge of the board at any point. To do this, you limit the starting cell for each type so that it ends on an edge cell of the board, something like (pseudo-code):
# Check four cells given start and direction.
def didWin(row, col, rdelta, cdelta):
# Check if start cell not populated.
if cell[row][col] == empty:
return false
# Check if any cell in sequence doesn't match.
for i = 1 to 3 inclusive:
if cell[row][col] != cell[row+rdelta*i][col+cdelta*i]:
return false
# Otherwise, it's a win
return true
def getWinner():
# Check all possible horizontals.
for row = 0 to 5 inclusive:
for col = 0 to 3 inclusive:
if didWin(row, col, 0, 1): # cdelta=1, right.
return cell[row][col]
# Check all possible verticals.
for col = 0 to 6 inclusive:
for row = 0 to 2 inclusive:
if didWin(row, col, 1, 0): # rdelta=1, down.
return cell[row][col]
# Check all right-downs.
for row = 0 to 2 inclusive:
for col = 0 to 3 inclusive:
if didWin(row, col, 1, 1): # r/cdelta=1, right-down.
return cell[row][col]
# Check all right-ups.
for row = 3 to 5 inclusive:
for col = 0 to 3 inclusive:
if didWin(row, col, 1, -1): # rdelta=1, cdelta=-1, right-up.
return cell[row][col]
# No winner.
return empty
(a) Another good reason for doing this is that, in an educational institution, they almost always value clarity of thought over cleverness. That clarity of thought will serve you well in the start of your career and, indeed, forty years into your career, such as where I am :-)
Related
this error appears to me in two classes specifically and referenced in the main. Honestly, I don't know what happened.
"Boxes::fillLadder(char**, int**, int, int, int)", referenced from:
Boxes::fill(char**, int**, int, int) in SnakesAndLadders2-455af6.o
Board::draw(char**, int**, int, int) in SnakesAndLadders2-455af6.o
"Boxes::fillSnake(char**, int**, int, int, int)", referenced from:
Boxes::fill(char**, int**, int, int) in SnakesAndLadders2-455af6.o
Board::draw(char**, int**, int, int) in SnakesAndLadders2-455af6.o
"Boxes::Boxes()", referenced from:
Board::draw(char**, int**, int, int) in SnakesAndLadders2-455af6.o
_main in SnakesAndLadders2-455af6.o
ld: symbol(s) not found for architecture x86_64
This is class Boxes
#include <iostream>
#include <string>
using namespace std;
class Boxes{
public:
Boxes();
void fill(char **board, int **positions, int y, int x);
void fillLadder(char **board, int **positions, int y, int x, int lenght);
void fillSnake(char **board, int **positions, int y, int x, int lenght);
};
void Boxes::fill(char **board, int **positions, int y, int x)
{
for (int i = 0; i < y; i++)
{
for (int w = 0; w < x; w++)
{
board[i][w] = 'N';
positions[i][w] = 0;
}
}
if (y % 2 != 0)
{
board[0][x - 1] = 'O';
}
else
{
board[0][0] = 'O';
}
board[y - 1][0] = 'O';
if (y < 8)
{
fillLadder(board, positions, y - 1, 2, y / 2);
fillLadder(board, positions, y / 2, 4, 2);
fillSnake(board, positions, 0, 1, -1 * y / 2 + 1);
}
if (y >= 8 && y <= 12)
{
fillLadder(board, positions, y - 1, 3, 3);
fillLadder(board, positions, 4, x - 3, 2);
fillLadder(board, positions, 2, x - 2, 2);
fillSnake(board, positions, 0, 4, -4);
fillSnake(board, positions, 4, x - 4, -4);
fillSnake(board, positions, 4, 0, -3);
}
if (y > 12)
{
fillLadder(board, positions, y - 1, 3, 6);
fillLadder(board, positions, 6, x - 3, 5);
fillLadder(board, positions, 7, x - 2, 6);
fillLadder(board, positions, 9, 3, 3);
fillSnake(board, positions, 0, 4, -7);
fillSnake(board, positions, 4, x - 4, -6);
fillSnake(board, positions, 7, 0, -3);
fillSnake(board, positions, 5, 2, -2);
}
}
This is class Board
#include <iostream>
#include <string>
#include <ctime>
#include "Player.h"
#include "Boxes.h"
using namespace std;
class Board{
public:
void loop(char **board, int **positions, int y, int x);
void draw(char **board, int **positions, int y, int x);
};
void Board::loop(char **board, int **positions, int x, int y)
{
player1.location = 0;
player2.location = 0;
player1.level = y - 1;
player2.level = y - 1;
bool game = true;
Player p;
bool playerFlag;
int &movement = movement;
void Movement(int &movement, bool playerFlag);
{
Dice dice;
int status = 0;
if (playerFlag == true)
{
std::cout << "Player 1: Press 1 to roll the dice." << std::endl;
cin >> status;
if (status == 1)
{
dice.roll();
movement = dice.roll();
std::cout << "Player 1 rolled a: " << dice.roll() << std::endl;
}
}
if (playerFlag == false)
{
std::cout << "Player 2: Press 2 to roll the dice." << std::endl;
cin >> status;
if (status == 2)
{
dice.roll();
movement = dice.roll();
std::cout << "Player 2 rolled a: " << dice.roll() << std::endl;
}
}
}
while (game == true)
{
p.Movement(player1.movement, true);
p.logic(board, positions, y, x, player1.movement, player1.location, player1.level, player1.movestatus);
if (p.checkWin(y, x, player1.location, player1.level) == true)
{
std::cout << "Player 1 HAS WON THE GAME !!!!!!" << std::endl;
game = false;
}
else
{
p.updatePlayerLevel(positions, y, x, player1.location, player1.level, player1.movestatus);
board[player1.level][player1.location] = player1.symbol;
draw(board, positions, y, x);
}
if (player2.on == true)
{
p.Movement(player2.movement, false);
p.logic(board, positions, y, x, player2.movement, player2.location, player2.level, player2.movestatus);
if (p.checkWin(y, x, player2.location, player2.level) == true)
{
std::cout << "Player 2 HAS WON THE GAME !!!!!!" << std::endl;
game = false;
}
else
{
p.updatePlayerLevel(positions, y, x, player2.location, player2.level, player2.movestatus);
board[player2.level][player2.location] = player2.symbol;
draw(board, positions, y, x);
}
}
}
}
void Board::draw(char **board, int **positions, int y, int x)
{
Boxes bx;
if (y % 2 != 0)
{
board[0][x - 1] = 'O';
}
else
{
board[0][0] = 'O';
}
board[y - 1][0] = 'O';
for (int i = 0; i < y; i++)
{
if ((y - 1) > 9)
{
std::cout << y - 1 << " ⎪" << std::endl;
}
else
{
std::cout << y - 1 << " ⎪" << std::endl;
}
for (int y = 0; y < x; y++)
{
std::cout << board[i][y] << " " << std::endl;
}
std::cout << " " << std::endl;
}
if (y < 8)
{
bx.fillLadder(board, positions, y - 1, 2, y / 2);
bx.fillLadder(board, positions, y / 2, 4, 2);
bx.fillLadder(board, positions, 0, 1, -1 * y / 2 + 1);
}
if (y >= 8 && y <= 12)
{
bx.fillLadder(board, positions, y - 1, 3, 3);
bx.fillLadder(board, positions, 4, x - 3, 2);
bx.fillLadder(board, positions, 2, x - 2, 2);
bx.fillSnake(board, positions, 0, 4, -4);
bx.fillSnake(board, positions, 4, x - 4, -4);
bx.fillSnake(board, positions, 4, 0, -3);
}
if (y > 12)
{
bx.fillLadder(board, positions, y - 1, 3, 6);
bx.fillLadder(board, positions, 6, x - 3, 5);
bx.fillLadder(board, positions, 7, x - 2, 6);
bx.fillLadder(board, positions, 9, 3, 3);
bx.fillSnake(board, positions, 0, 4, -7);
bx.fillSnake(board, positions, 4, x - 4, -6);
bx.fillSnake(board, positions, 7, 0, -3);
bx.fillSnake(board, positions, 5, 2, -2);
}
}
And the main
#include <iostream>
#include <string>
#include <ctime>
#include "Board.h"
using namespace std;
int main()
{
Boxes f;
Board bo;
std::cout << "****** SNAKES AND LADDERS ******" << std::endl;
int size_y;
int size_x;
std::cout << "What size board do you want? Pick the number of rows and columns." << std::endl;
std::cout << "For balance, best size is 10x10." << std::endl;
std::cout << "Rows: " << std::endl;
cin >> size_y;
std::cout << "Columns: " << std::endl;
cin >> size_x;
int flag;
std::cout << "Press 2 if you want to play multiplayer (2 players). Press 1 for single player." << std::endl;
cin >> flag;
if (flag == 2)
{
player2.on = true;
}
std::cout << "Player 1: Select a letter/number on the keyboard for your character." << std::endl;
cin >> player1.symbol;
if (player2.on == true)
{
std::cout << "PLayer 2: Select a letter/number on the keyboard for your character." << std::endl;
cin >> player2.symbol;
}
system("CLS");
char **board;
board = new char *[size_y];
int **position_status;
position_status = new int *[size_y];
for (int i = 0; i < size_y; i++)
{
board[i] = new char [size_x];
position_status[i] = new int [size_x];
}
f.fill(board, position_status, size_y, size_x);
bo.draw(board, position_status, size_y, size_x);
bo.loop(board, position_status, size_y, size_x);
char stop;
std::cout << "Press e to end the programme." << std::endl;
cin >> stop;
for (int i = 0; i < size_y; i++)
{
delete[] board[i];
delete[] position_status[i];
}
delete board;
delete position_status;
return 0;
}
This code is about a snakes and ladders game.
Let me know if you need the class player because I used it on the class board.
I have a 2d array like this:
arr = [0 3 1 0
1 2 0 2
0 0 2 0
1 2 0 0]
My aim is don't iterate over a column once we find maximum number in it.
In the first iteration, max number is 3 in 2nd column, so don't go to second column in future iterations.
Similarly in my 2nd iteration, max number is 2 in 4th column (Because we dont go to 2nd column anymore).
This is what i tried:
#include <iostream>
using namespace std;
int main()
{
//Input 2d array
int arr[4][4];
//Take the input
for(int i=0; i<4; i++)
{
for(int j=0; j<4; j++)
cin>>arr[i][j];
}
//Index array to store index of maximum number column
int index[4] = {-1,-1,-1,-1}
//Array to store max number in each row
int max_arr[4] = {0,0,0,0};
for(int i=0; i<4; i++)
{
int max_num = -1;
for(int j=0; j<4; j++)
{
if(j!=index[0] && j!=index[1] && j!=index[2] && j!=index[3])
{
if(max_num<arr[i][j])
{
max_num = arr[i][j];
index[j] = j;
}
}
}
max_arr[i] = max_num;
}
return 0;
}
The best way to go about this is to simply evaluate the array by columns. This can be done with a little math. In your case, you use a 4x4 array. Start at index 0, add 4, add 4, add 4, then subtract 11 (bringing you to position 1). Add 4, add 4, add 4, subtract 11 (bringing you to position 2). Etc...
Here is the code I used, which works and is doable for any size array!
#include <iostream>
int main()
{
constexpr size_t ARR_ROWS = 4;
constexpr size_t ARR_COLS = 4;
constexpr size_t ARR_SIZE = ARR_ROWS * ARR_COLS;
int arr[ARR_SIZE] {
0, 3, 1, 0,
1, 2, 0, 2,
0, 0, 2, 0,
1, 2, 0, 0
};
// Store max values for columns
int cols_max[ARR_COLS] { -1, -1, -1, -1 };
// Start at index 0, then at 4 (3 times) to evaluate first
// column. Next, subtract 11 from current index (12) to get
// to index 1 (start of column 2). Add 4 (3 times) to
// evaluate second column. Next, subtract 11 from current
// index (13) to get to index 2 (start of column 3). Etc...
size_t cur_index = 0;
size_t cur_col = 0;
const size_t subtract_to_start_next_col = ARR_SIZE - (ARR_COLS + 1);
while (cur_index < ARR_SIZE)
{
// Max function for 'cols_max'
if (cols_max[cur_col] < arr[cur_index])
cols_max[cur_col] = arr[cur_index];
if ( // When index is at the column's end (besides last value)
(cur_index >= ARR_SIZE - ARR_COLS) &&
(cur_index <= ARR_SIZE - 2)
)
{
cur_index -= subtract_to_start_next_col;
cur_col++;
}
else if (cur_index == ARR_SIZE - 1)
{ // When index is last value, add 1 to break loop
cur_index++;
}
else
{ // Nothing special, just go to next value in column
cur_index += ARR_COLS;
}
}
// Print columns' max values (optional)...
for (size_t i = 0; i < ARR_COLS; ++i)
{
std::cout
<< "Max for column " << (i + 1) << ": " << cols_max[i]
<< std::endl;
}
}
Feel free to ask if you have any questions!
You need 3 loops, first for iterations, second for rows, third for columns. If you have found max at column let's say 0, then you should blacklist that column and so on.
#include <iostream>
int main()
{
int m[ 4 ][ 4 ] = { { 0, 3, 1, 0 } ,
{ 1, 2, 0, 2 } ,
{ 0, 0, 2, 0 } ,
{ 1, 2, 0, 0 } };
constexpr int max_number_of_itr { 4 };
bool blacklisted[4] { false };
for ( auto itr = 0; itr < max_number_of_itr; ++itr )
{
auto max { -1 };
auto max_col_idx { -1 };
for ( auto row = 0; row < 4; ++row )
{
for ( auto col = 0; col < 4; ++col )
{
if ( blacklisted[ col ] )
continue;
auto val = m[ row ][ col ];
if ( val > max )
{
max = val;
max_col_idx = col;
}
}
}
blacklisted[ max_col_idx ] = true;
std::cout << "max is " << max << " col " << max_col_idx << " ignored." << std::endl;
}
}
index[ j ] = j;
change this to
index[ i ] = j;
I'm trying to write a program that allows the user to enter any coordinate on a chess board and complete the knight's tour using brute force recursion. I am getting an infinite loop and I have no idea why. This is in C++, and I have to write this only using brute force recursion. After entering the starting place for the knight, my console output window prints the current board after each move (only temporarily, for troubleshooting purposes), but according to my output, the move number is stuck at 1, and the program isn't trying any other moves. Any help is appreciated.
#include "stdafx.h"
#include <iostream>
#include <iomanip>
using namespace std;
void printBoard();
bool moveKnight(int col, int row, int movNum);
int totalMoves = 0;
int board[7][7] = { { 0 } };
int main()
{
cout << "Welcome to the Knight's Tour Program! Enter a starting place for the knight on a chess board to get started.\n";
int col;
int row;
int a;
int b;
while (1 == 1)
{
col = 0;
row = 0;
cout << "Enter column (0-7): ";
cin >> col;
cout << "Enter row (0-7): ";
cin >> row;
if (row < 0 || row > 7 || col < 0 || col > 7)
{
cout << "Invalid knight placement. Please try again.\n";
}
else
{
break;
}
}
int movNum = 1;
board[col][row] = movNum;
totalMoves++;
moveKnight(col, row, movNum);
if (moveKnight(col, row, movNum == true))
{
cout << "Tour finished! Total moves: " << totalMoves << endl;
printBoard();
cout << "\n\n";
}
system("pause");
return 0;
}
void printBoard()
{
cout << "Current board\n";
for (int i = 0; i < 8; i++)
{
for (int x = 0; x < 8; x++)
{
cout << setw(3) << board[i][x] << " ";
if (x == 7)
{
cout << "\n\n";
}
}
}
cout << "\n";
}
bool moveKnight(int col, int row, int movNum)
{
printBoard(); //just for troubleshooting
cout << "\n" << totalMoves << endl;
if (moveKnight(col, row, movNum) == false)
{
board[col][row] = 0; //if there are no available moves then set the current space to 0 and move back a spot
}
if (movNum == 64)
{
return true; //if tour complete return true
}
if (totalMoves % 10000 == 0)
{
printBoard(); //printBoard() every 10000 moves
}
if (col >= 0 && col <= 7 && row >= 0 && row <= 7 && board[row][col] == 0) //check if space is on board and if it is unoccupied
{
board[col][row] = movNum;
totalMoves++;
if (moveKnight(col + 1, row - 2, movNum + 1) != false)
moveKnight(col + 1, row - 2, movNum + 1);
else if (moveKnight(col + 2, row - 1, movNum + 1) != false)
moveKnight(col + 2, row - 1, movNum + 1);
else if (moveKnight(col + 2, row + 1, movNum + 1) != false)
moveKnight(col + 2, row + 1, movNum + 1);
else if (moveKnight(col + 1, row + 2, movNum + 1) != false)
moveKnight(col + 1, row + 2, movNum + 1);
else if (moveKnight(col - 1, row + 2, movNum + 1) != false)
moveKnight(col - 1, row + 2, movNum + 1);
else if (moveKnight(col - 2, row + 1, movNum + 1) != false)
moveKnight(col - 2, row + 1, movNum + 1);
else if (moveKnight(col - 2, row - 1, movNum + 1) != false)
moveKnight(col - 2, row - 1, movNum + 1);
else if (moveKnight(col - 1, row - 2, movNum + 1) != false)
moveKnight(col - 1, row - 2, movNum + 1);
else
return false;
}
}
If you look in the moveKnight() function, notice that the line if (moveKnight(col, row, movNum) == false) does a recursive call of the function no matter what the inputs are.
Whenever you use a recursive function, it must have what is called a base case, where a recursive call does not happen. Otherwise, the recursive calls will just keep going on until a stack overflow since one execution of the function will start another one which will start another one and so on..
By the way, the bunch of if statements in the function make no sense since you are calling a function and checking the output, and if it is true then you call the function a second time with the exact same arguments. Also, if you want an infinite loop that you will break later, there is no need for something like while(1 == 1). Use while(1) or while(true).
int board[7][7] = { { 0 } };
Chess board is 8 x 8, so you need 8 elements in the array (from 0 to up to and including 7, that's 8)
if (moveKnight(col, row, movNum == true))
You have syntax erros, the compiler will tell you about all this. In Visual Studio make sure warning level is set to 4. Then make sure the program is compiled with zero errors and zero warnings.
I would recommend writing a program which does not require user input. This will make it easier to debug the program and fix the logic.
Below is a simple recursion which moves the knight until the knight gets stuck at the end. You will have to further improve the logic so that it covers all the squares.
Make sure the recursive function is allowed to break. That's discussed in more detail in the other answer.
int board[8][8] = { 0 };
void printBoard()
{
cout << "Current board\n";
for(int i = 0; i < 8; i++)
{
for(int x = 0; x < 8; x++)
cout << board[i][x] << " ";
cout << "\n";
}
cout << "\n";
}
int test(int &row, int &col, int move_row, int move_col)
{
int r = row + move_row;
int c = col + move_col;
if(r >= 0 && r < 8 && c >= 0 && c < 8 && !board[r][c])
{
row = r;
col = c;
return 1;
}
return 0;
}
bool move_knight(int &row, int &col)
{
board[row][col] = 1;
printBoard();
system("pause");
if(!test(row, col, 1, 2))
if(!test(row, col, 1, -2))
if(!test(row, col, -1, 2))
if(!test(row, col, -1, -2))
if(!test(row, col, 2, 1))
if(!test(row, col, 2, -1))
if(!test(row, col, -2, 1))
if(!test(row, col, -2, -1))
return false;
move_knight(row, col);
return true;
}
int main()
{
int col = 0;
int row = 0;
move_knight(col, row);
system("pause");
return 0;
}
C++ beginner here. I'm currently trying to make a sudoku solving program, so I have to check whether a value exists in the 9x9 box it's located in.
This is my code for checking if the element follows the rules:
//constants for rows and columns of the sudoku puzzle, can be changed
const int ROWS = 9;
const int COLS = 9;
bool follows_rule(int grid[ROWS][COLS], int rowIndex, int colIndex, int value){
for (int i = 0; i < COLS; i++){
if (grid[rowIndex][i] == value) //check if there are any other values on the same column
return false;
if (grid[i][colIndex] == value) //or the same row
return false;
}
//to-do: check if another equal value exists in the 9x9 box
return true;
}
//returns true if another element has the same value as "value", false otherwise
bool exists_in_2d_array(int grid[ROWS][COLS], int value){
for (int x = 0; x < ROWS / 3; x++)
{
for (int y = 0; y < COLS / 3; y++)
{
if (grid[x][y] == value)
{
return true;
}
}
}
return false;
}
My idea was to find out which 9x9 box the coordinates of the current element lead to, then put that 9x9 grid in another 2D array and check if the element's value exists somewhere else in the grid. I don't really know how, though.
The SUDOKU rules require that the digit is used only once:
Rule 1: in each row
Rule 2: in each column
Rule 3: in each 3x3 subgrid of the 9x9 grid
Function follows_rule() checks for a given grid position, if the value would be allowed or not. For the moment it checks only rules 1 and 2. I propose you the following code for rule 3:
bool follows_rule(int grid[ROWS][COLS], int rowIndex, int colIndex, int value){
for (int i = 0; i < COLS; i++){
if (grid[rowIndex][i] == value)
return false;
if (grid[i][colIndex] == value) // ATTENTION THIS IS OK BECAUSE ROWS==COLS !!
return false;
}
// Check if another equal value exists in the 3x3 box
int sgc = (colIndex / 3) * 3; // in wich subgrid are we ?
int sgr = (rowIndex / 3) * 3;
// check all the elements of the 3x3 grid startic at sgr, sgc
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
if (grid[sgr + i][sgc + j] == value)
return false;
return true;
}
You can test the 3x3 verification with the following code:
int sudoku[ROWS][COLS] = {
{ 1, 0, 0, 0, 0, 0, 0, 8, 0 },
{ 0, 0, 2, 0, 0, 0, 0, 0, 0 },
{ 0, 3, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 1, 3, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 5, 0, 0, 0 },
{ 0, 0, 0, 0, 8, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
if (follows_rule(sudoku, 1, 0, 1) == false
&& follows_rule(sudoku, 1, 0, 4) == true
&& follows_rule(sudoku, 5, 5, 8) == false
&& follows_rule(sudoku, 5, 5, 1) == false
&& follows_rule(sudoku, 5, 5, 7) == true)
cout << "Test ok !" << endl;
else cout << "Tests failed" << endl;
Accepted answer does not calculate the subgrids correctly , sgc and and sgr needs to be multiplied with 3 too after division to crrectly identify the subgrid vertices
public boolean isValidEntry(char[][] board, int row , int col,char val)
{
for(int i = 0 ; i < 9 ;i++){
if(board[row][i] == val)
return false;
}
for(int j = 0 ; j < 9 ;j++){
if(board[j][col] == val)
return false;
}
int sgc = col / 3; // in wich subgrid are we ?
int sgr = row / 3;
// check all the elements of the 3x3 grid startic at sgr, sgc
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++)
if (board[(3*sgr) + i][(3*sgc) + j] == val)
return false;
}
return true;
}
I have to construct a 2d array with N,M rows and columns (N & M <= 5), then the user enters a certain index(location) like 2,3 (matrix[2][3]) it's assumed that the two numbers are in the bounds of the matrix. From then on I have to find the sum of the left and right diagonal that goes through the number, however the number is excluded from the sum.
So for example the 2d array is myArray[3][3]
*1* 15 *2*
2 *71* 8
*5* 22 *5*
So the user enters 1,1 that is myArray[1][1], in this case the number 71, the sum would be 1 + 5 + 2 + 5 ... And well my problem is how can i find those diagonals without going out of the bounds.
For the left top i would go:
row--
column--
while(row >= 0|| column >= 0)
For left bottom:
row++
colum++
while(row < N || column < M)
for right top:
row--
column++
while(row >= 0 || column < M)
for right bottom:
row++
column--
while(row < N || column >=0)
(this is bad written pseudo-code, sorry)
It works fine when I enter numbers that aren't in the top or bottom row, but in the cases that they are located there my program stops.
What you have is basically good pseudocode. My first thought was that you should be using &&'s instead of ||'s when determining if the location is out of bounds or not.
You also need some sort of way to exit early in case they give a bad location. Below is some code I wrote out quickly, and seems to work at a quick glance - I loop over every possible starting location including ones that are out of bounds.
#include <iostream>
const int N = 3;
const int M = 4;
int matrix[N][M] = {
{ 0, 1, 2, 3 },
{ 4, 5, 6, 7 },
{ 8, 9, 10, 11 }
};
int directional_sum(int row, int column, int row_inc, int column_inc)
{
int sum = 0;
if (row < 0 || column < 0 || row >= N || column >= M)
return sum;
int temp_row = row + row_inc;
int temp_column = column + column_inc;
while (temp_row >= 0 && temp_column >= 0 && temp_row < N && temp_column < M)
{
sum += matrix[temp_row][temp_column];
temp_row += row_inc;
temp_column += column_inc;
}
return sum;
}
int diagonal_sum(int row, int column)
{
int sum = 0;
sum += directional_sum(row, column, 1, 1);
sum += directional_sum(row, column, 1, -1);
sum += directional_sum(row, column, -1, 1);
sum += directional_sum(row, column, -1, -1);
return sum;
}
int main()
{
for (int i = -1; i <= N; i++)
{
for (int j = -1; j <= M; j++)
{
std::cout << "Sum for [" << i << ", " << j << "]: " << diagonal_sum(i, j) << std::endl;
}
}
return 0;
}