【C++】<图形库> 三人成棋(面向对象写法)

news2024/10/5 9:13:54

 目录

一、游戏需求

二、程序架构

三、代码实现

四、实现效果

五、已知BUG


一、游戏需求

构建一个五子棋游戏,在自定义棋盘宽度和高度的基础上,实现三人对战功能,并且能判定谁输谁赢。


二、程序架构

(1) 对象分析:

【1】 需要一个棋盘(ChessBoard)类来绘制棋盘。

【2】有三人对战,用白棋、黑棋和黄棋区分。因此,需要构建白棋玩家、黑棋玩家和黄棋玩家。另外,每个玩家下的棋子用vector容器来装。每个玩家还应该具有判定自己是否赢得比赛的方法。由于vector容器和相关方法只有略微不同,可以先构建一个玩家基类(Player),再派生出白棋(WhitePlayer)、黑棋(BlackPlayer)和黄棋(YellowPlayer)玩家类。

【3】需要创建棋子类(ChessPiece),有坐标和颜色属性。当不同的玩家落子时,白棋、黑棋和黄棋玩家类会创建各自颜色的棋子。

【4】玩家根据鼠标点击来落子,因此需要一个鼠标类(Mouse)来返回鼠标信息。

【5】菜单类(Menu)将主要的逻辑封装好,便于在main()中调用。

(2) 文件构成:

有main.cpp、ChessBoard.cpp、Player.cpp(将涉及玩家的类都放于此)、ChessPiece.cpp、Mouse.cpp、Menu.cpp,还有对应的头文件。


三、代码实现

【1】main.cpp:

#include <iostream>
#include <graphics.h>
#include "ChessBoard.h"
#include "Menu.h"
#include "Mouse.h"
#include "Player.h"

/**************************************************************
  *说明:【1】若使用win11系统,需修改相关设置才能正常运行
  *	        设置-->系统-->开发者选项-->终端-->windows控制台主机
  *     【2】在创建棋盘对象时,可以自定义棋盘的宽度和高度
  ************************************************************/

int main()
{
	//创建相关对象
	ChessBoard board;	//棋盘对象
	Menu menu;			//菜单对象
	Mouse mouse;		//鼠标对象
	WhitePlayer wp;		//白棋玩家
	BlackPlayer bp;		//黑棋玩家
	YellowPlayer yp;	//黄棋玩家

	while (1) {
		//显示主交互界面
		int choice = menu.mainInterface();
		
		//根据choice显示不同界面
		switch (choice) {
		case '1'://游戏对战
			menu.startGame(mouse, board, wp, bp, yp);
			break;
		case '2'://游戏介绍
			menu.introInterface();
			break;
		case '0'://退出游戏
			return 0;
		}
	}
	return 0;
}

【2】Player.h:

#pragma once
#include <vector>
#include <algorithm>
#include "ChessPiece.h"
#include "Mouse.h"
#include "ChessBoard.h"


/***********************************************************
  * @类名:	Player
  * @摘要:	玩家基类(抽象类)
  * @作者:	柯同学
  * @注意:	派生类必须重写generatePiece方法
  *********************************************************/
class Player{
private:
	std::vector<ChessPiece> pieces;	//保存棋子的动态数组

public:
	virtual ~Player() {}			//虚析构函数:防止内存泄漏

	std::vector<ChessPiece>& getPieces();	//返回棋子动态数组引用

	virtual void generatePiece(Mouse& mouse, Player& p1, Player& p2) = 0;	//纯虚函数:玩家落子

	bool isWin(ChessBoard& board);	//判断当前玩家是否赢
};


/***********************************************************
  * @类名:	WhitePlayer
  * @摘要:	白玩家类(继承Player)
  * @作者:	柯同学
  * @注意:	generatePiece下白棋
  *********************************************************/
class BlackPlayer;
class YellowPlayer;
class WhitePlayer : public Player{
public:
	void generatePiece(Mouse& mouse, Player& p1, Player& p2) override;
};


/***********************************************************
  * @类名:	BlackPlayer
  * @摘要:	黑玩家类(继承Player)
  * @作者:	柯同学
  * @注意:	generatePiece下黑棋
  *********************************************************/
class BlackPlayer : public Player {
public:
	void generatePiece(Mouse& mouse, Player& p1, Player& p2) override;
};


