好的,以下是一个使用 easyX 编写的五子棋程序,包含了悔棋和认输功能:
```cpp
#include <graphics.h>
#include <conio.h>
#include <time.h>
// 定义棋盘格子大小、边框宽度、棋子半径
const int CELL_SIZE = 40;
const int BORDER_WIDTH = 2;
const int CHESS_RADIUS = CELL_SIZE / 2 - BORDER_WIDTH;
// 定义棋盘大小、起始坐标
const int BOARD_SIZE = 15;
const int BOARD_X = CELL_SIZE;
const int BOARD_Y = CELL_SIZE;
// 定义窗口大小
const int WINDOW_WIDTH = CELL_SIZE * (BOARD_SIZE + 2);
const int WINDOW_HEIGHT = CELL_SIZE * (BOARD_SIZE + 2);
// 定义棋子颜色,0表示无棋子,1表示黑子,2表示白子
const int CHESS_COLOR[3] = { 0, RGB(0, 0, 0), RGB(255, 255, 255) };
// 定义游戏状态,0表示未开始,1表示进行中,2表示黑方胜利,3表示白方胜利,4表示平局
const int GAME_STATE[5] = { 0, 1, 2, 3, 4 };
// 定义游戏数据结构
struct GameData
{
int board[BOARD_SIZE][BOARD_SIZE]; // 棋盘
int gameState; // 游戏状态
int turn; // 下棋方,0表示黑方,1表示白方
int winner; // 胜者,0表示黑方,1表示白方
void init()
{
memset(board, 0, sizeof(board));
gameState = GAME_STATE[0];
turn = 0;
winner = -1;
}
void drawBoard()
{
// 绘制棋盘边框
setlinecolor(RGB(0, 0, 0));
setlinestyle(PS_SOLID, BORDER_WIDTH);
rectangle(BOARD_X - BORDER_WIDTH, BOARD_Y - BORDER_WIDTH,
BOARD_X + CELL_SIZE * BOARD_SIZE + BORDER_WIDTH,
BOARD_Y + CELL_SIZE * BOARD_SIZE + BORDER_WIDTH);
// 绘制棋盘格子
for (int i = 0; i < BOARD_SIZE; i++)
{
for (int j = 0; j < BOARD_SIZE; j++)
{
setfillcolor(RGB(214, 175, 87));
solidrectangle(BOARD_X + i * CELL_SIZE, BOARD_Y + j * CELL_SIZE,
BOARD_X + (i + 1) * CELL_SIZE, BOARD_Y + (j + 1) * CELL_SIZE);
}
}
// 绘制星位
setfillcolor(RGB(0, 0, 0));
solidcircle(BOARD_X + 3 * CELL_SIZE, BOARD_Y + 3 * CELL_SIZE, 4);
solidcircle(BOARD_X + 11 * CELL_SIZE, BOARD_Y + 3 * CELL_SIZE, 4);
solidcircle(BOARD_X + 7 * CELL_SIZE, BOARD_Y + 7 * CELL_SIZE, 4);
solidcircle(BOARD_X + 3 * CELL_SIZE, BOARD_Y + 11 * CELL_SIZE, 4);
solidcircle(BOARD_X + 11 * CELL_SIZE, BOARD_Y + 11 * CELL_SIZE, 4);
}
void drawChess(int x, int y)
{
// 计算棋子中心坐标
int cx = BOARD_X + x * CELL_SIZE + CELL_SIZE / 2;
int cy = BOARD_Y + y * CELL_SIZE + CELL_SIZE / 2;
// 绘制棋子
setfillcolor(CHESS_COLOR[board[x][y]]);
solidcircle(cx, cy, CHESS_RADIUS);
}
void play(int x, int y)
{
if (board[x][y] != 0) return; // 如果该位置已有棋子,返回
board[x][y] = turn + 1;
drawChess(x, y);
winner = checkWinner(x, y);
if (winner != -1)
{
gameState = GAME_STATE[winner + 2];
}
else if (isTie())
{
gameState = GAME_STATE[4];
}
else
{
turn = !turn;
}
}
int checkWinner(int x, int y)
{
int i, j, k, count;
// 横向判断
count = 0;
for (i = x - 4; i <= x + 4; i++)
{
if (i < 0 || i > BOARD_SIZE - 1) continue;
if (board[i][y] == turn + 1) count++;
else count = 0;
if (count == 5) return turn;
}
// 纵向判断
count = 0;
for (j = y - 4; j <= y + 4; j++)
{
if (j < 0 || j > BOARD_SIZE - 1) continue;
if (board[x][j] == turn + 1) count++;
else count = 0;
if (count == 5) return turn;
}
// 斜向判断(左上-右下)
count = 0;
for (k = -4; k <= 4; k++)
{
i = x + k;
j = y + k;
if (i < 0 || i > BOARD_SIZE - 1 || j < 0 || j > BOARD_SIZE - 1) continue;
if (board[i][j] == turn + 1) count++;
else count = 0;
if (count == 5) return turn;
}
// 斜向判断(左下-右上)
count = 0;
for (k = -4; k <= 4; k++)
{
i = x + k;
j = y - k;
if (i < 0 || i > BOARD_SIZE - 1 || j < 0 || j > BOARD_SIZE - 1) continue;
if (board[i][j] == turn + 1) count++;
else count = 0;
if (count == 5) return turn;
}
return -1;
}
bool isTie()
{
for (int i = 0; i < BOARD_SIZE; i++)
{
for (int j = 0; j < BOARD_SIZE; j++)
{
if (board[i][j] == 0) return false;
}
}
return true;
}
void undo()
{
// 找到上一步棋子的坐标,并将其擦除
int x = -1, y = -1;
for (int i = BOARD_SIZE - 1; i >= 0; i--)
{
for (int j = BOARD_SIZE - 1; j >= 0; j--)
{
if (board[i][j] != 0)
{
x = i;
y = j;
board[i][j] = 0;
break;
}
}
if (x != -1 && y != -1) break;
}
if (x == -1 || y == -1) return;
// 重新绘制棋盘和棋子
clearrectangle(BOARD_X + x * CELL_SIZE, BOARD_Y + y * CELL_SIZE,
BOARD_X + (x + 1) * CELL_SIZE, BOARD_Y + (y + 1) * CELL_SIZE);
drawBoard();
for (int i = 0; i < BOARD_SIZE; i++)
{
for (int j = 0; j < BOARD_SIZE; j++)
{
if (board[i][j] != 0)
{
drawChess(i, j);
}
}
}
// 恢复游戏状态
gameState = GAME_STATE[1];
turn = !turn;
winner = -1;
}
};
// 定义全局变量
GameData game;
// 定义悔棋和认输按钮位置
const int BUTTON_X = BOARD_X + CELL_SIZE * (BOARD_SIZE + 1) + 20;
const int BUTTON_Y = BOARD_Y + CELL_SIZE * 3;
const int BUTTON_WIDTH = 100;
const int BUTTON_HEIGHT = 40;
// 绘制悔棋按钮
void drawUndoButton()
{
setfillcolor(RGB(255, 0, 0));
settextcolor(RGB(255, 255, 255));
settextstyle(16, 0, _T("宋体"));
rectangle(BUTTON_X, BUTTON_Y, BUTTON_X + BUTTON_WIDTH, BUTTON_Y + BUTTON_HEIGHT);
outtextxy(BUTTON_X + 20, BUTTON_Y + 10, _T("悔棋"));
}
// 绘制认输按钮
void drawGiveUpButton()
{
setfillcolor(RGB(255, 0, 0));
settextcolor(RGB(255, 255, 255));
settextstyle(16, 0, _T("宋体"));
rectangle(BUTTON_X, BUTTON_Y + BUTTON_HEIGHT + 20,
BUTTON_X + BUTTON_WIDTH, BUTTON_Y + BUTTON_HEIGHT * 2 + 20);
outtextxy(BUTTON_X + 20, BUTTON_Y + BUTTON_HEIGHT + 30, _T("认输"));
}
// 判断鼠标是否在悔棋按钮上
bool isMouseOnUndoButton(int mx, int my)
{
return mx >= BUTTON_X && mx <= BUTTON_X + BUTTON_WIDTH &&
my >= BUTTON_Y && my <= BUTTON_Y + BUTTON_HEIGHT;
}
// 判断鼠标是否在认输按钮上
bool isMouseOnGiveUpButton(int mx, int my)
{
return mx >= BUTTON_X && mx <= BUTTON_X + BUTTON_WIDTH &&
my >= BUTTON_Y + BUTTON_HEIGHT + 20 && my <= BUTTON_Y + BUTTON_HEIGHT * 2 + 20;
}
// 处理鼠标消息
void onMouseMsg(MOUSEMSG msg)
{
if (msg.uMsg == WM_LBUTTONDOWN)
{
if (game.gameState != GAME_STATE[1]) return;
int mx = msg.x, my = msg.y;
if (mx >= BOARD_X && mx <= BOARD_X + CELL_SIZE * BOARD_SIZE &&
my >= BOARD_Y && my <= BOARD_Y + CELL_SIZE * BOARD_SIZE)
{
int x = (mx - BOARD_X) / CELL_SIZE;
int y = (my - BOARD_Y) / CELL_SIZE;
game.play(x, y);
}
else if (isMouseOnUndoButton(mx, my))
{
game.undo();
}
else if (isMouseOnGiveUpButton(mx, my))
{
game.gameState = GAME_STATE[game.turn + 2];
}
}
}
int main()
{
// 初始化窗口和游戏数据
initgraph(WINDOW_WIDTH, WINDOW_HEIGHT);
game.init();
// 绘制棋盘和按钮
game.drawBoard();
drawUndoButton();
drawGiveUpButton();
// 循环处理消息
while (true)
{
// 绘制游戏状态
if (game.gameState == GAME_STATE[2])
{
outtextxy(BOARD_X + CELL_SIZE * BOARD_SIZE / 2 - 40, BOARD_Y - 30, _T("黑方胜利"));
}
else if (game.gameState == GAME_STATE[3])
{
outtextxy(BOARD_X + CELL_SIZE * BOARD_SIZE / 2 - 40, BOARD_Y - 30, _T("白方胜利"));
}
else if (game.gameState == GAME_STATE[4])
{
outtextxy(BOARD_X + CELL_SIZE * BOARD_SIZE / 2 - 40, BOARD_Y - 30, _T("平局"));
}
// 处理鼠标消息
MOUSEMSG msg = GetMouseMsg();
if (msg.uMsg == WM_MOUSEMOVE)
{
// 如果鼠标移动到按钮上,改变按钮颜色
if (isMouseOnUndoButton(msg.x, msg.y))
{
setfillcolor(RGB(255, 128, 128));
settextcolor(RGB(255, 255, 255));
rectangle(BUTTON_X, BUTTON_Y, BUTTON_X + BUTTON_WIDTH, BUTTON_Y + BUTTON_HEIGHT);
outtextxy(BUTTON_X + 20, BUTTON_Y + 10, _T("悔棋"));
}
else if (isMouseOnGiveUpButton(msg.x, msg.y))
{
setfillcolor(RGB(255, 128, 128));
settextcolor(RGB(255, 255, 255));
rectangle(BUTTON_X, BUTTON_Y + BUTTON_HEIGHT + 20,
BUTTON_X + BUTTON_WIDTH, BUTTON_Y + BUTTON_HEIGHT * 2 +