源码(联机功能正在学习QwQ):
#include <graphics.h>
#include <conio.h>
#include <vector>
#include <iostream>
#include <cmath>
#include <windows.h>
#include <mmsystem.h>
#pragma comment(lib, "winmm.lib")
using namespace std;
// === 参数配置 ===
const int BOARD_SIZE = 15;
const int GRID = 35;
const int OFFSET = 30;
const int WIDTH = OFFSET * 2 + GRID * (BOARD_SIZE - 1);
const int HEIGHT = WIDTH;
const int MAX_WINS = 600;
// === 全局变量 ===
int board[BOARD_SIZE][BOARD_SIZE]; // 棋盘:0空 1玩家 2电脑
bool wins[BOARD_SIZE][BOARD_SIZE][MAX_WINS];
int myWin[MAX_WINS];
int computerWin[MAX_WINS];
int winCount = 0;
bool gameOver = false;
bool playerTurn = true;
bool playerIsWhite = false; // 记录玩家是否是白棋
// === 初始化赢法 ===
void initWins()
{
memset(wins, 0, sizeof(wins));
winCount = 0;
// 横向
for (int i = 0; i < BOARD_SIZE; i++)
for (int j = 0; j < BOARD_SIZE - 4; j++)
{
for (int k = 0; k < 5; k++) wins[i][j + k][winCount] = true;
winCount++;
}
// 纵向
for (int i = 0; i < BOARD_SIZE; i++)
for (int j = 0; j < BOARD_SIZE - 4; j++)
{
for (int k = 0; k < 5; k++) wins[j + k][i][winCount] = true;
winCount++;
}
// 正斜线 ↘
for (int i = 0; i < BOARD_SIZE - 4; i++)
for (int j = 0; j < BOARD_SIZE - 4; j++)
{
for (int k = 0; k < 5; k++) wins[i + k][j + k][winCount] = true;
winCount++;
}
// 反斜线 ↙
for (int i = 0; i < BOARD_SIZE - 4; i++)
for (int j = 4; j < BOARD_SIZE; j++)
{
for (int k = 0; k < 5; k++) wins[i + k][j - k][winCount] = true;
winCount++;
}
memset(myWin, 0, sizeof(myWin));
memset(computerWin, 0, sizeof(computerWin));
}
// === 更新统计 ===
void updateWinCounts()
{
for (int k = 0; k < winCount; k++)
{
myWin[k] = 0;
computerWin[k] = 0;
}
for (int i = 0; i < BOARD_SIZE; i++)
for (int j = 0; j < BOARD_SIZE; j++)
if (board[i][j] != 0)
for (int k = 0; k < winCount; k++)
if (wins[i][j][k])
{
if (board[i][j] == 1) myWin[k]++;
else if (board[i][j] == 2) computerWin[k]++;
}
}
// === 绘制棋盘 ===
void drawBoard()
{
setlinecolor(BLACK);
for (int i = 0; i < BOARD_SIZE; i++)
{
line(OFFSET, OFFSET + i * GRID, OFFSET + (BOARD_SIZE - 1) * GRID, OFFSET + i * GRID);
line(OFFSET + i * GRID, OFFSET, OFFSET + i * GRID, OFFSET + (BOARD_SIZE - 1) * GRID);
}
setfillcolor(WHITE);
fillcircle(OFFSET + 7 * GRID, OFFSET + 7 * GRID, 4);
fillcircle(OFFSET + 3 * GRID, OFFSET + 3 * GRID, 4);
fillcircle(OFFSET + 3 * GRID, OFFSET + 11 * GRID, 4);
fillcircle(OFFSET + 11 * GRID, OFFSET + 3 * GRID, 4);
fillcircle(OFFSET + 11 * GRID, OFFSET + 11 * GRID, 4);
}
// === 绘制棋子 ===
void drawPiece(int i, int j, int role)
{
int x = OFFSET + i * GRID;
int y = OFFSET + j * GRID;
if (role == 1) setfillcolor(BLACK);
else setfillcolor(WHITE);
solidcircle(x, y, 13);
}
// === 胜负判断 ===
void checkWin(int x, int y, int role)
{
int dx[4] = { 1, 0, 1, 1 };
int dy[4] = { 0, 1, 1, -1 };
for (int dir = 0; dir < 4; dir++)
{
int count = 1;
for (int step = 1; step < 5; step++)
{
int nx = x + dx[dir] * step, ny = y + dy[dir] * step;
if (nx < 0 || nx >= BOARD_SIZE || ny < 0 || ny >= BOARD_SIZE) break;
if (board[nx][ny] == role) count++; else break;
}
for (int step = 1; step < 5; step++)
{
int nx = x - dx[dir] * step, ny = y - dy[dir] * step;
if (nx < 0 || nx >= BOARD_SIZE || ny < 0 || ny >= BOARD_SIZE) break;
if (board[nx][ny] == role) count++; else break;
}
if (count >= 5)
{
// 发现五连,直接处理胜利提示和音效
gameOver = true;
settextstyle(25, 0, L"幼圆");
if (role == 1)
{
// role==1 黑棋
outtextxy(WIDTH / 2 - 100, HEIGHT / 2 - 40, L"黑棋胜利! 游戏结束");
// 如果玩家是白棋(playerIsWhite==true),那么对方,播放失败音
if (playerIsWhite == true)
{
PlaySound(L"failed.wav", NULL, SND_FILENAME | SND_ASYNC);
}
}
else
{
outtextxy(WIDTH / 2 - 100, HEIGHT / 2 - 40, L"白棋胜利! 游戏结束");
if (playerIsWhite == false)
{
PlaySound(L"failed.wav", NULL, SND_FILENAME | SND_ASYNC);
}
}
return; // 找到一条五连就结束检测
}
}
}
// === putPiece:统一落子逻辑 ===
void putPiece(int x, int y, int role)
{
board[x][y] = role;
drawPiece(x, y, role);
updateWinCounts();
PlaySound(L"kun.wav", NULL, SND_FILENAME | SND_ASYNC);
// 由 checkWin 内部处理胜利提示与 gameOver
checkWin(x, y, role);
}
// === 玩家下棋:返回坐标 ===
void getPlayerMove(int &i,int &j)
{
MOUSEMSG msg;
while (true)
{
msg = GetMouseMsg();
if (msg.uMsg == WM_LBUTTONDOWN)
{
i = (msg.x - OFFSET + GRID / 2) / GRID;
j = (msg.y - OFFSET + GRID / 2) / GRID;
if (i >= 0 && i < BOARD_SIZE && j >= 0 && j < BOARD_SIZE && board[i][j] == 0)
return ;
}
}
}
// === 电脑AI计算落子坐标 ===
void getComputerMove(int &bestX,int &bestY)
{
int myScore[BOARD_SIZE][BOARD_SIZE] = { 0 };
int computerScore[BOARD_SIZE][BOARD_SIZE] = { 0 };
int maxScore = 0;
bestX = 7;
bestY = 7;
for (int i = 0; i < BOARD_SIZE; i++)
for (int j = 0; j < BOARD_SIZE; j++)
if (board[i][j] == 0)
for (int k = 0; k < winCount; k++)
if (wins[i][j][k]) {
if (myWin[k] == 1) myScore[i][j] += 200;
else if (myWin[k] == 2) myScore[i][j] += 400;
else if (myWin[k] == 3) myScore[i][j] += 2000;
else if (myWin[k] == 4) myScore[i][j] += 10000;
if (computerWin[k] == 1) computerScore[i][j] += 220;
else if (computerWin[k] == 2) computerScore[i][j] += 420;
else if (computerWin[k] == 3) computerScore[i][j] += 2100;
else if (computerWin[k] == 4) computerScore[i][j] += 20000;
int score = max(myScore[i][j], computerScore[i][j]);
if (score > maxScore)
{
maxScore = score;
bestX = i; bestY = j;
}
}
return ;
}
// === 掷骰子决定先手 ===
void diceToDecideFirst()
{
srand((unsigned)time(NULL));
cleardevice();
settextcolor(GREEN);
outtextxy(WIDTH / 2 - 60, HEIGHT / 2 - 40, L"掷骰子决定先手中...");
Sleep(1000);
// 模拟掷骰子动画
for (int i = 0; i < 10; i++)
{
int playerDice = rand() % 6 + 1;
int computerDice = rand() % 6 + 1;
cleardevice();
wchar_t info[64];
swprintf(info, 64, L"玩家1:%d 玩家2:%d", playerDice, computerDice);
settextstyle(30, 0, L"幼圆");
outtextxy(WIDTH / 2 - 80, 60, L"默认先手是白棋");
settextcolor(GREEN);
outtextxy(WIDTH / 2 - 80, HEIGHT / 2 - 20, info);
Sleep(200);
}
// 最终结果
int playerDice = rand() % 6 + 1;
int computerDice = rand() % 6 + 1;
cleardevice();
settextstyle(20, 0, L"幼圆");
bool playerFirst;
if (playerDice > computerDice)
{
outtextxy(20, 10, L"你赢了骰子,你先手!");
playerFirst = true;
}
else if (playerDice < computerDice)
{
outtextxy(20, 10, L"对方赢了骰子,对方先手!");
playerFirst = false;
}
else
{
// 平局时默认玩家先手(你也可以重掷或其它规则)
outtextxy(20, 10, L"平局,默认玩家先手!");
playerFirst = true;
}
// 将结果写回全局变量:先手为白棋
playerTurn = playerFirst;
playerIsWhite = playerTurn; // 先手总是白棋
Sleep(1500);
}
// === 联机初始化 ===
void initGame_pair()
{
initgraph(WIDTH, HEIGHT);
setbkcolor(RGB(255, 228, 189));
cleardevice();
for (int i = 0; i < BOARD_SIZE; i++)
for (int j = 0; j < BOARD_SIZE; j++)
board[i][j] = 0;
// 掷骰子决定先手(该函数内部设置 playerTurn / playerIsWhite)
diceToDecideFirst();
gameOver = false;
initWins();
updateWinCounts();
drawBoard();
// 如果电脑先手(playerTurn==false),让电脑下第一步
if (!playerTurn)
{
int x, y;
getComputerMove(x, y);
putPiece(x, y, 2);
playerTurn = true;
}
}
// === 人机初始化 ===
void initGame()
{
initgraph(WIDTH, HEIGHT);
setbkcolor(RGB(255, 228, 189));
cleardevice();
for (int i = 0; i < BOARD_SIZE; i++)
for (int j = 0; j < BOARD_SIZE; j++)
board[i][j] = 0;
// 掷骰子决定先手(该函数内部设置 playerTurn / playerIsWhite)
diceToDecideFirst();
gameOver = false;
initWins();
updateWinCounts();
drawBoard();
// 如果电脑先手(playerTurn==false),让电脑下第一步
if (!playerTurn)
{
int x, y;
getComputerMove(x, y);
putPiece(x, y, 2);
playerTurn = true;
}
}
void restartGame()
{
cleardevice();
memset(board, 0, sizeof(board));
initWins();
updateWinCounts();
drawBoard();
gameOver = false;
}
// 选择游戏模式
int chooseGameMode()
{
initgraph(WIDTH, HEIGHT);
setbkcolor(RGB(255, 228, 189));
setfillcolor(RGB(255, 228, 189));
cleardevice();
fillrectangle(WIDTH / 2 - 100, HEIGHT / 2 - 60, WIDTH / 2 + 100, HEIGHT / 2 - 10); // 人机
fillrectangle(WIDTH / 2 - 100, HEIGHT / 2 + 10, WIDTH / 2 + 100, HEIGHT / 2 + 60); // 联机
settextcolor(GREEN);
settextstyle(30, 0, L"幼圆");
outtextxy(WIDTH / 2 - 80, 60, L"请选择模式");
settextcolor(RED);
outtextxy(WIDTH / 2 - 60, HEIGHT / 2 - 50, L"人机对战");
outtextxy(WIDTH / 2 - 60, HEIGHT / 2 + 20, L"联机对战");
while (1)
{
if (MouseHit())
{
MOUSEMSG msg = GetMouseMsg();
if (msg.uMsg == WM_LBUTTONDOWN)
{
// 人机按钮
if (msg.x >= WIDTH / 2 - 100 && msg.x <= WIDTH / 2 + 100 &&
msg.y >= HEIGHT / 2 - 60 && msg.y <= HEIGHT / 2 - 10)
{
closegraph();
return 1;
}
// 联机按钮
if (msg.x >= WIDTH / 2 - 100 && msg.x <= WIDTH / 2 + 100 &&
msg.y >= HEIGHT / 2 + 10 && msg.y <= HEIGHT / 2 + 60)
{
closegraph();
return 2;
}
}
}
Sleep(10);
}
}
// === 联机主循环 ===
void gameLoop_pair()
{
}
// === 人机主循环 ===
void gameLoop()
{
while (!gameOver)
{
int x, y;
if (playerTurn)
{
getPlayerMove(x, y);
putPiece(x, y, playerIsWhite ? 2 : 1);
playerTurn = false;
}
else
{
getComputerMove(x, y);
putPiece(x, y, playerIsWhite ? 1 : 2);
playerTurn = true;
}
}
settextcolor(RED);
outtextxy(10, HEIGHT - 30, L"点击鼠标左键重新开始,或关闭窗口退出。");
while (true)
{
if (MouseHit())
{
MOUSEMSG msg = GetMouseMsg();
if (msg.uMsg == WM_LBUTTONDOWN)
{
restartGame(); // 重开一局
switch (chooseGameMode())
{
case 1:
{
initGame();
gameLoop();
break;
}
case 2:
{
initGame_pair();
gameLoop_pair();
break;
}
}
// 重新进入循环
return;
}
}
if (!IsWindow(GetHWnd()))
{
break; // 用户关闭窗口时退出
}
}
}
// === 程序入口 ===
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int)
{
switch (chooseGameMode())
{
case 1:
{
initGame();
gameLoop();
break;
}
case 2:
{
initGame_pair();
gameLoop_pair();
break;
}
}
}