/***********************************************************
  * @类名:	YellowPlayer
  * @摘要:	黄玩家类(继承Player)
  * @作者:	柯同学
  * @注意:	generatePiece下黄棋
  *********************************************************/
class YellowPlayer : public Player {
public:
	void generatePiece(Mouse& mouse, Player& p1, Player& p2) override;
};

【3】Player.cpp:

#include "Player.h"


/***********************************************************
  * @函数名:Player::getPieces
  * @功  能:返回棋子动态数组的引用
  * @参  数:无
  * @返回值:棋子动态数组的引用
  *********************************************************/
std::vector<ChessPiece>& Player::getPieces() {
	return this->pieces; 
}


/***********************************************************
  * @函数名:Player::isWin
  * @功  能:判断当前玩家是否赢得游戏
  * @参  数:board---棋盘对象
  * @返回值:true---赢得游戏,false---没赢游戏
  *********************************************************/
bool Player::isWin(ChessBoard& board) {
	/* 得到最近一次下的棋子 */
	ChessPiece lastChess;
	if (pieces.size() > 0) {
		lastChess = pieces[pieces.size() - 1];
	}
	/* 获胜情况1:左右五连 */
	int leftWinFlag = 0;//胜利标志:4则赢
	std::vector<ChessPiece>::iterator p;
	for (int i = -4; i <= 4; ++i) {
		//越界则跳过
		if ((lastChess.getX() + i * BOARD_INTERVAL < 0) ||
			(lastChess.getX() + i * BOARD_INTERVAL > board.getWidth())) {
			continue;
		}
		//查找连续相连的棋子
		ChessPiece targetChess(lastChess.getX() + i * BOARD_INTERVAL, lastChess.getY(), lastChess.getColor());
		p = std::find(pieces.begin(), pieces.end(), targetChess);
		if (p != pieces.end()) {
			leftWinFlag++;
		}
		else {
			leftWinFlag = 0;
		}
		//胜利
		if (leftWinFlag >= 5)
			return true;
	}

	/* 获胜情况2:上下五连 */
	int upWinFlag = 0;
	for (int i = -4; i <= 4; ++i) {
		//越界则跳过
		if ((lastChess.getY() + i * BOARD_INTERVAL < 0) ||
			(lastChess.getY() + i * BOARD_INTERVAL > board.getWidth())) {
			continue;
		}
		//查找连续相连的棋子
		ChessPiece targetChess(lastChess.getX(), lastChess.getY() + i * BOARD_INTERVAL, lastChess.getColor());
		p = std::find(pieces.begin(), pieces.end(), targetChess);
		if (p != pieces.end()) {
			upWinFlag++;
		}
		else {
			upWinFlag = 0;
		}
		//胜利
		if (upWinFlag >= 5)
			return true;
	}

	/* 获胜情况3:左上--右下(斜右)五连 */
	int diarightWinFlag = 0;
	for (int i = -4; i <= 4; ++i) {
		//越界则跳过
		if ((lastChess.getY() + i * BOARD_INTERVAL < 0) ||
			(lastChess.getY() + i * BOARD_INTERVAL > board.getWidth())) {
			continue;
		}
		//查找连续相连的棋子
		ChessPiece targetChess(lastChess.getX() + i * BOARD_INTERVAL, lastChess.getY() - i * BOARD_INTERVAL, lastChess.getColor());
		p = std::find(pieces.begin(), pieces.end(), targetChess);
		if (p != pieces.end()) {
			diarightWinFlag++;
		}
		else {
			diarightWinFlag = 0;
		}
		//胜利
		if (diarightWinFlag >= 5)
			return true;
	}

	/* 获胜情况4:左下--右上(斜左)五连 */
	int dialeftWinFlag = 0;
	for (int i = -4; i <= 4; ++i) {
		//越界则跳过
		if ((lastChess.getY() + i * BOARD_INTERVAL < 0) ||
			(lastChess.getY() + i * BOARD_INTERVAL > board.getWidth())) {
			continue;
		}
		//查找连续相连的棋子
		ChessPiece targetChess(lastChess.getX() + i * BOARD_INTERVAL, lastChess.getY() + i * BOARD_INTERVAL, lastChess.getColor());
		p = std::find(pieces.begin(), pieces.end(), targetChess);
		if (p != pieces.end()) {
			dialeftWinFlag++;
		}
		else {
			dialeftWinFlag = 0;
		}
		//胜利
		if (dialeftWinFlag >= 5)
			return true;
	}
	return false;
}


