亲宝软件园·资讯

展开

C++五子棋游戏

Dandelion_gong 人气:0

在实现五子棋小游戏时,首先应该分为棋盘和玩家,我们先定义两个类:chessboard、player。分别提供棋盘的构造和玩家及游戏规则的确定。下面我们看下代码:

chessboard.h: 对棋盘chessboard类型进行定义

#ifndef _CHESSBOARD_H_
#define _CHESSBOARD_H_

#include <iostream>

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 <iostream>
#include <cstdlib>
#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 <iostream>
#include <string>
#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 <iostream>
#include <cstdlib>
#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 <iostream>
#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<<playerA.WinName()<<" 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个后显示赢,结束程序:

上面代码只实现了简单功能,图形画界面看起来并不是很好,还有很大改进空间。

加载全部内容

相关教程
猜你喜欢
用户评论