五子棋C++版

 

当前只完成了单机人人对战  后续会完成联机和AI的实现

 

定义棋盘

typedef struct
{
	int kind;
}Map;							//棋盘	0为无子 1为黑子 2为白子

Map maps[line_number + 1][line_number + 1];		//定义棋盘

定义棋子

typedef struct
{
	int x;
	int y;
	int kind;
}Record;				//记录每一步棋的坐标

int point_x, point_y;			//落子点的坐标
int kind_chess;				//1为黑子 2为白子

 

 1 void Startup()
 2 {
 3     
 4     //当前棋盘没有落子 kind全部置为0;
 5     for (int i = 1; i <= line_number; i++)
 6     {
 7         for (int j = 1; j <= line_number; j++)
 8         {
 9             maps[i][j].kind = 0;
10         }
11     }
12     //各种参数初始化
13     flag_leftmouse = 0;
14     number = 0;
15     kind_chess = 1;
16     step = width / (line_number + 1);
17     radius = step /2 - 1;
18     initgraph(width, heigh);
19     //设置背景颜色
20     setbkcolor(RGB(249, 214, 91));
21     cleardevice();
22 
23     setlinecolor(BLACK);
24     setlinestyle(PS_SOLID, 1);
25     // 画出棋盘横竖各line_number条交错的直线
26     for (int i = 1; i <= line_number; i++)
27     {
28         line(i*step, 1 * step, i*step, line_number * step);
29         line(1 * step, i*step, line_number * step, i*step);
30     }
31     button_left = step;
32     button_right = step * 4;
33     button_top = (line_number + 1)*step - step / 2;
34     button_bottom = heigh - step / 2;
35     //画出悔棋键
36     settextcolor(BLACK);
37     settextstyle(step*2-step/2, step - step/4, _T("宋体"));
38     outtextxy(button_left, button_top , _T("悔棋"));
39     //画出认输键
40     settextstyle(step * 2 - step / 2, step - step / 4, _T("宋体"));
41     outtextxy(button_left+4*step, button_top, _T("认输"));
42 }  
初始化棋盘

 

 1 //判断落子后是否胜利 即五连子 x,y,kind 分别为行数,列数,棋子的颜色
 2 int IsVictory(int x, int y, int kind)
 3 {
 4     //判断一列上是否有五连子
 5     int i = x;
 6     int j = y;
 7     int count = 0;
 8     while (i >= 1 && maps[i][j].kind == kind)
 9     {
10         i--;
11         count++;
12     }
13     i = x + 1;
14     while (i <= 19 && maps[i][j].kind == kind)
15     {
16         i++;
17         count++;
18     }
19     if (count == 5) return kind;
20     //判断一行上是否有五连子
21     i = x;
22     count = 0;
23     while (j >= 1 && maps[i][j].kind == kind)
24     {
25         j--;
26         count++;
27     }
28     j = y + 1;
29     while (j <= 19 && maps[i][j].kind == kind)
30     {
31         j++;
32         count++;
33     }
34     if (count == 5) return kind;
35     //判断左斜方向是否有五连子
36     i = x;
37     j = y;
38     count = 0;
39     while (i >= 1 && j >= 1 && maps[i][j].kind == kind)
40     {
41         j--;
42         i--;
43         count++;
44     }
45     i = x + 1;
46     j = y + 1;
47     while (j <= 19 && i <= 19 && maps[i][j].kind == kind)
48     {
49         j++;
50         i++;
51         count++;
52     }
53     if (count == 5) return kind;
54     //判断右斜方向是否有五连子
55     i = x;
56     j = y;
57     count = 0;
58     while (i <= 19 && j >= 1 && maps[i][j].kind == kind)
59     {
60         j--;
61         i++;
62         count++;
63     }
64     i = x - 1;
65     j = y + 1;
66     while (j <= 19 && i >= 1 && maps[i][j].kind == kind)
67     {
68         j++;
69         i--;
70         count++;
71     }
72     if (count == 5) return kind;
73     return 0;
74 }
判断胜利

 

 1 if (kind_chess == 1 && maps[point_y / (step)][point_x / step].kind == 0) //当前落子位置满足条件 
 2                     {
 3                         //记录落子点 用于悔棋键
 4                         number++;
 5                         records[number].x = point_y / step;
 6                         records[number].y = point_x / step;
 7                         records[number].kind = 1;
 8 
 9                         //绘图 覆盖
10                         setfillcolor(BLACK);
11                         solidcircle(point_x, point_y, radius);
12                         maps[point_y / step][point_x / step].kind = 1;
13                         kind_chess = 2;
14                         if (IsVictory(point_y / step, point_x / step, 1) == 1)
15                         {
16                             
17                             settextcolor(BLACK);
18                             settextstyle(48, 0, _T("宋体"));
19                             outtextxy(width / 2 - 60, heigh / 2, _T("黑方胜"));
20                             system("pause");
21                             goto L1;
22                         }
23                     }
落子

 

  1 // 五子棋.cpp: 定义控制台应用程序的入口点。
  2 
  3 //头文件区
  4 #include "stdafx.h"
  5 #include <graphics.h>
  6 #include <conio.h>
  7 
  8 //宏定义区
  9 #define width 640
 10 #define heigh 700                                    //定义窗口的长和宽
 11 #define line_number 15                                //定义棋盘的条数 横竖各line_number条线
 12 
 13 //结构体定义区
 14 typedef struct
 15 {
 16     int kind;
 17 }Map;                            //棋盘    0为无子 1为黑子 2为白子
 18 typedef struct
 19 {
 20     int x;
 21     int y;
 22     int kind;
 23 }Record;                        //记录每一步棋的坐标
 24 typedef struct {
 25     int x;
 26     int y;
 27 }Point;                        //记录最佳点的坐标
 28 
 29 //全局变量区
 30 MOUSEMSG m;
 31 int flag_leftmouse ;                                //标志是否按下左键
 32 int point_x, point_y;                                //落子点的坐标
 33 Map maps[line_number + 1][line_number + 1];            //定义棋盘
 34 Record records[line_number * line_number + 1];        //记录每一步落子的坐标
 35 int kind_chess;                                        //1为黑子 2为白子
 36 int step ;                                            //棋盘线与线之间的间距
 37 int radius;                                            //棋子半径
 38 int number;                                            //当前总落子数
 39 
 40 int button_left;                                    //按钮的上下左右界
 41 int button_right;
 42 int button_top;
 43 int button_bottom;
 44 
 45 //初始化
 46 void Startup()
 47 {
 48     
 49     //当前棋盘没有落子 kind全部置为0;
 50     for (int i = 1; i <= line_number; i++)
 51     {
 52         for (int j = 1; j <= line_number; j++)
 53         {
 54             maps[i][j].kind = 0;
 55         }
 56     }
 57     //各种参数初始化
 58     flag_leftmouse = 0;
 59     number = 0;
 60     kind_chess = 1;
 61     step = width / (line_number + 1);
 62     radius = step /2 - 1;
 63     initgraph(width, heigh);
 64     //设置背景颜色
 65     setbkcolor(RGB(249, 214, 91));
 66     cleardevice();
 67 
 68     setlinecolor(BLACK);
 69     setlinestyle(PS_SOLID, 1);
 70     // 画出棋盘横竖各line_number条交错的直线
 71     for (int i = 1; i <= line_number; i++)
 72     {
 73         line(i*step, 1 * step, i*step, line_number * step);
 74         line(1 * step, i*step, line_number * step, i*step);
 75     }
 76     button_left = step;
 77     button_right = step * 4;
 78     button_top = (line_number + 1)*step - step / 2;
 79     button_bottom = heigh - step / 2;
 80     //画出悔棋键
 81     settextcolor(BLACK);
 82     settextstyle(step*2-step/2, step - step/4, _T("宋体"));
 83     outtextxy(button_left, button_top , _T("悔棋"));
 84     //画出认输键
 85     settextstyle(step * 2 - step / 2, step - step / 4, _T("宋体"));
 86     outtextxy(button_left+4*step, button_top, _T("认输"));
 87 }  
 88 
 89 //判断落子后是否胜利 即五连子 x,y,kind 分别为行数,列数,棋子的颜色
 90 int IsVictory(int x, int y, int kind)
 91 {
 92     //判断一列上是否有五连子
 93     int i = x;
 94     int j = y;
 95     int count = 0;
 96     while (i >= 1 && maps[i][j].kind == kind)
 97     {
 98         i--;
 99         count++;
100     }
101     i = x + 1;
102     while (i <= 19 && maps[i][j].kind == kind)
103     {
104         i++;
105         count++;
106     }
107     if (count == 5) return kind;
108     //判断一行上是否有五连子
109     i = x;
110     count = 0;
111     while (j >= 1 && maps[i][j].kind == kind)
112     {
113         j--;
114         count++;
115     }
116     j = y + 1;
117     while (j <= 19 && maps[i][j].kind == kind)
118     {
119         j++;
120         count++;
121     }
122     if (count == 5) return kind;
123     //判断左斜方向是否有五连子
124     i = x;
125     j = y;
126     count = 0;
127     while (i >= 1 && j >= 1 && maps[i][j].kind == kind)
128     {
129         j--;
130         i--;
131         count++;
132     }
133     i = x + 1;
134     j = y + 1;
135     while (j <= 19 && i <= 19 && maps[i][j].kind == kind)
136     {
137         j++;
138         i++;
139         count++;
140     }
141     if (count == 5) return kind;
142     //判断右斜方向是否有五连子
143     i = x;
144     j = y;
145     count = 0;
146     while (i <= 19 && j >= 1 && maps[i][j].kind == kind)
147     {
148         j--;
149         i++;
150         count++;
151     }
152     i = x - 1;
153     j = y + 1;
154     while (j <= 19 && i >= 1 && maps[i][j].kind == kind)
155     {
156         j++;
157         i--;
158         count++;
159     }
160     if (count == 5) return kind;
161     return 0;
162 }
163 
164 //AI落子
165 /*void dropChessAt(Point p)
166 {
167     number++;
168     records[number].x = p.x;
169     records[number].y = p.y;
170     records[number].kind = 2;
171 
172     setfillcolor(WHITE);
173     solidcircle(p.y * step, p.x*step, radius);
174     maps[p.x][p.y].kind = 2;
175     kind_chess = 1;
176     if (IsVictory( p.x, p.y, 2) == 2)
177     {
178         settextcolor(WHITE);
179         settextstyle(48, 0, _T("宋体"));
180         outtextxy(width / 2 - 60, heigh / 2, _T("白方胜"));
181         system("pause");
182     }
183 }*/
184 
185 //其中p为当前点,i为方向,取值为从1到8的整数,对应8个方向,
186 //j为相对于p点的坐标值。在函数体内要依据方向对p的x、y的值进行处理。返回该点的落子
187 //情况,0表示无子,1或2分别表示两个player,-1表示超出棋盘界。
188 /*int getLine(Point p, int i, int j)
189 {
190     int x = p.x, y = p.y;
191     switch (i)
192     {
193     case 1:
194         x = x - j; break;                //上
195     case 2:
196         x = x + j; break;                //下
197     case 3:
198         y = y - j; break;                //左
199     case 4:
200         y = y + j; break;                //右
201     case 5:
202         y = y + j; x = x - i; break;    //右上
203     case 6:
204         y = y - j; x = x - i; break;    //左上
205     case 7:
206         y = y + j; x = x + i; break;    //右下
207     case 8:
208         y = y - j; x = x + i; break;    //左下
209     default:
210         break;
211     }
212     if (x<1 || y<1 || x>line_number || y>line_number) return -1;
213     return maps[x][y].kind;
214 }*/
215 
216 
217 //估值函数(核心)
218 /*int envaluate(Point p, int kind)
219 {
220     Point dir[8];
221     dir[0].x = -1; dir[0].y = 0;    //上
222     //dir[1].x = 1; dir[1].y = 0;     //下
223     //dir[2].x = 0; dir[2].y = -1;    //左
224     dir[1].x = 0; dir[1].y = 1;     //右
225     dir[2].x = -1; dir[2].y = -1;   //左上
226     dir[3].x = -1; dir[3].y = 1;    //右上
227     //dir[6].x = 1; dir[6].y = -1;    //左下
228     //dir[7].x = 1; dir[7].y = 1;       //右下
229     int value = 0;
230     //敌对方是谁
231     int opposite;
232     if (kind == 1)opposite = 2;
233     if (kind == 2)opposite = 1;
234     for (int i = 0; i < 4; i++)
235     {
236         
237     }
238     
239 }*/
240 
241 //轮到AI的回合
242 /*void IsTimeToAI()
243 {
244     Point bestAttack;   //最佳进攻点
245     Point bestDefend;    //最佳防守点
246 
247     int max1 = 0;
248     //循环遍历整个棋盘
249     for (int i = 1; i <= line_number; i++)
250     {
251         for (int j = 1; j <= line_number; j++)
252         {
253             if (maps[i][j].kind != 0) continue;
254             //当前点
255             Point c;
256             c.x = i;
257             c.y = j;
258             int value = envaluate(c, 2);
259             //int value = Evaluate(c);
260             if (max1 < value)
261             {
262                 max1 = value;
263                 bestAttack = c;
264             }
265         }
266     }
267     int max2 = 0;
268     for (int i = 1; i <= line_number; i++)
269     {
270         for (int j = 1; j <= line_number; j++)
271         {
272             if (maps[i][j].kind != 0) continue;
273             Point c;
274             c.x = i;
275             c.y = j;
276             int value = envaluate(c, 1);
277             //int value = Evaluate(c);
278             if (max2 < value)
279             {
280                 max2 = value;
281                 bestDefend = c;
282             }
283         }
284     }
285 
286     if (max1 >= max2)
287     {
288         dropChessAt(bestAttack);
289     }
290     else {
291         dropChessAt(bestDefend);
292     }
293 }*/
294 
295 //游戏开始
296 void ConsoleGame()
297 {
298 L1:
299     //初始化
300     Startup();
301     //主循环
302     while (1)
303     {
304         if (MouseHit())
305         {
306             m = GetMouseMsg();
307             if (m.mkLButton == true )  //按下鼠标左键时 
308             {
309                 flag_leftmouse = 1;
310             }
311             if (m.mkLButton == false && flag_leftmouse==1)  //当松开鼠标左键后开
312             {
313                 //鼠标按键范围在棋盘内时
314                 if (m.x >= step - radius && m.x <= (width - (step - radius)) && m.y >= step - radius && m.y <= (width - (step - radius)))
315                 {
316                     if (m.x % step < step / 2)
317                     {
318                         point_x = m.x - m.x % step;
319                     }
320                     if (m.x % step > step / 2)
321                     {
322                         point_x = m.x + (step - m.x % (step));
323                     }
324                     if (m.y % step < step / 2)
325                     {
326                         point_y = m.y - m.y % step;
327                     }
328                     if (m.y % step > step / 2)
329                     {
330                         point_y = m.y + (step - m.y % step);
331                     }
332                     if (kind_chess == 1 && maps[point_y / (step)][point_x / step].kind == 0)
333                     {
334                         number++;
335                         records[number].x = point_y / step;
336                         records[number].y = point_x / step;
337                         records[number].kind = 1;
338 
339                         setfillcolor(BLACK);
340                         solidcircle(point_x, point_y, radius);
341                         maps[point_y / step][point_x / step].kind = 1;
342                         kind_chess = 2;
343                         if (IsVictory(point_y / step, point_x / step, 1) == 1)
344                         {
345                             
346                             settextcolor(BLACK);
347                             settextstyle(48, 0, _T("宋体"));
348                             outtextxy(width / 2 - 60, heigh / 2, _T("黑方胜"));
349                             system("pause");
350                             goto L1;
351                         }
352                     }
353                     //人人对战时的后手方落子
354                     else if (kind_chess == 2 && maps[point_y / step][point_x / step].kind == 0)
355                     {
356                         
357                         number++;
358                         records[number].x = point_y / step;
359                         records[number].y = point_x / step;
360                         records[number].kind = 2;
361 
362                         setfillcolor(WHITE);
363                         solidcircle(point_x, point_y, radius);
364                         maps[point_y / step][point_x / step].kind = 2;
365                         kind_chess = 1;
366                         if (IsVictory(point_y / step, point_x / step, 2) == 2)
367                         {
368                             settextcolor(WHITE);
369                             settextstyle(48, 0, _T("宋体"));
370                             outtextxy(width / 2 - 60, heigh / 2, _T("白方胜"));
371                             system("pause");
372                             goto L1;
373                         }
374                     }
375                 }
376                 //鼠标按键范围在悔棋键范围内时
377                 if (m.x >= button_left && m.x <=button_right &&m.y >=button_top &&m.y <=button_bottom)
378                 {
379                     if (number >= 1)
380                     {
381                         int x = records[number].x;
382                         int y = records[number].y;
383                         kind_chess = records[number].kind;
384                         setfillcolor(RGB(249, 214, 91));
385                         solidcircle(y * step, x * step, radius);
386                         setlinecolor(BLACK);
387                         if (x == 1 && y ==1)
388                         {
389                             line(y*step, x*step , y*step, x*step + radius);
390                             line(y*step , x*step, y*step + radius, x*step);
391                         }
392                         else if (y == 1 && (x > 1 && x < line_number))
393                         {
394                             line(y*step, x*step-radius, y*step, x*step + radius);
395                             line(y*step, x*step, y*step + radius, x*step);
396                         }
397                         else if (y == 1 && x == line_number)
398                         {
399                             line(y*step, x*step - radius, y*step, x*step);
400                             line(y*step, x*step, y*step + radius, x*step);
401                         }
402                         else if (x == 1 && y > 1 && y < line_number)
403                         {
404                             line(y*step, x*step, y*step, x*step+radius);
405                             line(y*step-radius, x*step, y*step+radius , x*step);
406                         }
407                         else if (x == 1 && y == line_number)
408                         {
409                             line(y*step, x*step , y*step, x*step+radius);
410                             line(y*step - radius, x*step , y*step, x*step);
411                         }
412                         else if (y == line_number && x > 1 && x < line_number)
413                         {
414                             line(y*step, x*step - radius, y*step, x*step+radius);
415                             line(y*step-radius, x*step, y*step , x*step);
416                         }
417                         else if (y == line_number && x == line_number)
418                         {
419                             line(y*step, x*step - radius, y*step, x*step);
420                             line(y*step - radius, x*step, y*step, x*step);
421                         }
422                         else if (x == line_number && y > 1 && y < line_number)
423                         {
424                             line(y*step, x*step - radius, y*step, x*step );
425                             line(y*step - radius, x*step, y*step+radius, x*step);
426                         }
427                         else
428                         {
429                             line(y*step, x*step - radius, y*step, x*step + radius);
430                             line(y*step - radius, x*step, y*step + radius, x*step);
431                         }
432                         maps[x][y].kind = 0;
433                         number--;
434                     }    
435                 }
436                 //鼠标按键范围在认输键范围内时
437                 else if (m.x >= button_left + 4 * step && m.x <= button_right + 4 * step && m.y >= button_top && m.y <= button_bottom)
438                 {
439                     if (kind_chess == 1)
440                     {
441                         settextcolor(BLACK);
442                         settextstyle(48, 0, _T("宋体"));
443                         outtextxy(width / 2 - 60, heigh / 2, _T("白方胜"));
444                         system("pause");
445                         goto L1;
446                     }
447                     else
448                     {
449                         settextcolor(BLACK);
450                         settextstyle(48, 0, _T("宋体"));
451                         outtextxy(width / 2 - 60, heigh / 2, _T("黑方胜"));
452                         system("pause");
453                         goto L1;
454                     }
455                 }
456                 flag_leftmouse = 0;
457             }
458         }
459         /*if (kind_chess == 2)
460         {
461             //Sleep(40);
462             //IsTimeToAI();
463         }*/
464     }
465     _getch();
466 }
467 
468 
469 int main()
470 {
471     ConsoleGame();
472 }
源代码

 

posted @ 2018-12-04 10:31  谋莽台  阅读(672)  评论(0编辑  收藏  举报