/***********************************************************
  * @函数名:createNonDUP(中介函数)
  * @功  能:生成不重复的棋
  * @参  数:my---当前对象
  * @参  数:bplay---黑棋玩家
  * @参  数:yplay---白棋玩家
  * @参  数:target---目标棋子
  * @参  数:mouse---鼠标对象
  * @返回值:无
  *********************************************************/
void createNonDUP(Player& my, Player& bplay, Player& yplay, ChessPiece& target, Mouse& mouse) {
	//查找三个玩家的棋库中是否有target的坐标
	std::vector<ChessPiece>::iterator wp, bp, yp;
	wp = find(my.getPieces().begin(), my.getPieces().end(), target);
	bp = find(bplay.getPieces().begin(), bplay.getPieces().end(), target);
	yp = find(yplay.getPieces().begin(), yplay.getPieces().end(), target);
	//不存在重复的棋就加入对应容器,并绘制
	if (wp == my.getPieces().end() && bp == bplay.getPieces().end()
		&& yp == yplay.getPieces().end())
	{
		my.getPieces().push_back(target);
		setfillcolor(target.getColor());
		fillcircle(target.getX(), target.getY(), PIECE_RADIUS);
		mouse.setClickTotal(mouse.getClickTotal() + 1);
	}
}


/***********************************************************
  * @函数名:WhitePlayer::generatePiece
  * @功  能:白玩家:下白棋,并将棋子对象加入vector容器中
  * @参  数:mouse---鼠标对象
  * @参  数:p1---其他玩家
  * @参  数:p2---其他玩家
  * @返回值:无
  *********************************************************/
void WhitePlayer::generatePiece(Mouse& mouse, Player& p1, Player& p2) {
	if (mouse.detectClick()) {
		//创建棋对象,设置颜色为白色
		ChessPiece cp(mouse.getMouseMesg().x, mouse.getMouseMesg().y, WHITE);
		cp.fixChessPiece();
		//生成不重复的棋子,并绘制
		createNonDUP(*this, p1, p2, cp, mouse);
	}
}


/***********************************************************
  * @函数名:BlackPlayer::generatePiece
  * @功  能:黑玩家:下黑棋,并将棋子对象加入vector容器中
  * @参  数:mouse---鼠标对象
  * @参  数:p1---其他玩家
  * @参  数:p2---其他玩家
  * @返回值:无
  *********************************************************/
void BlackPlayer::generatePiece(Mouse& mouse, Player& p1, Player& p2) {
	if (mouse.detectClick()) {
		//创建棋对象,设置颜色为黑色
		ChessPiece cp(mouse.getMouseMesg().x, mouse.getMouseMesg().y, BLACK);
		cp.fixChessPiece();
		//生成不重复的棋子,并绘制
		createNonDUP(*this, p1, p2, cp, mouse);
	}
}


/***********************************************************
  * @函数名:YellowPlayer::generatePiece
  * @功  能:黄玩家:下黄棋,并将棋子对象加入vector容器中
  * @参  数:mouse---鼠标对象
  * @参  数:p1---其他玩家
  * @参  数:p2---其他玩家
  * @返回值:无
  *********************************************************/
void YellowPlayer::generatePiece(Mouse& mouse, Player& p1, Player& p2) {
	if (mouse.detectClick()) {
		//创建棋对象,设置颜色为黄色
		ChessPiece cp(mouse.getMouseMesg().x, mouse.getMouseMesg().y, YELLOW);
		cp.fixChessPiece();
		//生成不重复的棋子,并绘制
		createNonDUP(*this, p1, p2, cp, mouse);
	}
}

【4】ChessPiece.h:

#pragma once
#include <graphics.h>
#include "Mouse.h"
#include "ChessBoard.h"
#define PIECE_RADIUS	5	//棋子半径


/***********************************************************
  * @类名:	ChessPiece
  * @摘要:	棋子类
  * @作者:	柯同学
  * @注意:	默认棋子为白色
  *********************************************************/
