在实现五子棋小游戏时,首先应该分为棋盘和玩家,我们先定义两个类:chessboard、player。分别提供棋盘的构造和玩家及游戏规则的确定。下面我们看下代码:
chessboard.h: 对棋盘chessboard类型进行定义
#ifndef _CHESSBOARD_H_
#define _CHESSBOARD_H_
#include
using namespace std;
class ChessBoard //棋盘
{
public:
enum{ROW = 31, COL = 31}; //整个棋盘所占的行数和列数
char cSquare[ROW+1][COL+1]; //定义一个字符数组,用来打印棋盘
public:
ChessBoard(); //棋盘构造函数
void show(); //棋盘的显示
~ChessBoard(){} //析构函数
};
#endif
chessboard.cpp
#include
#include
#include "chessboard.h"
using namespace std;
//构造函数
ChessBoard::ChessBoard()
{
for(int i = 1; i <= ROW - 2; i += 2){ //将棋盘隔行放入‘-’.
for(int j = 1; j <= COL - 2; j += 2){
cSquare[i][j] = ' ';
cSquare[i][j+1] = '|';
cSquare[i+1][j] = '-';
cSquare[i+1][j+1] = '-';
}
}
//围出棋盘的四周
for(int j = 0; j < COL; j ++)
cSquare[0][j] = cSquare[ROW-1][j] = '-';
for(int i = 0; i < ROW; i ++)
cSquare[i][0] = cSquare[i][COL-1] = '|';
//空处棋盘落子空间
cSquare[ROW][0] = ' ';
cSquare[0][COL] = ' ';
//在最后以行打印出行、列下标0,1,2 ... A,B,C ...
for(int i = 1; i < 20; i += 2){
cSquare[i][COL] = i / 2 + 48;
cSquare[i+1][COL] = ' ';
cSquare[ROW][i] = i / 2 + 48;
cSquare[ROW][i+1] = ' ';
}
for(int j = 21; j < COL; j += 2){
cSquare[ROW][j] = j / 2 + 55;
cSquare[ROW][j+1] = ' ';
}
for(int j = 21; j < ROW; j += 2){
cSquare[j][COL] = j / 2 + 55;
cSquare[j+1][COL] = ' ';
}
}
void ChessBoard::show()
{
system("clear"); //清除缓存区数据
//显示棋盘
for(int i = 0; i <= ROW; ++i){
for(int j = 0; j <= COL; ++j)
cout << cSquare[i][j] << ' ';
cout << endl;
}
}
player.h:定义player类
#ifndef _PLAYER_H_
#define _PLAYER_H_
#include
#include
#include "chessboard.h"
using namespace std;
class Player
{
private:
string m_name;
char m_ChessType;
int m_x;
int m_y;
ChessBoard * m_ptBoard;
public:
enum{ROW = 31, COL = 31};
Player():m_name("no_name"),m_ChessType('?'),m_x(0),m_y(0),m_ptBoard(NULL){}
void attachToBoard(ChessBoard* ptBoard){m_ptBoard = ptBoard;}
bool isInChessBoard(int x, int y) const; //棋子是否罗在棋盘内
bool HisLine(int x, int y) const; //判断水平方向是否连够5个棋子
bool VisLine(int x, int y) const; //判断竖直方向是否连够5个棋子
bool LtoBottomisLine(int x, int y) const; //判断自左上角到右下角是否连够5个棋子
bool LtoTopisLine(int x, int y) const; //判断子右上角到左下角是否连够5个棋子
bool isWin() const; //是否赢
string WinName() const{return m_name;} //赢者姓名
void SetInfo(int no);
void SetChess(); //把玩家所选的符号放进所选为值
~Player(){}
};
#endif
player.cpp:
#include
#include
#include "player.h"
using namespace std;
bool Player::isInChessBoard(int x, int y) const
{
if(x < ROW - 1 && x > 0 && y < COL - 1 && y > 0)
return true;
else
return false;
}
void Player::SetInfo(int no)
{
cout << "Please No." << no <<" input your name(q to quit): \n";
getline(cin, m_name);
if("q" == m_name){
cout << "Bye Bye!" << endl;
exit(-1);
}
//如果键盘输入有错误,清楚错误标志和环中去,重新输入用户名称
while(!cin){
cin.clear();
cin.ignore(2048, '\n'); //1024清除缓存区数据
cout << "Please No." << no << " input your name agin(q to quit): " << endl;
getline(cin, m_name);
if("q" == m_name){cout << "Bye Bye!" << endl; exit(-1);}
}
cout << "Hello! " << this->m_name << ": Please Choose Your Chess Type '*' or '#': " << endl;
cin >> m_ChessType;
cin.get();
//如果用户输入q,则退出程序
if('q' == m_ChessType){cout << "Bye Bye" << endl; exit(-1);}
//如果键盘输入有误,或者用户输入的棋子团不属于预其设的*或#,则要求用户重新输入
while(!cin || (m_ChessType != '*' && m_ChessType != '#')){
cin.clear();
cin.sync();
cout << "Hello! " << this->m_name << ": Please Choose YOur Chess Type '*' or '#'(q to quit): \n";
cin >> m_ChessType;
cin.get();
if('q' == m_ChessType){cout << "Bye Bye!" << endl; exit(-1);}
}
}
//提示用户输入落子的坐标,并判断是否坐标在棋盘上,并把当前玩家选择的棋子图案字符,填充进当前输入的坐标
void Player::SetChess()
{
char x;
char y;
cout << this->m_name << ": Please input Position (x, y) of your Chess. (-, -) to quit" << endl;
cin >> x >> y;
if('-' == x && '-' == y){
cout << "Bye Bye!" << endl;
exit(-1);
}
#if 1
if(x >= '0' && x <= '9'){
m_x = (int) x - 48;
}else if(isupper(x)){
m_x = (int) x - 55;
}else if(islower(x)){
x = toupper(x);
m_x = (int) x - 55;
}
if(y >= '0' && y <= '9'){
m_y = (int) y - 48;
}else if(isupper(y)){
m_y = (int) y - 55;
}else if(islower(y)){
y = toupper(y);
m_y = (int) y - 55;
}
m_x = m_x + (1 * m_x + 1);
m_y = m_y + (1 * m_y + 1);
#endif
//如果键盘数据有错误或者输入的坐标已经存在其他棋子
while(!cin || m_ptBoard->cSquare[m_x][m_y] != ' '){
cin.clear();
cin.ignore(1024, '\n');
cout << this->m_name << ": Please Input Position (x, y) of Your Chess.(-, -) to quit" << endl;
cin >> x >> y;
//根据所输入进来的行、列角标找出相应的落子位置,并将操作玩家所对应的棋子符号填充到该位置(不区分大小写)
if('-' == x && '-' == y){
cout << "Bye Bye!" << endl;
exit(-1);
}
if(x >= '0' && x <= '9'){
m_x = (int) x - 48;
}else if(isupper(x)){
m_x = (int) x - 55;
}else if(islower(x)){
x = toupper(x);
m_x = (int) x - 55;
}
if(y >= '0' && y <= '9'){
m_y = (int) y - 48;
}else if(isupper(y)){
//cout << "m_y" << m_y << endl;
m_y = (int) y - 55;
//cout << "m_y" << m_y << endl;
}else if(islower(y)){
y = toupper(y);
m_y = (int) y - 55;
}
m_x = m_x + (1 * m_x + 1);
m_y = m_y + (1 * m_y + 1);
}
//填充进当前输入的坐标对应的棋盘的二维数组单元中
if(isInChessBoard(m_x, m_y)){
m_ptBoard->cSquare[m_x][m_y] = m_ChessType;
}
}
//判断是否在水平方向上形成5子连线
bool Player::HisLine(int x, int y) const
{
int num = 0;
for(int i = -8; i <= 8; i+=2){
if(isInChessBoard(x, y+i) && m_ptBoard->cSquare[x][y+i] == m_ChessType){ num++;
if(num == 5)
return true;
}
else
num = 0;
}
return false;
}
//判断是否在垂直方向上满足5子连线
bool Player::VisLine(int x, int y) const
{
int num = 0;
for(int i = -8; i <= 8; i+=2){
//如果当前坐标统一行的其他坐标在棋盘上,且其他坐标的图案和当前玩家的棋子图案相同,计数器雷家
if(isInChessBoard(x+i, y) && m_ptBoard->cSquare[x+i][y] == m_ChessType){
num++;
//连续同一行有5个坐标点的图案相同时,满足赢棋的条件
if(num == 5)
return true;
}
else
num = 0;
}
return false;
}
//判断是否在自左上角到右下角的方向上满足5子连线
bool Player::LtoBottomisLine(int x, int y) const
{
int num = 0;
for(int i = -8; i <= 8; i+=2){
//如果当前坐标沿自左上角到右下角的对角线方向的其他
if(isInChessBoard(x+i, y+i) && m_ptBoard->cSquare[x+i][y+i] == m_ChessType){
num++;
if(num == 5)
return true;
}
else
num = 0;
}
return false;
}
//判断是否在自左下角到右上角的方向上满足5子连线
bool Player::LtoTopisLine(int x, int y) const
{
int num = 0;
for(int i = -8; i <= 8; i+=2){
if(isInChessBoard(x-i, y+i) && m_ptBoard->cSquare[x-i][y+i] == m_ChessType){
num++;
if(num == 5)
return true;
}
else
num = 0;
}
return false;
}
bool Player::isWin()const
{
return (HisLine(m_x, m_y) || VisLine(m_x, m_y) || LtoBottomisLine(m_x, m_y) || LtoTopisLine(m_x, m_y)) ? true : false;
}
game.cpp:
#include
#include "player.h"
#include "chessboard.h"
using namespace std;
int main()
{
ChessBoard board;
Player playerA;
playerA.SetInfo(1);
playerA.attachToBoard(&board);
Player playerB;
playerB.SetInfo(2);
playerB.attachToBoard(&board);
board.show();
while(1){
//玩家1放下一粒棋子
playerA.SetChess();
if(playerA.isWin()){
//board.show();
cout<" Winner! Game Over!!\n";
break;
}
//显示当前棋盘中所有棋子的位置。
board.show();
//玩家2放下一粒棋子
playerB.SetChess();
if(playerB.isWin()){
cout << playerB.WinName() << " Winner! Game Over!!\n";
break;
}
board.show();
}
//运行出错
return 1;
}
下面给出一些运行结果:
最后一个插进去满5个后显示赢,结束程序:
上面代码只实现了简单功能,图形画界面看起来并不是很好,还有很大改进空间。