花时一个礼拜,终于做出了自己想要的五子棋游戏,虽然感觉还是有些地方不够完善,但是作为自己完成的第一个完整的项目,还是有些成就感的,特别在人机方面花费了自己蛮多心力,还好自己的人机也不算太笨,第一个项目和答辩也算圆满完成了!
在做五子棋的过程中,学习了easyx和人工智能部分的算法,下面是项目截图。
以下是代码,注释也写得较为清除。
#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
#include<graphics.h>
#include<conio.h>
#include<algorithm>
#pragma warning(disable:4996)
#include<mmsystem.h>
#pragma comment(lib,"winmm.lib")
using namespace std;
int Nowx, Nowy;//双人游戏当前下的棋子位置
int Playerx, Playery;//人机模式玩家当前下的棋子位置
int mp[16][16];//记录棋子位置状态
int Next[4][2] = { 0,1,1,0,1,1,-1,1 };
void CreatMenu();
int PlayBChess();
void DoubleGame();
void Play_Bgm();
int nx, ny;//棋子移动的当前位置
stack<int>ChessX;
stack<int>ChessY;
int RtimesW = 1,RtimesB = 1;//设置悔棋次数为1
int Mtimes = 2;//设置人机对战悔棋步数为两步
int flagW= 0;
int flagB = 0;
int stepPlayer = 0;//记录玩家赢棋步数
/*struct stone
{
int x, y, lianzi, dx, dy;
};*/
/*typedef struct node//用链表来存储每一局人机对战玩家获胜的步数
{
int data;
node* next;
}step;*/
//step* head;
void ClearStack()//清空栈
{
while (!ChessX.empty()) {
ChessX.pop();
ChessY.pop();
}
}
void initmap()//地图初始化
{
stepPlayer = 0;
RtimesW = 1, RtimesB = 1;
Mtimes = 2;
ClearStack();//重新游戏时清空栈
stepPlayer = 0;
for (int i = 0; i < 16; i++) {
for (int j = 0; j < 16; j++) {
mp[i][j] = 0;
}
}
}
int AllBoard()//判断棋盘是否下满
{
for (int i = 0; i < 16; i++) {
for (int j = 0; j < 16; j++) {
if (mp[i][j] == 0) {
return 0;
}
}
}return 1;
}
void PingJu()//设置平局弹窗
{
HWND dow = GetHWnd();
int window = MessageBox(NULL, "游戏结束!这盘是平局噢~是否重新开始游戏呢", "游戏结束", MB_OKCANCEL);
if (window == IDOK) {//是否开始重新游戏
initmap();//清除地图
DoubleGame();
}
else if (window == IDCANCEL) {
initmap();//清除地图
//cleardevice();//清屏
CreatMenu();//返回主菜单
}
}
void CreatBoard()
{
setbkcolor(RGB(190, 152, 122));//棋盘颜色
cleardevice();//清屏
setlinecolor(BLACK);
setlinestyle(PS_SOLID, 2);
rectangle(30, 30, 520, 520);
int space = 50;//设置棋盘左上角的位置
setlinestyle(PS_SOLID, 1);
for (int i = 0; i <16; i++) {//绘制棋盘
line(space, space + i * 30, 500, space + i * 30);
}
for (int i = 0; i < 16; i++) {
line( space + i * 30, space,space + i * 30,500);
}
setlinecolor(BLACK);
setfillcolor(RGB(126,89,61));
fillrectangle(540, 270, 650, 310);
fillrectangle(540, 330, 650, 370);
fillrectangle(540, 390, 650, 430);
settextstyle(15, 0, "宋体");
settextcolor(WHITE);
rectangle(553, 97, 650, 138);
rectangle(553,137 , 650, 178);
outtextxy(560, 100, "P1 白棋");
outtextxy(560, 120, "空格键下棋");
outtextxy(560, 145, "P2 黑棋");
outtextxy(560, 160, "Enter键下棋");
settextstyle(20, 0, "黑体");//设置字体
setbkmode(TRANSPARENT);//设置字体背景模式
settextcolor(BLACK);//设置选项字体颜色
outtextxy(548, 278, "按C键求和");
outtextxy(548, 338, "按R键悔棋");
outtextxy(548, 398, "按B键返回");
for (int i = 0; i < 16; i++) {
for (int j = 0; j < 16; j++) {
if (mp[i][j] == 1) {
setfillcolor(WHITE);
fillcircle(50+j*30, 50+i*30, 10);
}
if (mp[i][j] == 2) {
setfillcolor(BLACK);
fillcircle(50 + j * 30, 50 + i * 30, 10);
}
}
}
}
void CreatMachineBoard()
{
setbkcolor(RGB(190, 152, 122));//棋盘颜色
cleardevice();//清屏
setlinecolor(BLACK);
setlinestyle(PS_SOLID, 2);
rectangle(30, 30, 520, 520);
int space = 50;//设置棋盘左上角的位置
setlinestyle(PS_SOLID, 1);
for (int i = 0; i < 16; i++) {//绘制棋盘
line(space, space + i * 30, 500, space + i * 30);
}
for (int i = 0; i < 16; i++) {
line(space + i * 30, space, space + i * 30, 500);
}
setlinecolor(BLACK);
setfillcolor(RGB(126, 89, 61));
//fillrectangle(540, 270, 650, 310);
fillrectangle(540, 330, 650, 370);
fillrectangle(540, 390, 650, 430);
settextstyle(15, 0, "宋体");
settextcolor(WHITE);
rectangle(553, 97, 650, 138);
rectangle(553, 137, 650, 178);
outtextxy(560, 100, "玩家:白棋");
outtextxy(560, 120, "鼠标操作");
outtextxy(560, 145, "电脑:黑棋");
//(560, 160, "电脑");
settextstyle(20, 0, "黑体");//设置字体
setbkmode(TRANSPARENT);//设置字体背景模式
settextcolor(BLACK);//设置选项字体颜色
//outtextxy(548, 278, "认输");
outtextxy(568, 340, "悔棋");
outtextxy(568, 400, "返回");
for (int i = 0; i < 16; i++) {
for (int j = 0; j < 16; j++) {
if (mp[i][j] == 1) {
setfillcolor(WHITE);
fillcircle(50 + j * 30, 50 + i * 30, 10);
}
if (mp[i][j] == 2) {
setfillcolor(BLACK);
fillcircle(50 + j * 30, 50 + i * 30, 10);
}
}
}
}
void RegretChess()//悔棋操作,删除栈顶标记
{
mp[ChessY.top()][ChessX.top()] = 0;
}
int PlayWChess()//用键盘操作白棋下棋
{
//int x = 50, y = 50;//棋子的起始位置
flagW = 0;
while (1) {
CreatBoard();
setlinestyle(PS_SOLID, 2);
setlinecolor(GREEN);
rectangle(nx - 10, ny - 10, nx + 10, ny + 10);
char key = _getch();
switch (key) {
case 32:
if (mp[(ny - 50) / 30][(nx - 50) / 30] == 1 || mp[(ny - 50) / 30][(nx - 50) / 30] == 2) {
HWND dow = GetHWnd();
int window = MessageBox(dow, "错误:该位置已有棋子!", "提示", MB_OKCANCEL);
}
else {
Play_Bgm();
//mciSendString("play xqBGM", 0, 0, 0);
flagW = 1;
mp[(ny - 50) / 30][(nx - 50) / 30] = 1;//标记为白棋
Nowx = (nx - 50) / 30, Nowy = (ny - 50) / 30;
ChessX.push((nx - 50) / 30), ChessY.push((ny - 50) / 30);
break;
}
//case 72:
case 'w':
case 'W':
if (nx >= 50 && nx <= 500 && ny >= 80 && ny <= 500) { ny -= 30; }//往上移动
break;
//case 80:
case 's':
case 'S':
if (nx >= 50 && nx <= 500 && ny >= 50 && ny <= 470) { ny += 30; }//往下移动
break;
//case 75:
case 'a':
case 'A':
if (nx >= 80 && nx <= 500 && ny >= 50 && ny <= 500) {
nx -= 30;
}//往左移动
break;
//case 77:
case 'd':
case 'D':
if (nx >= 50 && nx <= 470 && ny >= 50 && ny <= 500) {
nx += 30;
}//往右移动
break;
case 'c':
case 'C':
flagW = 2;
return 2;//若求和则返回2
case 'R':
case 'r':
if (RtimesW != 0) {//当白棋悔棋次数不为0时,控制悔棋次数
RegretChess();
RtimesW--;
PlayBChess();
}
else {
HWND tishi = GetHWnd();
MessageBox(tishi, "悔棋次数已用光", "提示", MB_OKCANCEL);
}break;
case 'B':
case 'b':
return 1;
}if (flagW == 1) break;
}
return 0;
}
void Play_Bgm() {
mciSendString("play 下棋.wav", 0, 50, 0);
}
int PlayBChess()//用键盘操作黑棋下棋
{
flagB = 0;
while (1) {
CreatBoard();
//setfillcolor(RED);
//fillcircle(nx, ny, 10);
setlinestyle(PS_SOLID, 2);
setlinecolor(GREEN);
rectangle(nx-10,ny-10 , nx+10, ny+10);
char key = _getch();
switch (key) {
case 13:
if (mp[(ny - 50) / 30][(nx - 50) / 30] == 1 || mp[(ny - 50) / 30][(nx - 50) / 30] == 2) {
HWND dow = GetHWnd();
int window = MessageBox(dow, "错误:该位置已有棋子!", "提示", MB_OKCANCEL);
}
else {
Play_Bgm();
flagB = 1;
mp[(ny - 50) / 30][(nx - 50) / 30] = 2;//标记为黑棋
Nowx = (nx - 50) / 30, Nowy = (ny - 50) / 30;
ChessX.push((nx - 50) / 30), ChessY.push((ny - 50) / 30);
break;
}
case 72:
if (nx >= 50 && nx <= 500 && ny >= 80 && ny <= 500) { ny -= 30; }//往上移动
break;
case 80:
if (nx >= 50 && nx <= 500 && ny >= 50 && ny <= 470) { ny += 30; }//往下移动
break;
case 75:
if (nx >= 80 && nx <= 500 && ny >= 50 && ny <= 500) {
nx -= 30;
}//往左移动
break;
case 77:
if (nx >= 50 && nx <= 470 && ny >= 50 && ny <= 500) {
nx += 30;
}//往右移动
break;
case 'c':
case 'C':
flagB = 2;
return 1;
case 'R':
case 'r':
if (RtimesB!= 0) {//当白棋悔棋次数不为0时,控制悔棋次数
RegretChess();
RtimesB--;
PlayWChess();
}
else {
HWND tishi = GetHWnd();
MessageBox(tishi, "悔棋次数已用光", "提示", MB_OKCANCEL);
}
break;
case 'B':
case 'b':
return 1;
}if (flagB == 1) break;
}return 0;
}
int dfsW(int dx,int dy,int x, int y,int step)//运用dfs查找白棋连子数
{
if (mp[y][x]!=1) return step;//若白棋赢则返回该方向连起来的棋子数
if (mp[y][x] == 1) {
//cout << x << " "<<y;
int tx = x + dx;
int ty = y + dy;
//cout << " " << "step =" << step << " ";
dfsW(dx,dy,tx, ty,step+1);
}
}
int dfsB(int dx, int dy, int x, int y, int step)//运用dfs查找黑棋连子数
{
if (mp[y][x] != 2) return step;//若黑棋赢则返回该方向连起来的棋子数
if (mp[y][x] == 2) {
cout << x << " "<<y;
int tx = x + dx;
int ty = y + dy;
cout << " " << "step =" << step << " ";
dfsB(dx, dy, tx, ty, step + 1);
}
}
int SearchW(int x, int y)//判断白棋输赢
{
if (mp[y][x] == 1) {
for(int i=0;i<4;i++){
int tx = x + Next[i][0], ty = y + Next[i][1];
if (tx >= 0 && tx < 16 && ty >= 0 && ty < 16 && mp[ty][tx] == 1) {
if ((dfsW(Next[i][0], Next[i][1], x, y, 0) + dfsW(-1*Next[i][0], -1*Next[i][1], x, y, 0) - 1) >= 5) {
return 1;
}
}
}
}return 0;
}
int SearchB(int x, int y)//判断黑棋输赢
{
cout << "1";
if (mp[y][x] == 2) {
for (int i = 0; i < 4; i++) {
int tx = x + Next[i][0], ty = y + Next[i][1];
cout << "1";
if (tx >= 0 && tx < 16 && ty >= 0 && ty < 16 && mp[ty][tx] == 2) {
if ((dfsB(Next[i][0], Next[i][1], x, y, 0) + dfsB(-1*Next[i][0], -1*Next[i][1], x, y, 0) - 1) >= 5) {
return 1;
}
}
}
}return 0;
}
/*int bfs(int x, int y)
{
queue<stone>Chess;
stone
}*/
void PlayerPlay()//人机模式玩家用鼠标下棋
{
CreatMachineBoard();
MOUSEMSG msg;
while (1) {
setfillcolor(WHITE);
msg = GetMouseMsg();//接受鼠标信息
if (msg.uMsg == WM_LBUTTONDOWN) {//如果鼠标状态为按下左键
if (msg.x >= 35 && msg.x <= 515 && msg.y >= 35 && msg.y <= 515) {
if (mp[(msg.y - 35) / 30][(msg.x - 35) / 30] == 0) {
Play_Bgm();
fillcircle(msg.x, msg.y, 10);
ChessX.push((msg.x - 35) / 30), ChessY.push((msg.y - 35) / 30);
mp[(msg.y - 35) / 30][(msg.x - 35) / 30] = 1;//玩家下白棋
Playery = (msg.y - 35) / 30, Playerx = (msg.x - 35) / 30;
break;
}
else {
HWND dow = GetHWnd();
int window = MessageBox(dow, "错误:该位置已有棋子!", "提示", MB_OKCANCEL);
//break;
}
}
else if (msg.x > 540 && msg.x < 650 && msg.y>330 && msg.y < 370) {//当鼠标选中悔棋边框
if (Mtimes > 0) {//若剩余悔棋次数则悔棋
mp[ChessY.top()][ChessX.top()] = 0;
ChessY.pop(), ChessX.pop();//取出栈顶元素
mp[ChessY.top()][ChessX.top()] = 0;
Mtimes = Mtimes - 2;
PlayerPlay();
break;
}
else {
HWND tishi = GetHWnd();
MessageBox(tishi, "悔棋次数已用光", "提示", MB_OKCANCEL);
}
}
else if (msg.x > 540 && msg.x < 650 && msg.y>390 && msg.y < 430) {
initmap();//清除地图
CreatMenu();//返回主菜单
break;
}
}
}
}
void DoubleGame()
{
//mciSendString("open E:/Documents/temp/五子棋/五子棋/下棋.wav alias xqBGM", 0, 0, 0);
nx = 50, ny = 50;//棋子的起始位置
while (1) {
if (AllBoard() == 1) {//判断地图下满
PingJu();
break;
}
if (PlayWChess() == 1) {//先下白棋,再下黑棋
if (flagW == 0) {//标志为0时返回主菜单
initmap();//清除地图
//cleardevice();//清屏
CreatMenu();//返回主菜单
break;
}
else if (flagW == 2) {
HWND dow = GetHWnd();
int window = MessageBox(NULL, "求和成功~这盘是平局呢,是否重新开始游戏呢", "游戏结束", MB_OKCANCEL);
if (window == IDOK) {//是否开始重新游戏
initmap();//清除地图
DoubleGame();
}
else if (window == IDCANCEL) {//返回主菜单
initmap();//清除地图
//cleardevice();//清屏
CreatMenu();//返回主菜单
break;
}
}
}if (AllBoard() == 1) {//判断地图下满
PingJu();
break;
}
if (SearchW(Nowx, Nowy) == 1) {
mciSendString("play ./胜利呼喊声.wav", 0, 0, 0);
HWND dow = GetHWnd();
int window = MessageBox(NULL, "恭喜,玩家1获胜,亲,是否继续游戏呢", "游戏结束", MB_OKCANCEL);
if (window == IDOK) {//是否开始重新游戏
initmap();//清除地图
//CreatBoard();
DoubleGame();
}
else if (window == IDCANCEL) {
initmap();//清除地图
//cleardevice();//清屏
CreatMenu();//返回主菜单
}
break;
}
if (PlayBChess() == 1) {//先下白棋,再下黑棋
if (flagB == 0) {//如果标志为0则返回主菜单
initmap();//清除地图
//cleardevice();//清屏
CreatMenu();//返回主菜单
break;
}
else if (flagB == 2) {//如果标志为2
HWND dow = GetHWnd();
int window = MessageBox(NULL, "求和成功~这盘是平局呢,是否重新开始游戏呢", "游戏结束", MB_OKCANCEL);
if (window == IDOK) {//是否开始重新游戏
initmap();//清除地图
//CreatBoard();
DoubleGame();
}
else if (window == IDCANCEL) {
initmap();//清除地图
//cleardevice();//清屏
CreatMenu();//返回主菜单
}
break;
}
}
if (SearchB(Nowx, Nowy) == 1) {
mciSendString("play ./胜利呼喊声.wav", 0, 0, 0);
HWND dow = GetHWnd();
int window = MessageBox(dow, "恭喜,玩家2获胜,亲,是否继续游戏呢", "游戏结束", MB_OKCANCEL);
if (window == IDOK) {//是否开始重新游戏
initmap();//清除地图
//CreatBoard();
DoubleGame();
}
else if (window == IDCANCEL) {
initmap();//清除地图
//cleardevice();//清屏
CreatMenu();//返回主菜单
}
break;
}
}
}
int CountPScore(int empty, int lianzi)//计算分数,前者为空白位置数,后者为连子个数
{
int score = 0;//连一时分数为0
if (empty == 2 && lianzi == 3) score = 800;//活四分数为1000
else if (empty == 2 && lianzi == 2) score = 160;//活三为100
else if (empty == 1 && lianzi == 3) score = 240;//冲四为100
else if (empty == 1 && lianzi == 2) score = 120;//死三为50
else if (empty == 2 && lianzi == 1) score = 40;//连二为20
else if (lianzi == 4) score = 20000;//活五为20000
//cout << empty<<endl<<lianzi<<endl;
return score;
}
int CountAScore(int empty, int lianzi)//计算分数,前者为空白位置数,后者为连子个数
{//因为电脑先手,于是我们可以把电脑的分数设的比玩家高一点
int score = 0;//连一时分数为0
if (empty == 2 && lianzi == 3) score = 1200;//活四分数为1000
else if (empty == 2 && lianzi == 2) score = 200;//活三为100
else if (empty == 1 && lianzi == 3) score = 260;//冲四为100
else if (empty == 1 && lianzi == 2) score = 130;//死三为50
else if (empty == 2 && lianzi == 1) score = 45;//连二为20
else if (lianzi == 4) score = 30000;//活五为20000
//cout << empty << endl << lianzi << endl;
return score;
}
int PlayerScore(int y, int x)//每一次玩家下棋后该位置玩家下棋的分数
{
int sum = 0;//每个位置的总分数
//if (EndPlay(y, x)) return 20000;//判断一方取得胜利则返回20000
int empty = 0;
int Plianzi = 0;//前一个表示空白位置个数,后一个表示玩家棋两边连起来的个数
for (int i = 0; i < 4; i++) {//四个方向
empty = 0, Plianzi = 0;
for (int j = 1; j < 5; j++) {//往一个方向前进,计算一个方向连子个数
int nx = x + j * Next[i][0], ny = y + j * Next[i][1];
if (nx < 0 || nx>16 || ny < 0 || ny>16) {
break;
}
if (mp[ny][nx] == 0) {
empty++;
break;
}
if (mp[ny][nx] == 2) {
break;
}
else if (mp[ny][nx] == 1) {
Plianzi++;
}
}
for (int j = 1; j < 5; j++) {//往一个方向前进,计算一个方向连子个数
int nx = x + (-1) * j * Next[i][0], ny = y + (-1) * j * Next[i][1];
if (nx < 0 || nx >= 16 || ny < 0 || ny >= 16) {//判断出界
break;
}
if (mp[ny][nx] == 0) {
//若此时下一个位置为空白位置时
empty++;//空白位置数加一
break;
}
else if (mp[ny][nx] == 2) {
break;
}
else if (mp[ny][nx] == 1) {
//若此时下一个位置为白棋(即玩家棋)时
Plianzi++;//玩家棋连起来的个数
}
}sum += CountPScore(empty, Plianzi);//四个方向分数相加
}return sum;
}
int AIScore(int y, int x)//每一次玩家下棋后该位置电脑下棋的分数
{
int sum = 0;
int empty = 0; int Alianzi = 0;//前一个表示空白位置个数,后一个表示玩家棋连起来的个数
for (int i = 0; i < 4; i++) {//四个方向
empty = 0, Alianzi = 0;
for (int j = 1; j < 5; j++) {//往一个方向前进,计算一个方向连子个数
int nx = x + j * Next[i][0], ny = y + j * Next[i][1];
if (nx < 0 || nx >= 16 || ny < 0 || ny >= 16) {//判断出界
break;
}
if (mp[ny][nx] == 0) {
//若此时下一个位置为空白位置时
empty++;//空白位置数加一
break;
}
else if (mp[ny][nx] == 1) {
break;
}
else if (mp[ny][nx] == 2) {
//若此时下一个位置为黑棋(即电脑棋)时
Alianzi++;//玩家棋连起来的个数
}
}
for (int j = 1; j < 5; j++) {//往一个方向前进,计算一个方向连子个数
int nx = x + (-1) * j * Next[i][0], ny = y + (-1) * j * Next[i][1];
if (nx < 0 || nx >= 16 || ny < 0 || ny >= 16) {//判断出界
break;
}
if (mp[ny][nx] == 0) {
//若此时下一个位置为空白位置时
empty++;//空白位置数加一
break;
}
else if (mp[ny][nx] == 1) {
break;
}
else if (mp[ny][nx] == 2) {
//判断是否出界且若此时下一个位置为黑棋(即电脑棋)时
Alianzi++;//玩家棋连起来的个数
}
}sum += CountAScore(empty, Alianzi);//将四个方向的分数相加
}return sum;
}
int AIplay()//电脑下棋
{
CreatMachineBoard();
setfillcolor(BLACK);
if (mp[7][7] == 0) {
Play_Bgm();
fillcircle(7, 7, 10);
ChessX.push(7), ChessY.push(7);
mp[7][7] = 2;//电脑先下棋,第一个下棋盘中间,且是黑棋
return 0;
}
int ScoreMax = 0;
int mpx=0, mpy=0;
int AIscore;
for (int i = 0; i < 16; i++) {//y
for (int j = 0; j < 16; j++) {//x
if (mp[i][j]!= 0) continue;//此位置已被占
AIscore = PlayerScore(i,j)+ AIScore(i, j);//计算该位置分数,取两者之和,即可攻可守为最好方法
//cout << PlayerScore(i, j) << endl << AIScore(i, j);
if (AIscore == 0) {//分数为0直接跳过
continue;
}
else if (AIscore >= 30000) {//当分数大于等于30000,即可以连成五棋时,电脑胜利,结束游戏
fillcircle((j*30)+35+15, (i*30)+35+15 , 10);
ChessX.push(j), ChessY.push(i);
mp[i][j] = 2;
return 2;//电脑赢
}
else if (AIscore >ScoreMax) {
swap(AIscore, ScoreMax);//若当前位置分数比ScoreMax高,则交换数值
mpx = j; mpy = i;//记录下全位置分数最高的位置
}
}
}
Play_Bgm();
fillcircle((mpx * 30) + 35, (mpy * 30) + 35, 10);//在全位置分数最高的地方下棋
ChessX.push(mpx), ChessY.push(mpy);
mp[mpy][mpx] = 2;
return 0;
}
void MachineGame()
{
int step=0;//记录赢的步数
while (1) {
if (AllBoard() == 1) {//判断地图下满
PingJu();//平局窗口
break;
}
//AIplay();
if (AIplay() == 2) {//电脑赢局
mciSendString("play ./游戏失败.mp3", 0, 0, 0);
HWND dow = GetHWnd();
int window = MessageBox(NULL, "游戏结束,你失败了,是否重新开始游戏", "游戏结束", MB_OKCANCEL);
if (window == IDOK) {//是否开始重新游戏
initmap();//清除地图
MachineGame();
}
else if (window == IDCANCEL) {
initmap();//清除地图
CreatMenu();//返回主菜单
}
break;
}if (AllBoard() == 1) {//判断地图下满
PingJu();
break;
}
PlayerPlay();
step++;
if (SearchW(Playerx,Playery) == 1) {//玩家胜利
mciSendString("play ./胜利呼喊声.wav", 0, 0, 0);
FILE* test = fopen("排行榜.txt", "a");
fprintf(test, "%d ", step);//将玩家胜利的步数存入排行榜文件
fclose(test);
HWND dow = GetHWnd();
int window = MessageBox(NULL, "恭喜!你赢得本局游戏,是否继续游戏呢", "游戏结束", MB_OKCANCEL);
if (window == IDOK) {//是否开始重新游戏
initmap();//清除地图
MachineGame();
}
else if (window == IDCANCEL) {
initmap();//清除地图
CreatMenu();//返回主菜单
}
break;
}
}
}
void RankList()
{
IMAGE img;
loadimage(&img, "E:/Documents/temp/五子棋/五子棋/排行榜背景.jpg", 670, 550);
putimage(0, 0, &img);//插入图片
settextstyle(50, 0, "黑体");//设置字体
setbkmode(TRANSPARENT);//设置字体背景模式
settextcolor(RGB(88,88,88));//设置字体颜色
outtextxy(200,20, "排");
outtextxy( 300,20, "行");
outtextxy( 400,20, "榜");
settextcolor(RED);//设置字体颜色
settextstyle(30, 0, "宋体");//设置字体
outtextxy(120, 80, "第一名:");
outtextxy(120, 120, "第二名:");
outtextxy(120, 160, "第三名:");
settextcolor(BLACK);//设置字体颜色
settextstyle(20, 0, "宋体");//设置字体
outtextxy(120, 200, "第四名:");
outtextxy(120, 240, "第五名:");
outtextxy(120, 280, "第六名:");
outtextxy(120, 320, "第七名:");
outtextxy(120, 360, "第八名:");
outtextxy(120, 400, "第九名:");
outtextxy(120, 440, "第十名:");
int sstep[100] = { 0 };
FILE* test = fopen("排行榜.txt", "r");//从文件中读取数据
int i=0;
while (fscanf(test, "%d", &sstep[i]) != EOF) {
i++;
}
sort(sstep,sstep+i);//排序
int textx = 400, texty = 80;
for (int j = 0; j < i&&j<10; j++) {//从文件中读取数据生成排行榜
char str;
itoa(sstep[j], &str, 10);
settextstyle(25, 0, "华文琥珀");//设置字体
outtextxy(textx, texty,&str);
texty += 40;
}fclose(test);
setfillcolor(RGB(88, 88, 88));
fillrectangle(520, 500, 600, 530);
settextstyle(25, 0, "楷体");//设置字体
setbkmode(TRANSPARENT);//设置字体背景模式
settextcolor(BLACK);//设置字体颜色
outtextxy(530, 503, "返回");
MOUSEMSG msg;
while (1) {
msg = GetMouseMsg();//接受鼠标信息
if (msg.uMsg == WM_LBUTTONDOWN) {//如果鼠标状态为按下左键
if (msg.x > 520 && msg.x < 600 && msg.y>500 && msg.y < 530) {//返回主菜单
initmap();
CreatMenu();
}
}
}
}
void CreatMenu()//建立主菜单
{
//initgraph(670, 550);
IMAGE img;
loadimage(&img, "E:/Documents/temp/五子棋/五子棋/主菜单背景.jpg", 670, 550);
putimage(0, 0, &img);//插入图片
mciSendString("open E:/Documents/temp/五子棋/五子棋/背景音乐.mp3 alias bkBGM", 0, 0, 0);
mciSendString("play bkBGM repeat", 0, 0, 0);
setlinestyle(PS_SOLID, 1);//设置主菜单选项边框为实线,宽度为1像素
setfillcolor(RGB(187,128,96));//设置填充颜色
setlinecolor(WHITE);//设置线条颜色
int Left = 80, Top = 180, Right = 300, Bottom = 240;
for (int i = 1; i <= 4; i++) {//设置四个主菜单选项边框
fillrectangle(Left, Top, Right, Bottom);
Top += 90, Bottom += 90;
}
//setfillcolor(RGB(88, 88, 88));//设置填充颜色
//fillrectangle(50, 50, 120, 90);
//settextstyle(30,0,"楷体");//设置字体
setbkmode(TRANSPARENT);//设置字体背景模式
settextstyle(50, 0, "楷体");//设置字体
settextcolor(RGB(105, 55, 29));//设置字体颜色
outtextxy(85, 185, "双人模式");
outtextxy(85, 275, "人机模式");
outtextxy(110, 365, "排行榜");
outtextxy(85, 455, "退出游戏");
/*fillrectangle(80, 180, 300, 240);
fillrectangle(80,270,300,330);
fillrectangle(80, 360, 300, 420);
fillrectangle(80,450,300,510);*/
MOUSEMSG msg;
while (1) {
/* fillrectangle(50, 50, 120, 90);
*/
msg = GetMouseMsg();//接受鼠标信息
if (msg.uMsg == WM_LBUTTONDOWN) {//如果鼠标状态为按下左键
if (msg.x > 80 && msg.x < 300 && msg.y>180 && msg.y < 240) {
mciSendString("play ./开始音效.wav", 0, 0, 0);
DoubleGame();//开始双人游戏
break;
}
if (msg.x > 80 && msg.x < 300 && msg.y>270 && msg.y < 330) {
mciSendString("play ./开始音效.wav", 0, 0, 0);
MachineGame();//开始人机模式
break;
}
if (msg.x > 80 && msg.x < 300 && msg.y>360 && msg.y < 420) {
mciSendString("play ./开始音效.wav", 0, 0, 0);
RankList();//排行榜
break;
}
if (msg.x > 80 && msg.x < 300 && msg.y>450 && msg.y < 510) {
closegraph();//退出游戏
break;
}
}
}system("pause");
}
int main()
{
initgraph(670, 550,SHOWCONSOLE);
CreatMenu();
closegraph();
return 0;
}