class ChessPiece {
private:
	int x;		//横坐标
	int y;		//纵坐标
	int color;	//白色、黑色、黄色(分别对应白玩家、黑玩家、黄玩家)
public:
	ChessPiece(int x = 0, int y = 0, int color = WHITE) : x(x), y(y), color(color) {}

	bool operator==(const ChessPiece& cp);	//比较两个棋子坐标是否相等

	void setColor(int color);			//设置棋子颜色

	void setXY(int x, int y);			//设置棋子坐标

	int getX() { return x; }			//获取棋子x坐标

	int getY() { return y; }			//获取棋子y坐标

	int getColor() { return color; }	//获取棋子颜色

	void fixChessPiece();				//修正棋子坐标,并绘制棋子
};

【5】ChessPiece.cpp:

#include "ChessPiece.h"


/***********************************************************
  * @函数名:operator==
  * @功  能:==运算符重载:比较两个棋子的坐标是否相等
  * @参  数:cp---另一个棋子
  * @返回值:无
  *********************************************************/
bool ChessPiece::operator==(const ChessPiece& cp) {
	if (this->x == cp.x && this->y == cp.y)
		return true;
	return false;
}


/***********************************************************
  * @函数名:setColor
  * @功  能:设置棋子颜色
  * @参  数:color---棋子的颜色
  * @返回值:无
  *********************************************************/
void ChessPiece::setColor(int color) {
	this->color = color;
}


/***********************************************************
  * @函数名:setXY
  * @功  能:设置棋子坐标
  * @参  数:x---棋子的横坐标
  * @参  数:y---棋子的纵坐标
  * @返回值:无
  *********************************************************/
void ChessPiece::setXY(int x, int y) {
	this->x = x;
	this->y = y;
}


/***********************************************************
  * @函数名:createChessPiece
  * @功  能:修正棋子坐标
  * @参  数:无
  * @返回值:无
  *********************************************************/
void ChessPiece::fixChessPiece() {
	if (this->x >= 0 && this->y >= 0) {//范围合理
		if (this->x % BOARD_INTERVAL > BOARD_INTERVAL / 2) {
			int i;
			for (i = 0; i * BOARD_INTERVAL < this->x; i++);
			this->x = i * BOARD_INTERVAL;
		}
		else {
			this->x -= this->x % BOARD_INTERVAL;
		}
		if (this->y % BOARD_INTERVAL > BOARD_INTERVAL / 2) {
			int i;
			for (i = 0; i * BOARD_INTERVAL < this->y; i++);
			this->y = i * BOARD_INTERVAL;
		}
		else {
			this->y -= this->y % BOARD_INTERVAL;
		}
	}
	else {//坐标越界
		this->x = 0;
		this->y = 0;
	}
}

【6】ChessBoard.h:

#pragma once
#include <iostream>
#include <graphics.h>

#define BOARD_INTERVAL	20	//网格的间隔

/***********************************************************
  * @类名:	ChessBoard
  * @摘要:	棋盘类
  * @作者:	柯同学
  * @注意:	默认宽度和高度为400,400
  *********************************************************/
class ChessBoard {
private:
	int width;		//棋盘宽度
	int height;		//棋盘高度
public:
	ChessBoard(int w = 400, int h = 400) : width(w), height(h) {}

	void setWidth(int width);	//设置棋盘宽度

	void setHeight(int height);	//设置棋盘高度

	int getWidth();				//获取棋盘宽度

	int getHeight();			//获取棋盘高度

	void showBoard();			//绘制棋盘网格
};

【7】ChessBoard.cpp:

#include "ChessBoard.h"


/***********************************************************
  * @函数名:setWidth
  * @功  能:设置棋盘宽度
  * @参  数:width---要设置的属性
  * @返回值:无
  *********************************************************/
void ChessBoard::setWidth(int width) {
	this->width = width;
}


/***********************************************************
  * @函数名:setHeight
  * @功  能:设置棋盘高度
  * @参  数:height---要设置的属性
  * @返回值:无
  *********************************************************/
void ChessBoard::setHeight(int height) {
	this->height = height;
}


/***********************************************************
  * @函数名:getWidth
  * @功  能:获取棋盘宽度
  * @参  数:无
  * @返回值:棋盘的宽度
  *********************************************************/
int ChessBoard::getWidth() {
	return width;
}


/***********************************************************
  * @函数名:getHeight
  * @功  能:获取棋盘高度
  * @参  数:无
  * @返回值:棋盘的高度
  *********************************************************/
int ChessBoard::getHeight() {
	return height;
}


/***********************************************************
  * @函数名:showBoard
  * @功  能:绘制棋盘并显示
  * @参  数:无
  * @返回值:无
  *********************************************************/
void ChessBoard::showBoard() {
	std::cout << width << " " << height << std::endl;
	for (int i = 0; i <= width; i += BOARD_INTERVAL) {
		line(0, i, width, i);//横线
		line(i, 0, i, height);//竖线
	}
}

【8】Mouse.h:

#pragma once
#include <graphics.h>
#include <iostream>
#include "ChessPiece.h"

/***********************************************************
  * @类名:	Mouse
  * @摘要:	鼠标类
  * @作者:	柯同学
  * @注意:	无
  *********************************************************/
class Mouse {
private:
	ExMessage mouseMesg;	//鼠标信息,包含坐标、点击的键
	int clickTotal;			//鼠标有效点击次数
public:
	Mouse() : clickTotal(0) {}		//无参构造:鼠标次数初始化为0

	void setClickTotal(int num);	//设置鼠标点击次数

	int getClickTotal();			//获取鼠标点击次数

	ExMessage& getMouseMesg();		//获取鼠标信息

	bool detectClick();				//返回鼠标是否被点击
};

【9】mouse.cpp:

#include "Mouse.h"


/***********************************************************
  * @函数名:setClickTotal
  * @功  能:设置鼠标有效点击次数
  * @参  数:num---要设置的次数
  * @返回值:无
  *********************************************************/
void Mouse::setClickTotal(int num) {
	this->clickTotal = num;
}


/***********************************************************
  * @函数名:getClickTotal
  * @功  能:获取鼠标有效点击次数
  * @参  数:无
  * @返回值:鼠标有效点击次数
  *********************************************************/
int Mouse::getClickTotal() {
	return this->clickTotal;
}


/***********************************************************
  * @函数名:getMouseMesg
  * @功  能:获取鼠标信息:包含点击的坐标、鼠标键
  * @参  数:无
  * @返回值:鼠标信息
  *********************************************************/
ExMessage& Mouse::getMouseMesg() {
	return this->mouseMesg;
}


/***********************************************************
  * @函数名:detectClick
  * @功  能:返回鼠标是否被点击
  * @参  数:无
  * @返回值:true---鼠标被点击,false---鼠标没有被点击
  *********************************************************/
bool Mouse::detectClick() {
	if (peekmessage(&this->mouseMesg) && this->mouseMesg.message == WM_LBUTTONDOWN) {//鼠标左击
		return true;
	}
	return false;
}

【10】Menu.h:

#pragma once
#include <iostream>
#include <graphics.h>
#include <conio.h>
#include "ChessBoard.h"
#include "Mouse.h"
#include "Player.h"


/***********************************************************
  * @类名:	Menu
  * @摘要:	菜单类
  * @作者:	柯同学
  * @注意:	无
  *********************************************************/
class Menu {
/*************以下为Menu内部调用的函数***********************/
private:
	void multiPlayerPK(Mouse& mouse,		//哪个玩家落子
						WhitePlayer& wp,
						BlackPlayer& bp,
						YellowPlayer& yp);	

	void multiPlayerWin(ChessBoard& board,	//哪个玩家获胜
						WhitePlayer& wp,
						BlackPlayer& bp,
						YellowPlayer& yp);	

/*************以下为menu对外开放的函数**********************/
public:
	int mainInterface();					//主界面显示

	void introInterface();					//游戏介绍界面

	void startGame(Mouse& mouse, ChessBoard& board, 
				   WhitePlayer& wp, BlackPlayer& bp,
				   YellowPlayer& yp);		//三人对战界面
};

【11】Menu.cpp:

#include "Menu.h"


/***********************************************************
  * @函数名:mainInterface
  * @功  能:游戏主界面
  * @参  数:无
  * @返回值:无
  *********************************************************/
