基于c++的五子棋项目

前言

五子棋是世界智力运动会竞技项目之一,是一种两人对弈的纯策略型棋类游戏,是世界智力运动会竞技项目之一,通常双方分别使用黑白两色的棋子,下在棋盘直线与横线的交叉点上,先形成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版权协议,转载请附上原文出处链接和本声明。