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个后显示赢,结束程序:
上面代码只实现了简单功能,图形画界面看起来并不是很好,还有很大改进空间。
加载全部内容