int Menu::mainInterface() {
	initgraph(800, 600);
	setbkcolor(WHITE);
	cleardevice();
	settextstyle(70, 0, "Arial");
	settextcolor(BLACK);
	outtextxy(150, 120, "小游戏:三人成棋");
	setlinecolor(BLACK);
	settextstyle(50, 0, "Arial");
	outtextxy(280, 250, "1.开始游戏");
	outtextxy(280, 350, "2.游戏介绍");
	outtextxy(280, 450, "0.退出游戏");
	int keyNum = -1;
	while (1) {
		if (_kbhit()) {
			keyNum = _getch();
			if (keyNum == '1' || keyNum == '2' || keyNum == '0')
				break;
		}
	}
	closegraph();
	return keyNum;
}


/***********************************************************
  * @函数名:introInterface
  * @功  能:游戏介绍的界面
  * @参  数:无
  * @返回值:无
  *********************************************************/
void Menu::introInterface() {
	initgraph(800, 600, 0);
	setbkcolor(WHITE);
	cleardevice();
	settextstyle(70, 0, "Arial");
	settextcolor(BLACK);
	outtextxy(0, 0, "游戏介绍:");
	settextstyle(50, 0, "Arial");
	outtextxy(0, 100, "【1】游戏人数:三人");
	outtextxy(0, 200, "【2】下棋顺序:白棋、黑棋、黄棋");
	outtextxy(0, 300, "【3】返回提示:默认按0返回");
	outtextxy(0, 400, "【4】其他说明:基本已实现,但仍有bug");
	outtextxy(450, 500, "按0返回主菜单!");
	while (!_kbhit() || _getch() != '0');
	closegraph();
}


/***********************************************************
  * @函数名:startGame
  * @功  能:三人对战界面
  * @参  数:mouse---鼠标对象
  * @参  数:board---棋盘对象
  * @参  数:wp---白棋玩家
  * @参  数:bp---黑棋玩家
  * @参  数:yp---黄棋玩家
  * @返回值:无
  *********************************************************/
void Menu::startGame(Mouse& mouse, ChessBoard& board, WhitePlayer& wp, 
					 BlackPlayer& bp, YellowPlayer& yp) 
{
	//创建窗口,显示棋盘
	initgraph(board.getWidth(), board.getHeight(), 0);
	setbkcolor(RGB(245, 222, 181));
	setlinecolor(BLACK);
	cleardevice();
	board.showBoard();
	//主循环
	while (!_kbhit() || _getch() != '0') {//按'0'退出程序
		//玩家落子
		multiPlayerPK(mouse, wp, bp, yp);
		//玩家胜负判定
		multiPlayerWin(board, wp, bp, yp);
	}
	closegraph();
}


/***********************************************************
  * @函数名:multiPlayerPK
  * @功  能:确定哪个玩家落子,根据鼠标有效点击次数
  * @参  数:mouse---鼠标对象
  * @参  数:wp---白棋玩家
  * @参  数:bp---黑棋玩家
  * @参  数:yp---黄棋玩家
  * @返回值:无
  *********************************************************/
void Menu::multiPlayerPK(Mouse& mouse, WhitePlayer& wp, 
						 BlackPlayer& bp, YellowPlayer& yp)
{
	if (mouse.getClickTotal() % 3 == 0) {
		wp.generatePiece(mouse, bp, yp);//白棋落子
	}
	else if (mouse.getClickTotal() % 3 == 1) {
		bp.generatePiece(mouse, wp, yp);//黑棋落子
	}
	else {
		yp.generatePiece(mouse, wp, bp);//黄棋落子
	}
		
}


/***********************************************************
  * @函数名:multiPlayerWin
  * @功  能:确定哪个玩家获胜
  * @参  数:board---棋盘对象
  * @参  数:wp---白棋玩家
  * @参  数:bp---黑棋玩家
  * @参  数:yp---黄棋玩家
  * @返回值:无
  *********************************************************/
void Menu::multiPlayerWin(ChessBoard& board, WhitePlayer& wp, 
						  BlackPlayer& bp, YellowPlayer& yp) 
{
	if (wp.isWin(board)) {
		cleardevice();
		settextcolor(BLACK);
		settextstyle(30, 0, "Arial");
		outtextxy(25, board.getHeight() / 2 - 30, "白棋获胜!按0返回主界面!");
	}
	else if (bp.isWin(board)) {
		cleardevice();
		settextcolor(BLACK);
		settextstyle(30, 0, "Arial");
		outtextxy(25, board.getHeight() / 2 - 30, "黑棋获胜!按0返回主界面!");
	}
	else if (yp.isWin(board)) {
		cleardevice();
		settextcolor(BLACK);
		settextstyle(30, 0, "Arial");
		outtextxy(25, board.getHeight() / 2 - 30, "黄棋获胜!按0返回主界面!");
	}
}


四、实现效果

五、已知BUG

由于时间原因,已有的BUG在未来有时间后再修改:

【1】一局游戏下完后,从主菜单进来可能会停留在上次下棋后的界面。

【2】游戏输赢判定后,点击屏幕依然能下棋。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1693589.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

人工智能-YOLOv10-行人和车辆检测-yolo改进测距测速代码和原理

YOLOv10: 实时端到端目标检测技术的全新突破 YOLOv10代表了实时目标检测领域的重大进展&#xff0c;是YOLO系列模型的最新迭代&#xff0c;专为追求极致效率与精度平衡的应用场景设计。此项目由北京大学机器智能研究组&#xff08;THU-MIG&#xff09;的Ao Wang、Hui Chen、Li…

直击CHIMA 2024│美创全栈全新数安能力精彩亮相

5月17日&#xff0c;中国医院信息网络大会(CHIMA 2024)在南京正式拉开帷幕。本次大会以新质生产力理论为指导&#xff0c;以深化应用&#xff0c;融合创新&#xff0c;用信息技术赋能医院高质量发展为主题。 作为医疗数据安全的创新引领者和深耕实践者&#xff0c;美创科技再次…

IDEA通过tomcat运行注意事项

配置run--》edit configurations 以下的A B部分要保持一致 A和B的路径要保持一致

vue/core源码中ref源码的js化

起源&#xff1a; 当看见reactivity文件中的ref.ts文件长达五百多的ts代码后&#xff0c;突发奇想想看下转化成js有多少行。 进行转化&#xff1a; let shouldTrack true; // Define shouldTrack variable let activeEffect null; // Define activeEffect variable// 定义…

MATLAB system identification系统辨识app的使用

系统辨识 前言系统辨识第一步 选取时域数据到app第二步 分割数据第三步 设置传递函数的参数第四步 Estimate第五步 结束 前言 接上节&#xff1a;simulink-仿真以及PID参数整定 系统模型的辨识工作&#xff0c;在控制领域&#xff0c;一般用于开发控制器的先手工作。一般而言…

curl: (60) SSL certificate problem: self-signed certificat

目录&#xff1a; 1、背景2、测试结果 1、背景 今天帮忙客户排查问题&#xff0c;报错请求超时&#xff0c;但是ping客户的ip以及测试端口都是通的&#xff0c;最终不得不从中台服务器上发起请求客户回调接口&#xff0c;报错如下&#xff1a; 怀疑是客户的证书有问题&#xf…

测试网0撸大毛 — AI 公链ALIENX推出HAL Testnet活动(含保姆级教程)

近期&#xff0c;OpenAI推出了新一代的GPT-4o让AI再次获得关注。AI硬件销售商英伟达的股价也突破1000美元&#xff0c;市值攀升到2.6万亿美元。AI继续影响到我们生活的方方面面。 在加密货币行业&#xff0c;市场行情也逐渐走出低谷。以太坊现货ETF被批准&#xff0c;为整个市场…

51单片机 简单计算机实现

书接上回;http://t.csdnimg.cn/T4b0W 键盘位置如上 效果图 因为是四位,就没显示等于号, 而且段数比较少 显示不出来加号 所以 A ; B - ; C *; D / 基本原来都一样. 代码奉上 #include <reg51.h>#include <STRING.H>//利用矩阵键盘按键按下依次在数码管显…

九、OpenAI之图片生成(Image generation)

学习用DALL.E的API怎样生成和操作图片 1 介绍 图片API提供3个方法来和图片进行交互&#xff1a; 从0开始基于文字提示创建图片(DALL.E 3 and DALL.E2)基于一个新的提示词&#xff0c;通过让模型替换已有图像的某些区域来创建图像的编辑版本;&#xff08;DALL.E2&#xff09;…

