以前写过一个,只不过写的比较繁琐,这个能简单实现,去掉了各种花里胡哨(虽然都是简单的知识),本来是打算用c++实现的,发现还是c写起来好理解,毕竟学艺不精,哈哈哈
代码风格偏奇葩,接触编程时间不长,还有许多可以优化的地方,例如下方显示文字可以使用内联函数疯狂调用之类。
注释有的地方不太明确,如有bug可以反馈。
本人使用vs2017,如有编译错误,可修改项目属性
项目->属性->常规->字符集->多字节字符集;
此处修改为outtextxy输出文字函数中的第三个参数在调用时出错。
#include
#include
#include
#include
#include
#include
#define MAX 1000
using namespace std;
//全局变量存储棋盘的属性
struct G_chess {
int CHESS_R = 10;//每个棋子的半径
int CHESS_R_C = 5;//五个点的半径
int ROW = 35;//棋盘的行的长度
int COLOMU = 35;//棋盘列的长度
int start = 50;//棋盘的起始位置
int menu_start_x = start + 14 * COLOMU + 10;//菜单栏的x轴开始位置
int menu_start_y = start;//菜单栏的y轴开始位置
}G;
//每个棋子的位置属性
struct chess {
int map_x;//棋子所在行的位置
int map_y;//棋子所在列的位置
};
//棋盘上的各个棋子属性
class chess_piece {
public:
//初始化棋盘上的棋子个数
chess_piece() {
buffer = MAX;
}
//每下一个棋子,获取所下棋子的信息,收入棋子的属性中
void play(int x, int y) {
chess temp;
temp.map_x = x;
temp.map_y = y;
play_chess.push_back(temp);
}
friend ostream &operator<< (ostream& os, chess a);
//每下一个棋子,画出棋子
void down(int x, int y, int color) {
setfillcolor(color);
setlinecolor(color);
fillcircle(x, y, G.CHESS_R);
play(x, y);
}
void drow_back_line(vector& play_chess);//悔棋后,将棋盘复原
//每悔一次棋,将所下的棋子删除
void back() {
if (play_chess.empty()) {
setbkmode(TRANSPARENT);
settextstyle(30, 0, _T("楷体"));
outtextxy(G.start + 3 * G.COLOMU, G.start + 14 * G.COLOMU + 1, _T("请落子后再进行操作"));
return;
}
drow_back_line(play_chess);
play_chess.pop_back();
}
~chess_piece() { }
private:
int buffer;
vector play_chess;
};
int flag = BLACK;
void map();//生成地图
int mouse();//鼠标操作
inline int mouse_menu(MOUSEMSG &mou);//菜单处的鼠标操作
void drow_menu(int x, int y, const char *name, int UOD);//菜单框
bool judge(int x, int y);//判断游戏是否有一方获胜
int main()
{
int s = 1;
while (s) {
s = mouse();
}
closegraph();
return 0;
}
ostream & operator<<(ostream & os, chess a)
{
os << a.map_x << " " << a.map_y;
return os;
}
void map() {
chess_piece a;
initgraph(700, 640);
setfillcolor(RGB(172, 81, 24));
setfillstyle(BS_SOLID);
fillrectangle(0, 0, 700, 640);
setlinecolor(BLUE);
for (int i = 0; i <= G.start + 13 * G.COLOMU; i = i + G.COLOMU)
{
line(G.start + i, G.start, G.start + i, G.start + G.COLOMU * 14);
line(G.start, G.start + i, G.start + G.COLOMU * 14, G.start + i);
}
setfillcolor(GREEN);
fillcircle(G.start + 7 * G.COLOMU, G.start + 7 * G.COLOMU, G.CHESS_R_C);//画出天元点
fillcircle(G.start + 3 * G.COLOMU, G.start + 3 * G.COLOMU, G.CHESS_R_C);//画出四个星点
fillcircle(G.start + 3 * G.COLOMU, G.start + 11 * G.COLOMU, G.CHESS_R_C);
fillcircle(G.start + 11 * G.COLOMU, G.start + 3 * G.COLOMU, G.CHESS_R_C);
fillcircle(G.start + 11 * G.COLOMU, G.start + 11 * G.COLOMU, G.CHESS_R_C);
settextstyle(30, 0, _T("楷体"));
setbkmode(TRANSPARENT);
settextcolor(BLACK);
outtextxy(G.start + 5 * G.COLOMU, G.start / 3, _T("欢乐五子棋"));
drow_menu(G.menu_start_x, G.menu_start_y, "新局", 1);
drow_menu(G.menu_start_x, G.menu_start_y + G.COLOMU + 2, "悔棋", 1);
drow_menu(G.menu_start_x, G.menu_start_y + (G.COLOMU + 2) * 2, "退出", 1);
}
void chess_piece::drow_back_line(vector& play_chess) {
if (flag == BLACK)
{
settextstyle(60, 0, _T("楷体"));
setfillcolor(RGB(172, 81, 24));
solidrectangle(G.start + 4 * G.COLOMU, G.start + 15 * G.COLOMU, G.start + 8 * G.COLOMU, G.start + 15 * G.COLOMU + 60);
outtextxy(G.start + 4 * G.COLOMU, G.start + 15 * G.COLOMU, _T("白棋下!"));
flag = WHITE;
}
else {
settextstyle(60, 0, _T("楷体"));
setfillcolor(RGB(172, 81, 24));
solidrectangle(G.start + 4 * G.COLOMU, G.start + 15 * G.COLOMU, G.start + 8 * G.COLOMU, G.start + 15 * G.COLOMU + 60);
outtextxy(G.start + 4 * G.COLOMU, G.start + 15 * G.COLOMU, _T("黑棋下!"));
flag = BLACK;
}
vector::iterator iter = play_chess.end() - 1;
setfillcolor(RGB(172, 81, 24));
setlinecolor(RGB(172, 81, 24));
fillcircle(iter->map_x, iter->map_y, G.CHESS_R);
setlinecolor(BLUE);
int R = (iter->map_x - G.start) / G.COLOMU + 1;
int C = (iter->map_y - G.start) / G.COLOMU + 1;
cout << R << " " << C << endl;
if (R == 1 && C == 1)
{
line(iter->map_x, iter->map_y, iter->map_x + G.COLOMU / 2 + 1, iter->map_y);
line(iter->map_x, iter->map_y, iter->map_x, iter->map_y + G.COLOMU / 2 + 1);
}
else if (R == 15 && C == 1)
{
line(iter->map_x - G.COLOMU / 2 + 1, iter->map_y, iter->map_x, iter->map_y);
line(iter->map_x, iter->map_y, iter->map_x, iter->map_y + G.COLOMU / 2 + 1);
}
else if (R == 1 && C == 15) {
line(iter->map_x, iter->map_y, iter->map_x + G.COLOMU / 2 + 1, iter->map_y);
line(iter->map_x, iter->map_y - G.COLOMU / 2 + 1, iter->map_x, iter->map_y);
}
else if (R == 15 && C == 15) {
line(iter->map_x - G.COLOMU / 2 + 1, iter->map_y, iter->map_x, iter->map_y);
line(iter->map_x, iter->map_y - G.COLOMU / 2 + 1, iter->map_x, iter->map_y);
}
else if (R == 1) {
line(iter->map_x, iter->map_y, iter->map_x + G.COLOMU / 2 + 1, iter->map_y);
line(iter->map_x, iter->map_y - G.COLOMU / 2 + 1, iter->map_x, iter->map_y + G.COLOMU / 2 + 1);
}
else if (R == 15) {
line(iter->map_x - G.COLOMU / 2 + 1, iter->map_y, iter->map_x, iter->map_y);
line(iter->map_x, iter->map_y - G.COLOMU / 2 + 1, iter->map_x, iter->map_y + G.COLOMU / 2 + 1);
}
else if (C == 1) {
line(iter->map_x - G.COLOMU / 2 + 1, iter->map_y, iter->map_x + G.COLOMU / 2 + 1, iter->map_y);
line(iter->map_x, iter->map_y, iter->map_x, iter->map_y + G.COLOMU / 2 + 1);
}
else if (C == 15) {
line(iter->map_x - G.COLOMU / 2 + 1, iter->map_y, iter->map_x + G.COLOMU / 2 + 1, iter->map_y);
line(iter->map_x, iter->map_y - G.COLOMU / 2 + 1, iter->map_x, iter->map_y);
}
else {
line(iter->map_x - G.COLOMU / 2 + 1, iter->map_y, iter->map_x + G.COLOMU / 2 + 1, iter->map_y);
line(iter->map_x, iter->map_y - G.COLOMU / 2 + 1, iter->map_x, iter->map_y + G.COLOMU / 2 + 1);
}
if ((R == 8 && C == 8) || (R == 4 && C == 4) || (R == 4 && C == 12) || (R == 12 && C == 12) || (R == 12 && C == 4)) {
setfillcolor(GREEN);
setlinecolor(BLACK);
fillcircle(iter->map_x, iter->map_y, G.CHESS_R_C);
}
}
bool judge(int x, int y)
{
int color = getpixel(x, y);
int count = 1;
//横向检测
for (int i = x - G.COLOMU; i >= G.start; i -= G.COLOMU) {
if (getpixel(i, y) == color) count++;
else break;
}
for (int i = x + G.COLOMU; i <= G.start + 14 * G.COLOMU; i += G.COLOMU) {
if (getpixel(i, y) == color) count++;
else break;
}
if (count >= 5) return true;
count = 1;
//纵向检测
for (int i = y - G.COLOMU; i >= G.start; i -= G.COLOMU) {
if (getpixel(x, i) == color) count++;
else break;
}
for (int i = y + G.COLOMU; i <= G.start + 14 * G.COLOMU; i += G.COLOMU) {
if (getpixel(x, i) == color) count++;
else break;
}
if (count >= 5) return true;
count = 1;
//从右上到左下检测
for (int i = x - G.COLOMU, j = y - G.COLOMU; i >= G.start && j >= G.start; i -= G.COLOMU, j -= G.COLOMU) {
if (getpixel(i, j) == color) count++;
else break;
}
for (int i = x + G.COLOMU, j = y + G.COLOMU; i >= G.start && j >= G.start; i += G.COLOMU, j += G.COLOMU) {
if (getpixel(i, j) == color) count++;
else break;
}
if (count >= 5) return true;
count = 1;
//从左上到右下检测
for (int i = x + G.COLOMU, j = y - G.COLOMU; i >= G.start && j >= G.start; i += G.COLOMU, j -= G.COLOMU) {
if (getpixel(i, j) == color) count++;
else break;
}
for (int i = x - G.COLOMU, j = y + G.COLOMU; i >= G.start && j >= G.start; i -= G.COLOMU, j += G.COLOMU) {
if (getpixel(i, j) == color) count++;
else break;
}
if (count >= 5) return true;
return false;
}
int mouse() {
map();
chess_piece P;
while (1) {
MOUSEMSG mou = GetMouseMsg();
switch (mouse_menu(mou)) {
case 1: return 1;
case 2: P.back(); break;
case 3: return 0;
}
if (mou.uMsg == WM_LBUTTONDOWN) {
int x = ((mou.x - G.start + G.COLOMU / 2) / G.COLOMU)*G.COLOMU + G.start;
int y = ((mou.y - G.start + G.COLOMU / 2) / G.COLOMU)*G.COLOMU + G.start;
if (getpixel(x, y) == BLUE || getpixel(x, y) == GREEN)
{
setfillcolor(RGB(172, 81, 24));
solidrectangle(G.start + 3 * G.COLOMU, G.start + 14 * G.COLOMU + 1, G.start + 10 * 30 + 3 * G.COLOMU, +G.start + 14 * G.COLOMU + 1 + 30);
if (flag == WHITE) {
P.down(x, y, flag);
if (judge(x, y)) {
setbkmode(TRANSPARENT);
settextstyle(60, 0, _T("楷体"));
outtextxy(G.start + 4 * G.COLOMU, G.start + 4 * G.COLOMU, _T("白棋胜!"));
settextstyle(30, 0, _T("楷体"));
outtextxy(G.start + 3 * G.COLOMU, G.start + 14 * G.COLOMU + 1, _T("点击新局继续进行对局"));
break;
}
settextstyle(60, 0, _T("楷体"));
setfillcolor(RGB(172, 81, 24));
solidrectangle(G.start + 4 * G.COLOMU, G.start + 15 * G.COLOMU, G.start + 8 * G.COLOMU, G.start + 15 * G.COLOMU + 60);
outtextxy(G.start + 4 * G.COLOMU, G.start + 15 * G.COLOMU, _T("黑棋下!"));
flag = BLACK;
}
else {
P.down(x, y, flag);
if (judge(x, y)) {
setbkmode(TRANSPARENT);
settextstyle(60, 0, _T("楷体"));
outtextxy(G.start + 4 * G.COLOMU, G.start + 6 * G.COLOMU, _T("黑棋胜!"));
settextstyle(30, 0, _T("楷体"));
outtextxy(G.start + 3 * G.COLOMU, G.start + 14 * G.COLOMU + 1, _T("点击新局继续进行对局"));
break;
}
settextstyle(60, 0, _T("楷体"));
setfillcolor(RGB(172, 81, 24));
solidrectangle(G.start + 4 * G.COLOMU, G.start + 15 * G.COLOMU, G.start + 8 * G.COLOMU, G.start + 15 * G.COLOMU + 60);
outtextxy(G.start + 4 * G.COLOMU, G.start + 15 * G.COLOMU, _T("白棋下!"));
flag = WHITE;
}
}
}
}
while (1) {
MOUSEMSG m = GetMouseMsg();
switch (mouse_menu(m)) {
case 1:
return 1;
case 2:
setfillcolor(RGB(172, 81, 24));
solidrectangle(G.start + 3 * G.COLOMU, G.start + 14 * G.COLOMU + 1, G.start + 10 * 30 + 3 * G.COLOMU, +G.start + 14 * G.COLOMU + 1 + 30);
settextstyle(30, 0, _T("楷体"));
outtextxy(G.start + 3 * G.COLOMU, G.start + 14 * G.COLOMU + 1, _T("胜负乃兵家常事,再来!"));
break;
case 3: return 0;
}
}
return mouse();
}
int mouse_menu(MOUSEMSG &mou)
{
if (mou.uMsg == WM_LBUTTONDOWN) {
if (mou.x >= G.menu_start_x && mou.x <= (G.menu_start_x + G.COLOMU * 2) && mou.y >= G.menu_start_y && mou.y <= (G.menu_start_y + G.COLOMU))
{
drow_menu(G.menu_start_x, G.menu_start_y, "新局", 0);
}
if (mou.x >= G.menu_start_x && mou.x <= (G.menu_start_x + G.COLOMU * 2) && mou.y >= (G.menu_start_y + G.COLOMU + 2) && mou.y <= (G.menu_start_y + G.COLOMU * 2)) {
drow_menu(G.menu_start_x, G.menu_start_y + G.COLOMU + 2, "悔棋", 0);
}
if (mou.x >= G.menu_start_x && mou.x <= (G.menu_start_x + G.COLOMU * 2) && mou.y >= (G.menu_start_y + (G.COLOMU + 2) * 2) && mou.y <= (G.menu_start_y + G.COLOMU * 3)) {
drow_menu(G.menu_start_x, G.menu_start_y + (G.COLOMU + 2) * 2, "退出", 0);
}
}
if (mou.uMsg == WM_LBUTTONUP) {
drow_menu(G.menu_start_x, G.menu_start_y + (G.COLOMU + 2) * 2, "退出", 1);
drow_menu(G.menu_start_x, G.menu_start_y + G.COLOMU + 2, "悔棋", 1);
drow_menu(G.menu_start_x, G.menu_start_y, "新局", 1);
if (mou.x >= G.menu_start_x && mou.x <= (G.menu_start_x + G.COLOMU * 2) && mou.y >= G.menu_start_y&&mou.y <= (G.menu_start_y + G.COLOMU + 2))
{
drow_menu(G.menu_start_x, G.menu_start_y, "新局", 1);
return 1;
}
if (mou.x >= G.menu_start_x && mou.x <= (G.menu_start_x + G.COLOMU * 2) && mou.y >= (G.menu_start_y + G.COLOMU + 2) && mou.y <= (G.menu_start_y + (G.COLOMU + 2) * 2)) {
drow_menu(G.menu_start_x, G.menu_start_y + G.COLOMU + 2, "悔棋", 1);
return 2;
}
if (mou.x >= G.menu_start_x && mou.x <= (G.menu_start_x + G.COLOMU * 2) && mou.y >= (G.menu_start_y + (G.COLOMU + 2) * 2) && mou.y <= (G.menu_start_y + (G.COLOMU + 2) * 3)) {
drow_menu(G.menu_start_x, G.menu_start_y + (G.COLOMU + 2) * 2, "退出", 1);
return 3;
}
}
return 0;
}
inline void drow_menu(int x, int y, const char * name, int UOD)//UOD意为up or dowm
{
setfillcolor(LIGHTGRAY);
solidrectangle(x, y, x + G.COLOMU * 2, y + G.COLOMU * 1);
setfillcolor(WHITE);
settextstyle(30, 0, _T("宋体"));
if (UOD == 0) {
outtextxy(x + 4, y + 4, name);
solidrectangle(x, y + G.COLOMU - 2, x + G.COLOMU * 2, y + G.COLOMU);
solidrectangle(x + G.COLOMU * 2 - 2, y, x + G.COLOMU * 2, y + G.COLOMU * 1);
}
else if (UOD == 1) {
outtextxy(x + 2, y + 2, name);
solidrectangle(x, y, x + G.COLOMU * 2, y + 2);
solidrectangle(x, y, x + 2, y + G.COLOMU * 1);
}
}