前言
五子棋是世界智力运动会竞技项目之一,是一种两人对弈的纯策略型棋类游戏,是世界智力运动会竞技项目之一,通常双方分别使用黑白两色的棋子,下在棋盘直线与横线的交叉点上,先形成5子连线者获胜。
规则
(1)对局双方各执一色棋子。
(2)空棋盘开局。
(3)黑先、白后,交替下子,每次只能下一子。
(4)棋子下在棋盘的空白点上,棋子下定后,不得向其它点移动,不得从棋盘上拿掉或拿起另落别处。
(5)黑方的第一枚棋子可下在棋盘任意交叉点上。
棋盘是这个游戏构建的基础,我们首先来写棋盘
#ifndef CHESSBOARD_HPP
#define CHESSBOARD_HPP
#include "chess.hpp"
#include "config.hpp"
#include <cstring>
#include <errno.h>
class ChessBoard
{
public:
static ChessBoard* getInstance()
{
return cb;
}
void show()
{
char buf[1024] = {0};
FILE *fp = fopen(CHESS_BOARD_FILE,"r");
if(fp == NULL)
{
fprintf(stderr,"fail to open chessboard.txt:%s",strerror(errno));
return ;
}
cout << "\033[1;1H" << CHESS_BOARD_COLOR;
while(fgets(buf,sizeof(buf),fp) != NULL)
{
fputs(buf,stdout);
}
fclose(fp);
cout << "\033[0m";
}
bool isValidPostion(int line,int column)
{
if(line >= LINE || line < 0 || column >= COLUMN || column < 0)
return false;
return chess[line][column] == NULL ? true : false;
}
bool placeChess(Chess *chess)
{
int line = (chess->getY() - 1)/LINE_INTERVAL;
int column = (chess->getX() - 1)/COLUMN_INTERVAL;
if(isValidPostion(line,column))
{
this->chess[line][column] = chess;
chess->show();
curLine = line;
curColum = column;
return true;
}
return false;
}
bool isValidColorChess(int line,int column,char color)
{
if(line < 0 || line >= LINE || column < 0 || column >= COLUMN){
return false;
}
Chess *ch = chess[line][column];
if(ch == NULL){
return false;
}
if(ch->getColor() != color){
return false;
}
return true;
}
int getCurLine() const
{
return curLine;
}
int getCurColumn() const
{
return curColum;
}
private:
ChessBoard() : curLine(-1),curColum(-1)
{
for(int i = 0;i < LINE ;i++)
{
for(int j = 0;j < COLUMN; j++)
{
chess[i][j] = NULL;
}
}
}
~ChessBoard()
{
}
static ChessBoard *cb;
Chess *chess[LINE][COLUMN];
int curLine;
int curColum;
};
ChessBoard *ChessBoard::cb = new ChessBoard;
#endif接下来给棋盘设立颜色
#ifndef CURSOR_HPP
#define CURSOR_HPP
#include "config.hpp"
#include <iostream>
#include <cstdio>
using namespace std;
class Cursor
{
public:
Cursor() :x(X_CENTER),y(Y_CENTER)
{
show();
}
void show() const
{
printf("\033[%d;%dH",y,x);
}
void moveUp()
{
if(y - LINE_INTERVAL <= 0){
return ;
}
y -= LINE_INTERVAL;
show();
}
void moveDown()
{
if (y + LINE_INTERVAL > Y_MAX){
return ;
}
y += LINE_INTERVAL;
show();
}
void moveLeft()
{
if (x - COLUMN_INTERVAL <= 0){
return ;
}
x += LINE_INTERVAL;
show();
}
void moveRight()
{
if (x + COLUMN_INTERVAL > X_MAX)
{
return;
}
x += COLUMN_INTERVAL;
show();
}
void moveCenter()
{
x = X_CENTER;
y = Y_CENTER;
show();
}
int getX() const
{
return x;
}
int getY() const
{
return y;
}
private:
int x;
int y;
};
#endif
接下来定义棋子
#ifndef CHESS_HPP
#define CHESS_HPP
#include <iostream>
#include <cstdio>
using namespace std;
class Chess
{
public:
Chess(int x,int y,char color) : x(x),y(y),color(color)
{
}
virtual ~Chess ()
{
}
virtual void show() = 0;
int getX() const
{
return x;
}
int getY() const
{
return y;
}
char getColor() const
{
return color;
}
private:
int x;
int y;
char color;
};
#endif
黑棋
#ifndef BLACKCHESS_HPP
#define BLACKCHESS_HPP
#include "chess.hpp"
#include "config.hpp"
class BlackChess : public Chess
{
public:
BlackChess(int x,int y) : Chess(x, y, BLACK)
{
}
void show()
{
printf("\033[%d;%dH%s",getY(),getX() - 1,BLACK_COLOR);
printf("\033[%d;%dH",getY(),getX());
}
};
#endif
白棋
#ifndef WHITECHESS_HPP
#define WHITECHESS_HPP
#include "chess.hpp"
#include "config.hpp"
class WhiteChess : public Chess
{
public:
WhiteChess(int x,int y) : Chess(x, y, WHITE)
{
}
void show()
{
printf("\033[%d;%dH%s",getY(),getX() - 1,WHITE_COLOR);
printf("\033[%d;%dH",getY(),getX());
}
};
#endif
棋手
黑棋手
#ifndef BLACKPLAYER_HPP
#define BLACKPLAYER_HPP
#include "player.hpp"
#include "config.hpp"
#include "chessboard.hpp"
#include "blackchess.hpp"
class BlackPlayer : public Player
{
public:
BlackPlayer(const string &name) : Player(name,BLACK)
{
}
bool placeChess(int x,int y)
{
BlackChess *bc = new BlackChess(x,y);
if(!ChessBoard::getInstance()->placeChess(bc))
{
delete bc;
return false;
}
return true;
}
};
#endif
白棋手
#ifndef WHITEPLAYER_HPP
#define WHITEPLAYER_HPP
#include "player.hpp"
#include "config.hpp"
#include "chessboard.hpp"
#include "whitechess.hpp"
class WhitePlayer : public Player
{
public:
WhitePlayer(const string &name) : Player(name,WHITE)
{
}
bool placeChess(int x, int y)
{
WhiteChess *bc = new WhiteChess(x,y);
if (!ChessBoard::getInstance->placeChess(bc)){
delete bc;
return false;
}
return true;
}
};
#endif
裁判
#ifndef KEYHANDLE_HPP
#define KEYHANDLE_HPP
#include "Cursor.hpp"
#include "player.hpp"
#include <termios.h>
#include <unistd.h>
#include <stdlib.h>
class KeyHandle
{
public:
KeyHandle()
{
struct termios attr;
tcgetattr(0,&attr);
attr.c_lflag &= ~(ICANON | ECHO);
tcsetattr(0,TCSANOW,&attr);
}
~KeyHandle()
{
struct termios attr;
tcgetattr(0,&attr);
attr.c_lflag |= (ICANON | ECHO);
tcsetattr(0,TCSANOW,&attr);
}
bool waitPlayerPlaceChess(Player *Player)
{
char key = '\0';
bool ret = false;
while(1){
key = getchar();
switch(key){
case 'w':
case 'W':
cursor.moveUp();
break;
case 's':
case 'S':
cursor.moveDown();
break;
case 'a':
case 'A':
cursor.moveLeft();
break;
case 'd':
case 'D':
cursor.moveRight();
break;
case ' ':
ret = player->placeChess(cursor.getX(),cursor.getY());
break;
}
if(ret){
break;
}
}
}
private:
Cursor cursor;
};
#endif判定胜负条件
#ifndef ARBITRATION_HPP
#define ARBITRATION_HPP
#include "chessboard.hpp"
class Arbitration
{
public:
bool isWin(char color)
{
ChessBoard *cb = ChessBoard::getInstance();
int curLine = cb->getInstance();
int curColumn = cb->getCurColumn();
bool ret = false;
ret = isDirectionWin(curLine,curColumn,color,1,0);//水平方向
if(ret){
return true;
}
ret = isDirectionWin(curLine,curColumn,color,0,1);//垂直方向
if(ret){
return true;
}
ret = isDirectionWin(curLine,curColumn,color,1,1);//下坡方向
if(ret){
return true;
}
ret = isDirectionWin(curLine,curColumn,color,1,-1);//上坡方向
if(ret){
return true;
}
return false;
}
bool isDirectionWin(int line,int column,char color,int x,int y)
{
ChessBoard *cb = ChessBoard::getInstance();
int count = 1;
for(int i = 1;i<5;++i)
{
bool ret = cb->isValidColorChess(line + (i * y),column +(i * x),color );
if (!ret){
break;
}
++count;
}
for(int i = 1;i<5;++i)
{
bool ret = cb->isValidColorChess(line - (i * y),column - (i * x),color );
if (!ret){
break;
}
++count;
}
if (count >= 5){
return true;
}
return false;
}
};
#endif头文件棋子样貌定义,以及一些宏
#ifndef CONFIG_HPP
#define CONFIG_HPP
#define BLACK 0x1
#define WHITE 0X0
#define BLACK_COLOR "\033[31;40m[☠]"
#define WHITE_COLOR "\033[36;47m[☬]"
#define LINE 15
#define COLUMN 15
#define CHESS_BOARD_FILE "ChessBoard.txt"
#define CHESS_BOARD_COLOR "\033[43;37m"
#define LINE_INTERVAL 2
#define COLUMN_INTERVAL 4
#define X_MAX 57
#define Y_MAX 29
#define X_CENTER 29
#define Y_CENTER 15
#endif
以这个方式创建的五子棋项目会有一些问题,如果你的编辑框不够大,就会出现颜色泄露,属于正常现象,只需要在执行时拉大一点就可以了。
总结
以上就是今天所讲的主要内容,里面主要是首次运用VT100,就是给棋盘赋予颜色。
VT100是一个终端类型定义VT100控制码是用来在终端扩展显示的代码。主要用来在终端上任意坐标用不同的
颜色显示字符。所有的控制符是\033或\e打头(即ESC的ASCII码)用输出字符语句来输出。可以在命令行
用echo
命令,或者在C程序中用printf来输出VT100的控制字符。
版权声明:本文为m0_72084299原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。