2024洗地机哪个牌子好?洗地机十大品牌

洗地机在不同家庭环境中都能发挥其独特的优势&#xff0c;无论是大面积的地板还是狭小的角落&#xff0c;都能轻松应对。 对于有孩子或宠物的家庭&#xff0c;地面上经常会有各种杂物和污渍&#xff0c;洗地机强大的吸力和深度清洁功能&#xff0c;可以迅速清理掉这些脏东西&a…

嵩山为什么称为三水之源

三水指黄河、淮河、济河&#xff0c;这三条河流环绕在嵩山周边。 黄河横亘在嵩山北部&#xff0c;其支流伊洛河从西南方环绕嵩山&#xff0c;然后汇入黄河。济河&#xff0c;古称济水&#xff0c;源自济源王屋山&#xff0c;自身河道在东晋时代被黄河夺占&#xff0c;从此消失。…

C#_库的引用

类库的引用 还可以自己引用类库&#xff1a;解决方案-添加-新建项目 主程序 using System; using System.Windows.Forms; using Tools;namespace ConsoleApp2 {class Program{static void Main(string[] args){//Console.WriteLine("helloword");// Form form ne…

“腾讯云 AI 代码助手”体验

一、“腾讯云 AI 代码助手”体验 1、注册账号并进行实名认证 2、进入开发环境 3、体验javascript简单函数 代码如下&#xff1a; //请写一个两个日期计算的函数 function dateDiff(date1, date2) {return date2.getTime() - date1.getTime(); } var date1 new Date("2…

基于JAVA GUI体育馆管理系统的会员功能

Java GUI即Java图形用户界面&#xff0c;是一种使用图形化元素&#xff08;如窗口、按钮、文本框等&#xff09;来构建用户界面的技术。它基于Java的Swing框架&#xff0c;可以用于创建各种复杂的用户界面&#xff0c;包括窗口、对话框、菜单、按钮、文本框、复选框、下拉列表等…

安卓实现5个底部导航栏切换fragment

步骤&#xff0c;写 5 个 fragment 自定义的类5个布局文件&#xff1a; package com.xmkjsoft.xhgh.fragment;import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup;import androidx.annotation.NonNul…

焦化超低排平台选哪家好?(已解答)

在环保政策日益严格的背景下&#xff0c;焦化行业的超低排放改造成为企业转型升级的必经之路。朗观视觉小编建议&#xff0c;选择合适的焦化超低排平台对于确保改造效果和实现可持续发展具有重要意义。本文将从多个维度为您提供一份全面的评估与选择指南&#xff0c;帮助您在众…

Python_文件操作_学习

目录 一、关于文件的打开和关闭 1. 文件的打开 2.文件的关闭 二、文件的读取 1. 文件的读_r 2. 使用readline 3.使用readlines 三、文件的写入 1. 文本的新建写入 2.文本的追加写入 四、文件的删除和重命名 1.文件的重命名 2.文件的删除 五、文件的定位读写 1.t…

java: 无法访问org.springframework.ldap.core.LdapTemplate

完整错误&#xff1a; java: 无法访问org.springframework.ldap.core.LdapTemplate错误的类文件: /E:/apache-maven-3.6.3/repository/org/springframework/ldap/spring-ldap-core/3.2.3/spring-ldap-core-3.2.3.jar!/org/springframework/ldap/core/LdapTemplate.class类文件具…

微火问答:全域外卖和本地生活服务是同个项目吗?

当前&#xff0c;本地生活赛道火爆程度不断升级&#xff0c;作为其主要板块之一的团购外卖也持续迸发出新的活力。而全域运营的出现无疑是给团购外卖这把正在熊熊燃烧的烈火&#xff0c;又添了一把新柴&#xff01; 所谓全域运营&#xff0c;简单来说&#xff0c;就是指所有领…

英语学习笔记25——Mrs. Smith‘s kitchen

Mrs. Smith’s kitchen 史密斯太太的厨房 词汇 Vocabulary Mrs. 夫人【已婚】 复习&#xff1a;Mr. 先生 全名 / 姓    Mrs. 夫人 全名 / 丈夫的姓    Miss 小姐&#xff08;未婚&#xff09; 全名 / 姓    Ms. 女士 全名 / 姓 查看婚姻状况&#xff0c;可以观察…