Skip to content

Instantly share code, notes, and snippets.

@geocachecs
Created October 22, 2015 21:53
Show Gist options
  • Save geocachecs/d8d2f402b0843231231b to your computer and use it in GitHub Desktop.
Save geocachecs/d8d2f402b0843231231b to your computer and use it in GitHub Desktop.
2 Player Chess Game C++
#include "chess.h"
Square::Square()
{
piece = EMPTY;
color = NONE;
}
void Square::setSpace(Square* space)
{
color = space->getColor();
piece = space->getPiece();
}
void Square::setEmpty()
{
color = NONE;
piece = EMPTY;
}
Piece Square::getPiece()
{
return piece;
}
Color Square::getColor()
{
return color;
}
void Square::setPieceAndColor(Piece p, Color c)
{
piece = p;
color = c;
}
void Board::printBoard() {
using namespace std;
cout << " y: 0 1 2 3 4 5 6 7 " << endl << "x:" << endl;
for (int i = 0; i < 8; i++)
{
cout << " " << i << " ";
for (int j = 0; j < 8; j++)
{
Piece p = square[i][j].getPiece();
Color c = square[i][j].getColor();
switch (p)
{
case KING: (c == WHITE) ? cout << " K " : cout << " k ";
break;
case QUEEN: (c == WHITE) ? cout << " Q " : cout << " q ";
break;
case BISHOP:(c == WHITE) ? cout << " B " : cout << " b ";
break;
case KNIGHT:(c == WHITE) ? cout << " H " : cout << " h ";
break;
case ROOK: (c == WHITE) ? cout << " R " : cout << " r ";
break;
case PAWN: (c == WHITE) ? cout << " P " : cout << " p ";
break;
case EMPTY: cout << " " << "\21" << " ";
break;
default: cout << "XXX";
break;
}
}
cout << endl;
}
}
bool Board::doMove() {
using namespace std;
string move;
int x1, x2, y1, y2;
bool stop = false;
while (!stop)
{
(turn == WHITE) ? cout << "White's turn" << endl : cout << "Black's turn" << endl;
cout << "Type in your move as a single four character string. Use x-coordinates first in each pair." << endl;
cin >> move;
x1 = move[0] - 48;
y1 = move[1] - 48;
x2 = move[2] - 48;
y2 = move[3] - 48;
if (getSquare(x1, y1)->getColor() == turn)
{
if (makeMove(x1, y1, x2, y2) == false)
{
cout << "Invalid move, try again." << endl;
}
else
stop = true;
}
else
cout << "That's not your piece. Try again." << endl;
}
if (getSquare(x2, y2)->getPiece() == KING)
if (getSquare(x1, y1)->getColor() == WHITE)
{
cout << "WHITE WINS" << endl;
return false;
}
else
{
cout << "BLACK WINS" << endl;
return false;
}
if (turn == BLACK)
turn = WHITE;
else
turn = BLACK;
return true;
}
void Board::setBoard()
{
square[0][0].setPieceAndColor(ROOK, WHITE);
square[1][0].setPieceAndColor(KNIGHT, WHITE);
square[2][0].setPieceAndColor(BISHOP, WHITE);
square[3][0].setPieceAndColor(QUEEN, WHITE);
square[4][0].setPieceAndColor(KING, WHITE);
square[5][0].setPieceAndColor(BISHOP, WHITE);
square[6][0].setPieceAndColor(KNIGHT, WHITE);
square[7][0].setPieceAndColor(ROOK, WHITE);
square[0][7].setPieceAndColor(ROOK, BLACK);
square[1][7].setPieceAndColor(KNIGHT, BLACK);
square[2][7].setPieceAndColor(BISHOP, BLACK);
square[3][7].setPieceAndColor(QUEEN, BLACK);
square[4][7].setPieceAndColor(KING, BLACK);
square[5][7].setPieceAndColor(BISHOP, BLACK);
square[6][7].setPieceAndColor(KNIGHT, BLACK);
square[7][7].setPieceAndColor(ROOK, BLACK);
for (int i = 0; i < 8; i++)
{
square[i][1].setPieceAndColor(PAWN, WHITE);
square[i][6].setPieceAndColor(PAWN, BLACK);
}
for (int i = 2; i < 6; i++)
{
for (int j = 0; j < 8; j++)
square[j][i].setPieceAndColor(EMPTY, NONE);
}
for (int i = 0; i < 8; i++)
for (int j = 0; j < 8; j++)
{
square[i][j].setX(i);
square[i][j].setY(j);
}
}
bool Board::playGame()
{
system("cls");
printBoard();
return doMove();
}
bool Board::moveKing(Square* thisKing, Square* thatSpace) {
//off board inputs should be handled elsewhere (before this)
//squares with same color should be handled elsewhere (before this)
if (abs(thatSpace->getX() - thisKing->getX()) == 1)
if (abs(thatSpace->getY() - thisKing->getY()) == 1)
{
thatSpace->setSpace(thisKing);
thisKing->setEmpty();
return true;
}
else return false;
else return false;
}
bool Board::moveQueen(Square* thisQueen, Square* thatSpace) { //there might be problems with numbers of brackets
//off board inputs should be handled elsewhere (before this)
//squares with same color should be handled elsewhere (before this)
int queenX = thisQueen->getX();
int queenY = thisQueen->getY();
int thatX = thatSpace->getX();
int thatY = thatSpace->getY();
std::cout << "this";
int yIncrement;
int xIncrement;
bool invalid = false;
if (queenX != thatX || queenY != thatY)
{
if (queenX == thatX)
{
yIncrement = (thatY - queenY) / (abs(thatY - queenY));
for (int i = queenY + yIncrement; i != thatY; i += yIncrement)
{
if (square[thatX][i].getColor() != NONE)
return false;
}
}
else
if (queenY == thatY)
{
xIncrement = (thatX - queenX) / (abs(thatX - queenX));
for (int i = queenX + xIncrement; i != thatX; i += xIncrement)
{
if (square[i][thatY].getColor() != NONE)
return false;
}
}
else
if (abs(queenX - thatX) == abs(queenY - thatY))
{
xIncrement = (thatX - queenX) / (abs(thatX - queenX));
yIncrement = (thatY - queenY) / (abs(thatY - queenY));
for (int i = 1; i < abs(queenX - thatX); i++)
{
std::cout << "It got here somehow";
if (square[queenX + xIncrement*i][queenY + yIncrement*i].getColor() != NONE)
return false;
}
}
else
return false;
//if()
}
if (invalid == false)
{
thatSpace->setSpace(thisQueen);
thisQueen->setEmpty();
return true;
}
else
{
return false;
}
}
bool Board::moveBishop(Square* thisBishop, Square* thatSpace) { //there might be problems with number of brackets
int bishopX = thisBishop->getX();
int bishopY = thisBishop->getY();
int thatX = thatSpace->getX();
int thatY = thatSpace->getY();
bool invalid = false;
Square *s;
if (abs(bishopX - thatX) == abs(bishopY - thatY))
{
int xIncrement = (thatX - bishopX) / (abs(thatX - bishopX));
int yIncrement = (thatY - bishopY) / (abs(thatY - bishopY));
for (int i = 1; i < abs(bishopX - thatX); i++)
{
std::cout << "It got here somehow";
if (square[bishopX + xIncrement*i][bishopY + yIncrement*i].getColor() != NONE)
return false;
}
}
else
return false;
if (invalid == false)
{
thatSpace->setSpace(thisBishop);
thisBishop->setEmpty();
return true;
}
else
{
return false;
}
}
bool Board::moveKnight(Square* thisKnight, Square* thatSpace)
{
//off board inputs should be handled elsewhere (before this)
//squares with same color should be handled elsewhere (before this)
int knightX = thisKnight->getX();
int knightY = thisKnight->getY();
int thatX = thatSpace->getX();
int thatY = thatSpace->getY();
if ((abs(knightX - thatX) == 2 && abs(knightY - thatY) == 1) || (abs(knightX - thatX) == 1 && abs(knightY - thatY) == 2))
{
thatSpace->setSpace(thisKnight);
thisKnight->setEmpty();
return true;
}
else
{
return false;
}
}
bool Board::moveRook(Square* thisRook, Square* thatSpace)
{
//off board inputs should be handled elsewhere (before this)
//squares with same color should be handled elsewhere (before this)
int rookX = thisRook->getX();
int rookY = thisRook->getY();
int thatX = thatSpace->getX();
int thatY = thatSpace->getY();
bool invalid = false;
if (rookX != thatX || rookY != thatY)
{
if (rookX == thatX)
{
int yIncrement = (thatY - rookY) / (abs(thatY - rookY));
for (int i = rookY + yIncrement; i != thatY; i += yIncrement)
{
if (square[thatX][i].getColor() != NONE)
return false;
}
}
else
if (rookY == thatY)
{
int xIncrement = (thatX - rookX) / (abs(thatX - rookX));
for (int i = rookX + xIncrement; i != thatX; i += xIncrement)
{
if (square[i][thatY].getColor() != NONE)
return false;
}
}
else
return false;
}
if (invalid == false)
{
thatSpace->setSpace(thisRook);
thisRook->setEmpty();
return true;
}
else
{//Return some erorr or something. Probably return false;
std::cout << "That is an invalid move for rook";
return false;
}
}
bool Board::movePawn(Square* thisPawn, Square* thatSpace) {
//off board inputs should be handled elsewhere (before this)
//squares with same color should be handled elsewhere (before this)
using namespace std;
bool invalid = false;
int pawnX = thisPawn->getX();
int pawnY = thisPawn->getY();
int thatX = thatSpace->getX();
int thatY = thatSpace->getY();
if (thisPawn->getColor() == WHITE)
{
if (pawnX == thatX && thatY == pawnY + 1 && thatSpace->getColor() == NONE)
{
thatSpace->setSpace(thisPawn);
thisPawn->setEmpty();
return true;
}
else
if ((pawnX + 1 == thatX || pawnX - 1 == thatX) && pawnY + 1 == thatY && thatSpace->getColor() == BLACK)
{
thatSpace->setSpace(thisPawn);
thisPawn->setEmpty();
return true;
}
else
return false;
}
else
if (thisPawn->getColor() == BLACK)
{
if (pawnX == thatX && thatY == pawnY - 1 && thatSpace->getColor() == NONE)
{
thatSpace->setSpace(thisPawn);
thisPawn->setEmpty();
return true;
}
else
if ((pawnX + 1 == thatX || pawnX - 1 == thatX) && pawnY - 1 == thatY && thatSpace->getColor() == WHITE)
{
thatSpace->setSpace(thisPawn);
thisPawn->setEmpty();
return true;
}
else
return false;
}
else
return false;
}
bool Board::makeMove(int x1, int y1, int x2, int y2) {
//Checking for turns will be done previous to this
using namespace std;
if (x1 < 0 || x1>7 || y1 < 0 || y1>7 || x2 < 0 || x2>7 || y2 < 0 || y2>8)
{
std::cout << "One of your inputs was our of bounds" << std::endl;
return false;
}
Square* src = getSquare(x1, y1);
Square* dest = getSquare(x2, y2);
if (src->getColor() == dest->getColor() && dest->getColor() != NONE)
{
std::cout << "Invalid move: cannot land on your own piece" << std::endl;
return false;
}
switch (src->getPiece())
{
case KING: return moveKing(src, dest);
break;
case QUEEN: return moveQueen(src, dest);
break;
case BISHOP: return moveBishop(src, dest);
break;
case KNIGHT: return moveKnight(src, dest);
break;
case ROOK: return moveRook(src, dest);
break;
case PAWN: return movePawn(src, dest);
break;
case EMPTY: std::cout << "You do not have a piece there" << std::endl; return false;
break;
default: std::cerr << "Something went wrong in the switch statement in makeMove()" << std::endl;
break;
}
return false;
}
#pragma once
#include <iostream>
#include <cmath>
#include <string>
enum Piece { KING, QUEEN, BISHOP, KNIGHT, ROOK, PAWN, EMPTY };
enum Color { WHITE, BLACK, NONE };
class Square
{
Piece piece;
Color color;
int x, y;
public:
void setSpace(Square*);
void setEmpty();
void setPieceAndColor(Piece, Color);
Piece getPiece();
Color getColor();
void setX(int ex) { x = ex; }
void setY(int why) { y = why; }
int getX() { return x; }
int getY() { return y; }
Square();
};
class Board
{
Square square[8][8];
Color turn=WHITE;
bool moveKing(Square* thisKing, Square* thatSpace);
bool moveQueen(Square* thisQueen, Square* thatSpace);
bool moveBishop(Square* thisBishop, Square* thatSpace);
bool moveKnight(Square* thisKnight, Square* thatSpace);
bool moveRook(Square* thisRook, Square* thatSpace);
bool movePawn(Square* thisPawn, Square* thatSpace);
bool makeMove(int x1, int y1, int x2, int y2);
void printBoard();
public:
Square* getSquare(int x, int y) {
return &square[x][y];
}
void setSquare(Square * s, int x, int y){
square[x][y]=*s;
}
bool doMove();
void setBoard();
bool playGame();
};
#include <iostream>
#include <string>
#include "chess.h"
using namespace std;
int main()
{
Board b;
string s;
bool newgame = true;
cout << " _____ _ _ ______ _____ _____ \n / ____| | | | ____|/ ____/ ____| \n | | | |__| | |__ | (___| (___ \n | | | __ | __| \\___ \\___ \\ \n | |____| | | | |____ ____) |___) | \n \\_____|_| |_|______|_____/_____/ \n" << endl;
cout << "A game by George Harter"<<endl;
cout << "Enter any key to continue" << endl;
cin >> s;
while(newgame){
b.setBoard();
while (b.playGame());
cout << "Do you want to play again? (y for yes, anything else for no) ";
cin >> s;
if (s != "y")
newgame = false;
}
return 0;
}
@Reefri
Copy link

Reefri commented Sep 21, 2024

Line 180/181, in chess.cpp : both "if" should be combined with an "or" gate like written below :
if ((abs(thatSpace->getX() - thisKing->getX()) == 1) || (abs(thatSpace->getY() - thisKing->getY()) == 1))

Or else, you wont be able to move the king up, down, left or right !

@Himanshu962005
Copy link

❌ Missing Features (Optional to Add)
No input validation for bad characters

No move logging/history

No check/checkmate logic

No castling

No pawn promotion

No en passant

Noob Code Hai

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment